Merge remote-tracking branch 'upstream/master'
Conflicts: src/qt/overviewpage.cpp src/qt/transactiondesc.cpp
This commit is contained in:
172
src/Makefile.am
172
src/Makefile.am
@@ -1,16 +1,54 @@
|
||||
include Makefile.include
|
||||
AM_CPPFLAGS = $(INCLUDES)
|
||||
AM_LDFLAGS = $(PTHREAD_CFLAGS)
|
||||
|
||||
AM_CPPFLAGS += -I$(builddir)
|
||||
if USE_LIBSECP256K1
|
||||
secp256k1/libsecp256k1.la: $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
|
||||
@$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
|
||||
endif
|
||||
|
||||
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)
|
||||
|
||||
if USE_LIBSECP256K1
|
||||
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
|
||||
endif
|
||||
|
||||
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
|
||||
LIBBITCOINQT=qt/libbitcoinqt.a
|
||||
|
||||
noinst_LIBRARIES = \
|
||||
libbitcoin_server.a \
|
||||
libbitcoin_common.a \
|
||||
libbitcoin_cli.a
|
||||
libbitcoin_cli.a \
|
||||
libbitcoin_util.a \
|
||||
crypto/libbitcoin_crypto.a
|
||||
if ENABLE_WALLET
|
||||
BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
|
||||
noinst_LIBRARIES += libbitcoin_wallet.a
|
||||
endif
|
||||
|
||||
bin_PROGRAMS =
|
||||
TESTS =
|
||||
|
||||
if BUILD_BITCOIND
|
||||
bin_PROGRAMS += bitcoind
|
||||
@@ -20,17 +58,16 @@ if BUILD_BITCOIN_CLI
|
||||
bin_PROGRAMS += bitcoin-cli
|
||||
endif
|
||||
|
||||
SUBDIRS = . $(BUILD_QT) $(BUILD_TEST)
|
||||
DIST_SUBDIRS = . qt test
|
||||
.PHONY: FORCE
|
||||
# bitcoin core #
|
||||
BITCOIN_CORE_H = \
|
||||
addrman.h \
|
||||
alert.h \
|
||||
allocators.h \
|
||||
base58.h bignum.h \
|
||||
base58.h \
|
||||
bloom.h \
|
||||
chainparams.h \
|
||||
chainparamsbase.h \
|
||||
checkpoints.h \
|
||||
checkqueue.h \
|
||||
clientversion.h \
|
||||
@@ -52,6 +89,7 @@ BITCOIN_CORE_H = \
|
||||
netbase.h \
|
||||
net.h \
|
||||
noui.h \
|
||||
pow.h \
|
||||
protocol.h \
|
||||
rpcclient.h \
|
||||
rpcprotocol.h \
|
||||
@@ -60,6 +98,7 @@ BITCOIN_CORE_H = \
|
||||
serialize.h \
|
||||
sync.h \
|
||||
threadsafety.h \
|
||||
timedata.h \
|
||||
tinyformat.h \
|
||||
txdb.h \
|
||||
txmempool.h \
|
||||
@@ -68,7 +107,8 @@ BITCOIN_CORE_H = \
|
||||
util.h \
|
||||
version.h \
|
||||
walletdb.h \
|
||||
wallet.h
|
||||
wallet.h \
|
||||
compat/sanity.h
|
||||
|
||||
JSON_H = \
|
||||
json/json_spirit.h \
|
||||
@@ -82,35 +122,40 @@ JSON_H = \
|
||||
json/json_spirit_writer_template.h
|
||||
|
||||
obj/build.h: FORCE
|
||||
@$(MKDIR_P) $(abs_top_builddir)/src/obj
|
||||
@$(MKDIR_P) $(builddir)/obj
|
||||
@$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
|
||||
$(abs_top_srcdir)
|
||||
version.o: obj/build.h
|
||||
libbitcoin_util_a-version.$(OBJEXT): obj/build.h
|
||||
|
||||
# server: shared between bitcoind and bitcoin-qt
|
||||
libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
libbitcoin_server_a_SOURCES = \
|
||||
addrman.cpp \
|
||||
alert.cpp \
|
||||
bloom.cpp \
|
||||
checkpoints.cpp \
|
||||
coins.cpp \
|
||||
init.cpp \
|
||||
keystore.cpp \
|
||||
leveldbwrapper.cpp \
|
||||
main.cpp \
|
||||
miner.cpp \
|
||||
net.cpp \
|
||||
noui.cpp \
|
||||
pow.cpp \
|
||||
rpcblockchain.cpp \
|
||||
rpcmining.cpp \
|
||||
rpcmisc.cpp \
|
||||
rpcnet.cpp \
|
||||
rpcrawtransaction.cpp \
|
||||
rpcserver.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 \
|
||||
@@ -120,41 +165,74 @@ libbitcoin_wallet_a_SOURCES = \
|
||||
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/sha2.cpp \
|
||||
crypto/ripemd160.cpp \
|
||||
crypto/common.h \
|
||||
crypto/sha2.h \
|
||||
crypto/sha1.h \
|
||||
crypto/ripemd160.h
|
||||
|
||||
# common: shared between bitcoind, and bitcoin-qt and non-server tools
|
||||
libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
libbitcoin_common_a_SOURCES = \
|
||||
base58.cpp \
|
||||
allocators.cpp \
|
||||
base58.cpp \
|
||||
chainparams.cpp \
|
||||
coins.cpp \
|
||||
core.cpp \
|
||||
hash.cpp \
|
||||
key.cpp \
|
||||
keystore.cpp \
|
||||
netbase.cpp \
|
||||
protocol.cpp \
|
||||
rpcprotocol.cpp \
|
||||
script.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 = \
|
||||
chainparamsbase.cpp \
|
||||
rpcprotocol.cpp \
|
||||
sync.cpp \
|
||||
uint256.cpp \
|
||||
util.cpp \
|
||||
version.cpp \
|
||||
compat/glibc_sanity.cpp \
|
||||
compat/glibcxx_sanity.cpp \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
if GLIBC_BACK_COMPAT
|
||||
libbitcoin_common_a_SOURCES += compat/glibc_compat.cpp
|
||||
libbitcoin_common_a_SOURCES += compat/glibcxx_compat.cpp
|
||||
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_SOURCES = \
|
||||
rpcclient.cpp \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
nodist_libbitcoin_common_a_SOURCES = $(top_srcdir)/src/obj/build.h
|
||||
nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
|
||||
#
|
||||
|
||||
# bitcoind binary #
|
||||
bitcoind_LDADD = \
|
||||
libbitcoin_server.a \
|
||||
libbitcoin_cli.a \
|
||||
libbitcoin_common.a \
|
||||
$(LIBBITCOIN_SERVER) \
|
||||
$(LIBBITCOIN_COMMON) \
|
||||
$(LIBBITCOIN_UTIL) \
|
||||
$(LIBBITCOIN_CRYPTO) \
|
||||
$(LIBLEVELDB) \
|
||||
$(LIBMEMENV)
|
||||
|
||||
if USE_LIBSECP256K1
|
||||
bitcoind_LDADD += secp256k1/libsecp256k1.la
|
||||
endif
|
||||
|
||||
if ENABLE_WALLET
|
||||
bitcoind_LDADD += libbitcoin_wallet.a
|
||||
endif
|
||||
@@ -165,39 +243,61 @@ if TARGET_WINDOWS
|
||||
bitcoind_SOURCES += bitcoind-res.rc
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS += $(BDB_CPPFLAGS)
|
||||
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS)
|
||||
bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
|
||||
# bitcoin-cli binary #
|
||||
bitcoin_cli_LDADD = \
|
||||
libbitcoin_cli.a \
|
||||
libbitcoin_common.a \
|
||||
$(LIBBITCOIN_CLI) \
|
||||
$(LIBBITCOIN_COMMON) \
|
||||
$(LIBBITCOIN_UTIL) \
|
||||
$(LIBBITCOIN_CRYPTO) \
|
||||
$(BOOST_LIBS)
|
||||
bitcoin_cli_SOURCES = bitcoin-cli.cpp
|
||||
bitcoin_cli_SOURCES = \
|
||||
bitcoin-cli.cpp
|
||||
|
||||
if USE_LIBSECP256K1
|
||||
bitcoin_cli_LDADD += secp256k1/libsecp256k1.la
|
||||
endif
|
||||
bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||
#
|
||||
|
||||
if TARGET_WINDOWS
|
||||
bitcoin_cli_SOURCES += bitcoin-cli-res.rc
|
||||
endif
|
||||
|
||||
# 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
|
||||
leveldb/libleveldb.a: leveldb/libmemenv.a
|
||||
|
||||
leveldb/%.a:
|
||||
@echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \
|
||||
CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \
|
||||
OPT="$(CXXFLAGS) $(CPPFLAGS)"
|
||||
|
||||
qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_cli_a_SOURCES)
|
||||
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
|
||||
@cd $(top_srcdir); XGETTEXT=$(XGETTEXT) share/qt/extract_strings_qt.py
|
||||
|
||||
CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno
|
||||
|
||||
DISTCLEANFILES = obj/build.h
|
||||
|
||||
EXTRA_DIST = leveldb Makefile.include
|
||||
EXTRA_DIST = leveldb secp256k1
|
||||
|
||||
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) -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,79 +0,0 @@
|
||||
if EMBEDDED_LEVELDB
|
||||
LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/include
|
||||
LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/helpers/memenv
|
||||
LIBLEVELDB += $(top_builddir)/src/leveldb/libleveldb.a
|
||||
LIBMEMENV += $(top_builddir)/src/leveldb/libmemenv.a
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = $(INCLUDES) \
|
||||
-I$(top_builddir)/src/obj \
|
||||
$(BDB_CPPFLAGS) \
|
||||
$(BOOST_CPPFLAGS) $(BOOST_INCLUDES)
|
||||
AM_CPPFLAGS += $(LEVELDB_CPPFLAGS)
|
||||
AM_LDFLAGS = $(PTHREAD_CFLAGS)
|
||||
|
||||
LIBBITCOIN_SERVER=$(top_builddir)/src/libbitcoin_server.a
|
||||
LIBBITCOIN_WALLET=$(top_builddir)/src/libbitcoin_wallet.a
|
||||
LIBBITCOIN_COMMON=$(top_builddir)/src/libbitcoin_common.a
|
||||
LIBBITCOIN_CLI=$(top_builddir)/src/libbitcoin_cli.a
|
||||
LIBBITCOINQT=$(top_builddir)/src/qt/libbitcoinqt.a
|
||||
|
||||
$(LIBBITCOIN):
|
||||
$(MAKE) -C $(top_builddir)/src $(@F)
|
||||
|
||||
if EMBEDDED_LEVELDB
|
||||
$(LIBLEVELDB) $(LIBMEMENV):
|
||||
$(MAKE) -C $(top_builddir)/src leveldb/$(@F)
|
||||
endif
|
||||
|
||||
$(LIBBITCOINQT):
|
||||
$(MAKE) -C $(top_builddir)/src/qt $(@F)
|
||||
|
||||
.mm.o:
|
||||
$(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
.rc.o:
|
||||
@test -f $(WINDRES) && $(WINDRES) -i $< -o $@ || \
|
||||
echo error: could not build $@
|
||||
|
||||
ui_%.h: %.ui
|
||||
@test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D)
|
||||
@test -f $(UIC) && QT_SELECT=$(QT_SELECT) $(UIC) -o $(abs_builddir)/$@ $(abs_srcdir)/$< || echo error: could not build $(abs_builddir)/$@
|
||||
$(SED) -e '/^\*\*.*Created:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,}
|
||||
$(SED) -e '/^\*\*.*by:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,}
|
||||
|
||||
%.moc: %.cpp
|
||||
QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $<
|
||||
$(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,}
|
||||
$(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,}
|
||||
|
||||
moc_%.cpp: %.h
|
||||
QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $<
|
||||
$(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,}
|
||||
$(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,}
|
||||
|
||||
%.qm: %.ts
|
||||
@test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D)
|
||||
@test -f $(LRELEASE) && QT_SELECT=$(QT_SELECT) $(LRELEASE) $(abs_srcdir)/$< -qm $(abs_builddir)/$@ || \
|
||||
echo error: could not build $(abs_builddir)/$@
|
||||
|
||||
%.pb.cc %.pb.h: %.proto
|
||||
test -f $(PROTOC) && $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<) || \
|
||||
echo error: could not build $@
|
||||
|
||||
%.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 $@"
|
||||
417
src/Makefile.qt.include
Normal file
417
src/Makefile.qt.include
Normal file
@@ -0,0 +1,417 @@
|
||||
bin_PROGRAMS += qt/bitcoin-qt
|
||||
noinst_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_monitoreddatamapper.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/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/monitoreddatamapper.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/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/toolbar.png \
|
||||
qt/res/icons/toolbar_testnet.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/monitoreddatamapper.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) $(LIBLEVELDB) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
|
||||
if USE_LIBSECP256K1
|
||||
qt_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la
|
||||
endif
|
||||
qt_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS)
|
||||
|
||||
#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 $@
|
||||
51
src/Makefile.qttest.include
Normal file
51
src/Makefile.qttest.include
Normal file
@@ -0,0 +1,51 @@
|
||||
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)
|
||||
|
||||
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) $(LIBLEVELDB) \
|
||||
$(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
|
||||
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
|
||||
if USE_LIBSECP256K1
|
||||
qt_test_test_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la
|
||||
endif
|
||||
qt_test_test_bitcoin_qt_LDFLAGS = $(QT_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)
|
||||
109
src/Makefile.test.include
Normal file
109
src/Makefile.test.include
Normal file
@@ -0,0 +1,109 @@
|
||||
TESTS += test/test_bitcoin
|
||||
bin_PROGRAMS += test/test_bitcoin
|
||||
TEST_SRCDIR = test
|
||||
TEST_BINARY=test/test_bitcoin$(EXEEXT)
|
||||
|
||||
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/canonical_tests.cpp \
|
||||
test/checkblock_tests.cpp \
|
||||
test/Checkpoints_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/miner_tests.cpp \
|
||||
test/mruset_tests.cpp \
|
||||
test/multisig_tests.cpp \
|
||||
test/netbase_tests.cpp \
|
||||
test/pmt_tests.cpp \
|
||||
test/rpc_tests.cpp \
|
||||
test/script_P2SH_tests.cpp \
|
||||
test/script_tests.cpp \
|
||||
test/serialize_tests.cpp \
|
||||
test/sigopcount_tests.cpp \
|
||||
test/skiplist_tests.cpp \
|
||||
test/test_bitcoin.cpp \
|
||||
test/transaction_tests.cpp \
|
||||
test/uint256_tests.cpp \
|
||||
test/util_tests.cpp \
|
||||
test/scriptnum_tests.cpp \
|
||||
test/sighash_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) $(LIBLEVELDB) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB)
|
||||
if ENABLE_WALLET
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
|
||||
endif
|
||||
|
||||
if USE_LIBSECP256K1
|
||||
test_test_bitcoin_LDADD += secp256k1/libsecp256k1.la
|
||||
endif
|
||||
|
||||
test_test_bitcoin_LDADD += $(BDB_LIBS)
|
||||
|
||||
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)
|
||||
|
||||
%.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 $@"
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
#include "sync.h"
|
||||
#include "timedata.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <map>
|
||||
@@ -420,7 +421,7 @@ public:
|
||||
Check();
|
||||
}
|
||||
if (fRet)
|
||||
LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString().c_str(), nTried, nNew);
|
||||
LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString(), nTried, nNew);
|
||||
return fRet;
|
||||
}
|
||||
|
||||
@@ -436,7 +437,7 @@ public:
|
||||
Check();
|
||||
}
|
||||
if (nAdd)
|
||||
LogPrint("addrman", "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString().c_str(), nTried, nNew);
|
||||
LogPrint("addrman", "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew);
|
||||
return nAdd > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
#include "alert.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "key.h"
|
||||
#include "net.h"
|
||||
#include "timedata.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
184
src/base58.cpp
184
src/base58.cpp
@@ -2,11 +2,18 @@
|
||||
// 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 "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";
|
||||
@@ -89,3 +96,180 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
|
||||
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 {
|
||||
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;
|
||||
ret.Set(&vchData[0], &vchData[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());
|
||||
}
|
||||
|
||||
257
src/base58.h
257
src/base58.h
@@ -15,17 +15,12 @@
|
||||
#define BITCOIN_BASE58_H
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "hash.h"
|
||||
#include "key.h"
|
||||
#include "script.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
|
||||
/**
|
||||
* Encode a byte sequence as a base58-encoded string.
|
||||
* pbegin and pend cannot be NULL, unless both are.
|
||||
@@ -35,10 +30,7 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
|
||||
/**
|
||||
* Encode a byte vector as a base58-encoded string
|
||||
*/
|
||||
inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
return EncodeBase58(&vch[0], &vch[0] + vch.size());
|
||||
}
|
||||
std::string EncodeBase58(const std::vector<unsigned char>& vch);
|
||||
|
||||
/**
|
||||
* Decode a base58-encoded string (psz) into a byte vector (vchRet).
|
||||
@@ -51,55 +43,24 @@ 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.
|
||||
*/
|
||||
inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
return DecodeBase58(str.c_str(), vchRet);
|
||||
}
|
||||
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet);
|
||||
|
||||
/**
|
||||
* Encode a byte vector into a base58-encoded string, including checksum
|
||||
*/
|
||||
inline 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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (!DecodeBase58(psz, vchRet))
|
||||
return false;
|
||||
if (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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
return DecodeBase58Check(str.c_str(), vchRet);
|
||||
}
|
||||
inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
|
||||
|
||||
/**
|
||||
* Base class for all base58-encoded data
|
||||
@@ -114,64 +75,15 @@ protected:
|
||||
typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
|
||||
vector_uchar vchData;
|
||||
|
||||
CBase58Data()
|
||||
{
|
||||
vchVersion.clear();
|
||||
vchData.clear();
|
||||
}
|
||||
|
||||
void 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 SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend)
|
||||
{
|
||||
SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
|
||||
}
|
||||
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)
|
||||
{
|
||||
std::vector<unsigned char> vchTemp;
|
||||
DecodeBase58Check(psz, vchTemp);
|
||||
if (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 SetString(const std::string& str)
|
||||
{
|
||||
return SetString(str.c_str());
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
std::vector<unsigned char> vch = vchVersion;
|
||||
vch.insert(vch.end(), vchData.begin(), vchData.end());
|
||||
return EncodeBase58Check(vch);
|
||||
}
|
||||
|
||||
int 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;
|
||||
}
|
||||
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; }
|
||||
@@ -186,140 +98,37 @@ public:
|
||||
* 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;
|
||||
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
|
||||
{
|
||||
private:
|
||||
CBitcoinAddress *addr;
|
||||
class CBitcoinAddress : public CBase58Data {
|
||||
public:
|
||||
CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
|
||||
bool operator()(const CKeyID &id) const;
|
||||
bool operator()(const CScriptID &id) const;
|
||||
bool operator()(const CNoDestination &no) const;
|
||||
bool Set(const CKeyID &id);
|
||||
bool Set(const CScriptID &id);
|
||||
bool Set(const CTxDestination &dest);
|
||||
bool IsValid() 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;
|
||||
};
|
||||
|
||||
class CBitcoinAddress : public CBase58Data
|
||||
{
|
||||
public:
|
||||
bool Set(const CKeyID &id) {
|
||||
SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Set(const CScriptID &id) {
|
||||
SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Set(const CTxDestination &dest)
|
||||
{
|
||||
return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
bool fCorrectSize = vchData.size() == 20;
|
||||
bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
|
||||
vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||
return fCorrectSize && fKnownVersion;
|
||||
}
|
||||
|
||||
CBitcoinAddress()
|
||||
{
|
||||
}
|
||||
|
||||
CBitcoinAddress(const CTxDestination &dest)
|
||||
{
|
||||
Set(dest);
|
||||
}
|
||||
|
||||
CBitcoinAddress(const std::string& strAddress)
|
||||
{
|
||||
SetString(strAddress);
|
||||
}
|
||||
|
||||
CBitcoinAddress(const char* pszAddress)
|
||||
{
|
||||
SetString(pszAddress);
|
||||
}
|
||||
|
||||
CTxDestination 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 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 IsScript() const {
|
||||
return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||
}
|
||||
};
|
||||
|
||||
bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); }
|
||||
bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); }
|
||||
bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; }
|
||||
|
||||
/**
|
||||
* A base58-encoded secret key
|
||||
*/
|
||||
class CBitcoinSecret : public CBase58Data
|
||||
{
|
||||
public:
|
||||
void SetKey(const CKey& vchSecret)
|
||||
{
|
||||
assert(vchSecret.IsValid());
|
||||
SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
|
||||
if (vchSecret.IsCompressed())
|
||||
vchData.push_back(1);
|
||||
}
|
||||
void SetKey(const CKey& vchSecret);
|
||||
CKey GetKey();
|
||||
bool IsValid() const;
|
||||
bool SetString(const char* pszSecret);
|
||||
bool SetString(const std::string& strSecret);
|
||||
|
||||
CKey GetKey()
|
||||
{
|
||||
CKey ret;
|
||||
ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool 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 SetString(const char* pszSecret)
|
||||
{
|
||||
return CBase58Data::SetString(pszSecret) && IsValid();
|
||||
}
|
||||
|
||||
bool SetString(const std::string& strSecret)
|
||||
{
|
||||
return SetString(strSecret.c_str());
|
||||
}
|
||||
|
||||
CBitcoinSecret(const CKey& vchSecret)
|
||||
{
|
||||
SetKey(vchSecret);
|
||||
}
|
||||
|
||||
CBitcoinSecret()
|
||||
{
|
||||
}
|
||||
CBitcoinSecret(const CKey& vchSecret) { SetKey(vchSecret); }
|
||||
CBitcoinSecret() {}
|
||||
};
|
||||
|
||||
template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtKeyBase : public CBase58Data
|
||||
|
||||
595
src/bignum.h
595
src/bignum.h
@@ -1,595 +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_BIGNUM_H
|
||||
#define BITCOIN_BIGNUM_H
|
||||
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/** Errors thrown by the bignum class */
|
||||
class bignum_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
|
||||
};
|
||||
|
||||
|
||||
/** RAII encapsulated BN_CTX (OpenSSL bignum context) */
|
||||
class CAutoBN_CTX
|
||||
{
|
||||
protected:
|
||||
BN_CTX* pctx;
|
||||
BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
|
||||
|
||||
public:
|
||||
CAutoBN_CTX()
|
||||
{
|
||||
pctx = BN_CTX_new();
|
||||
if (pctx == NULL)
|
||||
throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
|
||||
}
|
||||
|
||||
~CAutoBN_CTX()
|
||||
{
|
||||
if (pctx != NULL)
|
||||
BN_CTX_free(pctx);
|
||||
}
|
||||
|
||||
operator BN_CTX*() { return pctx; }
|
||||
BN_CTX& operator*() { return *pctx; }
|
||||
BN_CTX** operator&() { return &pctx; }
|
||||
bool operator!() { return (pctx == NULL); }
|
||||
};
|
||||
|
||||
|
||||
/** C++ wrapper for BIGNUM (OpenSSL bignum) */
|
||||
class CBigNum : public BIGNUM
|
||||
{
|
||||
public:
|
||||
CBigNum()
|
||||
{
|
||||
BN_init(this);
|
||||
}
|
||||
|
||||
CBigNum(const CBigNum& b)
|
||||
{
|
||||
BN_init(this);
|
||||
if (!BN_copy(this, &b))
|
||||
{
|
||||
BN_clear_free(this);
|
||||
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
|
||||
}
|
||||
}
|
||||
|
||||
CBigNum& operator=(const CBigNum& b)
|
||||
{
|
||||
if (!BN_copy(this, &b))
|
||||
throw bignum_error("CBigNum::operator= : BN_copy failed");
|
||||
return (*this);
|
||||
}
|
||||
|
||||
~CBigNum()
|
||||
{
|
||||
BN_clear_free(this);
|
||||
}
|
||||
|
||||
//CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'.
|
||||
CBigNum(signed char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(long long n) { BN_init(this); setint64(n); }
|
||||
CBigNum(unsigned char n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned short n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned int n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned long n) { BN_init(this); setulong(n); }
|
||||
CBigNum(unsigned long long n) { BN_init(this); setuint64(n); }
|
||||
explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }
|
||||
|
||||
explicit CBigNum(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
BN_init(this);
|
||||
setvch(vch);
|
||||
}
|
||||
|
||||
void setulong(unsigned long n)
|
||||
{
|
||||
if (!BN_set_word(this, n))
|
||||
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
|
||||
}
|
||||
|
||||
unsigned long getulong() const
|
||||
{
|
||||
return BN_get_word(this);
|
||||
}
|
||||
|
||||
unsigned int getuint() const
|
||||
{
|
||||
return BN_get_word(this);
|
||||
}
|
||||
|
||||
int getint() const
|
||||
{
|
||||
unsigned long n = BN_get_word(this);
|
||||
if (!BN_is_negative(this))
|
||||
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
|
||||
else
|
||||
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
|
||||
}
|
||||
|
||||
void setint64(int64_t sn)
|
||||
{
|
||||
unsigned char pch[sizeof(sn) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fNegative;
|
||||
uint64_t n;
|
||||
|
||||
if (sn < (int64_t)0)
|
||||
{
|
||||
// Since the minimum signed integer cannot be represented as positive so long as its type is signed,
|
||||
// and it's not well-defined what happens if you make it unsigned before negating it,
|
||||
// we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate
|
||||
n = -(sn + 1);
|
||||
++n;
|
||||
fNegative = true;
|
||||
} else {
|
||||
n = sn;
|
||||
fNegative = false;
|
||||
}
|
||||
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char c = (n >> 56) & 0xff;
|
||||
n <<= 8;
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = (fNegative ? 0x80 : 0);
|
||||
else if (fNegative)
|
||||
c |= 0x80;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
}
|
||||
|
||||
void setuint64(uint64_t n)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned char c = (n >> 56) & 0xff;
|
||||
n <<= 8;
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = 0;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
}
|
||||
|
||||
void setuint256(uint256 n)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fLeadingZeroes = true;
|
||||
unsigned char* pbegin = (unsigned char*)&n;
|
||||
unsigned char* psrc = pbegin + sizeof(n);
|
||||
while (psrc != pbegin)
|
||||
{
|
||||
unsigned char c = *(--psrc);
|
||||
if (fLeadingZeroes)
|
||||
{
|
||||
if (c == 0)
|
||||
continue;
|
||||
if (c & 0x80)
|
||||
*p++ = 0;
|
||||
fLeadingZeroes = false;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
unsigned int nSize = p - (pch + 4);
|
||||
pch[0] = (nSize >> 24) & 0xff;
|
||||
pch[1] = (nSize >> 16) & 0xff;
|
||||
pch[2] = (nSize >> 8) & 0xff;
|
||||
pch[3] = (nSize >> 0) & 0xff;
|
||||
BN_mpi2bn(pch, p - pch, this);
|
||||
}
|
||||
|
||||
uint256 getuint256() const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
if (nSize < 4)
|
||||
return 0;
|
||||
std::vector<unsigned char> vch(nSize);
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
if (vch.size() > 4)
|
||||
vch[4] &= 0x7f;
|
||||
uint256 n = 0;
|
||||
for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
|
||||
((unsigned char*)&n)[i] = vch[j];
|
||||
return n;
|
||||
}
|
||||
|
||||
void setvch(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
std::vector<unsigned char> vch2(vch.size() + 4);
|
||||
unsigned int nSize = vch.size();
|
||||
// BIGNUM's byte stream format expects 4 bytes of
|
||||
// big endian size data info at the front
|
||||
vch2[0] = (nSize >> 24) & 0xff;
|
||||
vch2[1] = (nSize >> 16) & 0xff;
|
||||
vch2[2] = (nSize >> 8) & 0xff;
|
||||
vch2[3] = (nSize >> 0) & 0xff;
|
||||
// swap data to big endian
|
||||
reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
|
||||
BN_mpi2bn(&vch2[0], vch2.size(), this);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> getvch() const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
if (nSize <= 4)
|
||||
return std::vector<unsigned char>();
|
||||
std::vector<unsigned char> vch(nSize);
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
vch.erase(vch.begin(), vch.begin() + 4);
|
||||
reverse(vch.begin(), vch.end());
|
||||
return vch;
|
||||
}
|
||||
|
||||
// The "compact" format is a representation of a whole
|
||||
// number N using an unsigned 32bit number similar to a
|
||||
// floating point format.
|
||||
// The most significant 8 bits are the unsigned exponent of base 256.
|
||||
// This exponent can be thought of as "number of bytes of N".
|
||||
// The lower 23 bits are the mantissa.
|
||||
// Bit number 24 (0x800000) represents the sign of N.
|
||||
// N = (-1^sign) * mantissa * 256^(exponent-3)
|
||||
//
|
||||
// Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn().
|
||||
// MPI uses the most significant bit of the first byte as sign.
|
||||
// Thus 0x1234560000 is compact (0x05123456)
|
||||
// and 0xc0de000000 is compact (0x0600c0de)
|
||||
// (0x05c0de00) would be -0x40de000000
|
||||
//
|
||||
// Bitcoin only uses this "compact" format for encoding difficulty
|
||||
// targets, which are unsigned 256bit quantities. Thus, all the
|
||||
// complexities of the sign bit and using base 256 are probably an
|
||||
// implementation accident.
|
||||
//
|
||||
// This implementation directly uses shifts instead of going
|
||||
// through an intermediate MPI representation.
|
||||
CBigNum& SetCompact(unsigned int nCompact)
|
||||
{
|
||||
unsigned int nSize = nCompact >> 24;
|
||||
bool fNegative =(nCompact & 0x00800000) != 0;
|
||||
unsigned int nWord = nCompact & 0x007fffff;
|
||||
if (nSize <= 3)
|
||||
{
|
||||
nWord >>= 8*(3-nSize);
|
||||
BN_set_word(this, nWord);
|
||||
}
|
||||
else
|
||||
{
|
||||
BN_set_word(this, nWord);
|
||||
BN_lshift(this, this, 8*(nSize-3));
|
||||
}
|
||||
BN_set_negative(this, fNegative);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int GetCompact() const
|
||||
{
|
||||
unsigned int nSize = BN_num_bytes(this);
|
||||
unsigned int nCompact = 0;
|
||||
if (nSize <= 3)
|
||||
nCompact = BN_get_word(this) << 8*(3-nSize);
|
||||
else
|
||||
{
|
||||
CBigNum bn;
|
||||
BN_rshift(&bn, this, 8*(nSize-3));
|
||||
nCompact = BN_get_word(&bn);
|
||||
}
|
||||
// The 0x00800000 bit denotes the sign.
|
||||
// Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
|
||||
if (nCompact & 0x00800000)
|
||||
{
|
||||
nCompact >>= 8;
|
||||
nSize++;
|
||||
}
|
||||
nCompact |= nSize << 24;
|
||||
nCompact |= (BN_is_negative(this) ? 0x00800000 : 0);
|
||||
return nCompact;
|
||||
}
|
||||
|
||||
void SetHex(const std::string& str)
|
||||
{
|
||||
// skip 0x
|
||||
const char* psz = str.c_str();
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
bool fNegative = false;
|
||||
if (*psz == '-')
|
||||
{
|
||||
fNegative = true;
|
||||
psz++;
|
||||
}
|
||||
if (psz[0] == '0' && tolower(psz[1]) == 'x')
|
||||
psz += 2;
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
|
||||
// hex string to bignum
|
||||
*this = 0;
|
||||
int n;
|
||||
while ((n = HexDigit(*psz)) != -1)
|
||||
{
|
||||
*this <<= 4;
|
||||
*this += n;
|
||||
++psz;
|
||||
}
|
||||
if (fNegative)
|
||||
*this = 0 - *this;
|
||||
}
|
||||
|
||||
std::string ToString(int nBase=10) const
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum bnBase = nBase;
|
||||
CBigNum bn0 = 0;
|
||||
std::string str;
|
||||
CBigNum bn = *this;
|
||||
BN_set_negative(&bn, false);
|
||||
CBigNum dv;
|
||||
CBigNum rem;
|
||||
if (BN_cmp(&bn, &bn0) == 0)
|
||||
return "0";
|
||||
while (BN_cmp(&bn, &bn0) > 0)
|
||||
{
|
||||
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
|
||||
throw bignum_error("CBigNum::ToString() : BN_div failed");
|
||||
bn = dv;
|
||||
unsigned int c = rem.getulong();
|
||||
str += "0123456789abcdef"[c];
|
||||
}
|
||||
if (BN_is_negative(this))
|
||||
str += "-";
|
||||
reverse(str.begin(), str.end());
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string GetHex() const
|
||||
{
|
||||
return ToString(16);
|
||||
}
|
||||
|
||||
unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const
|
||||
{
|
||||
return ::GetSerializeSize(getvch(), nType, nVersion);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const
|
||||
{
|
||||
::Serialize(s, getvch(), nType, nVersion);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION)
|
||||
{
|
||||
std::vector<unsigned char> vch;
|
||||
::Unserialize(s, vch, nType, nVersion);
|
||||
setvch(vch);
|
||||
}
|
||||
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return BN_is_zero(this);
|
||||
}
|
||||
|
||||
CBigNum& operator+=(const CBigNum& b)
|
||||
{
|
||||
if (!BN_add(this, this, &b))
|
||||
throw bignum_error("CBigNum::operator+= : BN_add failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator-=(const CBigNum& b)
|
||||
{
|
||||
*this = *this - b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator*=(const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
if (!BN_mul(this, this, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator*= : BN_mul failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator/=(const CBigNum& b)
|
||||
{
|
||||
*this = *this / b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator%=(const CBigNum& b)
|
||||
{
|
||||
*this = *this % b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator<<=(unsigned int shift)
|
||||
{
|
||||
if (!BN_lshift(this, this, shift))
|
||||
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBigNum& operator>>=(unsigned int shift)
|
||||
{
|
||||
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
|
||||
// if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL
|
||||
CBigNum a = 1;
|
||||
a <<= shift;
|
||||
if (BN_cmp(&a, this) > 0)
|
||||
{
|
||||
*this = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (!BN_rshift(this, this, shift))
|
||||
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
CBigNum& operator++()
|
||||
{
|
||||
// prefix operator
|
||||
if (!BN_add(this, this, BN_value_one()))
|
||||
throw bignum_error("CBigNum::operator++ : BN_add failed");
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBigNum operator++(int)
|
||||
{
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
++(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CBigNum& operator--()
|
||||
{
|
||||
// prefix operator
|
||||
CBigNum r;
|
||||
if (!BN_sub(&r, this, BN_value_one()))
|
||||
throw bignum_error("CBigNum::operator-- : BN_sub failed");
|
||||
*this = r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBigNum operator--(int)
|
||||
{
|
||||
// postfix operator
|
||||
const CBigNum ret = *this;
|
||||
--(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
|
||||
friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_add(&r, &a, &b))
|
||||
throw bignum_error("CBigNum::operator+ : BN_add failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_sub(&r, &a, &b))
|
||||
throw bignum_error("CBigNum::operator- : BN_sub failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator-(const CBigNum& a)
|
||||
{
|
||||
CBigNum r(a);
|
||||
BN_set_negative(&r, !BN_is_negative(&r));
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_mul(&r, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator* : BN_mul failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_div(&r, NULL, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator/ : BN_div failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum r;
|
||||
if (!BN_mod(&r, &a, &b, pctx))
|
||||
throw bignum_error("CBigNum::operator% : BN_div failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
|
||||
{
|
||||
CBigNum r;
|
||||
if (!BN_lshift(&r, &a, shift))
|
||||
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
|
||||
{
|
||||
CBigNum r = a;
|
||||
r >>= shift;
|
||||
return r;
|
||||
}
|
||||
|
||||
inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
|
||||
inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
|
||||
inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
|
||||
inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
|
||||
inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); }
|
||||
inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); }
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,6 @@
|
||||
#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
|
||||
#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core developers"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
|
||||
@@ -7,11 +7,39 @@
|
||||
#include "init.h"
|
||||
#include "rpcclient.h"
|
||||
#include "rpcprotocol.h"
|
||||
#include "ui_interface.h" /* for _(...) */
|
||||
#include "chainparams.h"
|
||||
#include "chainparamsbase.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> " + _("Specify configuration file (default: 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> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n";
|
||||
strUsage += " -rpcport=<port> " + _("Connect to JSON-RPC on <port> (default: 8332 or testnet: 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
|
||||
@@ -33,22 +61,23 @@ static bool AppInitRPC(int argc, char* argv[])
|
||||
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
// Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause)
|
||||
if (!SelectParamsFromCommandLine()) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (argc<2 || mapArgs.count("-?") || mapArgs.count("--help"))
|
||||
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
|
||||
{
|
||||
// First part of help message is specific to RPC client
|
||||
std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n\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";
|
||||
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(true);
|
||||
strUsage += "\n" + HelpMessageCli();
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s", strUsage.c_str());
|
||||
return false;
|
||||
@@ -56,22 +85,154 @@ static bool AppInitRPC(int argc, char* argv[])
|
||||
return true;
|
||||
}
|
||||
|
||||
Object CallRPC(const string& strMethod, const Array& params)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
|
||||
bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started
|
||||
do {
|
||||
bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort())));
|
||||
if (fConnected) break;
|
||||
if (fWait)
|
||||
MilliSleep(1000);
|
||||
else
|
||||
throw runtime_error("couldn't connect to server");
|
||||
} while (fWait);
|
||||
|
||||
// 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
strPrint = "error: " + write_string(error, false);
|
||||
int code = find_value(error.get_obj(), "code").get_int();
|
||||
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);
|
||||
}
|
||||
}
|
||||
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 abs(RPC_MISC_ERROR);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "AppInitRPC()");
|
||||
return abs(RPC_MISC_ERROR);
|
||||
return EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "AppInitRPC()");
|
||||
return abs(RPC_MISC_ERROR);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int ret = abs(RPC_MISC_ERROR);
|
||||
int ret = EXIT_FAILURE;
|
||||
try
|
||||
{
|
||||
ret = CommandLineRPC(argc, argv);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#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
|
||||
#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core developers"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "rpcserver.h"
|
||||
#include "rpcclient.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
#include "noui.h"
|
||||
@@ -77,25 +76,27 @@ bool AppInit(int argc, char* argv[])
|
||||
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
// Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause)
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
||||
if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
|
||||
{
|
||||
// First part of help message is specific to bitcoind / RPC client
|
||||
std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n\n" +
|
||||
_("Usage:") + "\n" +
|
||||
" bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n" +
|
||||
_("Usage (deprecated, use bitcoin-cli):") + "\n" +
|
||||
" bitcoind [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
|
||||
" bitcoind [options] help " + _("List commands") + "\n" +
|
||||
" bitcoind [options] help <command> " + _("Get help for a command") + "\n";
|
||||
std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n";
|
||||
|
||||
strUsage += "\n" + HelpMessage(HMM_BITCOIND);
|
||||
strUsage += "\n" + HelpMessageCli(false);
|
||||
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;
|
||||
@@ -109,8 +110,8 @@ bool AppInit(int argc, char* argv[])
|
||||
|
||||
if (fCommandLine)
|
||||
{
|
||||
int ret = CommandLineRPC(argc, argv);
|
||||
exit(ret);
|
||||
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);
|
||||
@@ -172,15 +173,10 @@ bool AppInit(int argc, char* argv[])
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
bool fRet = false;
|
||||
SetupEnvironment();
|
||||
|
||||
// Connect bitcoind signal handlers
|
||||
noui_connect();
|
||||
|
||||
fRet = AppInit(argc, argv);
|
||||
|
||||
if (fRet && fDaemon)
|
||||
return 0;
|
||||
|
||||
return (fRet ? 0 : 1);
|
||||
return (AppInit(argc, argv) ? 0 : 1);
|
||||
}
|
||||
|
||||
@@ -94,12 +94,19 @@ bool CBloomFilter::contains(const uint256& hash) const
|
||||
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, const uint256& hash)
|
||||
bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
||||
{
|
||||
bool fFound = false;
|
||||
// Match if the filter contains the hash of tx
|
||||
@@ -108,6 +115,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& ha
|
||||
return true;
|
||||
if (isEmpty)
|
||||
return false;
|
||||
const uint256& hash = tx.GetHash();
|
||||
if (contains(hash))
|
||||
fFound = true;
|
||||
|
||||
|
||||
@@ -78,12 +78,14 @@ public:
|
||||
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, const uint256& hash);
|
||||
bool IsRelevantAndUpdate(const CTransaction& tx);
|
||||
|
||||
// Checks for empty and full filters to avoid wasting cpu
|
||||
void UpdateEmptyFull();
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
#include "chainparams.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "core.h"
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::assign;
|
||||
|
||||
//
|
||||
@@ -100,6 +99,8 @@ unsigned int pnSeed[] =
|
||||
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.
|
||||
@@ -109,9 +110,14 @@ public:
|
||||
pchMessageStart[3] = 0xd9;
|
||||
vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
|
||||
nDefaultPort = 8333;
|
||||
nRPCPort = 8332;
|
||||
bnProofOfWorkLimit = CBigNum(~uint256(0) >> 32);
|
||||
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. Note that the output of the genesis coinbase cannot
|
||||
// be spent as it did not originally exist in the database.
|
||||
@@ -122,10 +128,10 @@ public:
|
||||
// CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
|
||||
// vMerkleTree: 4a5e1e
|
||||
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
|
||||
CTransaction txNew;
|
||||
CMutableTransaction txNew;
|
||||
txNew.vin.resize(1);
|
||||
txNew.vout.resize(1);
|
||||
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||
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 = 50 * COIN;
|
||||
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
|
||||
genesis.vtx.push_back(txNew);
|
||||
@@ -167,27 +173,25 @@ public:
|
||||
addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
|
||||
vFixedSeeds.push_back(addr);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const CBlock& GenesisBlock() const { return genesis; }
|
||||
virtual Network NetworkID() const { return CChainParams::MAIN; }
|
||||
|
||||
virtual const vector<CAddress>& FixedSeeds() const {
|
||||
return vFixedSeeds;
|
||||
fRequireRPCPassword = true;
|
||||
fMiningRequiresPeers = true;
|
||||
fDefaultCheckMemPool = false;
|
||||
fAllowMinDifficultyBlocks = false;
|
||||
fRequireStandard = true;
|
||||
fMineBlocksOnDemand = false;
|
||||
}
|
||||
protected:
|
||||
CBlock genesis;
|
||||
vector<CAddress> vFixedSeeds;
|
||||
};
|
||||
static CMainParams mainParams;
|
||||
|
||||
|
||||
//
|
||||
// Testnet (v3)
|
||||
//
|
||||
class CTestNetParams : public CMainParams {
|
||||
public:
|
||||
CTestNetParams() {
|
||||
networkID = CBaseChainParams::TESTNET;
|
||||
strNetworkID = "test";
|
||||
// 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.
|
||||
@@ -197,8 +201,12 @@ public:
|
||||
pchMessageStart[3] = 0x07;
|
||||
vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a");
|
||||
nDefaultPort = 18333;
|
||||
nRPCPort = 18332;
|
||||
strDataDir = "testnet3";
|
||||
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;
|
||||
@@ -208,6 +216,7 @@ public:
|
||||
|
||||
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"));
|
||||
|
||||
@@ -216,55 +225,73 @@ public:
|
||||
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);
|
||||
|
||||
fRequireRPCPassword = true;
|
||||
fMiningRequiresPeers = true;
|
||||
fDefaultCheckMemPool = false;
|
||||
fAllowMinDifficultyBlocks = true;
|
||||
fRequireStandard = false;
|
||||
fMineBlocksOnDemand = false;
|
||||
}
|
||||
virtual Network NetworkID() const { return CChainParams::TESTNET; }
|
||||
};
|
||||
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;
|
||||
bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
|
||||
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.nBits = 0x207fffff;
|
||||
genesis.nNonce = 2;
|
||||
hashGenesisBlock = genesis.GetHash();
|
||||
nDefaultPort = 18444;
|
||||
strDataDir = "regtest";
|
||||
assert(hashGenesisBlock == uint256("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
|
||||
|
||||
vSeeds.clear(); // Regtest mode doesn't have any DNS seeds.
|
||||
}
|
||||
|
||||
virtual bool RequireRPCPassword() const { return false; }
|
||||
virtual Network NetworkID() const { return CChainParams::REGTEST; }
|
||||
fRequireRPCPassword = false;
|
||||
fMiningRequiresPeers = false;
|
||||
fDefaultCheckMemPool = true;
|
||||
fAllowMinDifficultyBlocks = true;
|
||||
fRequireStandard = false;
|
||||
fMineBlocksOnDemand = true;
|
||||
}
|
||||
};
|
||||
static CRegTestParams regTestParams;
|
||||
|
||||
static CChainParams *pCurrentParams = &mainParams;
|
||||
static CChainParams *pCurrentParams = 0;
|
||||
|
||||
const CChainParams &Params() {
|
||||
assert(pCurrentParams);
|
||||
return *pCurrentParams;
|
||||
}
|
||||
|
||||
void SelectParams(CChainParams::Network network) {
|
||||
void SelectParams(CBaseChainParams::Network network) {
|
||||
SelectBaseParams(network);
|
||||
switch (network) {
|
||||
case CChainParams::MAIN:
|
||||
case CBaseChainParams::MAIN:
|
||||
pCurrentParams = &mainParams;
|
||||
break;
|
||||
case CChainParams::TESTNET:
|
||||
case CBaseChainParams::TESTNET:
|
||||
pCurrentParams = &testNetParams;
|
||||
break;
|
||||
case CChainParams::REGTEST:
|
||||
case CBaseChainParams::REGTEST:
|
||||
pCurrentParams = ®TestParams;
|
||||
break;
|
||||
default:
|
||||
@@ -274,19 +301,9 @@ void SelectParams(CChainParams::Network network) {
|
||||
}
|
||||
|
||||
bool SelectParamsFromCommandLine() {
|
||||
bool fRegTest = GetBoolArg("-regtest", false);
|
||||
bool fTestNet = GetBoolArg("-testnet", false);
|
||||
|
||||
if (fTestNet && fRegTest) {
|
||||
if (!SelectBaseParamsFromCommandLine())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fRegTest) {
|
||||
SelectParams(CChainParams::REGTEST);
|
||||
} else if (fTestNet) {
|
||||
SelectParams(CChainParams::TESTNET);
|
||||
} else {
|
||||
SelectParams(CChainParams::MAIN);
|
||||
}
|
||||
SelectParams(BaseParams().NetworkID());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,22 +6,18 @@
|
||||
#ifndef BITCOIN_CHAIN_PARAMS_H
|
||||
#define BITCOIN_CHAIN_PARAMS_H
|
||||
|
||||
#include "bignum.h"
|
||||
#include "core.h"
|
||||
#include "chainparamsbase.h"
|
||||
#include "protocol.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define MESSAGE_START_SIZE 4
|
||||
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
|
||||
|
||||
class CAddress;
|
||||
class CBlock;
|
||||
|
||||
struct CDNSSeedData {
|
||||
string name, host;
|
||||
CDNSSeedData(const string &strName, const string &strHost) : name(strName), host(strHost) {}
|
||||
std::string name, host;
|
||||
CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -34,14 +30,6 @@ struct CDNSSeedData {
|
||||
class CChainParams
|
||||
{
|
||||
public:
|
||||
enum Network {
|
||||
MAIN,
|
||||
TESTNET,
|
||||
REGTEST,
|
||||
|
||||
MAX_NETWORK_TYPES
|
||||
};
|
||||
|
||||
enum Base58Type {
|
||||
PUBKEY_ADDRESS,
|
||||
SCRIPT_ADDRESS,
|
||||
@@ -54,32 +42,67 @@ public:
|
||||
|
||||
const uint256& HashGenesisBlock() const { return hashGenesisBlock; }
|
||||
const MessageStartChars& MessageStart() const { return pchMessageStart; }
|
||||
const vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
|
||||
const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
|
||||
int GetDefaultPort() const { return nDefaultPort; }
|
||||
const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
|
||||
const uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
|
||||
int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; }
|
||||
virtual const CBlock& GenesisBlock() const = 0;
|
||||
virtual bool RequireRPCPassword() const { return true; }
|
||||
const string& DataDir() const { return strDataDir; }
|
||||
virtual Network NetworkID() const = 0;
|
||||
const vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
|
||||
const std::vector<unsigned char> &Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
|
||||
virtual const vector<CAddress>& FixedSeeds() const = 0;
|
||||
int RPCPort() const { return nRPCPort; }
|
||||
/* 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 argument */
|
||||
bool DefaultCheckMemPool() const { return fDefaultCheckMemPool; }
|
||||
/* Allow mining of a min-difficulty block */
|
||||
bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; }
|
||||
/* 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; }
|
||||
CBaseChainParams::Network NetworkID() const { return networkID; }
|
||||
/* 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; }
|
||||
protected:
|
||||
CChainParams() {}
|
||||
|
||||
uint256 hashGenesisBlock;
|
||||
MessageStartChars pchMessageStart;
|
||||
// Raw pub key bytes for the broadcast alert signing key.
|
||||
vector<unsigned char> vAlertPubKey;
|
||||
std::vector<unsigned char> vAlertPubKey;
|
||||
int nDefaultPort;
|
||||
int nRPCPort;
|
||||
CBigNum bnProofOfWorkLimit;
|
||||
uint256 bnProofOfWorkLimit;
|
||||
int nSubsidyHalvingInterval;
|
||||
string strDataDir;
|
||||
vector<CDNSSeedData> vSeeds;
|
||||
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 fDefaultCheckMemPool;
|
||||
bool fAllowMinDifficultyBlocks;
|
||||
bool fRequireStandard;
|
||||
bool fMineBlocksOnDemand;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -89,7 +112,7 @@ protected:
|
||||
const CChainParams &Params();
|
||||
|
||||
/** Sets the params returned by Params() to those for the given network. */
|
||||
void SelectParams(CChainParams::Network network);
|
||||
void SelectParams(CBaseChainParams::Network network);
|
||||
|
||||
/**
|
||||
* Looks for -regtest or -testnet and then calls SelectParams as appropriate.
|
||||
@@ -97,13 +120,4 @@ void SelectParams(CChainParams::Network network);
|
||||
*/
|
||||
bool SelectParamsFromCommandLine();
|
||||
|
||||
inline bool TestNet() {
|
||||
// Note: it's deliberate that this returns "false" for regression test mode.
|
||||
return Params().NetworkID() == CChainParams::TESTNET;
|
||||
}
|
||||
|
||||
inline bool RegTest() {
|
||||
return Params().NetworkID() == CChainParams::REGTEST;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
93
src/chainparamsbase.cpp
Normal file
93
src/chainparamsbase.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 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 "chainparamsbase.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "util.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;
|
||||
|
||||
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;
|
||||
default:
|
||||
assert(false && "Unimplemented network");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectBaseParamsFromCommandLine() {
|
||||
bool fRegTest = GetBoolArg("-regtest", false);
|
||||
bool fTestNet = GetBoolArg("-testnet", false);
|
||||
|
||||
if (fTestNet && fRegTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fRegTest) {
|
||||
SelectBaseParams(CBaseChainParams::REGTEST);
|
||||
} else if (fTestNet) {
|
||||
SelectBaseParams(CBaseChainParams::TESTNET);
|
||||
} else {
|
||||
SelectBaseParams(CBaseChainParams::MAIN);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
52
src/chainparamsbase.h
Normal file
52
src/chainparamsbase.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 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_CHAIN_PARAMS_BASE_H
|
||||
#define BITCOIN_CHAIN_PARAMS_BASE_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* 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,
|
||||
|
||||
MAX_NETWORK_TYPES
|
||||
};
|
||||
|
||||
const std::string& DataDir() const { return strDataDir; }
|
||||
int RPCPort() const { return nRPCPort; }
|
||||
Network NetworkID() const { return networkID; }
|
||||
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 then calls SelectParams as appropriate.
|
||||
* Returns false if an invalid combination is given.
|
||||
*/
|
||||
bool SelectBaseParamsFromCommandLine();
|
||||
|
||||
#endif
|
||||
@@ -12,8 +12,8 @@
|
||||
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
namespace Checkpoints
|
||||
{
|
||||
namespace Checkpoints {
|
||||
|
||||
typedef std::map<int, uint256> MapCheckpoints;
|
||||
|
||||
// How many times we expect transactions after the last checkpoint to
|
||||
@@ -66,8 +66,8 @@ namespace Checkpoints
|
||||
;
|
||||
static const CCheckpointData dataTestnet = {
|
||||
&mapCheckpointsTestnet,
|
||||
1338180505,
|
||||
16341,
|
||||
1337966069,
|
||||
1488,
|
||||
300
|
||||
};
|
||||
|
||||
@@ -83,9 +83,9 @@ namespace Checkpoints
|
||||
};
|
||||
|
||||
const CCheckpointData &Checkpoints() {
|
||||
if (Params().NetworkID() == CChainParams::TESTNET)
|
||||
if (Params().NetworkID() == CBaseChainParams::TESTNET)
|
||||
return dataTestnet;
|
||||
else if (Params().NetworkID() == CChainParams::MAIN)
|
||||
else if (Params().NetworkID() == CBaseChainParams::MAIN)
|
||||
return data;
|
||||
else
|
||||
return dataRegtest;
|
||||
@@ -127,7 +127,7 @@ namespace Checkpoints
|
||||
} else {
|
||||
double nCheapBefore = data.nTransactionsLastCheckpoint;
|
||||
double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint;
|
||||
double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay;
|
||||
double nExpensiveAfter = (nNow - pindex->GetBlockTime())/86400.0*data.fTransactionsPerDay;
|
||||
fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor;
|
||||
fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor;
|
||||
}
|
||||
@@ -161,4 +161,5 @@ namespace Checkpoints
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Checkpoints
|
||||
|
||||
@@ -13,8 +13,8 @@ class uint256;
|
||||
/** Block-chain checkpoints are compiled-in sanity checks.
|
||||
* They are updated every release or three.
|
||||
*/
|
||||
namespace Checkpoints
|
||||
{
|
||||
namespace Checkpoints {
|
||||
|
||||
// Returns true if block passes checkpoint checks
|
||||
bool CheckBlock(int nHeight, const uint256& hash);
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Checkpoints
|
||||
double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks = true);
|
||||
|
||||
extern bool fEnabled;
|
||||
}
|
||||
|
||||
} //namespace Checkpoints
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
#define CLIENTVERSION_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#include "config/bitcoin-config.h"
|
||||
#else
|
||||
//
|
||||
// client versioning and copyright year
|
||||
//
|
||||
|
||||
// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it
|
||||
// These need to be macros, as version.cpp's and bitcoin*-res.rc's voodoo requires it
|
||||
#define CLIENT_VERSION_MAJOR 0
|
||||
#define CLIENT_VERSION_MINOR 9
|
||||
#define CLIENT_VERSION_REVISION 99
|
||||
@@ -28,4 +28,7 @@
|
||||
#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"
|
||||
|
||||
#endif // CLIENTVERSION_H
|
||||
|
||||
@@ -55,7 +55,7 @@ bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return fal
|
||||
bool CCoinsView::HaveCoins(const uint256 &txid) { return false; }
|
||||
uint256 CCoinsView::GetBestBlock() { return uint256(0); }
|
||||
bool CCoinsView::SetBestBlock(const uint256 &hashBlock) { return false; }
|
||||
bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) { return false; }
|
||||
bool CCoinsView::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
|
||||
bool CCoinsView::GetStats(CCoinsStats &stats) { return false; }
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ bool CCoinsViewBacked::HaveCoins(const uint256 &txid) { return base->HaveCoins(t
|
||||
uint256 CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); }
|
||||
bool CCoinsViewBacked::SetBestBlock(const uint256 &hashBlock) { return base->SetBestBlock(hashBlock); }
|
||||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
||||
bool CCoinsViewBacked::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
|
||||
bool CCoinsViewBacked::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
|
||||
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stats); }
|
||||
|
||||
CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), hashBlock(0) { }
|
||||
@@ -83,20 +83,20 @@ bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<uint256,CCoins>::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) {
|
||||
std::map<uint256,CCoins>::iterator it = cacheCoins.lower_bound(txid);
|
||||
CCoinsMap::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) {
|
||||
CCoinsMap::iterator it = cacheCoins.lower_bound(txid);
|
||||
if (it != cacheCoins.end() && it->first == txid)
|
||||
return it;
|
||||
CCoins tmp;
|
||||
if (!base->GetCoins(txid,tmp))
|
||||
return cacheCoins.end();
|
||||
std::map<uint256,CCoins>::iterator ret = cacheCoins.insert(it, std::make_pair(txid, CCoins()));
|
||||
CCoinsMap::iterator ret = cacheCoins.insert(it, std::make_pair(txid, CCoins()));
|
||||
tmp.swap(ret->second);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CCoins &CCoinsViewCache::GetCoins(const uint256 &txid) {
|
||||
std::map<uint256,CCoins>::iterator it = FetchCoins(txid);
|
||||
CCoinsMap::iterator it = FetchCoins(txid);
|
||||
assert(it != cacheCoins.end());
|
||||
return it->second;
|
||||
}
|
||||
@@ -121,8 +121,8 @@ bool CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlockIn) {
|
||||
for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
|
||||
bool CCoinsViewCache::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
|
||||
for (CCoinsMap::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
|
||||
cacheCoins[it->first] = it->second;
|
||||
hashBlock = hashBlockIn;
|
||||
return true;
|
||||
|
||||
11
src/coins.h
11
src/coins.h
@@ -239,6 +239,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<uint256,CCoins> CCoinsMap;
|
||||
|
||||
struct CCoinsStats
|
||||
{
|
||||
@@ -275,7 +276,7 @@ public:
|
||||
virtual bool SetBestBlock(const uint256 &hashBlock);
|
||||
|
||||
// Do a bulk modification (multiple SetCoins + one SetBestBlock)
|
||||
virtual bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock);
|
||||
virtual bool BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||
|
||||
// Calculate statistics about the unspent transaction output set
|
||||
virtual bool GetStats(CCoinsStats &stats);
|
||||
@@ -299,7 +300,7 @@ public:
|
||||
uint256 GetBestBlock();
|
||||
bool SetBestBlock(const uint256 &hashBlock);
|
||||
void SetBackend(CCoinsView &viewIn);
|
||||
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock);
|
||||
bool BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||
bool GetStats(CCoinsStats &stats);
|
||||
};
|
||||
|
||||
@@ -309,7 +310,7 @@ class CCoinsViewCache : public CCoinsViewBacked
|
||||
{
|
||||
protected:
|
||||
uint256 hashBlock;
|
||||
std::map<uint256,CCoins> cacheCoins;
|
||||
CCoinsMap cacheCoins;
|
||||
|
||||
public:
|
||||
CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false);
|
||||
@@ -320,7 +321,7 @@ public:
|
||||
bool HaveCoins(const uint256 &txid);
|
||||
uint256 GetBestBlock();
|
||||
bool SetBestBlock(const uint256 &hashBlock);
|
||||
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock);
|
||||
bool BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||
|
||||
// Return a modifiable reference to a CCoins. Check HaveCoins first.
|
||||
// Many methods explicitly require a CCoinsViewCache because of this method, to reduce
|
||||
@@ -352,7 +353,7 @@ public:
|
||||
const CTxOut &GetOutputFor(const CTxIn& input);
|
||||
|
||||
private:
|
||||
std::map<uint256,CCoins>::iterator FetchCoins(const uint256 &txid);
|
||||
CCoinsMap::iterator FetchCoins(const uint256 &txid);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,19 +1,28 @@
|
||||
#include "bitcoin-config.h"
|
||||
// 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.
|
||||
|
||||
#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);
|
||||
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;
|
||||
if (a >= FD_SETSIZE)
|
||||
__chk_fail ();
|
||||
return a / __NFDBITS;
|
||||
}
|
||||
extern "C" FDELT_TYPE __fdelt_chk(FDELT_TYPE) __attribute__((weak, alias("__fdelt_warn")));
|
||||
|
||||
67
src/compat/glibc_sanity.cpp
Normal file
67
src/compat/glibc_sanity.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// 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.
|
||||
|
||||
#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,49 +1,55 @@
|
||||
// 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 <cstddef>
|
||||
#include <istream>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
|
||||
#ifndef _GLIBCXX_USE_NOEXCEPT
|
||||
#define _GLIBCXX_USE_NOEXCEPT throw()
|
||||
#define _GLIBCXX_USE_NOEXCEPT throw()
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
|
||||
const char* bad_exception::what() const throw()
|
||||
{
|
||||
return "std::bad_exception";
|
||||
return "std::bad_exception";
|
||||
}
|
||||
|
||||
const char* bad_cast::what() const throw()
|
||||
{
|
||||
return "std::bad_cast";
|
||||
return "std::bad_cast";
|
||||
}
|
||||
|
||||
const char* bad_alloc::what() const throw()
|
||||
{
|
||||
return "std::bad_alloc";
|
||||
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;
|
||||
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
|
||||
|
||||
@@ -61,8 +67,8 @@ out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT { }
|
||||
// Used with permission.
|
||||
// See: https://github.com/madlib/madlib/commit/c3db418c0d34d6813608f2137fef1012ce03043d
|
||||
|
||||
void
|
||||
ctype<char>::_M_widen_init() const {
|
||||
void ctype<char>::_M_widen_init() const
|
||||
{
|
||||
char __tmp[sizeof(_M_widen)];
|
||||
for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
|
||||
__tmp[__i] = __i;
|
||||
|
||||
65
src/compat/glibcxx_sanity.cpp
Normal file
65
src/compat/glibcxx_sanity.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
// 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 <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();
|
||||
}
|
||||
11
src/compat/sanity.h
Normal file
11
src/compat/sanity.h
Normal file
@@ -0,0 +1,11 @@
|
||||
// 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 BITCON_COMPAT_SANITY_H
|
||||
#define BITCON_COMPAT_SANITY_H
|
||||
|
||||
bool glibc_sanity_test();
|
||||
bool glibcxx_sanity_test();
|
||||
|
||||
#endif // BITCON_COMPAT_SANITY_H
|
||||
0
src/config/.empty
Normal file
0
src/config/.empty
Normal file
79
src/core.cpp
79
src/core.cpp
@@ -72,38 +72,67 @@ void CTxOut::print() const
|
||||
LogPrintf("%s\n", ToString());
|
||||
}
|
||||
|
||||
uint256 CTransaction::GetHash() const
|
||||
CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize)
|
||||
{
|
||||
if (nSize > 0)
|
||||
nSatoshisPerK = nFeePaid*1000/nSize;
|
||||
else
|
||||
nSatoshisPerK = 0;
|
||||
}
|
||||
|
||||
int64_t CFeeRate::GetFee(size_t nSize) const
|
||||
{
|
||||
return nSatoshisPerK*nSize / 1000;
|
||||
}
|
||||
|
||||
std::string CFeeRate::ToString() const
|
||||
{
|
||||
std::string result = FormatMoney(nSatoshisPerK) + " BTC/kB";
|
||||
return result;
|
||||
}
|
||||
|
||||
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
|
||||
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
|
||||
|
||||
uint256 CMutableTransaction::GetHash() const
|
||||
{
|
||||
return SerializeHash(*this);
|
||||
}
|
||||
|
||||
bool CTransaction::IsNewerThan(const CTransaction& old) const
|
||||
void CTransaction::UpdateHash() const
|
||||
{
|
||||
if (vin.size() != old.vin.size())
|
||||
*const_cast<uint256*>(&hash) = SerializeHash(*this);
|
||||
}
|
||||
|
||||
CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
|
||||
|
||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
CTransaction& CTransaction::operator=(const CTransaction &tx) {
|
||||
*const_cast<int*>(&nVersion) = tx.nVersion;
|
||||
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
|
||||
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
|
||||
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
|
||||
*const_cast<uint256*>(&hash) = tx.hash;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CTransaction::IsEquivalentTo(const CTransaction& tx) const
|
||||
{
|
||||
if (nVersion != tx.nVersion ||
|
||||
nLockTime != tx.nLockTime ||
|
||||
vin.size() != tx.vin.size() ||
|
||||
vout != tx.vout)
|
||||
return false;
|
||||
for (unsigned int i = 0; i < vin.size(); i++)
|
||||
if (vin[i].prevout != old.vin[i].prevout)
|
||||
return false;
|
||||
|
||||
bool fNewer = false;
|
||||
unsigned int nLowest = std::numeric_limits<unsigned int>::max();
|
||||
for (unsigned int i = 0; i < vin.size(); i++)
|
||||
{
|
||||
if (vin[i].nSequence != old.vin[i].nSequence)
|
||||
{
|
||||
if (vin[i].nSequence <= nLowest)
|
||||
{
|
||||
fNewer = false;
|
||||
nLowest = vin[i].nSequence;
|
||||
}
|
||||
if (old.vin[i].nSequence < nLowest)
|
||||
{
|
||||
fNewer = true;
|
||||
nLowest = old.vin[i].nSequence;
|
||||
}
|
||||
}
|
||||
if (vin[i].nSequence != tx.vin[i].nSequence ||
|
||||
vin[i].prevout != tx.vin[i].prevout)
|
||||
return false;
|
||||
}
|
||||
return fNewer;
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t CTransaction::GetValueOut() const
|
||||
@@ -140,7 +169,7 @@ double CTransaction::ComputePriority(double dPriorityInputs, unsigned int nTxSiz
|
||||
std::string CTransaction::ToString() const
|
||||
{
|
||||
std::string str;
|
||||
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n",
|
||||
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n",
|
||||
GetHash().ToString().substr(0,10),
|
||||
nVersion,
|
||||
vin.size(),
|
||||
@@ -269,7 +298,7 @@ uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMer
|
||||
|
||||
void CBlock::print() const
|
||||
{
|
||||
LogPrintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
|
||||
LogPrintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
|
||||
GetHash().ToString(),
|
||||
nVersion,
|
||||
hashPrevBlock.ToString(),
|
||||
|
||||
140
src/core.h
140
src/core.h
@@ -112,6 +112,32 @@ public:
|
||||
|
||||
|
||||
|
||||
/** Type-safe wrapper class to for fee rates
|
||||
* (how much to pay based on transaction size)
|
||||
*/
|
||||
class CFeeRate
|
||||
{
|
||||
private:
|
||||
int64_t nSatoshisPerK; // unit is satoshis-per-1,000-bytes
|
||||
public:
|
||||
CFeeRate() : nSatoshisPerK(0) { }
|
||||
explicit CFeeRate(int64_t _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
|
||||
CFeeRate(int64_t nFeePaid, size_t nSize);
|
||||
CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
|
||||
|
||||
int64_t GetFee(size_t size) const; // unit returned is satoshis
|
||||
int64_t 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;
|
||||
|
||||
IMPLEMENT_SERIALIZE( READWRITE(nSatoshisPerK); )
|
||||
};
|
||||
|
||||
|
||||
/** An output of a transaction. It contains the public key that the next input
|
||||
* must be able to sign with to claim it.
|
||||
@@ -148,17 +174,18 @@ public:
|
||||
|
||||
uint256 GetHash() const;
|
||||
|
||||
bool IsDust(int64_t nMinRelayTxFee) const
|
||||
bool IsDust(CFeeRate minRelayTxFee) const
|
||||
{
|
||||
// "Dust" is defined in terms of CTransaction::nMinRelayTxFee,
|
||||
// "Dust" is defined in terms of CTransaction::minRelayTxFee,
|
||||
// which has units satoshis-per-kilobyte.
|
||||
// If you'd pay more than 1/3 in fees
|
||||
// to spend something, then we consider it dust.
|
||||
// A typical txout is 34 bytes big, and will
|
||||
// need a CTxIn of at least 148 bytes to spend,
|
||||
// need a CTxIn of at least 148 bytes to spend:
|
||||
// so dust is a txout less than 546 satoshis
|
||||
// with default nMinRelayTxFee.
|
||||
return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < nMinRelayTxFee);
|
||||
// with default minRelayTxFee.
|
||||
size_t nSize = GetSerializeSize(SER_DISK,0)+148u;
|
||||
return (nValue < 3*minRelayTxFee.GetFee(nSize));
|
||||
}
|
||||
|
||||
friend bool operator==(const CTxOut& a, const CTxOut& b)
|
||||
@@ -177,49 +204,59 @@ public:
|
||||
};
|
||||
|
||||
|
||||
struct CMutableTransaction;
|
||||
|
||||
/** The basic transaction that is broadcasted on the network and contained in
|
||||
* blocks. A transaction can contain multiple inputs and outputs.
|
||||
*/
|
||||
class CTransaction
|
||||
{
|
||||
private:
|
||||
/** Memory only. */
|
||||
const uint256 hash;
|
||||
void UpdateHash() const;
|
||||
|
||||
public:
|
||||
static int64_t nMinTxFee;
|
||||
static int64_t nMinRelayTxFee;
|
||||
static const int CURRENT_VERSION=1;
|
||||
int nVersion;
|
||||
std::vector<CTxIn> vin;
|
||||
std::vector<CTxOut> vout;
|
||||
unsigned int nLockTime;
|
||||
|
||||
CTransaction()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
// The local variables are made const to prevent unintended modification
|
||||
// without updating the cached hash value. However, CTransaction is not
|
||||
// actually immutable; deserialization and assignment are implemented,
|
||||
// and bypass the constness. This is safe, as they update the entire
|
||||
// structure, including the hash.
|
||||
const int nVersion;
|
||||
const std::vector<CTxIn> vin;
|
||||
const std::vector<CTxOut> vout;
|
||||
const unsigned int nLockTime;
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(this->nVersion);
|
||||
/** Construct a CTransaction that qualifies as IsNull() */
|
||||
CTransaction();
|
||||
|
||||
/** Convert a CMutableTransaction into a CTransaction. */
|
||||
CTransaction(const CMutableTransaction &tx);
|
||||
|
||||
CTransaction& operator=(const CTransaction& tx);
|
||||
|
||||
IMPLEMENT_SERIALIZE(
|
||||
READWRITE(*const_cast<int*>(&this->nVersion));
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(vin);
|
||||
READWRITE(vout);
|
||||
READWRITE(nLockTime);
|
||||
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
|
||||
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
|
||||
READWRITE(*const_cast<unsigned int*>(&nLockTime));
|
||||
if (fRead)
|
||||
UpdateHash();
|
||||
)
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
nVersion = CTransaction::CURRENT_VERSION;
|
||||
vin.clear();
|
||||
vout.clear();
|
||||
nLockTime = 0;
|
||||
bool IsNull() const {
|
||||
return vin.empty() && vout.empty();
|
||||
}
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
return (vin.empty() && vout.empty());
|
||||
const uint256& GetHash() const {
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint256 GetHash() const;
|
||||
bool IsNewerThan(const CTransaction& old) const;
|
||||
// True if only scriptSigs are different
|
||||
bool IsEquivalentTo(const CTransaction& tx) const;
|
||||
|
||||
// Return sum of txouts.
|
||||
int64_t GetValueOut() const;
|
||||
@@ -236,22 +273,43 @@ public:
|
||||
|
||||
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
||||
{
|
||||
return (a.nVersion == b.nVersion &&
|
||||
a.vin == b.vin &&
|
||||
a.vout == b.vout &&
|
||||
a.nLockTime == b.nLockTime);
|
||||
return a.hash == b.hash;
|
||||
}
|
||||
|
||||
friend bool operator!=(const CTransaction& a, const CTransaction& b)
|
||||
{
|
||||
return !(a == b);
|
||||
return a.hash != b.hash;
|
||||
}
|
||||
|
||||
|
||||
std::string ToString() const;
|
||||
void print() const;
|
||||
};
|
||||
|
||||
/** A mutable version of CTransaction. */
|
||||
struct CMutableTransaction
|
||||
{
|
||||
int nVersion;
|
||||
std::vector<CTxIn> vin;
|
||||
std::vector<CTxOut> vout;
|
||||
unsigned int nLockTime;
|
||||
|
||||
CMutableTransaction();
|
||||
CMutableTransaction(const CTransaction& tx);
|
||||
|
||||
IMPLEMENT_SERIALIZE(
|
||||
READWRITE(this->nVersion);
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(vin);
|
||||
READWRITE(vout);
|
||||
READWRITE(nLockTime);
|
||||
)
|
||||
|
||||
/** Compute the hash of this CMutableTransaction. This is computed on the
|
||||
* fly, as opposed to GetHash() in CTransaction, which uses a cached result.
|
||||
*/
|
||||
uint256 GetHash() const;
|
||||
};
|
||||
|
||||
/** wrapper for CTxOut that provides a more compact serialization */
|
||||
class CTxOutCompressor
|
||||
{
|
||||
@@ -440,12 +498,6 @@ public:
|
||||
|
||||
uint256 BuildMerkleTree() const;
|
||||
|
||||
const uint256 &GetTxHash(unsigned int nIndex) const {
|
||||
assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
|
||||
assert(nIndex < vtx.size());
|
||||
return vMerkleTree[nIndex];
|
||||
}
|
||||
|
||||
std::vector<uint256> GetMerkleBranch(int nIndex) const;
|
||||
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
|
||||
void print() const;
|
||||
|
||||
93
src/crypto/common.h
Normal file
93
src/crypto/common.h
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 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_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
|
||||
204
src/crypto/ripemd160.cpp
Normal file
204
src/crypto/ripemd160.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
// Copyright (c) 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 "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;
|
||||
}
|
||||
27
src/crypto/ripemd160.h
Normal file
27
src/crypto/ripemd160.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 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_RIPEMD160_H
|
||||
#define BITCOIN_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
|
||||
192
src/crypto/sha1.cpp
Normal file
192
src/crypto/sha1.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
// Copyright (c) 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 "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;
|
||||
}
|
||||
27
src/crypto/sha1.h
Normal file
27
src/crypto/sha1.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 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_SHA1_H
|
||||
#define BITCOIN_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
|
||||
398
src/crypto/sha2.cpp
Normal file
398
src/crypto/sha2.cpp
Normal file
@@ -0,0 +1,398 @@
|
||||
// Copyright (c) 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 "crypto/sha2.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
|
||||
|
||||
/// 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-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;
|
||||
}
|
||||
|
||||
////// 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;
|
||||
}
|
||||
|
||||
////// HMAC-SHA-512
|
||||
|
||||
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);
|
||||
}
|
||||
60
src/crypto/sha2.h
Normal file
60
src/crypto/sha2.h
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 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_SHA2_H
|
||||
#define BITCOIN_SHA2_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();
|
||||
};
|
||||
|
||||
/** 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();
|
||||
};
|
||||
|
||||
/** 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
|
||||
41
src/hash.cpp
41
src/hash.cpp
@@ -56,44 +56,3 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
|
||||
|
||||
return h1;
|
||||
}
|
||||
|
||||
int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len)
|
||||
{
|
||||
unsigned char key[128];
|
||||
if (len <= 128)
|
||||
{
|
||||
memcpy(key, pkey, len);
|
||||
memset(key + len, 0, 128-len);
|
||||
}
|
||||
else
|
||||
{
|
||||
SHA512_CTX ctxKey;
|
||||
SHA512_Init(&ctxKey);
|
||||
SHA512_Update(&ctxKey, pkey, len);
|
||||
SHA512_Final(key, &ctxKey);
|
||||
memset(key + 64, 0, 64);
|
||||
}
|
||||
|
||||
for (int n=0; n<128; n++)
|
||||
key[n] ^= 0x5c;
|
||||
SHA512_Init(&pctx->ctxOuter);
|
||||
SHA512_Update(&pctx->ctxOuter, key, 128);
|
||||
|
||||
for (int n=0; n<128; n++)
|
||||
key[n] ^= 0x5c ^ 0x36;
|
||||
SHA512_Init(&pctx->ctxInner);
|
||||
return SHA512_Update(&pctx->ctxInner, key, 128);
|
||||
}
|
||||
|
||||
int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len)
|
||||
{
|
||||
return SHA512_Update(&pctx->ctxInner, pdata, len);
|
||||
}
|
||||
|
||||
int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
SHA512_Final(buf, &pctx->ctxInner);
|
||||
SHA512_Update(&pctx->ctxOuter, buf, 64);
|
||||
return SHA512_Final(pmd, &pctx->ctxOuter);
|
||||
}
|
||||
|
||||
189
src/hash.h
189
src/hash.h
@@ -6,55 +6,138 @@
|
||||
#ifndef BITCOIN_HASH_H
|
||||
#define BITCOIN_HASH_H
|
||||
|
||||
#include "crypto/sha2.h"
|
||||
#include "crypto/ripemd160.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/ripemd.h>
|
||||
#include <openssl/sha.h>
|
||||
/** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */
|
||||
class CHash256 {
|
||||
private:
|
||||
CSHA256 sha;
|
||||
public:
|
||||
static const size_t OUTPUT_SIZE = CSHA256::OUTPUT_SIZE;
|
||||
|
||||
void Finalize(unsigned char hash[OUTPUT_SIZE]) {
|
||||
unsigned char buf[sha.OUTPUT_SIZE];
|
||||
sha.Finalize(buf);
|
||||
sha.Reset().Write(buf, sha.OUTPUT_SIZE).Finalize(hash);
|
||||
}
|
||||
|
||||
CHash256& Write(const unsigned char *data, size_t len) {
|
||||
sha.Write(data, len);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CHash256& Reset() {
|
||||
sha.Reset();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/** A hasher class for Bitcoin's 160-bit hash (SHA-256 + RIPEMD-160). */
|
||||
class CHash160 {
|
||||
private:
|
||||
CSHA256 sha;
|
||||
public:
|
||||
static const size_t OUTPUT_SIZE = CRIPEMD160::OUTPUT_SIZE;
|
||||
|
||||
void Finalize(unsigned char hash[OUTPUT_SIZE]) {
|
||||
unsigned char buf[sha.OUTPUT_SIZE];
|
||||
sha.Finalize(buf);
|
||||
CRIPEMD160().Write(buf, sha.OUTPUT_SIZE).Finalize(hash);
|
||||
}
|
||||
|
||||
CHash160& Write(const unsigned char *data, size_t len) {
|
||||
sha.Write(data, len);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CHash160& Reset() {
|
||||
sha.Reset();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/** Compute the 256-bit hash of an object. */
|
||||
template<typename T1>
|
||||
inline uint256 Hash(const T1 pbegin, const T1 pend)
|
||||
{
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
|
||||
uint256 hash2;
|
||||
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
static const unsigned char pblank[1] = {};
|
||||
uint256 result;
|
||||
CHash256().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]))
|
||||
.Finalize((unsigned char*)&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Compute the 256-bit hash of the concatenation of two objects. */
|
||||
template<typename T1, typename T2>
|
||||
inline uint256 Hash(const T1 p1begin, const T1 p1end,
|
||||
const T2 p2begin, const T2 p2end) {
|
||||
static const unsigned char pblank[1] = {};
|
||||
uint256 result;
|
||||
CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]))
|
||||
.Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]))
|
||||
.Finalize((unsigned char*)&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Compute the 256-bit hash of the concatenation of three objects. */
|
||||
template<typename T1, typename T2, typename T3>
|
||||
inline uint256 Hash(const T1 p1begin, const T1 p1end,
|
||||
const T2 p2begin, const T2 p2end,
|
||||
const T3 p3begin, const T3 p3end) {
|
||||
static const unsigned char pblank[1] = {};
|
||||
uint256 result;
|
||||
CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]))
|
||||
.Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]))
|
||||
.Write(p3begin == p3end ? pblank : (const unsigned char*)&p3begin[0], (p3end - p3begin) * sizeof(p3begin[0]))
|
||||
.Finalize((unsigned char*)&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Compute the 160-bit hash an object. */
|
||||
template<typename T1>
|
||||
inline uint160 Hash160(const T1 pbegin, const T1 pend)
|
||||
{
|
||||
static unsigned char pblank[1] = {};
|
||||
uint160 result;
|
||||
CHash160().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]))
|
||||
.Finalize((unsigned char*)&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Compute the 160-bit hash of a vector. */
|
||||
inline uint160 Hash160(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
return Hash160(vch.begin(), vch.end());
|
||||
}
|
||||
|
||||
/** A writer stream (for serialization) that computes a 256-bit hash. */
|
||||
class CHashWriter
|
||||
{
|
||||
private:
|
||||
SHA256_CTX ctx;
|
||||
CHash256 ctx;
|
||||
|
||||
public:
|
||||
int nType;
|
||||
int nVersion;
|
||||
|
||||
void Init() {
|
||||
SHA256_Init(&ctx);
|
||||
}
|
||||
|
||||
CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {
|
||||
Init();
|
||||
}
|
||||
CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
|
||||
|
||||
CHashWriter& write(const char *pch, size_t size) {
|
||||
SHA256_Update(&ctx, pch, size);
|
||||
ctx.Write((const unsigned char*)pch, size);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// invalidates the object
|
||||
uint256 GetHash() {
|
||||
uint256 hash1;
|
||||
SHA256_Final((unsigned char*)&hash1, &ctx);
|
||||
uint256 hash2;
|
||||
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
uint256 result;
|
||||
ctx.Finalize((unsigned char*)&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -65,41 +148,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline uint256 Hash(const T1 p1begin, const T1 p1end,
|
||||
const T2 p2begin, const T2 p2end)
|
||||
{
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0]));
|
||||
SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0]));
|
||||
SHA256_Final((unsigned char*)&hash1, &ctx);
|
||||
uint256 hash2;
|
||||
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
inline uint256 Hash(const T1 p1begin, const T1 p1end,
|
||||
const T2 p2begin, const T2 p2end,
|
||||
const T3 p3begin, const T3 p3end)
|
||||
{
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0]));
|
||||
SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0]));
|
||||
SHA256_Update(&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof(p3begin[0]));
|
||||
SHA256_Final((unsigned char*)&hash1, &ctx);
|
||||
uint256 hash2;
|
||||
SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
}
|
||||
|
||||
/** Compute the 256-bit hash of an object's serialization. */
|
||||
template<typename T>
|
||||
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
|
||||
{
|
||||
@@ -108,32 +157,6 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
|
||||
return ss.GetHash();
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
inline uint160 Hash160(const T1 pbegin, const T1 pend)
|
||||
{
|
||||
static unsigned char pblank[1];
|
||||
uint256 hash1;
|
||||
SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
|
||||
uint160 hash2;
|
||||
RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
|
||||
return hash2;
|
||||
}
|
||||
|
||||
inline uint160 Hash160(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
return Hash160(vch.begin(), vch.end());
|
||||
}
|
||||
|
||||
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SHA512_CTX ctxInner;
|
||||
SHA512_CTX ctxOuter;
|
||||
} HMAC_SHA512_CTX;
|
||||
|
||||
int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len);
|
||||
int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len);
|
||||
int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx);
|
||||
|
||||
#endif
|
||||
|
||||
211
src/init.cpp
211
src/init.cpp
@@ -4,13 +4,14 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "init.h"
|
||||
|
||||
#include "addrman.h"
|
||||
#include "checkpoints.h"
|
||||
#include "key.h"
|
||||
#include "main.h"
|
||||
#include "miner.h"
|
||||
#include "net.h"
|
||||
@@ -25,10 +26,12 @@
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include "compat/sanity.h"
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@@ -39,7 +42,6 @@ using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
std::string strWalletFile;
|
||||
CWallet* pwalletMain;
|
||||
#endif
|
||||
|
||||
@@ -59,6 +61,8 @@ enum BindFlags {
|
||||
BF_REPORT_ERROR = (1U << 1)
|
||||
};
|
||||
|
||||
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
|
||||
CClientUIInterface uiInterface;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -113,7 +117,6 @@ void Shutdown()
|
||||
RenameThread("bitcoin-shutoff");
|
||||
mempool.AddTransactionsUpdated(1);
|
||||
StopRPCThreads();
|
||||
ShutdownRPCMining();
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain)
|
||||
bitdb.Flush(false);
|
||||
@@ -121,6 +124,14 @@ void Shutdown()
|
||||
#endif
|
||||
StopNode();
|
||||
UnregisterNodeSignals(GetNodeSignals());
|
||||
|
||||
boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
|
||||
CAutoFile est_fileout = CAutoFile(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION);
|
||||
if (est_fileout)
|
||||
mempool.WriteFeeEstimates(est_fileout);
|
||||
else
|
||||
LogPrintf("failed to write fee estimates");
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
#ifdef ENABLE_WALLET
|
||||
@@ -185,9 +196,9 @@ bool static Bind(const CService &addr, unsigned int flags) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Core-specific options shared between UI, daemon and RPC client
|
||||
std::string HelpMessage(HelpMessageMode hmm)
|
||||
std::string HelpMessage(HelpMessageMode mode)
|
||||
{
|
||||
// When adding new options to the categories, please keep and ensure alphabetical ordering.
|
||||
string strUsage = _("Options:") + "\n";
|
||||
strUsage += " -? " + _("This help message") + "\n";
|
||||
strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n";
|
||||
@@ -195,7 +206,7 @@ std::string HelpMessage(HelpMessageMode hmm)
|
||||
strUsage += " -checkblocks=<n> " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n";
|
||||
strUsage += " -checklevel=<n> " + _("How thorough the block verification of -checkblocks is (0-4, default: 3)") + "\n";
|
||||
strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n";
|
||||
if (hmm == HMM_BITCOIND)
|
||||
if (mode == HMM_BITCOIND)
|
||||
{
|
||||
#if !defined(WIN32)
|
||||
strUsage += " -daemon " + _("Run in the background as a daemon and accept commands") + "\n";
|
||||
@@ -205,6 +216,7 @@ std::string HelpMessage(HelpMessageMode hmm)
|
||||
strUsage += " -dbcache=<n> " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n";
|
||||
strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n";
|
||||
strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n";
|
||||
strUsage += " -maxorphanblocks=<n> " + strprintf(_("Keep at most <n> unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n";
|
||||
strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n";
|
||||
strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n";
|
||||
strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n";
|
||||
@@ -227,9 +239,8 @@ std::string HelpMessage(HelpMessageMode hmm)
|
||||
strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n";
|
||||
strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n";
|
||||
strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n";
|
||||
strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS proxy") + "\n";
|
||||
strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS5 proxy") + "\n";
|
||||
strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n";
|
||||
strUsage += " -socks=<n> " + _("Select SOCKS version for -proxy (4 or 5, default: 5)") + "\n";
|
||||
strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n";
|
||||
#ifdef USE_UPNP
|
||||
#if USE_UPNP
|
||||
@@ -242,14 +253,18 @@ std::string HelpMessage(HelpMessageMode hmm)
|
||||
#ifdef ENABLE_WALLET
|
||||
strUsage += "\n" + _("Wallet options:") + "\n";
|
||||
strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n";
|
||||
strUsage += " -paytxfee=<amt> " + _("Fee per kB to add to transactions you send") + "\n";
|
||||
strUsage += " -mintxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CWallet::minTxFee.GetFeePerK())) + "\n";
|
||||
strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n";
|
||||
strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n";
|
||||
strUsage += " -respendnotify=<cmd> " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n";
|
||||
strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n";
|
||||
strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n";
|
||||
strUsage += " -txconfirmtarget=<n> " + _("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)") + "\n";
|
||||
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n";
|
||||
strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n";
|
||||
strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
|
||||
strUsage += " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n";
|
||||
strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n";
|
||||
strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n";
|
||||
#endif
|
||||
|
||||
strUsage += "\n" + _("Debugging/Testing options:") + "\n";
|
||||
@@ -263,25 +278,26 @@ std::string HelpMessage(HelpMessageMode hmm)
|
||||
strUsage += " -dropmessagestest=<n> " + _("Randomly drop 1 of every <n> network messages") + "\n";
|
||||
strUsage += " -fuzzmessagestest=<n> " + _("Randomly fuzz 1 of every <n> network messages") + "\n";
|
||||
strUsage += " -flushwallet " + _("Run a thread to flush wallet periodically (default: 1)") + "\n";
|
||||
strUsage += " -stopafterblockimport " + _("Stop running after importing blocks from disk (default: 0)") + "\n";
|
||||
}
|
||||
strUsage += " -debug=<category> " + _("Output debugging information (default: 0, supplying <category> is optional)") + "\n";
|
||||
strUsage += " " + _("If <category> is not supplied, output all debugging information.") + "\n";
|
||||
strUsage += " " + _("<category> can be:");
|
||||
strUsage += " addrman, alert, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below
|
||||
if (hmm == HMM_BITCOIN_QT)
|
||||
if (mode == HMM_BITCOIN_QT)
|
||||
strUsage += ", qt";
|
||||
strUsage += ".\n";
|
||||
strUsage += " -gen " + _("Generate coins (default: 0)") + "\n";
|
||||
strUsage += " -genproclimit=<n> " + _("Set the processor limit for when generation is on (-1 = unlimited, default: -1)") + "\n";
|
||||
strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n";
|
||||
strUsage += " -logips " + _("Include IP addresses in debug output (default: 0)") + "\n";
|
||||
strUsage += " -logtimestamps " + _("Prepend debug output with timestamp (default: 1)") + "\n";
|
||||
if (GetBoolArg("-help-debug", false))
|
||||
{
|
||||
strUsage += " -limitfreerelay=<n> " + _("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15)") + "\n";
|
||||
strUsage += " -maxsigcachesize=<n> " + _("Limit size of signature cache to <n> entries (default: 50000)") + "\n";
|
||||
}
|
||||
strUsage += " -mintxfee=<amt> " + _("Fees smaller than this are considered zero fee (for transaction creation) (default:") + " " + FormatMoney(CTransaction::nMinTxFee) + ")" + "\n";
|
||||
strUsage += " -minrelaytxfee=<amt> " + _("Fees smaller than this are considered zero fee (for relaying) (default:") + " " + FormatMoney(CTransaction::nMinRelayTxFee) + ")" + "\n";
|
||||
strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n";
|
||||
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
|
||||
if (GetBoolArg("-help-debug", false))
|
||||
{
|
||||
@@ -296,6 +312,8 @@ std::string HelpMessage(HelpMessageMode hmm)
|
||||
strUsage += " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n";
|
||||
strUsage += " -testnet " + _("Use the test network") + "\n";
|
||||
|
||||
strUsage += "\n" + _("Node relay options:") + "\n";
|
||||
strUsage += " -datacarrier " + _("Relay and mine data carrier transactions (default: 1)") + "\n";
|
||||
strUsage += "\n" + _("Block creation options:") + "\n";
|
||||
strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n";
|
||||
strUsage += " -blockmaxsize=<n> " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n";
|
||||
@@ -303,10 +321,11 @@ std::string HelpMessage(HelpMessageMode hmm)
|
||||
|
||||
strUsage += "\n" + _("RPC server options:") + "\n";
|
||||
strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n";
|
||||
strUsage += " -rpcbind=<addr> " + _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)") + "\n";
|
||||
strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
|
||||
strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
|
||||
strUsage += " -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332)") + "\n";
|
||||
strUsage += " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified IP address") + "\n";
|
||||
strUsage += " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times") + "\n";
|
||||
strUsage += " -rpcthreads=<n> " + _("Set the number of threads to service RPC calls (default: 4)") + "\n";
|
||||
|
||||
strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
|
||||
@@ -318,6 +337,18 @@ std::string HelpMessage(HelpMessageMode hmm)
|
||||
return strUsage;
|
||||
}
|
||||
|
||||
std::string LicenseInfo()
|
||||
{
|
||||
return FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" +
|
||||
"\n" +
|
||||
FormatParagraph(_("This is experimental software.")) + "\n" +
|
||||
"\n" +
|
||||
FormatParagraph(_("Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.")) + "\n" +
|
||||
"\n" +
|
||||
FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.")) +
|
||||
"\n";
|
||||
}
|
||||
|
||||
struct CImportingNow
|
||||
{
|
||||
CImportingNow() {
|
||||
@@ -381,6 +412,28 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
|
||||
LogPrintf("Warning: Could not open blocks file %s\n", path.string());
|
||||
}
|
||||
}
|
||||
|
||||
if (GetBoolArg("-stopafterblockimport", false)) {
|
||||
LogPrintf("Stopping after block import\n");
|
||||
StartShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/** Sanity checks
|
||||
* Ensure that Bitcoin is running in a usable environment with all
|
||||
* necessary library support.
|
||||
*/
|
||||
bool InitSanityCheck(void)
|
||||
{
|
||||
if(!ECC_InitSanityCheck()) {
|
||||
InitError("OpenSSL appears to lack support for elliptic curve cryptography. For more "
|
||||
"information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries");
|
||||
return false;
|
||||
}
|
||||
if (!glibc_sanity_test() || !glibcxx_sanity_test())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Initialize bitcoin.
|
||||
@@ -489,7 +542,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
// -zapwallettx implies a rescan
|
||||
if (GetBoolArg("-zapwallettxes", false)) {
|
||||
if (SoftSetBoolArg("-rescan", true))
|
||||
LogPrintf("AppInit2 : parameter interaction: -zapwallettxes=1 -> setting -rescan=1\n");
|
||||
LogPrintf("AppInit2 : parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n");
|
||||
}
|
||||
|
||||
// Make sure enough file descriptors are available
|
||||
@@ -513,9 +566,16 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
// Check for -debugnet (deprecated)
|
||||
if (GetBoolArg("-debugnet", false))
|
||||
InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net"));
|
||||
// Check for -socks - as this is a privacy risk to continue, exit here
|
||||
if (mapArgs.count("-socks"))
|
||||
return InitError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
|
||||
// Check for -tor - as this is a privacy risk to continue, exit here
|
||||
if (GetBoolArg("-tor", false))
|
||||
return InitError(_("Error: Unsupported argument -tor found, use -onion."));
|
||||
|
||||
fBenchmark = GetBoolArg("-benchmark", false);
|
||||
mempool.setSanityCheck(GetBoolArg("-checkmempool", RegTest()));
|
||||
// Checkmempool defaults to true in regtest mode
|
||||
mempool.setSanityCheck(GetBoolArg("-checkmempool", Params().DefaultCheckMemPool()));
|
||||
Checkpoints::fEnabled = GetBoolArg("-checkpoints", true);
|
||||
|
||||
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
|
||||
@@ -530,6 +590,8 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
fServer = GetBoolArg("-server", false);
|
||||
fPrintToConsole = GetBoolArg("-printtoconsole", false);
|
||||
fLogTimestamps = GetBoolArg("-logtimestamps", true);
|
||||
fLogIPs = GetBoolArg("-logips", false);
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
#ifdef ENABLE_WALLET
|
||||
bool fDisableWallet = GetBoolArg("-disablewallet", false);
|
||||
#endif
|
||||
@@ -553,36 +615,47 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
// a transaction spammer can cheaply fill blocks using
|
||||
// 1-satoshi-fee transactions. It should be set above the real
|
||||
// cost to you of processing a transaction.
|
||||
if (mapArgs.count("-mintxfee"))
|
||||
{
|
||||
int64_t n = 0;
|
||||
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
|
||||
CTransaction::nMinTxFee = n;
|
||||
else
|
||||
return InitError(strprintf(_("Invalid amount for -mintxfee=<amount>: '%s'"), mapArgs["-mintxfee"]));
|
||||
}
|
||||
if (mapArgs.count("-minrelaytxfee"))
|
||||
{
|
||||
int64_t n = 0;
|
||||
if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0)
|
||||
CTransaction::nMinRelayTxFee = n;
|
||||
::minRelayTxFee = CFeeRate(n);
|
||||
else
|
||||
return InitError(strprintf(_("Invalid amount for -minrelaytxfee=<amount>: '%s'"), mapArgs["-minrelaytxfee"]));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
if (mapArgs.count("-mintxfee"))
|
||||
{
|
||||
int64_t n = 0;
|
||||
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
|
||||
CWallet::minTxFee = CFeeRate(n);
|
||||
else
|
||||
return InitError(strprintf(_("Invalid amount for -mintxfee=<amount>: '%s'"), mapArgs["-mintxfee"]));
|
||||
}
|
||||
if (mapArgs.count("-paytxfee"))
|
||||
{
|
||||
if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
|
||||
int64_t nFeePerK = 0;
|
||||
if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
|
||||
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"]));
|
||||
if (nTransactionFee > nHighTransactionFeeWarning)
|
||||
if (nFeePerK > nHighTransactionFeeWarning)
|
||||
InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
|
||||
payTxFee = CFeeRate(nFeePerK, 1000);
|
||||
if (payTxFee < ::minRelayTxFee)
|
||||
{
|
||||
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
|
||||
mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
|
||||
}
|
||||
}
|
||||
nTxConfirmTarget = GetArg("-txconfirmtarget", 1);
|
||||
bSpendZeroConfChange = GetArg("-spendzeroconfchange", true);
|
||||
|
||||
strWalletFile = GetArg("-wallet", "wallet.dat");
|
||||
std::string strWalletFile = GetArg("-wallet", "wallet.dat");
|
||||
#endif
|
||||
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
|
||||
// Sanity check
|
||||
if (!InitSanityCheck())
|
||||
return InitError(_("Initialization sanity check failed. Bitcoin Core is shutting down."));
|
||||
|
||||
std::string strDataDir = GetDataDir().string();
|
||||
#ifdef ENABLE_WALLET
|
||||
@@ -610,6 +683,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));
|
||||
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
|
||||
LogPrintf("Using data directory %s\n", strDataDir);
|
||||
LogPrintf("Using config file %s\n", GetConfigFile().string());
|
||||
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
|
||||
std::ostringstream strErrors;
|
||||
|
||||
@@ -674,10 +748,6 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
|
||||
RegisterNodeSignals(GetNodeSignals());
|
||||
|
||||
int nSocksVersion = GetArg("-socks", 5);
|
||||
if (nSocksVersion != 4 && nSocksVersion != 5)
|
||||
return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion));
|
||||
|
||||
if (mapArgs.count("-onlynet")) {
|
||||
std::set<enum Network> nets;
|
||||
BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) {
|
||||
@@ -701,40 +771,34 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"]));
|
||||
|
||||
if (!IsLimited(NET_IPV4))
|
||||
SetProxy(NET_IPV4, addrProxy, nSocksVersion);
|
||||
if (nSocksVersion > 4) {
|
||||
if (!IsLimited(NET_IPV6))
|
||||
SetProxy(NET_IPV6, addrProxy, nSocksVersion);
|
||||
SetNameProxy(addrProxy, nSocksVersion);
|
||||
}
|
||||
SetProxy(NET_IPV4, addrProxy);
|
||||
if (!IsLimited(NET_IPV6))
|
||||
SetProxy(NET_IPV6, addrProxy);
|
||||
SetNameProxy(addrProxy);
|
||||
fProxy = true;
|
||||
}
|
||||
|
||||
// -onion can override normal proxy, -noonion disables tor entirely
|
||||
// -tor here is a temporary backwards compatibility measure
|
||||
if (mapArgs.count("-tor"))
|
||||
printf("Notice: option -tor has been replaced with -onion and will be removed in a later version.\n");
|
||||
if (!(mapArgs.count("-onion") && mapArgs["-onion"] == "0") &&
|
||||
!(mapArgs.count("-tor") && mapArgs["-tor"] == "0") &&
|
||||
(fProxy || mapArgs.count("-onion") || mapArgs.count("-tor"))) {
|
||||
(fProxy || mapArgs.count("-onion"))) {
|
||||
CService addrOnion;
|
||||
if (!mapArgs.count("-onion") && !mapArgs.count("-tor"))
|
||||
if (!mapArgs.count("-onion"))
|
||||
addrOnion = addrProxy;
|
||||
else
|
||||
addrOnion = mapArgs.count("-onion")?CService(mapArgs["-onion"], 9050):CService(mapArgs["-tor"], 9050);
|
||||
addrOnion = CService(mapArgs["-onion"], 9050);
|
||||
if (!addrOnion.IsValid())
|
||||
return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs.count("-onion")?mapArgs["-onion"]:mapArgs["-tor"]));
|
||||
SetProxy(NET_TOR, addrOnion, 5);
|
||||
return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"]));
|
||||
SetProxy(NET_TOR, addrOnion);
|
||||
SetReachable(NET_TOR);
|
||||
}
|
||||
|
||||
// see Step 2: parameter interactions for more information about these
|
||||
fNoListen = !GetBoolArg("-listen", true);
|
||||
fListen = GetBoolArg("-listen", DEFAULT_LISTEN);
|
||||
fDiscover = GetBoolArg("-discover", true);
|
||||
fNameLookup = GetBoolArg("-dns", true);
|
||||
|
||||
bool fBound = false;
|
||||
if (!fNoListen) {
|
||||
if (fListen) {
|
||||
if (mapArgs.count("-bind")) {
|
||||
BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
|
||||
CService addrBind;
|
||||
@@ -855,7 +919,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
}
|
||||
|
||||
uiInterface.InitMessage(_("Verifying blocks..."));
|
||||
if (!VerifyDB(GetArg("-checklevel", 3),
|
||||
if (!CVerifyDB().VerifyDB(GetArg("-checklevel", 3),
|
||||
GetArg("-checkblocks", 288))) {
|
||||
strLoadError = _("Corrupted block database detected");
|
||||
break;
|
||||
@@ -911,7 +975,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
|
||||
{
|
||||
uint256 hash = (*mi).first;
|
||||
if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
|
||||
if (boost::algorithm::starts_with(hash.ToString(), strMatch))
|
||||
{
|
||||
CBlockIndex* pindex = (*mi).second;
|
||||
CBlock block;
|
||||
@@ -927,17 +991,26 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
|
||||
CAutoFile est_filein = CAutoFile(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION);
|
||||
if (est_filein)
|
||||
mempool.ReadFeeEstimates(est_filein);
|
||||
|
||||
// ********************************************************* Step 8: load wallet
|
||||
#ifdef ENABLE_WALLET
|
||||
if (fDisableWallet) {
|
||||
pwalletMain = NULL;
|
||||
LogPrintf("Wallet disabled!\n");
|
||||
} else {
|
||||
|
||||
// needed to restore wallet transaction meta data after -zapwallettxes
|
||||
std::vector<CWalletTx> vWtx;
|
||||
|
||||
if (GetBoolArg("-zapwallettxes", false)) {
|
||||
uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
|
||||
|
||||
pwalletMain = new CWallet(strWalletFile);
|
||||
DBErrors nZapWalletRet = pwalletMain->ZapWalletTx();
|
||||
DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(vWtx);
|
||||
if (nZapWalletRet != DB_LOAD_OK) {
|
||||
uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted"));
|
||||
return false;
|
||||
@@ -1032,6 +1105,29 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
||||
pwalletMain->SetBestChain(chainActive.GetLocator());
|
||||
nWalletDBUpdated++;
|
||||
|
||||
// Restore wallet transaction metadata after -zapwallettxes=1
|
||||
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
|
||||
{
|
||||
BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
|
||||
{
|
||||
uint256 hash = wtxOld.GetHash();
|
||||
std::map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
|
||||
if (mi != pwalletMain->mapWallet.end())
|
||||
{
|
||||
const CWalletTx* copyFrom = &wtxOld;
|
||||
CWalletTx* copyTo = &mi->second;
|
||||
copyTo->mapValue = copyFrom->mapValue;
|
||||
copyTo->vOrderForm = copyFrom->vOrderForm;
|
||||
copyTo->nTimeReceived = copyFrom->nTimeReceived;
|
||||
copyTo->nTimeSmart = copyFrom->nTimeSmart;
|
||||
copyTo->fFromMe = copyFrom->fFromMe;
|
||||
copyTo->strFromAccount = copyFrom->strFromAccount;
|
||||
copyTo->nOrderPos = copyFrom->nOrderPos;
|
||||
copyTo->WriteToDisk();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // (!fDisableWallet)
|
||||
#else // ENABLE_WALLET
|
||||
@@ -1078,17 +1174,16 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
//// debug print
|
||||
LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
|
||||
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
|
||||
LogPrintf("nBestHeight = %d\n", chainActive.Height());
|
||||
#ifdef ENABLE_WALLET
|
||||
LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
|
||||
LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);
|
||||
LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
|
||||
LogPrintf("setKeyPool.size() = %u\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
|
||||
LogPrintf("mapWallet.size() = %u\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);
|
||||
LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
|
||||
#endif
|
||||
|
||||
InitRespendFilter();
|
||||
StartNode(threadGroup);
|
||||
// InitRPCMining is needed here so getwork/getblocktemplate in the GUI debug console works properly.
|
||||
InitRPCMining();
|
||||
if (fServer)
|
||||
StartRPCThreads();
|
||||
|
||||
|
||||
@@ -12,9 +12,8 @@ class CWallet;
|
||||
|
||||
namespace boost {
|
||||
class thread_group;
|
||||
};
|
||||
} // namespace boost
|
||||
|
||||
extern std::string strWalletFile;
|
||||
extern CWallet* pwalletMain;
|
||||
|
||||
void StartShutdown();
|
||||
@@ -29,6 +28,9 @@ enum HelpMessageMode
|
||||
HMM_BITCOIN_QT
|
||||
};
|
||||
|
||||
/** Help for options shared between UI and daemon (for -help) */
|
||||
std::string HelpMessage(HelpMessageMode mode);
|
||||
/** Returns licensing information (for -version) */
|
||||
std::string LicenseInfo();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
|
||||
namespace json_spirit
|
||||
{
|
||||
const spirit_namespace::int_parser < boost::int64_t > int64_p = spirit_namespace::int_parser < boost::int64_t >();
|
||||
const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >();
|
||||
const spirit_namespace::int_parser < int64_t > int64_p = spirit_namespace::int_parser < int64_t >();
|
||||
const spirit_namespace::uint_parser< uint64_t > uint64_p = spirit_namespace::uint_parser< uint64_t >();
|
||||
|
||||
template< class Iter_type >
|
||||
bool is_eq( Iter_type first, Iter_type last, const char* c_str )
|
||||
@@ -270,12 +270,12 @@ namespace json_spirit
|
||||
add_to_current( Value_type() );
|
||||
}
|
||||
|
||||
void new_int( boost::int64_t i )
|
||||
void new_int( int64_t i )
|
||||
{
|
||||
add_to_current( i );
|
||||
}
|
||||
|
||||
void new_uint64( boost::uint64_t ui )
|
||||
void new_uint64( uint64_t ui )
|
||||
{
|
||||
add_to_current( ui );
|
||||
}
|
||||
@@ -425,8 +425,8 @@ namespace json_spirit
|
||||
typedef boost::function< void( Char_type ) > Char_action;
|
||||
typedef boost::function< void( Iter_type, Iter_type ) > Str_action;
|
||||
typedef boost::function< void( double ) > Real_action;
|
||||
typedef boost::function< void( boost::int64_t ) > Int_action;
|
||||
typedef boost::function< void( boost::uint64_t ) > Uint64_action;
|
||||
typedef boost::function< void( int64_t ) > Int_action;
|
||||
typedef boost::function< void( uint64_t ) > Uint64_action;
|
||||
|
||||
Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) );
|
||||
Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) );
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
@@ -45,8 +45,8 @@ namespace json_spirit
|
||||
Value_impl( const Array& value );
|
||||
Value_impl( bool value );
|
||||
Value_impl( int value );
|
||||
Value_impl( boost::int64_t value );
|
||||
Value_impl( boost::uint64_t value );
|
||||
Value_impl( int64_t value );
|
||||
Value_impl( uint64_t value );
|
||||
Value_impl( double value );
|
||||
|
||||
Value_impl( const Value_impl& other );
|
||||
@@ -65,8 +65,8 @@ namespace json_spirit
|
||||
const Array& get_array() const;
|
||||
bool get_bool() const;
|
||||
int get_int() const;
|
||||
boost::int64_t get_int64() const;
|
||||
boost::uint64_t get_uint64() const;
|
||||
int64_t get_int64() const;
|
||||
uint64_t get_uint64() const;
|
||||
double get_real() const;
|
||||
|
||||
Object& get_obj();
|
||||
@@ -83,7 +83,7 @@ namespace json_spirit
|
||||
|
||||
typedef boost::variant< String_type,
|
||||
boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >,
|
||||
bool, boost::int64_t, double > Variant;
|
||||
bool, int64_t, double > Variant;
|
||||
|
||||
Value_type type_;
|
||||
Variant v_;
|
||||
@@ -258,13 +258,13 @@ namespace json_spirit
|
||||
template< class Config >
|
||||
Value_impl< Config >::Value_impl( int value )
|
||||
: type_( int_type )
|
||||
, v_( static_cast< boost::int64_t >( value ) )
|
||||
, v_( static_cast< int64_t >( value ) )
|
||||
, is_uint64_( false )
|
||||
{
|
||||
}
|
||||
|
||||
template< class Config >
|
||||
Value_impl< Config >::Value_impl( boost::int64_t value )
|
||||
Value_impl< Config >::Value_impl( int64_t value )
|
||||
: type_( int_type )
|
||||
, v_( value )
|
||||
, is_uint64_( false )
|
||||
@@ -272,9 +272,9 @@ namespace json_spirit
|
||||
}
|
||||
|
||||
template< class Config >
|
||||
Value_impl< Config >::Value_impl( boost::uint64_t value )
|
||||
Value_impl< Config >::Value_impl( uint64_t value )
|
||||
: type_( int_type )
|
||||
, v_( static_cast< boost::int64_t >( value ) )
|
||||
, v_( static_cast< int64_t >( value ) )
|
||||
, is_uint64_( true )
|
||||
{
|
||||
}
|
||||
@@ -390,19 +390,19 @@ namespace json_spirit
|
||||
}
|
||||
|
||||
template< class Config >
|
||||
boost::int64_t Value_impl< Config >::get_int64() const
|
||||
int64_t Value_impl< Config >::get_int64() const
|
||||
{
|
||||
check_type( int_type );
|
||||
|
||||
return boost::get< boost::int64_t >( v_ );
|
||||
return boost::get< int64_t >( v_ );
|
||||
}
|
||||
|
||||
template< class Config >
|
||||
boost::uint64_t Value_impl< Config >::get_uint64() const
|
||||
uint64_t Value_impl< Config >::get_uint64() const
|
||||
{
|
||||
check_type( int_type );
|
||||
|
||||
return static_cast< boost::uint64_t >( get_int64() );
|
||||
return static_cast< uint64_t >( get_int64() );
|
||||
}
|
||||
|
||||
template< class Config >
|
||||
@@ -481,13 +481,13 @@ namespace json_spirit
|
||||
}
|
||||
|
||||
template< class Value >
|
||||
boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > )
|
||||
int64_t get_value( const Value& value, Type_to_type< int64_t > )
|
||||
{
|
||||
return value.get_int64();
|
||||
}
|
||||
|
||||
template< class Value >
|
||||
boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > )
|
||||
uint64_t get_value( const Value& value, Type_to_type< uint64_t > )
|
||||
{
|
||||
return value.get_uint64();
|
||||
}
|
||||
|
||||
249
src/key.cpp
249
src/key.cpp
@@ -4,14 +4,35 @@
|
||||
|
||||
#include "key.h"
|
||||
|
||||
#include "crypto/sha2.h"
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#ifdef USE_SECP256K1
|
||||
#include <secp256k1.h>
|
||||
#else
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
// anonymous namespace with local implementation code (OpenSSL interaction)
|
||||
namespace {
|
||||
|
||||
#ifdef USE_SECP256K1
|
||||
#include <secp256k1.h>
|
||||
class CSecp256k1Init {
|
||||
public:
|
||||
CSecp256k1Init() {
|
||||
secp256k1_start();
|
||||
}
|
||||
~CSecp256k1Init() {
|
||||
secp256k1_stop();
|
||||
}
|
||||
};
|
||||
static CSecp256k1Init instance_of_csecp256k1;
|
||||
|
||||
#else
|
||||
|
||||
// Generate a private key from just the secret parameter
|
||||
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
||||
{
|
||||
@@ -332,30 +353,61 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
}; // end of anonymous namespace
|
||||
#endif
|
||||
|
||||
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[0] = {};
|
||||
|
||||
} // anon namespace
|
||||
|
||||
bool CKey::Check(const unsigned char *vch) {
|
||||
// Do not convert to OpenSSL's data structures for range-checking keys,
|
||||
// it's easy enough to do directly.
|
||||
static const unsigned char vchMax[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
|
||||
};
|
||||
bool fIsZero = true;
|
||||
for (int i=0; i<32 && fIsZero; i++)
|
||||
if (vch[i] != 0)
|
||||
fIsZero = false;
|
||||
if (fIsZero)
|
||||
return false;
|
||||
for (int i=0; i<32; i++) {
|
||||
if (vch[i] < vchMax[i])
|
||||
return true;
|
||||
if (vch[i] > vchMax[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return CompareBigEndian(vch, 32, vchZero, 0) > 0 &&
|
||||
CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0;
|
||||
}
|
||||
|
||||
bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) {
|
||||
return CompareBigEndian(vch, len, vchZero, 0) > 0 &&
|
||||
CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
|
||||
}
|
||||
|
||||
void CKey::MakeNewKey(bool fCompressedIn) {
|
||||
@@ -367,10 +419,15 @@ void CKey::MakeNewKey(bool fCompressedIn) {
|
||||
}
|
||||
|
||||
bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
|
||||
#ifdef USE_SECP256K1
|
||||
if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
|
||||
return false;
|
||||
#else
|
||||
CECKey key;
|
||||
if (!key.SetPrivKey(privkey))
|
||||
return false;
|
||||
key.GetSecretBytes(vch);
|
||||
#endif
|
||||
fCompressed = fCompressedIn;
|
||||
fValid = true;
|
||||
return true;
|
||||
@@ -378,114 +435,167 @@ bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
|
||||
|
||||
CPrivKey CKey::GetPrivKey() const {
|
||||
assert(fValid);
|
||||
CPrivKey privkey;
|
||||
#ifdef USE_SECP256K1
|
||||
privkey.resize(279);
|
||||
int privkeylen = 279;
|
||||
int ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
|
||||
assert(ret);
|
||||
privkey.resize(privkeylen);
|
||||
#else
|
||||
CECKey key;
|
||||
key.SetSecretBytes(vch);
|
||||
CPrivKey privkey;
|
||||
key.GetPrivKey(privkey, fCompressed);
|
||||
#endif
|
||||
return privkey;
|
||||
}
|
||||
|
||||
CPubKey CKey::GetPubKey() const {
|
||||
assert(fValid);
|
||||
CPubKey pubkey;
|
||||
#ifdef USE_SECP256K1
|
||||
int clen = 65;
|
||||
int ret = secp256k1_ecdsa_pubkey_create((unsigned char*)pubkey.begin(), &clen, begin(), fCompressed);
|
||||
assert(ret);
|
||||
assert(pubkey.IsValid());
|
||||
assert((int)pubkey.size() == clen);
|
||||
#else
|
||||
CECKey key;
|
||||
key.SetSecretBytes(vch);
|
||||
CPubKey pubkey;
|
||||
key.GetPubKey(pubkey, fCompressed);
|
||||
#endif
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
|
||||
if (!fValid)
|
||||
return false;
|
||||
#ifdef USE_SECP256K1
|
||||
vchSig.resize(72);
|
||||
int nSigLen = 72;
|
||||
CKey nonce;
|
||||
do {
|
||||
nonce.MakeNewKey(true);
|
||||
if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin()))
|
||||
break;
|
||||
} while(true);
|
||||
vchSig.resize(nSigLen);
|
||||
return true;
|
||||
#else
|
||||
CECKey key;
|
||||
key.SetSecretBytes(vch);
|
||||
return key.Sign(hash, vchSig);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
|
||||
if (!fValid)
|
||||
return false;
|
||||
CECKey key;
|
||||
key.SetSecretBytes(vch);
|
||||
vchSig.resize(65);
|
||||
int rec = -1;
|
||||
#ifdef USE_SECP256K1
|
||||
CKey nonce;
|
||||
do {
|
||||
nonce.MakeNewKey(true);
|
||||
if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec))
|
||||
break;
|
||||
} while(true);
|
||||
#else
|
||||
CECKey key;
|
||||
key.SetSecretBytes(vch);
|
||||
if (!key.SignCompact(hash, &vchSig[1], rec))
|
||||
return false;
|
||||
#endif
|
||||
assert(rec != -1);
|
||||
vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
|
||||
#ifdef USE_SECP256K1
|
||||
if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
|
||||
return false;
|
||||
#else
|
||||
CECKey key;
|
||||
if (!key.SetPrivKey(privkey, fSkipCheck))
|
||||
return false;
|
||||
|
||||
key.GetSecretBytes(vch);
|
||||
#endif
|
||||
fCompressed = vchPubKey.IsCompressed();
|
||||
fValid = true;
|
||||
|
||||
|
||||
if (fSkipCheck)
|
||||
return true;
|
||||
|
||||
|
||||
if (GetPubKey() != vchPubKey)
|
||||
return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
#ifdef USE_SECP256K1
|
||||
if (secp256k1_ecdsa_verify((const unsigned char*)&hash, 32, &vchSig[0], vchSig.size(), begin(), size()) != 1)
|
||||
return false;
|
||||
#else
|
||||
CECKey key;
|
||||
if (!key.SetPubKey(*this))
|
||||
return false;
|
||||
if (!key.Verify(hash, vchSig))
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
|
||||
if (vchSig.size() != 65)
|
||||
return false;
|
||||
int recid = (vchSig[0] - 27) & 3;
|
||||
bool fComp = (vchSig[0] - 27) & 4;
|
||||
#ifdef USE_SECP256K1
|
||||
int pubkeylen = 65;
|
||||
if (!secp256k1_ecdsa_recover_compact((const unsigned char*)&hash, 32, &vchSig[1], (unsigned char*)begin(), &pubkeylen, fComp, recid))
|
||||
return false;
|
||||
assert((int)size() == pubkeylen);
|
||||
#else
|
||||
CECKey key;
|
||||
if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4))
|
||||
return false;
|
||||
key.GetPubKey(*this, (vchSig[0] - 27) & 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPubKey::VerifyCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
if (vchSig.size() != 65)
|
||||
return false;
|
||||
CECKey key;
|
||||
if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4))
|
||||
return false;
|
||||
CPubKey pubkeyRec;
|
||||
key.GetPubKey(pubkeyRec, IsCompressed());
|
||||
if (*this != pubkeyRec)
|
||||
if (!key.Recover(hash, &vchSig[1], recid))
|
||||
return false;
|
||||
key.GetPubKey(*this, fComp);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPubKey::IsFullyValid() const {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
#ifdef USE_SECP256K1
|
||||
if (!secp256k1_ecdsa_pubkey_verify(begin(), size()))
|
||||
return false;
|
||||
#else
|
||||
CECKey key;
|
||||
if (!key.SetPubKey(*this))
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPubKey::Decompress() {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
#ifdef USE_SECP256K1
|
||||
int clen = size();
|
||||
int ret = secp256k1_ecdsa_pubkey_decompress((unsigned char*)begin(), &clen);
|
||||
assert(ret);
|
||||
assert(clen == (int)size());
|
||||
#else
|
||||
CECKey key;
|
||||
if (!key.SetPubKey(*this))
|
||||
return false;
|
||||
key.GetPubKey(*this, false);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -495,12 +605,10 @@ void static BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, un
|
||||
num[1] = (nChild >> 16) & 0xFF;
|
||||
num[2] = (nChild >> 8) & 0xFF;
|
||||
num[3] = (nChild >> 0) & 0xFF;
|
||||
HMAC_SHA512_CTX ctx;
|
||||
HMAC_SHA512_Init(&ctx, chainCode, 32);
|
||||
HMAC_SHA512_Update(&ctx, &header, 1);
|
||||
HMAC_SHA512_Update(&ctx, data, 32);
|
||||
HMAC_SHA512_Update(&ctx, num, 4);
|
||||
HMAC_SHA512_Final(output, &ctx);
|
||||
CHMAC_SHA512(chainCode, 32).Write(&header, 1)
|
||||
.Write(data, 32)
|
||||
.Write(num, 4)
|
||||
.Finalize(output);
|
||||
}
|
||||
|
||||
bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
|
||||
@@ -517,7 +625,12 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild
|
||||
BIP32Hash(cc, nChild, 0, begin(), out);
|
||||
}
|
||||
memcpy(ccChild, out+32, 32);
|
||||
#ifdef USE_SECP256K1
|
||||
memcpy((unsigned char*)keyChild.begin(), begin(), 32);
|
||||
bool ret = secp256k1_ecdsa_privkey_tweak_add((unsigned char*)keyChild.begin(), out);
|
||||
#else
|
||||
bool ret = CECKey::TweakSecret((unsigned char*)keyChild.begin(), begin(), out);
|
||||
#endif
|
||||
UnlockObject(out);
|
||||
keyChild.fCompressed = true;
|
||||
keyChild.fValid = ret;
|
||||
@@ -531,10 +644,15 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned i
|
||||
unsigned char out[64];
|
||||
BIP32Hash(cc, nChild, *begin(), begin()+1, out);
|
||||
memcpy(ccChild, out+32, 32);
|
||||
#ifdef USE_SECP256K1
|
||||
pubkeyChild = *this;
|
||||
bool ret = secp256k1_ecdsa_pubkey_tweak_add((unsigned char*)pubkeyChild.begin(), pubkeyChild.size(), out);
|
||||
#else
|
||||
CECKey key;
|
||||
bool ret = key.SetPubKey(*this);
|
||||
ret &= key.TweakPublic(out);
|
||||
key.GetPubKey(pubkeyChild, true);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -547,13 +665,10 @@ bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
|
||||
}
|
||||
|
||||
void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
|
||||
static const char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
|
||||
HMAC_SHA512_CTX ctx;
|
||||
HMAC_SHA512_Init(&ctx, hashkey, sizeof(hashkey));
|
||||
HMAC_SHA512_Update(&ctx, seed, nSeedLen);
|
||||
static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
|
||||
unsigned char out[64];
|
||||
LockObject(out);
|
||||
HMAC_SHA512_Final(out, &ctx);
|
||||
CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out);
|
||||
key.Set(&out[0], &out[32], true);
|
||||
memcpy(vchChainCode, &out[32], 32);
|
||||
UnlockObject(out);
|
||||
@@ -616,3 +731,19 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
|
||||
out.nChild = nChild;
|
||||
return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode);
|
||||
}
|
||||
|
||||
bool ECC_InitSanityCheck() {
|
||||
#ifdef USE_SECP256K1
|
||||
return true;
|
||||
#else
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
10
src/key.h
10
src/key.h
@@ -156,10 +156,6 @@ public:
|
||||
// If this public key is not fully valid, the return value will be false.
|
||||
bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const;
|
||||
|
||||
// Verify a compact signature (~65 bytes).
|
||||
// See CKey::SignCompact.
|
||||
bool VerifyCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) const;
|
||||
|
||||
// Recover a public key from a compact signature.
|
||||
bool RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
@@ -269,6 +265,9 @@ public:
|
||||
|
||||
// Load private key and check that public key matches.
|
||||
bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck);
|
||||
|
||||
// Check whether an element of a signature (r or s) is valid.
|
||||
static bool CheckSignatureElement(const unsigned char *vch, int len, bool half);
|
||||
};
|
||||
|
||||
struct CExtPubKey {
|
||||
@@ -307,4 +306,7 @@ struct CExtKey {
|
||||
void SetMaster(const unsigned char *seed, unsigned int nSeedLen);
|
||||
};
|
||||
|
||||
/** Check that required EC support is available at runtime */
|
||||
bool ECC_InitSanityCheck(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,9 @@ bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
|
||||
|
||||
bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
|
||||
{
|
||||
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
||||
return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
|
||||
|
||||
LOCK(cs_KeyStore);
|
||||
mapScripts[redeemScript.GetID()] = redeemScript;
|
||||
return true;
|
||||
@@ -56,3 +59,15 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
setWatchOnly.insert(dest);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
return setWatchOnly.count(dest) > 0;
|
||||
}
|
||||
|
||||
@@ -8,11 +8,21 @@
|
||||
|
||||
#include "key.h"
|
||||
#include "sync.h"
|
||||
#include "script.h" // for CNoDestination
|
||||
|
||||
#include <boost/signals2/signal.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
class CScript;
|
||||
|
||||
/** A txout script template with a specific destination. It is either:
|
||||
* * CNoDestination: no destination set
|
||||
* * CKeyID: TX_PUBKEYHASH destination
|
||||
* * CScriptID: TX_SCRIPTHASH destination
|
||||
* A CTxDestination is the internal data type encoded in a CBitcoinAddress
|
||||
*/
|
||||
typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
|
||||
|
||||
/** A virtual base class for key stores */
|
||||
class CKeyStore
|
||||
{
|
||||
@@ -36,10 +46,15 @@ public:
|
||||
virtual bool AddCScript(const CScript& redeemScript) =0;
|
||||
virtual bool HaveCScript(const CScriptID &hash) const =0;
|
||||
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0;
|
||||
|
||||
// Support for Watch-only addresses
|
||||
virtual bool AddWatchOnly(const CScript &dest) =0;
|
||||
virtual bool HaveWatchOnly(const CScript &dest) const =0;
|
||||
};
|
||||
|
||||
typedef std::map<CKeyID, CKey> KeyMap;
|
||||
typedef std::map<CScriptID, CScript > ScriptMap;
|
||||
typedef std::set<CScript> WatchOnlySet;
|
||||
|
||||
/** Basic key store, that keeps keys in an address->secret map */
|
||||
class CBasicKeyStore : public CKeyStore
|
||||
@@ -47,6 +62,7 @@ class CBasicKeyStore : public CKeyStore
|
||||
protected:
|
||||
KeyMap mapKeys;
|
||||
ScriptMap mapScripts;
|
||||
WatchOnlySet setWatchOnly;
|
||||
|
||||
public:
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
|
||||
@@ -88,6 +104,9 @@ public:
|
||||
virtual bool AddCScript(const CScript& redeemScript);
|
||||
virtual bool HaveCScript(const CScriptID &hash) const;
|
||||
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const;
|
||||
|
||||
virtual bool AddWatchOnly(const CScript &dest);
|
||||
virtual bool HaveWatchOnly(const CScript &dest) const;
|
||||
};
|
||||
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
||||
|
||||
@@ -72,7 +72,7 @@ SHARED = $(SHARED1)
|
||||
else
|
||||
# Update db.h if you change these.
|
||||
SHARED_MAJOR = 1
|
||||
SHARED_MINOR = 15
|
||||
SHARED_MINOR = 17
|
||||
SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT)
|
||||
SHARED2 = $(SHARED1).$(SHARED_MAJOR)
|
||||
SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR)
|
||||
@@ -190,19 +190,20 @@ PLATFORMSROOT=/Applications/Xcode.app/Contents/Developer/Platforms
|
||||
SIMULATORROOT=$(PLATFORMSROOT)/iPhoneSimulator.platform/Developer
|
||||
DEVICEROOT=$(PLATFORMSROOT)/iPhoneOS.platform/Developer
|
||||
IOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/version CFBundleShortVersionString)
|
||||
IOSARCH=-arch armv6 -arch armv7 -arch armv7s -arch arm64
|
||||
|
||||
.cc.o:
|
||||
mkdir -p ios-x86/$(dir $@)
|
||||
$(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@
|
||||
$(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@
|
||||
mkdir -p ios-arm/$(dir $@)
|
||||
xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
|
||||
xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@
|
||||
lipo ios-x86/$@ ios-arm/$@ -create -output $@
|
||||
|
||||
.c.o:
|
||||
mkdir -p ios-x86/$(dir $@)
|
||||
$(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@
|
||||
$(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@
|
||||
mkdir -p ios-arm/$(dir $@)
|
||||
xcrun -sdk iphoneos $(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
|
||||
xcrun -sdk iphoneos $(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@
|
||||
lipo ios-x86/$@ ios-arm/$@ -create -output $@
|
||||
|
||||
else
|
||||
|
||||
@@ -29,19 +29,14 @@ std::string LogFileName(const std::string& name, uint64_t number) {
|
||||
return MakeFileName(name, number, "log");
|
||||
}
|
||||
|
||||
// TableFileName returns the filenames we usually write to, while
|
||||
// SSTTableFileName returns the alternative filenames we also try to read from
|
||||
// for backward compatibility. For now, swap them around.
|
||||
// TODO: when compatibility is no longer necessary, swap them back
|
||||
// (TableFileName to use "ldb" and SSTTableFileName to use "sst").
|
||||
std::string TableFileName(const std::string& name, uint64_t number) {
|
||||
assert(number > 0);
|
||||
return MakeFileName(name, number, "sst");
|
||||
return MakeFileName(name, number, "ldb");
|
||||
}
|
||||
|
||||
std::string SSTTableFileName(const std::string& name, uint64_t number) {
|
||||
assert(number > 0);
|
||||
return MakeFileName(name, number, "ldb");
|
||||
return MakeFileName(name, number, "sst");
|
||||
}
|
||||
|
||||
std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
|
||||
|
||||
@@ -133,7 +133,9 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch) {
|
||||
|
||||
case kEof:
|
||||
if (in_fragmented_record) {
|
||||
ReportCorruption(scratch->size(), "partial record without end(3)");
|
||||
// This can be caused by the writer dying immediately after
|
||||
// writing a physical record but before completing the next; don't
|
||||
// treat it as a corruption, just ignore the entire logical record.
|
||||
scratch->clear();
|
||||
}
|
||||
return false;
|
||||
@@ -193,13 +195,12 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result) {
|
||||
eof_ = true;
|
||||
}
|
||||
continue;
|
||||
} else if (buffer_.size() == 0) {
|
||||
// End of file
|
||||
return kEof;
|
||||
} else {
|
||||
size_t drop_size = buffer_.size();
|
||||
// Note that if buffer_ is non-empty, we have a truncated header at the
|
||||
// end of the file, which can be caused by the writer crashing in the
|
||||
// middle of writing the header. Instead of considering this an error,
|
||||
// just report EOF.
|
||||
buffer_.clear();
|
||||
ReportCorruption(drop_size, "truncated record at end of file");
|
||||
return kEof;
|
||||
}
|
||||
}
|
||||
@@ -213,8 +214,14 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result) {
|
||||
if (kHeaderSize + length > buffer_.size()) {
|
||||
size_t drop_size = buffer_.size();
|
||||
buffer_.clear();
|
||||
ReportCorruption(drop_size, "bad record length");
|
||||
return kBadRecord;
|
||||
if (!eof_) {
|
||||
ReportCorruption(drop_size, "bad record length");
|
||||
return kBadRecord;
|
||||
}
|
||||
// If the end of the file has been reached without reading |length| bytes
|
||||
// of payload, assume the writer died in the middle of writing the record.
|
||||
// Don't report a corruption.
|
||||
return kEof;
|
||||
}
|
||||
|
||||
if (type == kZeroType && length == 0) {
|
||||
|
||||
@@ -351,20 +351,32 @@ TEST(LogTest, BadRecordType) {
|
||||
ASSERT_EQ("OK", MatchError("unknown record type"));
|
||||
}
|
||||
|
||||
TEST(LogTest, TruncatedTrailingRecord) {
|
||||
TEST(LogTest, TruncatedTrailingRecordIsIgnored) {
|
||||
Write("foo");
|
||||
ShrinkSize(4); // Drop all payload as well as a header byte
|
||||
ASSERT_EQ("EOF", Read());
|
||||
ASSERT_EQ(kHeaderSize - 1, DroppedBytes());
|
||||
ASSERT_EQ("OK", MatchError("truncated record at end of file"));
|
||||
// Truncated last record is ignored, not treated as an error.
|
||||
ASSERT_EQ(0, DroppedBytes());
|
||||
ASSERT_EQ("", ReportMessage());
|
||||
}
|
||||
|
||||
TEST(LogTest, BadLength) {
|
||||
const int kPayloadSize = kBlockSize - kHeaderSize;
|
||||
Write(BigString("bar", kPayloadSize));
|
||||
Write("foo");
|
||||
// Least significant size byte is stored in header[4].
|
||||
IncrementByte(4, 1);
|
||||
ASSERT_EQ("foo", Read());
|
||||
ASSERT_EQ(kBlockSize, DroppedBytes());
|
||||
ASSERT_EQ("OK", MatchError("bad record length"));
|
||||
}
|
||||
|
||||
TEST(LogTest, BadLengthAtEndIsIgnored) {
|
||||
Write("foo");
|
||||
ShrinkSize(1);
|
||||
ASSERT_EQ("EOF", Read());
|
||||
ASSERT_EQ(kHeaderSize + 2, DroppedBytes());
|
||||
ASSERT_EQ("OK", MatchError("bad record length"));
|
||||
ASSERT_EQ(0, DroppedBytes());
|
||||
ASSERT_EQ("", ReportMessage());
|
||||
}
|
||||
|
||||
TEST(LogTest, ChecksumMismatch) {
|
||||
@@ -415,6 +427,24 @@ TEST(LogTest, UnexpectedFirstType) {
|
||||
ASSERT_EQ("OK", MatchError("partial record without end"));
|
||||
}
|
||||
|
||||
TEST(LogTest, MissingLastIsIgnored) {
|
||||
Write(BigString("bar", kBlockSize));
|
||||
// Remove the LAST block, including header.
|
||||
ShrinkSize(14);
|
||||
ASSERT_EQ("EOF", Read());
|
||||
ASSERT_EQ("", ReportMessage());
|
||||
ASSERT_EQ(0, DroppedBytes());
|
||||
}
|
||||
|
||||
TEST(LogTest, PartialLastIsIgnored) {
|
||||
Write(BigString("bar", kBlockSize));
|
||||
// Cause a bad record length in the LAST block.
|
||||
ShrinkSize(1);
|
||||
ASSERT_EQ("EOF", Read());
|
||||
ASSERT_EQ("", ReportMessage());
|
||||
ASSERT_EQ(0, DroppedBytes());
|
||||
}
|
||||
|
||||
TEST(LogTest, ErrorJoinsRecords) {
|
||||
// Consider two fragmented records:
|
||||
// first(R1) last(R1) first(R2) last(R2)
|
||||
|
||||
@@ -242,7 +242,6 @@ class Repairer {
|
||||
}
|
||||
|
||||
void ExtractMetaData() {
|
||||
std::vector<TableInfo> kept;
|
||||
for (size_t i = 0; i < table_numbers_.size(); i++) {
|
||||
ScanTable(table_numbers_[i]);
|
||||
}
|
||||
|
||||
@@ -54,20 +54,6 @@ static int64_t TotalFileSize(const std::vector<FileMetaData*>& files) {
|
||||
return sum;
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::string IntSetToString(const std::set<uint64_t>& s) {
|
||||
std::string result = "{";
|
||||
for (std::set<uint64_t>::const_iterator it = s.begin();
|
||||
it != s.end();
|
||||
++it) {
|
||||
result += (result.size() > 1) ? "," : "";
|
||||
result += NumberToString(*it);
|
||||
}
|
||||
result += "}";
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Version::~Version() {
|
||||
assert(refs_ == 0);
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
Does not support:
|
||||
. getters for the option types
|
||||
. custom comparators that implement key shortening
|
||||
. capturing post-write-snapshot
|
||||
. custom iter, db, env, cache implementations using just the C bindings
|
||||
|
||||
Some conventions:
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace leveldb {
|
||||
|
||||
// Update Makefile if you change these
|
||||
static const int kMajorVersion = 1;
|
||||
static const int kMinorVersion = 15;
|
||||
static const int kMinorVersion = 17;
|
||||
|
||||
struct Options;
|
||||
struct ReadOptions;
|
||||
|
||||
@@ -94,7 +94,7 @@ inline bool operator!=(const Slice& x, const Slice& y) {
|
||||
}
|
||||
|
||||
inline int Slice::compare(const Slice& b) const {
|
||||
const int min_len = (size_ < b.size_) ? size_ : b.size_;
|
||||
const size_t min_len = (size_ < b.size_) ? size_ : b.size_;
|
||||
int r = memcmp(data_, b.data_, min_len);
|
||||
if (r == 0) {
|
||||
if (size_ < b.size_) r = -1;
|
||||
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
if (!status.ok()) {
|
||||
if (status.IsNotFound())
|
||||
return false;
|
||||
LogPrintf("LevelDB read failure: %s\n", status.ToString().c_str());
|
||||
LogPrintf("LevelDB read failure: %s\n", status.ToString());
|
||||
HandleError(status);
|
||||
}
|
||||
try {
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
if (!status.ok()) {
|
||||
if (status.IsNotFound())
|
||||
return false;
|
||||
LogPrintf("LevelDB read failure: %s\n", status.ToString().c_str());
|
||||
LogPrintf("LevelDB read failure: %s\n", status.ToString());
|
||||
HandleError(status);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -100,7 +100,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
|
||||
BITCOIN_QT_PATH_PROGS([LRELEASE], [lrelease-qt${bitcoin_qt_got_major_vers} lrelease${bitcoin_qt_got_major_vers} lrelease], $qt_bin_path)
|
||||
BITCOIN_QT_PATH_PROGS([LUPDATE], [lupdate-qt${bitcoin_qt_got_major_vers} lupdate${bitcoin_qt_got_major_vers} lupdate],$qt_bin_path, yes)
|
||||
|
||||
MOC_DEFS='-DHAVE_CONFIG_H -I$(top_srcdir)/src'
|
||||
MOC_DEFS='-DHAVE_CONFIG_H -I$(srcdir)'
|
||||
case $host in
|
||||
*darwin*)
|
||||
BITCOIN_QT_CHECK([
|
||||
|
||||
1156
src/main.cpp
1156
src/main.cpp
File diff suppressed because it is too large
Load Diff
169
src/main.h
169
src/main.h
@@ -7,10 +7,9 @@
|
||||
#define BITCOIN_MAIN_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "bignum.h"
|
||||
#include "chainparams.h"
|
||||
#include "coins.h"
|
||||
#include "core.h"
|
||||
@@ -44,10 +43,12 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
|
||||
static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
|
||||
/** The maximum allowed number of signature check operations in a block (network rule) */
|
||||
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
|
||||
/** Maxiumum number of signature check operations in an IsStandard() P2SH script */
|
||||
static const unsigned int MAX_P2SH_SIGOPS = 15;
|
||||
/** The maximum number of orphan transactions kept in memory */
|
||||
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
|
||||
/** The maximum number of orphan blocks kept in memory */
|
||||
static const unsigned int MAX_ORPHAN_BLOCKS = 750;
|
||||
/** Default for -maxorphanblocks, maximum number of orphan blocks kept in memory */
|
||||
static const unsigned int DEFAULT_MAX_ORPHAN_BLOCKS = 750;
|
||||
/** The maximum size of a blk?????.dat file (since 0.8) */
|
||||
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
|
||||
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
|
||||
@@ -67,12 +68,6 @@ static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 128;
|
||||
/** Timeout in seconds before considering a block download peer unresponsive. */
|
||||
static const unsigned int BLOCK_DOWNLOAD_TIMEOUT = 60;
|
||||
|
||||
#ifdef USE_UPNP
|
||||
static const int fHaveUPnP = true;
|
||||
#else
|
||||
static const int fHaveUPnP = false;
|
||||
#endif
|
||||
|
||||
/** "reject" message codes **/
|
||||
static const unsigned char REJECT_MALFORMED = 0x01;
|
||||
static const unsigned char REJECT_INVALID = 0x10;
|
||||
@@ -98,12 +93,12 @@ extern bool fBenchmark;
|
||||
extern int nScriptCheckThreads;
|
||||
extern bool fTxIndex;
|
||||
extern unsigned int nCoinCacheSize;
|
||||
extern CFeeRate minRelayTxFee;
|
||||
|
||||
// Minimum disk space required - used in CheckDiskSpace()
|
||||
static const uint64_t nMinDiskSpace = 52428800;
|
||||
|
||||
|
||||
class CCoinsDB;
|
||||
class CBlockTreeDB;
|
||||
struct CDiskBlockPos;
|
||||
class CTxUndo;
|
||||
@@ -114,6 +109,9 @@ struct CNodeStateStats;
|
||||
|
||||
struct CBlockTemplate;
|
||||
|
||||
/** Initialize respend bloom filter **/
|
||||
void InitRespendFilter();
|
||||
|
||||
/** Register a wallet to receive updates from core */
|
||||
void RegisterWallet(CWalletInterface* pwalletIn);
|
||||
/** Unregister a wallet from core */
|
||||
@@ -121,7 +119,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn);
|
||||
/** Unregister all wallets from core */
|
||||
void UnregisterAllWallets();
|
||||
/** Push an updated transaction to all registered wallets */
|
||||
void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL);
|
||||
void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL);
|
||||
|
||||
/** Register with a network node to receive its signals */
|
||||
void RegisterNodeSignals(CNodeSignals& nodeSignals);
|
||||
@@ -146,8 +144,6 @@ bool InitBlockIndex();
|
||||
bool LoadBlockIndex();
|
||||
/** Unload database information */
|
||||
void UnloadBlockIndex();
|
||||
/** Verify consistency of the block and coin databases */
|
||||
bool VerifyDB(int nCheckLevel, int nCheckDepth);
|
||||
/** Print the loaded block tree */
|
||||
void PrintBlockTree();
|
||||
/** Process protocol messages received from a given node */
|
||||
@@ -156,12 +152,6 @@ bool ProcessMessages(CNode* pfrom);
|
||||
bool SendMessages(CNode* pto, bool fSendTrickle);
|
||||
/** Run an instance of the script checking thread */
|
||||
void ThreadScriptCheck();
|
||||
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
||||
/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */
|
||||
unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime);
|
||||
/** Get the number of active peers */
|
||||
int GetNumBlocksOfPeers();
|
||||
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
|
||||
bool IsInitialBlockDownload();
|
||||
/** Format a string that describes several potential problems detected by the core */
|
||||
@@ -171,7 +161,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, b
|
||||
/** Find the best known block, and make it the tip of the block chain */
|
||||
bool ActivateBestChain(CValidationState &state);
|
||||
int64_t GetBlockValue(int nHeight, int64_t nFees);
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock);
|
||||
|
||||
void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev);
|
||||
|
||||
@@ -200,6 +189,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||
|
||||
struct CNodeStateStats {
|
||||
int nMisbehavior;
|
||||
int nSyncHeight;
|
||||
};
|
||||
|
||||
struct CDiskBlockPos
|
||||
@@ -256,14 +246,7 @@ struct CDiskTxPos : public CDiskBlockPos
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum GetMinFee_mode
|
||||
{
|
||||
GMF_RELAY,
|
||||
GMF_SEND,
|
||||
};
|
||||
|
||||
int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode);
|
||||
int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
|
||||
|
||||
//
|
||||
// Check transaction inputs, and make sure any
|
||||
@@ -298,22 +281,15 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
|
||||
unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& mapInputs);
|
||||
|
||||
|
||||
inline bool AllowFree(double dPriority)
|
||||
{
|
||||
// Large (in bytes) low-priority (new, small-coin) transactions
|
||||
// need a fee.
|
||||
return dPriority > COIN * 144 / 250;
|
||||
}
|
||||
|
||||
// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
|
||||
// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
|
||||
// instead of being performed inline.
|
||||
bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &view, bool fScriptChecks = true,
|
||||
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC,
|
||||
unsigned int flags = STANDARD_SCRIPT_VERIFY_FLAGS,
|
||||
std::vector<CScriptCheck> *pvChecks = NULL);
|
||||
|
||||
// Apply the effects of this transaction on the UTXO set represented by view
|
||||
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash);
|
||||
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight);
|
||||
|
||||
// Context-independent validity checks
|
||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
||||
@@ -477,7 +453,7 @@ public:
|
||||
int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
|
||||
bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
|
||||
int GetBlocksToMaturity() const;
|
||||
bool AcceptToMemoryPool(bool fLimitFree=true);
|
||||
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true);
|
||||
};
|
||||
|
||||
|
||||
@@ -603,11 +579,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
|
||||
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos);
|
||||
|
||||
// Context-independent validity checks
|
||||
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
|
||||
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
|
||||
// Store block on disk
|
||||
// if dbp is provided, the file is known to already reside on disk
|
||||
bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp = NULL);
|
||||
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL);
|
||||
bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);
|
||||
|
||||
|
||||
|
||||
@@ -696,6 +674,9 @@ public:
|
||||
// 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;
|
||||
|
||||
@@ -731,10 +712,11 @@ public:
|
||||
// (memory only) Sequencial id assigned to distinguish order in which blocks are received.
|
||||
uint32_t nSequenceId;
|
||||
|
||||
CBlockIndex()
|
||||
void SetNull()
|
||||
{
|
||||
phashBlock = NULL;
|
||||
pprev = NULL;
|
||||
pskip = NULL;
|
||||
nHeight = 0;
|
||||
nFile = 0;
|
||||
nDataPos = 0;
|
||||
@@ -752,19 +734,14 @@ public:
|
||||
nNonce = 0;
|
||||
}
|
||||
|
||||
CBlockIndex()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
CBlockIndex(CBlockHeader& block)
|
||||
{
|
||||
phashBlock = NULL;
|
||||
pprev = NULL;
|
||||
nHeight = 0;
|
||||
nFile = 0;
|
||||
nDataPos = 0;
|
||||
nUndoPos = 0;
|
||||
nChainWork = 0;
|
||||
nTx = 0;
|
||||
nChainTx = 0;
|
||||
nStatus = 0;
|
||||
nSequenceId = 0;
|
||||
SetNull();
|
||||
|
||||
nVersion = block.nVersion;
|
||||
hashMerkleRoot = block.hashMerkleRoot;
|
||||
@@ -814,18 +791,19 @@ public:
|
||||
return (int64_t)nTime;
|
||||
}
|
||||
|
||||
CBigNum GetBlockWork() const
|
||||
uint256 GetBlockWork() const
|
||||
{
|
||||
CBigNum bnTarget;
|
||||
bnTarget.SetCompact(nBits);
|
||||
if (bnTarget <= 0)
|
||||
uint256 bnTarget;
|
||||
bool fNegative;
|
||||
bool fOverflow;
|
||||
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
|
||||
if (fNegative || fOverflow || bnTarget == 0)
|
||||
return 0;
|
||||
return (CBigNum(1)<<256) / (bnTarget+1);
|
||||
}
|
||||
|
||||
bool CheckIndex() const
|
||||
{
|
||||
return CheckProofOfWork(GetBlockHash(), nBits);
|
||||
// We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
|
||||
// as it's too large for a uint256. However, as 2**256 is at least as large
|
||||
// as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
|
||||
// or ~bnTarget / (nTarget+1) + 1.
|
||||
return (~bnTarget / (bnTarget + 1)) + 1;
|
||||
}
|
||||
|
||||
enum { nMedianTimeSpan=11 };
|
||||
@@ -844,31 +822,58 @@ public:
|
||||
return pbegin[(pend - pbegin)/2];
|
||||
}
|
||||
|
||||
int64_t GetMedianTime() const;
|
||||
|
||||
/**
|
||||
* Returns true if there are nRequired or more blocks of minVersion or above
|
||||
* in the last nToCheck blocks, starting at pstart and going backwards.
|
||||
* in the last Params().ToCheckBlockUpgradeMajority() blocks, starting at pstart
|
||||
* and going backwards.
|
||||
*/
|
||||
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart,
|
||||
unsigned int nRequired, unsigned int nToCheck);
|
||||
unsigned int nRequired);
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||
pprev, nHeight,
|
||||
hashMerkleRoot.ToString().c_str(),
|
||||
GetBlockHash().ToString().c_str());
|
||||
hashMerkleRoot.ToString(),
|
||||
GetBlockHash().ToString());
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
LogPrintf("%s\n", ToString().c_str());
|
||||
LogPrintf("%s\n", 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
|
||||
{
|
||||
@@ -925,14 +930,14 @@ public:
|
||||
std::string str = "CDiskBlockIndex(";
|
||||
str += CBlockIndex::ToString();
|
||||
str += strprintf("\n hashBlock=%s, hashPrev=%s)",
|
||||
GetBlockHash().ToString().c_str(),
|
||||
hashPrev.ToString().c_str());
|
||||
GetBlockHash().ToString(),
|
||||
hashPrev.ToString());
|
||||
return str;
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
LogPrintf("%s\n", ToString().c_str());
|
||||
LogPrintf("%s\n", ToString());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -999,6 +1004,14 @@ public:
|
||||
std::string GetRejectReason() const { return strRejectReason; }
|
||||
};
|
||||
|
||||
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */
|
||||
class CVerifyDB {
|
||||
public:
|
||||
CVerifyDB();
|
||||
~CVerifyDB();
|
||||
bool VerifyDB(int nCheckLevel, int nCheckDepth);
|
||||
};
|
||||
|
||||
/** An in-memory indexed chain of blocks. */
|
||||
class CChain {
|
||||
private:
|
||||
@@ -1054,14 +1067,14 @@ public:
|
||||
|
||||
/** Find the last common block between this chain and a locator. */
|
||||
CBlockIndex *FindFork(const CBlockLocator &locator) const;
|
||||
|
||||
/** Find the last common block between this chain and a block index entry. */
|
||||
CBlockIndex *FindFork(CBlockIndex *pindex) const;
|
||||
};
|
||||
|
||||
/** The currently-connected chain of blocks. */
|
||||
extern CChain chainActive;
|
||||
|
||||
/** The currently best known chain of headers (some of which may be invalid). */
|
||||
extern CChain chainMostWork;
|
||||
|
||||
/** Global variable that points to the active CCoinsView (protected by cs_main) */
|
||||
extern CCoinsViewCache *pcoinsTip;
|
||||
|
||||
@@ -1110,7 +1123,7 @@ public:
|
||||
|
||||
class CWalletInterface {
|
||||
protected:
|
||||
virtual void SyncTransaction(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) =0;
|
||||
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) =0;
|
||||
virtual void EraseFromWallet(const uint256 &hash) =0;
|
||||
virtual void SetBestChain(const CBlockLocator &locator) =0;
|
||||
virtual void UpdatedTransaction(const uint256 &hash) =0;
|
||||
|
||||
460
src/miner.cpp
460
src/miner.cpp
@@ -3,90 +3,67 @@
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "miner.h"
|
||||
|
||||
#include "core.h"
|
||||
#include "hash.h"
|
||||
#include "main.h"
|
||||
#include "net.h"
|
||||
#include "pow.h"
|
||||
#ifdef ENABLE_WALLET
|
||||
#include "wallet.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BitcoinMiner
|
||||
//
|
||||
|
||||
int static FormatHashBlocks(void* pbuffer, unsigned int len)
|
||||
{
|
||||
unsigned char* pdata = (unsigned char*)pbuffer;
|
||||
unsigned int blocks = 1 + ((len + 8) / 64);
|
||||
unsigned char* pend = pdata + 64 * blocks;
|
||||
memset(pdata + len, 0, 64 * blocks - len);
|
||||
pdata[len] = 0x80;
|
||||
unsigned int bits = len * 8;
|
||||
pend[-1] = (bits >> 0) & 0xff;
|
||||
pend[-2] = (bits >> 8) & 0xff;
|
||||
pend[-3] = (bits >> 16) & 0xff;
|
||||
pend[-4] = (bits >> 24) & 0xff;
|
||||
return blocks;
|
||||
}
|
||||
|
||||
static const unsigned int pSHA256InitState[8] =
|
||||
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
||||
|
||||
void SHA256Transform(void* pstate, void* pinput, const void* pinit)
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
unsigned char data[64];
|
||||
|
||||
SHA256_Init(&ctx);
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
ctx.h[i] = ((uint32_t*)pinit)[i];
|
||||
|
||||
SHA256_Update(&ctx, data, sizeof(data));
|
||||
for (int i = 0; i < 8; i++)
|
||||
((uint32_t*)pstate)[i] = ctx.h[i];
|
||||
}
|
||||
|
||||
// Some explaining would be appreciated
|
||||
//
|
||||
// Unconfirmed transactions in the memory pool often depend on other
|
||||
// transactions in the memory pool. When we select transactions from the
|
||||
// pool, we select by highest priority or fee rate, so we might consider
|
||||
// transactions that depend on transactions that aren't yet in the block.
|
||||
// The COrphan class keeps track of these 'temporary orphans' while
|
||||
// CreateBlock is figuring out which transactions to include.
|
||||
//
|
||||
class COrphan
|
||||
{
|
||||
public:
|
||||
const CTransaction* ptx;
|
||||
set<uint256> setDependsOn;
|
||||
CFeeRate feeRate;
|
||||
double dPriority;
|
||||
double dFeePerKb;
|
||||
|
||||
COrphan(const CTransaction* ptxIn)
|
||||
COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
|
||||
{
|
||||
ptx = ptxIn;
|
||||
dPriority = dFeePerKb = 0;
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
LogPrintf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
|
||||
ptx->GetHash().ToString(), dPriority, dFeePerKb);
|
||||
LogPrintf("COrphan(hash=%s, dPriority=%.1f, fee=%s)\n",
|
||||
ptx->GetHash().ToString(), dPriority, feeRate.ToString());
|
||||
BOOST_FOREACH(uint256 hash, setDependsOn)
|
||||
LogPrintf(" setDependsOn %s\n", hash.ToString());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
uint64_t nLastBlockTx = 0;
|
||||
uint64_t nLastBlockSize = 0;
|
||||
|
||||
// We want to sort transactions by priority and fee, so:
|
||||
typedef boost::tuple<double, double, const CTransaction*> TxPriority;
|
||||
// We want to sort transactions by priority and fee rate, so:
|
||||
typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
|
||||
class TxPriorityCompare
|
||||
{
|
||||
bool byFee;
|
||||
|
||||
public:
|
||||
TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
|
||||
|
||||
bool operator()(const TxPriority& a, const TxPriority& b)
|
||||
{
|
||||
if (byFee)
|
||||
@@ -113,14 +90,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||
|
||||
// Create coinbase tx
|
||||
CTransaction txNew;
|
||||
CMutableTransaction txNew;
|
||||
txNew.vin.resize(1);
|
||||
txNew.vin[0].prevout.SetNull();
|
||||
txNew.vout.resize(1);
|
||||
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
|
||||
|
||||
// Add our coinbase tx as first transaction
|
||||
pblock->vtx.push_back(txNew);
|
||||
// Add dummy coinbase tx as first transaction
|
||||
pblock->vtx.push_back(CTransaction());
|
||||
pblocktemplate->vTxFees.push_back(-1); // updated at end
|
||||
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
|
||||
|
||||
@@ -141,6 +118,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
|
||||
// Collect memory pool transactions into the block
|
||||
int64_t nFees = 0;
|
||||
|
||||
{
|
||||
LOCK2(cs_main, mempool.cs);
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
@@ -210,18 +188,18 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
||||
dPriority = tx.ComputePriority(dPriority, nTxSize);
|
||||
|
||||
// This is a more accurate fee-per-kilobyte than is used by the client code, because the
|
||||
// client code rounds up the size to the nearest 1K. That's good, because it gives an
|
||||
// incentive to create smaller transactions.
|
||||
double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0);
|
||||
uint256 hash = tx.GetHash();
|
||||
mempool.ApplyDeltas(hash, dPriority, nTotalIn);
|
||||
|
||||
CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
|
||||
|
||||
if (porphan)
|
||||
{
|
||||
porphan->dPriority = dPriority;
|
||||
porphan->dFeePerKb = dFeePerKb;
|
||||
porphan->feeRate = feeRate;
|
||||
}
|
||||
else
|
||||
vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &mi->second.GetTx()));
|
||||
vecPriority.push_back(TxPriority(dPriority, feeRate, &mi->second.GetTx()));
|
||||
}
|
||||
|
||||
// Collect transactions into block
|
||||
@@ -237,7 +215,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
{
|
||||
// Take highest priority transaction off the priority queue:
|
||||
double dPriority = vecPriority.front().get<0>();
|
||||
double dFeePerKb = vecPriority.front().get<1>();
|
||||
CFeeRate feeRate = vecPriority.front().get<1>();
|
||||
const CTransaction& tx = *(vecPriority.front().get<2>());
|
||||
|
||||
std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
|
||||
@@ -254,10 +232,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
continue;
|
||||
|
||||
// Skip free transactions if we're past the minimum block size:
|
||||
if (fSortedByFee && (dFeePerKb < CTransaction::nMinRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
|
||||
const uint256& hash = tx.GetHash();
|
||||
double dPriorityDelta = 0;
|
||||
int64_t nFeeDelta = 0;
|
||||
mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
|
||||
if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
|
||||
continue;
|
||||
|
||||
// Prioritize by fee once past the priority size or we run out of high-priority
|
||||
// Prioritise by fee once past the priority size or we run out of high-priority
|
||||
// transactions:
|
||||
if (!fSortedByFee &&
|
||||
((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
|
||||
@@ -276,13 +258,15 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
|
||||
continue;
|
||||
|
||||
// Note that flags: we don't want to set mempool/IsStandard()
|
||||
// policy here, but we still have to ensure that the block we
|
||||
// create only contains transactions that are valid in new blocks.
|
||||
CValidationState state;
|
||||
if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH))
|
||||
if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS))
|
||||
continue;
|
||||
|
||||
CTxUndo txundo;
|
||||
uint256 hash = tx.GetHash();
|
||||
UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
|
||||
UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1);
|
||||
|
||||
// Added
|
||||
pblock->vtx.push_back(tx);
|
||||
@@ -295,8 +279,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
|
||||
if (fPrintPriority)
|
||||
{
|
||||
LogPrintf("priority %.1f feeperkb %.1f txid %s\n",
|
||||
dPriority, dFeePerKb, tx.GetHash().ToString());
|
||||
LogPrintf("priority %.1f fee %s txid %s\n",
|
||||
dPriority, feeRate.ToString(), tx.GetHash().ToString());
|
||||
}
|
||||
|
||||
// Add transactions that depend on this one to the priority queue
|
||||
@@ -309,7 +293,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
porphan->setDependsOn.erase(hash);
|
||||
if (porphan->setDependsOn.empty())
|
||||
{
|
||||
vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx));
|
||||
vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
|
||||
std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
|
||||
}
|
||||
}
|
||||
@@ -321,7 +305,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
nLastBlockSize = nBlockSize;
|
||||
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
|
||||
|
||||
pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
|
||||
// Compute final coinbase transaction.
|
||||
txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
|
||||
txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0;
|
||||
pblock->vtx[0] = txNew;
|
||||
pblocktemplate->vTxFees[0] = -nFees;
|
||||
|
||||
// Fill in header
|
||||
@@ -329,7 +316,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
UpdateTime(*pblock, pindexPrev);
|
||||
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
|
||||
pblock->nNonce = 0;
|
||||
pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
|
||||
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
|
||||
|
||||
CBlockIndex indexDummy(*pblock);
|
||||
@@ -355,58 +341,14 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
|
||||
}
|
||||
++nExtraNonce;
|
||||
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
|
||||
pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS;
|
||||
assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
|
||||
CMutableTransaction txCoinbase(pblock->vtx[0]);
|
||||
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
|
||||
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
|
||||
|
||||
pblock->vtx[0] = txCoinbase;
|
||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||
}
|
||||
|
||||
|
||||
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
|
||||
{
|
||||
//
|
||||
// Pre-build hash buffers
|
||||
//
|
||||
struct
|
||||
{
|
||||
struct unnamed2
|
||||
{
|
||||
int nVersion;
|
||||
uint256 hashPrevBlock;
|
||||
uint256 hashMerkleRoot;
|
||||
unsigned int nTime;
|
||||
unsigned int nBits;
|
||||
unsigned int nNonce;
|
||||
}
|
||||
block;
|
||||
unsigned char pchPadding0[64];
|
||||
uint256 hash1;
|
||||
unsigned char pchPadding1[64];
|
||||
}
|
||||
tmp;
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
tmp.block.nVersion = pblock->nVersion;
|
||||
tmp.block.hashPrevBlock = pblock->hashPrevBlock;
|
||||
tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
|
||||
tmp.block.nTime = pblock->nTime;
|
||||
tmp.block.nBits = pblock->nBits;
|
||||
tmp.block.nNonce = pblock->nNonce;
|
||||
|
||||
FormatHashBlocks(&tmp.block, sizeof(tmp.block));
|
||||
FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
|
||||
|
||||
// Byte swap all the input buffer
|
||||
for (unsigned int i = 0; i < sizeof(tmp)/4; i++)
|
||||
((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
|
||||
|
||||
// Precalc the first half of the first hash, which stays constant
|
||||
SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);
|
||||
|
||||
memcpy(pdata, &tmp.block, 128);
|
||||
memcpy(phash1, &tmp.hash1, 64);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -417,34 +359,34 @@ int64_t nHPSTimerStart = 0;
|
||||
|
||||
//
|
||||
// ScanHash scans nonces looking for a hash with at least some zero bits.
|
||||
// It operates on big endian data. Caller does the byte reversing.
|
||||
// All input buffers are 16-byte aligned. nNonce is usually preserved
|
||||
// between calls, but periodically or if nNonce is 0xffff0000 or above,
|
||||
// the block is rebuilt and nNonce starts over at zero.
|
||||
// The nonce is usually preserved between calls, but periodically or if the
|
||||
// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
|
||||
// zero.
|
||||
//
|
||||
unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
|
||||
bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
|
||||
{
|
||||
unsigned int& nNonce = *(unsigned int*)(pdata + 12);
|
||||
for (;;)
|
||||
{
|
||||
// Crypto++ SHA256
|
||||
// Hash pdata using pmidstate as the starting state into
|
||||
// pre-formatted buffer phash1, then hash phash1 into phash
|
||||
// Write the first 76 bytes of the block header to a double-SHA256 state.
|
||||
CHash256 hasher;
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << *pblock;
|
||||
assert(ss.size() == 80);
|
||||
hasher.Write((unsigned char*)&ss[0], 76);
|
||||
|
||||
while (true) {
|
||||
nNonce++;
|
||||
SHA256Transform(phash1, pdata, pmidstate);
|
||||
SHA256Transform(phash, phash1, pSHA256InitState);
|
||||
|
||||
// Write the last 4 bytes of the block header (the nonce) to a copy of
|
||||
// the double-SHA256 state, and compute the result.
|
||||
CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash);
|
||||
|
||||
// Return the nonce if the hash has at least some zero bits,
|
||||
// caller will check if it has enough to reach the target
|
||||
if (((unsigned short*)phash)[14] == 0)
|
||||
return nNonce;
|
||||
if (((uint16_t*)phash)[15] == 0)
|
||||
return true;
|
||||
|
||||
// If nothing found after trying for a while, return -1
|
||||
if ((nNonce & 0xffff) == 0)
|
||||
{
|
||||
nHashesDone = 0xffff+1;
|
||||
return (unsigned int) -1;
|
||||
}
|
||||
return false;
|
||||
if ((nNonce & 0xfff) == 0)
|
||||
boost::this_thread::interruption_point();
|
||||
}
|
||||
@@ -463,7 +405,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
|
||||
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
|
||||
{
|
||||
uint256 hash = pblock->GetHash();
|
||||
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
|
||||
uint256 hashTarget = uint256().SetCompact(pblock->nBits);
|
||||
|
||||
if (hash > hashTarget)
|
||||
return false;
|
||||
@@ -479,22 +421,22 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
|
||||
LOCK(cs_main);
|
||||
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
|
||||
return error("BitcoinMiner : generated block is stale");
|
||||
|
||||
// Remove key from key pool
|
||||
reservekey.KeepKey();
|
||||
|
||||
// Track how many getdata requests this block gets
|
||||
{
|
||||
LOCK(wallet.cs_wallet);
|
||||
wallet.mapRequestCount[pblock->GetHash()] = 0;
|
||||
}
|
||||
|
||||
// Process this block the same as if we had received it from another node
|
||||
CValidationState state;
|
||||
if (!ProcessBlock(state, NULL, pblock))
|
||||
return error("BitcoinMiner : ProcessBlock, block not accepted");
|
||||
}
|
||||
|
||||
// Remove key from key pool
|
||||
reservekey.KeepKey();
|
||||
|
||||
// Track how many getdata requests this block gets
|
||||
{
|
||||
LOCK(wallet.cs_wallet);
|
||||
wallet.mapRequestCount[pblock->GetHash()] = 0;
|
||||
}
|
||||
|
||||
// Process this block the same as if we had received it from another node
|
||||
CValidationState state;
|
||||
if (!ProcessBlock(state, NULL, pblock))
|
||||
return error("BitcoinMiner : ProcessBlock, block not accepted");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -508,135 +450,115 @@ void static BitcoinMiner(CWallet *pwallet)
|
||||
CReserveKey reservekey(pwallet);
|
||||
unsigned int nExtraNonce = 0;
|
||||
|
||||
try { while (true) {
|
||||
if (Params().NetworkID() != CChainParams::REGTEST) {
|
||||
// Busy-wait for the network to come online so we don't waste time mining
|
||||
// on an obsolete chain. In regtest mode we expect to fly solo.
|
||||
while (vNodes.empty())
|
||||
MilliSleep(1000);
|
||||
}
|
||||
|
||||
//
|
||||
// Create new block
|
||||
//
|
||||
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
|
||||
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
|
||||
if (!pblocktemplate.get())
|
||||
return;
|
||||
CBlock *pblock = &pblocktemplate->block;
|
||||
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
|
||||
|
||||
LogPrintf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
|
||||
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
|
||||
|
||||
//
|
||||
// Pre-build hash buffers
|
||||
//
|
||||
char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf);
|
||||
char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf);
|
||||
char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf);
|
||||
|
||||
FormatHashBuffers(pblock, pmidstate, pdata, phash1);
|
||||
|
||||
unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4);
|
||||
unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8);
|
||||
unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
int64_t nStart = GetTime();
|
||||
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
|
||||
uint256 hashbuf[2];
|
||||
uint256& hash = *alignup<16>(hashbuf);
|
||||
while (true)
|
||||
{
|
||||
unsigned int nHashesDone = 0;
|
||||
unsigned int nNonceFound;
|
||||
|
||||
// Crypto++ SHA256
|
||||
nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1,
|
||||
(char*)&hash, nHashesDone);
|
||||
|
||||
// Check if something found
|
||||
if (nNonceFound != (unsigned int) -1)
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof(hash)/4; i++)
|
||||
((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]);
|
||||
|
||||
if (hash <= hashTarget)
|
||||
{
|
||||
// Found a solution
|
||||
pblock->nNonce = ByteReverse(nNonceFound);
|
||||
assert(hash == pblock->GetHash());
|
||||
|
||||
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
||||
CheckWork(pblock, *pwallet, reservekey);
|
||||
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
||||
|
||||
// In regression test mode, stop mining after a block is found. This
|
||||
// allows developers to controllably generate a block on demand.
|
||||
if (Params().NetworkID() == CChainParams::REGTEST)
|
||||
throw boost::thread_interrupted();
|
||||
|
||||
break;
|
||||
}
|
||||
try {
|
||||
while (true) {
|
||||
if (Params().MiningRequiresPeers()) {
|
||||
// Busy-wait for the network to come online so we don't waste time mining
|
||||
// on an obsolete chain. In regtest mode we expect to fly solo.
|
||||
while (vNodes.empty())
|
||||
MilliSleep(1000);
|
||||
}
|
||||
|
||||
// Meter hashes/sec
|
||||
static int64_t nHashCounter;
|
||||
if (nHPSTimerStart == 0)
|
||||
{
|
||||
nHPSTimerStart = GetTimeMillis();
|
||||
nHashCounter = 0;
|
||||
}
|
||||
else
|
||||
nHashCounter += nHashesDone;
|
||||
if (GetTimeMillis() - nHPSTimerStart > 4000)
|
||||
{
|
||||
static CCriticalSection cs;
|
||||
//
|
||||
// Create new block
|
||||
//
|
||||
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
|
||||
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
|
||||
if (!pblocktemplate.get())
|
||||
return;
|
||||
CBlock *pblock = &pblocktemplate->block;
|
||||
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
|
||||
|
||||
LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
|
||||
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
int64_t nStart = GetTime();
|
||||
uint256 hashTarget = uint256().SetCompact(pblock->nBits);
|
||||
uint256 hash;
|
||||
uint32_t nNonce = 0;
|
||||
uint32_t nOldNonce = 0;
|
||||
while (true) {
|
||||
bool fFound = ScanHash(pblock, nNonce, &hash);
|
||||
uint32_t nHashesDone = nNonce - nOldNonce;
|
||||
nOldNonce = nNonce;
|
||||
|
||||
// Check if something found
|
||||
if (fFound)
|
||||
{
|
||||
LOCK(cs);
|
||||
if (GetTimeMillis() - nHPSTimerStart > 4000)
|
||||
if (hash <= hashTarget)
|
||||
{
|
||||
dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
|
||||
nHPSTimerStart = GetTimeMillis();
|
||||
nHashCounter = 0;
|
||||
static int64_t nLogTime;
|
||||
if (GetTime() - nLogTime > 30 * 60)
|
||||
// Found a solution
|
||||
pblock->nNonce = nNonce;
|
||||
assert(hash == pblock->GetHash());
|
||||
|
||||
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
||||
CheckWork(pblock, *pwallet, reservekey);
|
||||
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
||||
|
||||
// In regression test mode, stop mining after a block is found.
|
||||
if (Params().MineBlocksOnDemand())
|
||||
throw boost::thread_interrupted();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Meter hashes/sec
|
||||
static int64_t nHashCounter;
|
||||
if (nHPSTimerStart == 0)
|
||||
{
|
||||
nHPSTimerStart = GetTimeMillis();
|
||||
nHashCounter = 0;
|
||||
}
|
||||
else
|
||||
nHashCounter += nHashesDone;
|
||||
if (GetTimeMillis() - nHPSTimerStart > 4000)
|
||||
{
|
||||
static CCriticalSection cs;
|
||||
{
|
||||
LOCK(cs);
|
||||
if (GetTimeMillis() - nHPSTimerStart > 4000)
|
||||
{
|
||||
nLogTime = GetTime();
|
||||
LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
|
||||
dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
|
||||
nHPSTimerStart = GetTimeMillis();
|
||||
nHashCounter = 0;
|
||||
static int64_t nLogTime;
|
||||
if (GetTime() - nLogTime > 30 * 60)
|
||||
{
|
||||
nLogTime = GetTime();
|
||||
LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for stop or if block needs to be rebuilt
|
||||
boost::this_thread::interruption_point();
|
||||
if (vNodes.empty() && Params().NetworkID() != CChainParams::REGTEST)
|
||||
break;
|
||||
if (nBlockNonce >= 0xffff0000)
|
||||
break;
|
||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
||||
break;
|
||||
if (pindexPrev != chainActive.Tip())
|
||||
break;
|
||||
// Check for stop or if block needs to be rebuilt
|
||||
boost::this_thread::interruption_point();
|
||||
// Regtest mode doesn't require peers
|
||||
if (vNodes.empty() && Params().MiningRequiresPeers())
|
||||
break;
|
||||
if (nNonce >= 0xffff0000)
|
||||
break;
|
||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
||||
break;
|
||||
if (pindexPrev != chainActive.Tip())
|
||||
break;
|
||||
|
||||
// Update nTime every few seconds
|
||||
UpdateTime(*pblock, pindexPrev);
|
||||
nBlockTime = ByteReverse(pblock->nTime);
|
||||
if (TestNet())
|
||||
{
|
||||
// Changing pblock->nTime can change work required on testnet:
|
||||
nBlockBits = ByteReverse(pblock->nBits);
|
||||
hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
|
||||
// Update nTime every few seconds
|
||||
UpdateTime(*pblock, pindexPrev);
|
||||
if (Params().AllowMinDifficultyBlocks())
|
||||
{
|
||||
// Changing pblock->nTime can change work required on testnet:
|
||||
hashTarget.SetCompact(pblock->nBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
catch (boost::thread_interrupted)
|
||||
{
|
||||
LogPrintf("BitcoinMiner terminated\n");
|
||||
@@ -649,8 +571,9 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
|
||||
static boost::thread_group* minerThreads = NULL;
|
||||
|
||||
if (nThreads < 0) {
|
||||
if (Params().NetworkID() == CChainParams::REGTEST)
|
||||
nThreads = 1;
|
||||
// In regtest threads defaults to 1
|
||||
if (Params().DefaultMinerThreads())
|
||||
nThreads = Params().DefaultMinerThreads();
|
||||
else
|
||||
nThreads = boost::thread::hardware_concurrency();
|
||||
}
|
||||
@@ -670,5 +593,4 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
|
||||
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
@@ -10,11 +10,12 @@
|
||||
|
||||
class CBlock;
|
||||
class CBlockIndex;
|
||||
struct CBlockTemplate;
|
||||
class CReserveKey;
|
||||
class CScript;
|
||||
class CWallet;
|
||||
|
||||
struct CBlockTemplate;
|
||||
|
||||
/** Run the miner threads */
|
||||
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads);
|
||||
/** Generate a new block, without valid proof-of-work */
|
||||
@@ -22,12 +23,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
|
||||
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
|
||||
/** Modify the extranonce in a block */
|
||||
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
|
||||
/** Do mining precalculation */
|
||||
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
|
||||
/** Check mined block */
|
||||
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
|
||||
/** Base sha256 mining transform */
|
||||
void SHA256Transform(void* pstate, void* pinput, const void* pinit);
|
||||
|
||||
extern double dHashesPerSec;
|
||||
extern int64_t nHPSTimerStart;
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
bool empty() const { return set.empty(); }
|
||||
iterator find(const key_type& k) const { return set.find(k); }
|
||||
size_type count(const key_type& k) const { return set.count(k); }
|
||||
void clear() { set.clear(); queue.clear(); }
|
||||
bool inline friend operator==(const mruset<T>& a, const mruset<T>& b) { return a.set == b.set; }
|
||||
bool inline friend operator==(const mruset<T>& a, const std::set<T>& b) { return a.set == b; }
|
||||
bool inline friend operator<(const mruset<T>& a, const mruset<T>& b) { return a.set < b.set; }
|
||||
|
||||
229
src/net.cpp
229
src/net.cpp
@@ -4,7 +4,7 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "net.h"
|
||||
@@ -36,18 +36,27 @@
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
|
||||
// Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
|
||||
#ifdef WIN32
|
||||
#ifndef PROTECTION_LEVEL_UNRESTRICTED
|
||||
#define PROTECTION_LEVEL_UNRESTRICTED 10
|
||||
#endif
|
||||
#ifndef IPV6_PROTECTION_LEVEL
|
||||
#define IPV6_PROTECTION_LEVEL 23
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
static const int MAX_OUTBOUND_CONNECTIONS = 8;
|
||||
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
|
||||
|
||||
|
||||
//
|
||||
// Global state variables
|
||||
//
|
||||
bool fDiscover = true;
|
||||
bool fListen = true;
|
||||
uint64_t nLocalServices = NODE_NETWORK;
|
||||
CCriticalSection cs_mapLocalHost;
|
||||
map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
||||
@@ -99,7 +108,7 @@ unsigned short GetListenPort()
|
||||
// find 'best' local address for a particular peer
|
||||
bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
|
||||
{
|
||||
if (fNoListen)
|
||||
if (!fListen)
|
||||
return false;
|
||||
|
||||
int nBestScore = -1;
|
||||
@@ -178,7 +187,7 @@ bool RecvLine(SOCKET hSocket, string& strLine)
|
||||
{
|
||||
// socket error
|
||||
int nErr = WSAGetLastError();
|
||||
LogPrint("net", "recv failed: %d\n", nErr);
|
||||
LogPrint("net", "recv failed: %s\n", NetworkErrorString(nErr));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -471,11 +480,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// debug print
|
||||
LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
|
||||
pszDest ? pszDest : addrConnect.ToString(),
|
||||
pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
|
||||
pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
|
||||
|
||||
// Connect
|
||||
SOCKET hSocket;
|
||||
@@ -483,16 +491,14 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
||||
{
|
||||
addrman.Attempt(addrConnect);
|
||||
|
||||
LogPrint("net", "connected %s\n", pszDest ? pszDest : addrConnect.ToString());
|
||||
|
||||
// Set to non-blocking
|
||||
#ifdef WIN32
|
||||
u_long nOne = 1;
|
||||
if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
|
||||
LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
|
||||
LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %s\n", NetworkErrorString(WSAGetLastError()));
|
||||
#else
|
||||
if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
|
||||
LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
|
||||
LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %s\n", NetworkErrorString(errno));
|
||||
#endif
|
||||
|
||||
// Add node
|
||||
@@ -505,12 +511,11 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
|
||||
}
|
||||
|
||||
pnode->nTimeConnected = GetTime();
|
||||
|
||||
return pnode;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CNode::CloseSocketDisconnect()
|
||||
@@ -518,7 +523,7 @@ void CNode::CloseSocketDisconnect()
|
||||
fDisconnect = true;
|
||||
if (hSocket != INVALID_SOCKET)
|
||||
{
|
||||
LogPrint("net", "disconnecting node %s\n", addrName);
|
||||
LogPrint("net", "disconnecting peer=%d\n", id);
|
||||
closesocket(hSocket);
|
||||
hSocket = INVALID_SOCKET;
|
||||
}
|
||||
@@ -533,11 +538,6 @@ void CNode::CloseSocketDisconnect()
|
||||
pnodeSync = NULL;
|
||||
}
|
||||
|
||||
void CNode::Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CNode::PushVersion()
|
||||
{
|
||||
int nBestHeight = g_signals.GetHeight().get_value_or(0);
|
||||
@@ -547,7 +547,10 @@ void CNode::PushVersion()
|
||||
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
|
||||
CAddress addrMe = GetLocalAddress(&addr);
|
||||
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
|
||||
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), addr.ToString());
|
||||
if (fLogIPs)
|
||||
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id);
|
||||
else
|
||||
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id);
|
||||
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
|
||||
nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
|
||||
}
|
||||
@@ -652,6 +655,9 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes)
|
||||
|
||||
pch += handled;
|
||||
nBytes -= handled;
|
||||
|
||||
if (msg.complete())
|
||||
msg.nTime = GetTimeMicros();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -684,7 +690,6 @@ int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
|
||||
|
||||
// switch state to reading message data
|
||||
in_data = true;
|
||||
vRecv.resize(hdr.nMessageSize);
|
||||
|
||||
return nCopy;
|
||||
}
|
||||
@@ -694,6 +699,11 @@ int CNetMessage::readData(const char *pch, unsigned int nBytes)
|
||||
unsigned int nRemaining = hdr.nMessageSize - nDataPos;
|
||||
unsigned int nCopy = std::min(nRemaining, nBytes);
|
||||
|
||||
if (vRecv.size() < nDataPos + nCopy) {
|
||||
// Allocate up to 256 KiB ahead, but never more than the total message size.
|
||||
vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
|
||||
}
|
||||
|
||||
memcpy(&vRecv[nDataPos], pch, nCopy);
|
||||
nDataPos += nCopy;
|
||||
|
||||
@@ -736,7 +746,7 @@ void SocketSendData(CNode *pnode)
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
|
||||
{
|
||||
LogPrintf("socket send error %d\n", nErr);
|
||||
LogPrintf("socket send error %s\n", NetworkErrorString(nErr));
|
||||
pnode->CloseSocketDisconnect();
|
||||
}
|
||||
}
|
||||
@@ -779,7 +789,6 @@ void ThreadSocketHandler()
|
||||
|
||||
// close socket and cleanup
|
||||
pnode->CloseSocketDisconnect();
|
||||
pnode->Cleanup();
|
||||
|
||||
// hold in disconnected pool until all refs are released
|
||||
if (pnode->fNetworkNode || pnode->fInbound)
|
||||
@@ -823,7 +832,6 @@ void ThreadSocketHandler()
|
||||
uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Find which sockets have data to receive
|
||||
//
|
||||
@@ -845,6 +853,7 @@ void ThreadSocketHandler()
|
||||
hSocketMax = max(hSocketMax, hListenSocket);
|
||||
have_fds = true;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
@@ -896,7 +905,7 @@ void ThreadSocketHandler()
|
||||
if (have_fds)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
LogPrintf("socket select error %d\n", nErr);
|
||||
LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
|
||||
for (unsigned int i = 0; i <= hSocketMax; i++)
|
||||
FD_SET(i, &fdsetRecv);
|
||||
}
|
||||
@@ -905,58 +914,58 @@ void ThreadSocketHandler()
|
||||
MilliSleep(timeout.tv_usec/1000);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Accept new connections
|
||||
//
|
||||
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
|
||||
if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
|
||||
{
|
||||
struct sockaddr_storage sockaddr;
|
||||
socklen_t len = sizeof(sockaddr);
|
||||
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
|
||||
CAddress addr;
|
||||
int nInbound = 0;
|
||||
if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
|
||||
{
|
||||
struct sockaddr_storage sockaddr;
|
||||
socklen_t len = sizeof(sockaddr);
|
||||
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
|
||||
CAddress addr;
|
||||
int nInbound = 0;
|
||||
|
||||
if (hSocket != INVALID_SOCKET)
|
||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
|
||||
LogPrintf("Warning: Unknown socket family\n");
|
||||
if (hSocket != INVALID_SOCKET)
|
||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
|
||||
LogPrintf("Warning: Unknown socket family\n");
|
||||
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->fInbound)
|
||||
nInbound++;
|
||||
}
|
||||
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr != WSAEWOULDBLOCK)
|
||||
LogPrintf("socket error accept failed: %d\n", nErr);
|
||||
}
|
||||
else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
}
|
||||
else if (CNode::IsBanned(addr))
|
||||
{
|
||||
LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
|
||||
closesocket(hSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint("net", "accepted connection %s\n", addr.ToString());
|
||||
CNode* pnode = new CNode(hSocket, addr, "", true);
|
||||
pnode->AddRef();
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
vNodes.push_back(pnode);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->fInbound)
|
||||
nInbound++;
|
||||
}
|
||||
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr != WSAEWOULDBLOCK)
|
||||
LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
|
||||
}
|
||||
else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
}
|
||||
else if (CNode::IsBanned(addr))
|
||||
{
|
||||
LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
|
||||
closesocket(hSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
CNode* pnode = new CNode(hSocket, addr, "", true);
|
||||
pnode->AddRef();
|
||||
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
vNodes.push_back(pnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Service each socket
|
||||
//
|
||||
@@ -1007,7 +1016,7 @@ void ThreadSocketHandler()
|
||||
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
|
||||
{
|
||||
if (!pnode->fDisconnect)
|
||||
LogPrintf("socket recv error %d\n", nErr);
|
||||
LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
|
||||
pnode->CloseSocketDisconnect();
|
||||
}
|
||||
}
|
||||
@@ -1030,23 +1039,27 @@ void ThreadSocketHandler()
|
||||
//
|
||||
// Inactivity checking
|
||||
//
|
||||
if (pnode->vSendMsg.empty())
|
||||
pnode->nLastSendEmpty = GetTime();
|
||||
if (GetTime() - pnode->nTimeConnected > 60)
|
||||
int64_t nTime = GetTime();
|
||||
if (nTime - pnode->nTimeConnected > 60)
|
||||
{
|
||||
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
|
||||
{
|
||||
LogPrint("net", "socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
|
||||
LogPrint("net", "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id);
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
|
||||
else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
|
||||
{
|
||||
LogPrintf("socket not sending\n");
|
||||
LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
else if (GetTime() - pnode->nLastRecv > 90*60)
|
||||
else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
|
||||
{
|
||||
LogPrintf("socket inactivity timeout\n");
|
||||
LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
|
||||
{
|
||||
LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
}
|
||||
@@ -1427,21 +1440,21 @@ void ThreadOpenAddedConnections()
|
||||
}
|
||||
|
||||
// if successful, this moves the passed grant to the constructed node
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot)
|
||||
{
|
||||
//
|
||||
// Initiate outbound network connection
|
||||
//
|
||||
boost::this_thread::interruption_point();
|
||||
if (!strDest)
|
||||
if (!pszDest) {
|
||||
if (IsLocal(addrConnect) ||
|
||||
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
|
||||
FindNode(addrConnect.ToStringIPPort().c_str()))
|
||||
return false;
|
||||
if (strDest && FindNode(strDest))
|
||||
} else if (FindNode(pszDest))
|
||||
return false;
|
||||
|
||||
CNode* pnode = ConnectNode(addrConnect, strDest);
|
||||
CNode* pnode = ConnectNode(addrConnect, pszDest);
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
if (!pnode)
|
||||
@@ -1458,13 +1471,13 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
|
||||
|
||||
// for now, use a very simple selection metric: the node from which we received
|
||||
// most recently
|
||||
double static NodeSyncScore(const CNode *pnode) {
|
||||
return -pnode->nLastRecv;
|
||||
static int64_t NodeSyncScore(const CNode *pnode) {
|
||||
return pnode->nLastRecv;
|
||||
}
|
||||
|
||||
void static StartSync(const vector<CNode*> &vNodes) {
|
||||
CNode *pnodeNewSync = NULL;
|
||||
double dBestScore = 0;
|
||||
int64_t nBestScore = 0;
|
||||
|
||||
int nBestHeight = g_signals.GetHeight().get_value_or(0);
|
||||
|
||||
@@ -1476,10 +1489,10 @@ void static StartSync(const vector<CNode*> &vNodes) {
|
||||
(pnode->nStartingHeight > (nBestHeight - 144)) &&
|
||||
(pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
|
||||
// if ok, compare node's score with the best so far
|
||||
double dScore = NodeSyncScore(pnode);
|
||||
if (pnodeNewSync == NULL || dScore > dBestScore) {
|
||||
int64_t nScore = NodeSyncScore(pnode);
|
||||
if (pnodeNewSync == NULL || nScore > nBestScore) {
|
||||
pnodeNewSync = pnode;
|
||||
dBestScore = dScore;
|
||||
nBestScore = nScore;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1577,7 +1590,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
||||
socklen_t len = sizeof(sockaddr);
|
||||
if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
|
||||
{
|
||||
strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString());
|
||||
strError = strprintf("Error: Bind address family for %s not supported", addrBind.ToString());
|
||||
LogPrintf("%s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@@ -1585,23 +1598,21 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
||||
SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (hListenSocket == INVALID_SOCKET)
|
||||
{
|
||||
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
|
||||
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()));
|
||||
LogPrintf("%s\n", strError);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef SO_NOSIGPIPE
|
||||
// Different way of disabling SIGPIPE on BSD
|
||||
setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
// Allow binding if the port is still in TIME_WAIT state after
|
||||
// the program was closed and restarted. Not an issue on windows.
|
||||
// the program was closed and restarted. Not an issue on windows!
|
||||
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
// Set to non-blocking, incoming connections will also inherit this
|
||||
if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
|
||||
@@ -1609,7 +1620,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
||||
if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
|
||||
strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %s)", NetworkErrorString(WSAGetLastError()));
|
||||
LogPrintf("%s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@@ -1625,10 +1636,8 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
|
||||
int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
|
||||
// this call is allowed to fail
|
||||
setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
|
||||
int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
|
||||
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1638,7 +1647,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
||||
if (nErr == WSAEADDRINUSE)
|
||||
strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin Core is probably already running."), addrBind.ToString());
|
||||
else
|
||||
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString(), nErr, strerror(nErr));
|
||||
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
|
||||
LogPrintf("%s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@@ -1647,7 +1656,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
||||
// Listen for incoming connections
|
||||
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
|
||||
{
|
||||
strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %d)"), WSAGetLastError());
|
||||
strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
|
||||
LogPrintf("%s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@@ -1736,10 +1745,8 @@ void StartNode(boost::thread_group& threadGroup)
|
||||
else
|
||||
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "dnsseed", &ThreadDNSAddressSeed));
|
||||
|
||||
#ifdef USE_UPNP
|
||||
// Map ports with UPnP
|
||||
MapPort(GetBoolArg("-upnp", USE_UPNP));
|
||||
#endif
|
||||
MapPort(GetBoolArg("-upnp", DEFAULT_UPNP));
|
||||
|
||||
// Send and receive from sockets, accept connections
|
||||
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "net", &ThreadSocketHandler));
|
||||
@@ -1773,9 +1780,8 @@ bool StopNode()
|
||||
class CNetCleanup
|
||||
{
|
||||
public:
|
||||
CNetCleanup()
|
||||
{
|
||||
}
|
||||
CNetCleanup() {}
|
||||
|
||||
~CNetCleanup()
|
||||
{
|
||||
// Close sockets
|
||||
@@ -1785,7 +1791,7 @@ public:
|
||||
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
|
||||
if (hListenSocket != INVALID_SOCKET)
|
||||
if (closesocket(hListenSocket) == SOCKET_ERROR)
|
||||
LogPrintf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
|
||||
LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
|
||||
|
||||
// clean up some globals (to help leak detection)
|
||||
BOOST_FOREACH(CNode *pnode, vNodes)
|
||||
@@ -1794,6 +1800,7 @@ public:
|
||||
delete pnode;
|
||||
vNodes.clear();
|
||||
vNodesDisconnected.clear();
|
||||
vhListenSocket.clear();
|
||||
delete semOutbound;
|
||||
semOutbound = NULL;
|
||||
delete pnodeLocalHost;
|
||||
@@ -1813,17 +1820,17 @@ instance_of_cnetcleanup;
|
||||
|
||||
|
||||
|
||||
void RelayTransaction(const CTransaction& tx, const uint256& hash)
|
||||
void RelayTransaction(const CTransaction& tx)
|
||||
{
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss.reserve(10000);
|
||||
ss << tx;
|
||||
RelayTransaction(tx, hash, ss);
|
||||
RelayTransaction(tx, ss);
|
||||
}
|
||||
|
||||
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
|
||||
void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
|
||||
{
|
||||
CInv inv(MSG_TX, hash);
|
||||
CInv inv(MSG_TX, tx.GetHash());
|
||||
{
|
||||
LOCK(cs_mapRelay);
|
||||
// Expire old relay messages
|
||||
@@ -1845,7 +1852,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
|
||||
LOCK(pnode->cs_filter);
|
||||
if (pnode->pfilter)
|
||||
{
|
||||
if (pnode->pfilter->IsRelevantAndUpdate(tx, hash))
|
||||
if (pnode->pfilter->IsRelevantAndUpdate(tx))
|
||||
pnode->PushInventory(inv);
|
||||
} else
|
||||
pnode->PushInventory(inv);
|
||||
|
||||
52
src/net.h
52
src/net.h
@@ -34,10 +34,22 @@ class CNode;
|
||||
|
||||
namespace boost {
|
||||
class thread_group;
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
|
||||
static const int PING_INTERVAL = 2 * 60;
|
||||
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
|
||||
static const int TIMEOUT_INTERVAL = 20 * 60;
|
||||
/** The maximum number of entries in an 'inv' protocol message */
|
||||
static const unsigned int MAX_INV_SZ = 50000;
|
||||
/** -listen default */
|
||||
static const bool DEFAULT_LISTEN = true;
|
||||
/** -upnp default */
|
||||
#ifdef USE_UPNP
|
||||
static const bool DEFAULT_UPNP = USE_UPNP;
|
||||
#else
|
||||
static const bool DEFAULT_UPNP = false;
|
||||
#endif
|
||||
|
||||
inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
|
||||
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
|
||||
@@ -48,10 +60,11 @@ bool GetMyExternalIP(CNetAddr& ipRet);
|
||||
void AddressCurrentlyConnected(const CService& addr);
|
||||
CNode* FindNode(const CNetAddr& ip);
|
||||
CNode* FindNode(const CService& ip);
|
||||
CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL);
|
||||
CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL);
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
|
||||
void MapPort(bool fUseUPnP);
|
||||
unsigned short GetListenPort();
|
||||
bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string()));
|
||||
bool BindListenPort(const CService &bindAddr, std::string& strError);
|
||||
void StartNode(boost::thread_group& threadGroup);
|
||||
bool StopNode();
|
||||
void SocketSendData(CNode *pnode);
|
||||
@@ -98,6 +111,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
|
||||
|
||||
|
||||
extern bool fDiscover;
|
||||
extern bool fListen;
|
||||
extern uint64_t nLocalServices;
|
||||
extern uint64_t nLocalHostNonce;
|
||||
extern CAddrMan addrman;
|
||||
@@ -122,7 +136,7 @@ struct LocalServiceInfo {
|
||||
};
|
||||
|
||||
extern CCriticalSection cs_mapLocalHost;
|
||||
extern map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
||||
extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
||||
|
||||
class CNodeStats
|
||||
{
|
||||
@@ -159,11 +173,14 @@ public:
|
||||
CDataStream vRecv; // received message data
|
||||
unsigned int nDataPos;
|
||||
|
||||
int64_t nTime; // time (in microseconds) of message receipt.
|
||||
|
||||
CNetMessage(int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn) {
|
||||
hdrbuf.resize(24);
|
||||
in_data = false;
|
||||
nHdrPos = 0;
|
||||
nDataPos = 0;
|
||||
nTime = 0;
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
@@ -209,7 +226,6 @@ public:
|
||||
|
||||
int64_t nLastSend;
|
||||
int64_t nLastRecv;
|
||||
int64_t nLastSendEmpty;
|
||||
int64_t nTimeConnected;
|
||||
CAddress addr;
|
||||
std::string addrName;
|
||||
@@ -255,7 +271,7 @@ public:
|
||||
|
||||
// flood relay
|
||||
std::vector<CAddress> vAddrToSend;
|
||||
std::set<CAddress> setAddrKnown;
|
||||
mruset<CAddress> setAddrKnown;
|
||||
bool fGetAddr;
|
||||
std::set<uint256> setKnown;
|
||||
|
||||
@@ -265,13 +281,17 @@ public:
|
||||
CCriticalSection cs_inventory;
|
||||
std::multimap<int64_t, CInv> mapAskFor;
|
||||
|
||||
// Ping time measurement
|
||||
// Ping time measurement:
|
||||
// The pong reply we're expecting, or 0 if no pong expected.
|
||||
uint64_t nPingNonceSent;
|
||||
// Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
|
||||
int64_t nPingUsecStart;
|
||||
// Last measured round-trip time.
|
||||
int64_t nPingUsecTime;
|
||||
// Whether a ping is requested.
|
||||
bool fPingQueued;
|
||||
|
||||
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION)
|
||||
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000)
|
||||
{
|
||||
nServices = 0;
|
||||
hSocket = hSocketIn;
|
||||
@@ -280,7 +300,6 @@ public:
|
||||
nLastRecv = 0;
|
||||
nSendBytes = 0;
|
||||
nRecvBytes = 0;
|
||||
nLastSendEmpty = GetTime();
|
||||
nTimeConnected = GetTime();
|
||||
addr = addrIn;
|
||||
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
||||
@@ -314,6 +333,11 @@ public:
|
||||
id = nLastNodeId++;
|
||||
}
|
||||
|
||||
if (fLogIPs)
|
||||
LogPrint("net", "Added connection to %s peer=%d\n", addrName, id);
|
||||
else
|
||||
LogPrint("net", "Added connection peer=%d\n", id);
|
||||
|
||||
// Be shy and don't send version until we hear
|
||||
if (hSocket != INVALID_SOCKET && !fInbound)
|
||||
PushVersion();
|
||||
@@ -430,7 +454,7 @@ public:
|
||||
nRequestTime = it->second;
|
||||
else
|
||||
nRequestTime = 0;
|
||||
LogPrint("net", "askfor %s %d (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
|
||||
LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str(), id);
|
||||
|
||||
// Make sure not to reuse time indexes to keep things in the same order
|
||||
int64_t nNow = GetTimeMicros() - 1000000;
|
||||
@@ -498,7 +522,7 @@ public:
|
||||
assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
|
||||
memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum));
|
||||
|
||||
LogPrint("net", "(%d bytes)\n", nSize);
|
||||
LogPrint("net", "(%d bytes) peer=%d\n", nSize, id);
|
||||
|
||||
std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
|
||||
ssSend.GetAndClear(*it);
|
||||
@@ -676,8 +700,6 @@ public:
|
||||
void Subscribe(unsigned int nChannel, unsigned int nHops=0);
|
||||
void CancelSubscribe(unsigned int nChannel);
|
||||
void CloseSocketDisconnect();
|
||||
void Cleanup();
|
||||
|
||||
|
||||
// Denial-of-service detection/prevention
|
||||
// The idea is to detect peers that are behaving
|
||||
@@ -709,8 +731,8 @@ public:
|
||||
|
||||
|
||||
class CTransaction;
|
||||
void RelayTransaction(const CTransaction& tx, const uint256& hash);
|
||||
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss);
|
||||
void RelayTransaction(const CTransaction& tx);
|
||||
void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
|
||||
|
||||
/** Access to the (IP) address database (peers.dat) */
|
||||
class CAddrDB
|
||||
|
||||
363
src/netbase.cpp
363
src/netbase.cpp
@@ -3,6 +3,14 @@
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETADDRINFO_A
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "netbase.h"
|
||||
|
||||
#include "hash.h"
|
||||
@@ -11,6 +19,9 @@
|
||||
#include "util.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#if HAVE_INET_PTON
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
@@ -25,7 +36,7 @@ using namespace std;
|
||||
|
||||
// Settings
|
||||
static proxyType proxyInfo[NET_MAX];
|
||||
static proxyType nameproxyInfo;
|
||||
static CService nameProxy;
|
||||
static CCriticalSection cs_proxyInfos;
|
||||
int nConnectTimeout = 5000;
|
||||
bool fNameLookup = false;
|
||||
@@ -47,12 +58,10 @@ void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
|
||||
bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
|
||||
bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
|
||||
if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
|
||||
char *endp = NULL;
|
||||
int n = strtol(in.c_str() + colon + 1, &endp, 10);
|
||||
if (endp && *endp == 0 && n >= 0) {
|
||||
int32_t n;
|
||||
if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
|
||||
in = in.substr(0, colon);
|
||||
if (n > 0 && n < 0x10000)
|
||||
portOut = n;
|
||||
portOut = n;
|
||||
}
|
||||
}
|
||||
if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
|
||||
@@ -73,9 +82,30 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETADDRINFO_A
|
||||
struct in_addr ipv4_addr;
|
||||
#ifdef HAVE_INET_PTON
|
||||
if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) {
|
||||
vIP.push_back(CNetAddr(ipv4_addr));
|
||||
return true;
|
||||
}
|
||||
|
||||
struct in6_addr ipv6_addr;
|
||||
if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) {
|
||||
vIP.push_back(CNetAddr(ipv6_addr));
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
ipv4_addr.s_addr = inet_addr(pszName);
|
||||
if (ipv4_addr.s_addr != INADDR_NONE) {
|
||||
vIP.push_back(CNetAddr(ipv4_addr));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct addrinfo aiHint;
|
||||
memset(&aiHint, 0, sizeof(struct addrinfo));
|
||||
|
||||
aiHint.ai_socktype = SOCK_STREAM;
|
||||
aiHint.ai_protocol = IPPROTO_TCP;
|
||||
aiHint.ai_family = AF_UNSPEC;
|
||||
@@ -84,8 +114,33 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
|
||||
#else
|
||||
aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
|
||||
#endif
|
||||
|
||||
struct addrinfo *aiRes = NULL;
|
||||
#ifdef HAVE_GETADDRINFO_A
|
||||
struct gaicb gcb, *query = &gcb;
|
||||
memset(query, 0, sizeof(struct gaicb));
|
||||
gcb.ar_name = pszName;
|
||||
gcb.ar_request = &aiHint;
|
||||
int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL);
|
||||
if (nErr)
|
||||
return false;
|
||||
|
||||
do {
|
||||
// Should set the timeout limit to a resonable value to avoid
|
||||
// generating unnecessary checking call during the polling loop,
|
||||
// while it can still response to stop request quick enough.
|
||||
// 2 seconds looks fine in our situation.
|
||||
struct timespec ts = { 2, 0 };
|
||||
gai_suspend(&query, 1, &ts);
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
nErr = gai_error(query);
|
||||
if (0 == nErr)
|
||||
aiRes = query->ar_result;
|
||||
} while (nErr == EAI_INPROGRESS);
|
||||
#else
|
||||
int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
|
||||
#endif
|
||||
if (nErr)
|
||||
return false;
|
||||
|
||||
@@ -125,11 +180,6 @@ bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nM
|
||||
return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
|
||||
}
|
||||
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions)
|
||||
{
|
||||
return LookupHost(pszName, vIP, nMaxSolutions, false);
|
||||
}
|
||||
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
@@ -163,50 +213,6 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
|
||||
return Lookup(pszName, addr, portDefault, false);
|
||||
}
|
||||
|
||||
bool static Socks4(const CService &addrDest, SOCKET& hSocket)
|
||||
{
|
||||
LogPrintf("SOCKS4 connecting %s\n", addrDest.ToString());
|
||||
if (!addrDest.IsIPv4())
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Proxy destination is not IPv4");
|
||||
}
|
||||
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
|
||||
struct sockaddr_in addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Cannot get proxy destination address");
|
||||
}
|
||||
memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
|
||||
memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
|
||||
char* pszSocks4 = pszSocks4IP;
|
||||
int nSize = sizeof(pszSocks4IP);
|
||||
|
||||
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet[8];
|
||||
if (recv(hSocket, pchRet, 8, 0) != 8)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet[1] != 0x5a)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
if (pchRet[1] != 0x5b)
|
||||
LogPrintf("ERROR: Proxy returned error %d\n", pchRet[1]);
|
||||
return false;
|
||||
}
|
||||
LogPrintf("SOCKS4 connected %s\n", addrDest.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool static Socks5(string strDest, int port, SOCKET& hSocket)
|
||||
{
|
||||
LogPrintf("SOCKS5 connecting %s\n", strDest);
|
||||
@@ -344,8 +350,9 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
||||
|
||||
if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
// WSAEINVAL is here because some legacy version of winsock uses it
|
||||
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
|
||||
if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
|
||||
{
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = nTimeout / 1000;
|
||||
@@ -363,7 +370,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
||||
}
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
LogPrintf("select() for %s failed: %i\n", addrConnect.ToString(), WSAGetLastError());
|
||||
LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
@@ -374,13 +381,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
LogPrintf("getsockopt() for %s failed: %i\n", addrConnect.ToString(), WSAGetLastError());
|
||||
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet != 0)
|
||||
{
|
||||
LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), strerror(nRet));
|
||||
LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
@@ -391,7 +398,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
||||
else
|
||||
#endif
|
||||
{
|
||||
LogPrintf("connect() to %s failed: %i\n", addrConnect.ToString(), WSAGetLastError());
|
||||
LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
@@ -416,53 +423,49 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) {
|
||||
bool SetProxy(enum Network net, CService addrProxy) {
|
||||
assert(net >= 0 && net < NET_MAX);
|
||||
if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5)
|
||||
return false;
|
||||
if (nSocksVersion != 0 && !addrProxy.IsValid())
|
||||
if (!addrProxy.IsValid())
|
||||
return false;
|
||||
LOCK(cs_proxyInfos);
|
||||
proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion);
|
||||
proxyInfo[net] = addrProxy;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
|
||||
assert(net >= 0 && net < NET_MAX);
|
||||
LOCK(cs_proxyInfos);
|
||||
if (!proxyInfo[net].second)
|
||||
if (!proxyInfo[net].IsValid())
|
||||
return false;
|
||||
proxyInfoOut = proxyInfo[net];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetNameProxy(CService addrProxy, int nSocksVersion) {
|
||||
if (nSocksVersion != 0 && nSocksVersion != 5)
|
||||
return false;
|
||||
if (nSocksVersion != 0 && !addrProxy.IsValid())
|
||||
bool SetNameProxy(CService addrProxy) {
|
||||
if (!addrProxy.IsValid())
|
||||
return false;
|
||||
LOCK(cs_proxyInfos);
|
||||
nameproxyInfo = std::make_pair(addrProxy, nSocksVersion);
|
||||
nameProxy = addrProxy;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetNameProxy(proxyType &nameproxyInfoOut) {
|
||||
bool GetNameProxy(CService &nameProxyOut) {
|
||||
LOCK(cs_proxyInfos);
|
||||
if (!nameproxyInfo.second)
|
||||
if(!nameProxy.IsValid())
|
||||
return false;
|
||||
nameproxyInfoOut = nameproxyInfo;
|
||||
nameProxyOut = nameProxy;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HaveNameProxy() {
|
||||
LOCK(cs_proxyInfos);
|
||||
return nameproxyInfo.second != 0;
|
||||
return nameProxy.IsValid();
|
||||
}
|
||||
|
||||
bool IsProxy(const CNetAddr &addr) {
|
||||
LOCK(cs_proxyInfos);
|
||||
for (int i = 0; i < NET_MAX; i++) {
|
||||
if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first))
|
||||
if (addr == (CNetAddr)proxyInfo[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -471,31 +474,18 @@ bool IsProxy(const CNetAddr &addr) {
|
||||
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
{
|
||||
proxyType proxy;
|
||||
|
||||
// no proxy needed
|
||||
// no proxy needed (none set for target network)
|
||||
if (!GetProxy(addrDest.GetNetwork(), proxy))
|
||||
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
|
||||
|
||||
SOCKET hSocket = INVALID_SOCKET;
|
||||
|
||||
// first connect to proxy server
|
||||
if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout))
|
||||
if (!ConnectSocketDirectly(proxy, hSocket, nTimeout))
|
||||
return false;
|
||||
|
||||
// do socks negotiation
|
||||
switch (proxy.second) {
|
||||
case 4:
|
||||
if (!Socks4(addrDest, hSocket))
|
||||
return false;
|
||||
break;
|
||||
case 5:
|
||||
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
closesocket(hSocket);
|
||||
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
|
||||
return false;
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
@@ -509,30 +499,25 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
|
||||
|
||||
SOCKET hSocket = INVALID_SOCKET;
|
||||
|
||||
proxyType nameproxy;
|
||||
GetNameProxy(nameproxy);
|
||||
CService nameProxy;
|
||||
GetNameProxy(nameProxy);
|
||||
|
||||
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port);
|
||||
CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port);
|
||||
if (addrResolved.IsValid()) {
|
||||
addr = addrResolved;
|
||||
return ConnectSocket(addr, hSocketRet, nTimeout);
|
||||
}
|
||||
addr = CService("0.0.0.0:0");
|
||||
if (!nameproxy.second)
|
||||
return false;
|
||||
if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout))
|
||||
return false;
|
||||
|
||||
switch(nameproxy.second) {
|
||||
default:
|
||||
case 4:
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
case 5:
|
||||
if (!Socks5(strDest, port, hSocket))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
addr = CService("0.0.0.0:0");
|
||||
|
||||
if (!HaveNameProxy())
|
||||
return false;
|
||||
// first connect to name proxy server
|
||||
if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout))
|
||||
return false;
|
||||
// do socks negotiation
|
||||
if (!Socks5(strDest, (unsigned short)port, hSocket))
|
||||
return false;
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
@@ -548,6 +533,22 @@ void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||
}
|
||||
|
||||
void CNetAddr::SetRaw(Network network, const uint8_t *ip_in)
|
||||
{
|
||||
switch(network)
|
||||
{
|
||||
case NET_IPV4:
|
||||
memcpy(ip, pchIPv4, 12);
|
||||
memcpy(ip+12, ip_in, 4);
|
||||
break;
|
||||
case NET_IPV6:
|
||||
memcpy(ip, ip_in, 16);
|
||||
break;
|
||||
default:
|
||||
assert(!"invalid network");
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
|
||||
|
||||
bool CNetAddr::SetSpecial(const std::string &strName)
|
||||
@@ -571,13 +572,12 @@ CNetAddr::CNetAddr()
|
||||
|
||||
CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
|
||||
{
|
||||
memcpy(ip, pchIPv4, 12);
|
||||
memcpy(ip+12, &ipv4Addr, 4);
|
||||
SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
|
||||
{
|
||||
memcpy(ip, &ipv6Addr, 16);
|
||||
SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
|
||||
@@ -1122,3 +1122,138 @@ void CService::SetPort(unsigned short portIn)
|
||||
{
|
||||
port = portIn;
|
||||
}
|
||||
|
||||
CSubNet::CSubNet():
|
||||
valid(false)
|
||||
{
|
||||
memset(netmask, 0, sizeof(netmask));
|
||||
}
|
||||
|
||||
CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup)
|
||||
{
|
||||
size_t slash = strSubnet.find_last_of('/');
|
||||
std::vector<CNetAddr> vIP;
|
||||
|
||||
valid = true;
|
||||
// Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
|
||||
memset(netmask, 255, sizeof(netmask));
|
||||
|
||||
std::string strAddress = strSubnet.substr(0, slash);
|
||||
if (LookupHost(strAddress.c_str(), vIP, 1, fAllowLookup))
|
||||
{
|
||||
network = vIP[0];
|
||||
if (slash != strSubnet.npos)
|
||||
{
|
||||
std::string strNetmask = strSubnet.substr(slash + 1);
|
||||
int32_t n;
|
||||
// IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
|
||||
int noffset = network.IsIPv4() ? (12 * 8) : 0;
|
||||
if (ParseInt32(strNetmask, &n)) // If valid number, assume /24 symtex
|
||||
{
|
||||
if(n >= 0 && n <= (128 - noffset)) // Only valid if in range of bits of address
|
||||
{
|
||||
n += noffset;
|
||||
// Clear bits [n..127]
|
||||
for (; n < 128; ++n)
|
||||
netmask[n>>3] &= ~(1<<(n&7));
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
else // If not a valid number, try full netmask syntax
|
||||
{
|
||||
if (LookupHost(strNetmask.c_str(), vIP, 1, false)) // Never allow lookup for netmask
|
||||
{
|
||||
// Remember: GetByte returns bytes in reversed order
|
||||
// Copy only the *last* four bytes in case of IPv4, the rest of the mask should stay 1's as
|
||||
// we don't want pchIPv4 to be part of the mask.
|
||||
int asize = network.IsIPv4() ? 4 : 16;
|
||||
for(int x=0; x<asize; ++x)
|
||||
netmask[15-x] = vIP[0].GetByte(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CSubNet::Match(const CNetAddr &addr) const
|
||||
{
|
||||
if (!valid || !addr.IsValid())
|
||||
return false;
|
||||
for(int x=0; x<16; ++x)
|
||||
if ((addr.GetByte(x) & netmask[15-x]) != network.GetByte(x))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CSubNet::ToString() const
|
||||
{
|
||||
std::string strNetmask;
|
||||
if (network.IsIPv4())
|
||||
strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
|
||||
else
|
||||
strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
|
||||
netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
|
||||
netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
|
||||
netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
|
||||
return network.ToString() + "/" + strNetmask;
|
||||
}
|
||||
|
||||
bool CSubNet::IsValid() const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool operator==(const CSubNet& a, const CSubNet& b)
|
||||
{
|
||||
return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16);
|
||||
}
|
||||
|
||||
bool operator!=(const CSubNet& a, const CSubNet& b)
|
||||
{
|
||||
return !(a==b);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
std::string NetworkErrorString(int err)
|
||||
{
|
||||
char buf[256];
|
||||
buf[0] = 0;
|
||||
if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buf, sizeof(buf), NULL))
|
||||
{
|
||||
return strprintf("%s (%d)", buf, err);
|
||||
}
|
||||
else
|
||||
{
|
||||
return strprintf("Unknown error (%d)", err);
|
||||
}
|
||||
}
|
||||
#else
|
||||
std::string NetworkErrorString(int err)
|
||||
{
|
||||
char buf[256];
|
||||
const char *s = buf;
|
||||
buf[0] = 0;
|
||||
/* Too bad there are two incompatible implementations of the
|
||||
* thread-safe strerror. */
|
||||
#ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
|
||||
s = strerror_r(err, buf, sizeof(buf));
|
||||
#else /* POSIX variant always returns message in buffer */
|
||||
(void) strerror_r(err, buf, sizeof(buf));
|
||||
#endif
|
||||
return strprintf("%s (%d)", s, err);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define BITCOIN_NETBASE_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "compat.h"
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <vector>
|
||||
|
||||
extern int nConnectTimeout;
|
||||
extern bool fNameLookup;
|
||||
|
||||
#ifdef WIN32
|
||||
// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error
|
||||
@@ -33,9 +34,6 @@ enum Network
|
||||
NET_MAX,
|
||||
};
|
||||
|
||||
extern int nConnectTimeout;
|
||||
extern bool fNameLookup;
|
||||
|
||||
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
|
||||
class CNetAddr
|
||||
{
|
||||
@@ -49,6 +47,13 @@ class CNetAddr
|
||||
explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
|
||||
void Init();
|
||||
void SetIP(const CNetAddr& ip);
|
||||
|
||||
/**
|
||||
* Set raw IPv4 or IPv6 address (in network byte order)
|
||||
* @note Only NET_IPV4 and NET_IPV6 are allowed for network.
|
||||
*/
|
||||
void SetRaw(Network network, const uint8_t *data);
|
||||
|
||||
bool SetSpecial(const std::string &strName); // for Tor addresses
|
||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor)
|
||||
@@ -90,6 +95,29 @@ class CNetAddr
|
||||
)
|
||||
};
|
||||
|
||||
class CSubNet
|
||||
{
|
||||
protected:
|
||||
/// Network (base) address
|
||||
CNetAddr network;
|
||||
/// Netmask, in network byte order
|
||||
uint8_t netmask[16];
|
||||
/// Is this value valid? (only used to signal parse errors)
|
||||
bool valid;
|
||||
|
||||
public:
|
||||
CSubNet();
|
||||
explicit CSubNet(const std::string &strSubnet, bool fAllowLookup = false);
|
||||
|
||||
bool Match(const CNetAddr &addr) const;
|
||||
|
||||
std::string ToString() const;
|
||||
bool IsValid() const;
|
||||
|
||||
friend bool operator==(const CSubNet& a, const CSubNet& b);
|
||||
friend bool operator!=(const CSubNet& a, const CSubNet& b);
|
||||
};
|
||||
|
||||
/** A combination of a network address (CNetAddr) and a (TCP) port */
|
||||
class CService : public CNetAddr
|
||||
{
|
||||
@@ -133,21 +161,22 @@ class CService : public CNetAddr
|
||||
)
|
||||
};
|
||||
|
||||
typedef std::pair<CService, int> proxyType;
|
||||
typedef CService proxyType;
|
||||
|
||||
enum Network ParseNetwork(std::string net);
|
||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
||||
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
|
||||
bool SetProxy(enum Network net, CService addrProxy);
|
||||
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
|
||||
bool IsProxy(const CNetAddr &addr);
|
||||
bool SetNameProxy(CService addrProxy, int nSocksVersion = 5);
|
||||
bool SetNameProxy(CService addrProxy);
|
||||
bool HaveNameProxy();
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0);
|
||||
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
|
||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
|
||||
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
|
||||
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout);
|
||||
/** Return readable error string for a network error code */
|
||||
std::string NetworkErrorString(int err);
|
||||
|
||||
#endif
|
||||
|
||||
119
src/pow.cpp
Normal file
119
src/pow.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
// 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 "pow.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "core.h"
|
||||
#include "main.h"
|
||||
#include "uint256.h"
|
||||
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
|
||||
{
|
||||
unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact();
|
||||
|
||||
// Genesis block
|
||||
if (pindexLast == NULL)
|
||||
return nProofOfWorkLimit;
|
||||
|
||||
// Only change once per interval
|
||||
if ((pindexLast->nHeight+1) % Params().Interval() != 0)
|
||||
{
|
||||
if (Params().AllowMinDifficultyBlocks())
|
||||
{
|
||||
// Special difficulty rule for testnet:
|
||||
// If the new block's timestamp is more than 2* 10 minutes
|
||||
// then allow mining of a min-difficulty block.
|
||||
if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + Params().TargetSpacing()*2)
|
||||
return nProofOfWorkLimit;
|
||||
else
|
||||
{
|
||||
// Return the last non-special-min-difficulty-rules-block
|
||||
const CBlockIndex* pindex = pindexLast;
|
||||
while (pindex->pprev && pindex->nHeight % Params().Interval() != 0 && pindex->nBits == nProofOfWorkLimit)
|
||||
pindex = pindex->pprev;
|
||||
return pindex->nBits;
|
||||
}
|
||||
}
|
||||
return pindexLast->nBits;
|
||||
}
|
||||
|
||||
// Go back by what we want to be 14 days worth of blocks
|
||||
const CBlockIndex* pindexFirst = pindexLast;
|
||||
for (int i = 0; pindexFirst && i < Params().Interval()-1; i++)
|
||||
pindexFirst = pindexFirst->pprev;
|
||||
assert(pindexFirst);
|
||||
|
||||
// Limit adjustment step
|
||||
int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
|
||||
LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan);
|
||||
if (nActualTimespan < Params().TargetTimespan()/4)
|
||||
nActualTimespan = Params().TargetTimespan()/4;
|
||||
if (nActualTimespan > Params().TargetTimespan()*4)
|
||||
nActualTimespan = Params().TargetTimespan()*4;
|
||||
|
||||
// Retarget
|
||||
uint256 bnNew;
|
||||
uint256 bnOld;
|
||||
bnNew.SetCompact(pindexLast->nBits);
|
||||
bnOld = bnNew;
|
||||
bnNew *= nActualTimespan;
|
||||
bnNew /= Params().TargetTimespan();
|
||||
|
||||
if (bnNew > Params().ProofOfWorkLimit())
|
||||
bnNew = Params().ProofOfWorkLimit();
|
||||
|
||||
/// debug print
|
||||
LogPrintf("GetNextWorkRequired RETARGET\n");
|
||||
LogPrintf("Params().TargetTimespan() = %d nActualTimespan = %d\n", Params().TargetTimespan(), nActualTimespan);
|
||||
LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString());
|
||||
LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString());
|
||||
|
||||
return bnNew.GetCompact();
|
||||
}
|
||||
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits)
|
||||
{
|
||||
bool fNegative;
|
||||
bool fOverflow;
|
||||
uint256 bnTarget;
|
||||
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
|
||||
|
||||
// Check range
|
||||
if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit())
|
||||
return error("CheckProofOfWork() : nBits below minimum work");
|
||||
|
||||
// Check proof of work matches claimed amount
|
||||
if (hash > bnTarget)
|
||||
return error("CheckProofOfWork() : hash doesn't match nBits");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// minimum amount of work that could possibly be required nTime after
|
||||
// minimum work required was nBase
|
||||
//
|
||||
unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime)
|
||||
{
|
||||
const uint256 &bnLimit = Params().ProofOfWorkLimit();
|
||||
// Testnet has min-difficulty blocks
|
||||
// after Params().TargetSpacing()*2 time between blocks:
|
||||
if (Params().AllowMinDifficultyBlocks() && nTime > Params().TargetSpacing()*2)
|
||||
return bnLimit.GetCompact();
|
||||
|
||||
uint256 bnResult;
|
||||
bnResult.SetCompact(nBase);
|
||||
while (nTime > 0 && bnResult < bnLimit)
|
||||
{
|
||||
// Maximum 400% adjustment...
|
||||
bnResult *= 4;
|
||||
// ... in best-case exactly 4-times-normal target time
|
||||
nTime -= Params().TargetTimespan()*4;
|
||||
}
|
||||
if (bnResult > bnLimit)
|
||||
bnResult = bnLimit;
|
||||
return bnResult.GetCompact();
|
||||
}
|
||||
23
src/pow.h
Normal file
23
src/pow.h
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
// 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_POW_H
|
||||
#define BITCOIN_POW_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class CBlockIndex;
|
||||
class CBlockHeader;
|
||||
class uint256;
|
||||
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock);
|
||||
|
||||
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
||||
/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */
|
||||
unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime);
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
@@ -10,14 +10,16 @@
|
||||
#ifndef __INCLUDED_PROTOCOL_H__
|
||||
#define __INCLUDED_PROTOCOL_H__
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "netbase.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#define MESSAGE_START_SIZE 4
|
||||
|
||||
/** Message header.
|
||||
* (4) message start.
|
||||
* (12) command.
|
||||
@@ -62,6 +64,14 @@ class CMessageHeader
|
||||
enum
|
||||
{
|
||||
NODE_NETWORK = (1 << 0),
|
||||
|
||||
// Bits 24-31 are reserved for temporary experiments. Just pick a bit that
|
||||
// isn't getting used, or one not being used much, and notify the
|
||||
// bitcoin-development mailing list. Remember that service bits are just
|
||||
// unauthenticated advertisements, so your code must be robust against
|
||||
// collisions and other cases where nodes may be advertising a service they
|
||||
// do not actually support. Other service bits should be allocated via the
|
||||
// BIP process.
|
||||
};
|
||||
|
||||
/** A CService with information about it as peer */
|
||||
|
||||
9
src/qt/Makefile
Normal file
9
src/qt/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
.PHONY: FORCE
|
||||
all: FORCE
|
||||
$(MAKE) -C .. bitcoin_qt test_bitcoin_qt
|
||||
clean: FORCE
|
||||
$(MAKE) -C .. bitcoin_qt_clean test_bitcoin_qt_clean
|
||||
check: FORCE
|
||||
$(MAKE) -C .. test_bitcoin_qt_check
|
||||
bitcoin-qt bitcoin-qt.exe: FORCE
|
||||
$(MAKE) -C .. bitcoin_qt
|
||||
@@ -1,378 +0,0 @@
|
||||
include $(top_srcdir)/src/Makefile.include
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src \
|
||||
-I$(top_builddir)/src/qt \
|
||||
-I$(top_builddir)/src/qt/forms \
|
||||
$(PROTOBUF_CFLAGS) \
|
||||
$(QR_CFLAGS)
|
||||
bin_PROGRAMS = bitcoin-qt
|
||||
noinst_LIBRARIES = libbitcoinqt.a
|
||||
SUBDIRS = . $(BUILD_TEST_QT)
|
||||
DIST_SUBDIRS = . test
|
||||
|
||||
# bitcoin qt core #
|
||||
QT_TS = \
|
||||
locale/bitcoin_ach.ts \
|
||||
locale/bitcoin_af_ZA.ts \
|
||||
locale/bitcoin_ar.ts \
|
||||
locale/bitcoin_be_BY.ts \
|
||||
locale/bitcoin_bg.ts \
|
||||
locale/bitcoin_bs.ts \
|
||||
locale/bitcoin_ca_ES.ts \
|
||||
locale/bitcoin_ca.ts \
|
||||
locale/bitcoin_ca@valencia.ts \
|
||||
locale/bitcoin_cmn.ts \
|
||||
locale/bitcoin_cs.ts \
|
||||
locale/bitcoin_cy.ts \
|
||||
locale/bitcoin_da.ts \
|
||||
locale/bitcoin_de.ts \
|
||||
locale/bitcoin_el_GR.ts \
|
||||
locale/bitcoin_en.ts \
|
||||
locale/bitcoin_eo.ts \
|
||||
locale/bitcoin_es_CL.ts \
|
||||
locale/bitcoin_es_DO.ts \
|
||||
locale/bitcoin_es_MX.ts \
|
||||
locale/bitcoin_es.ts \
|
||||
locale/bitcoin_es_UY.ts \
|
||||
locale/bitcoin_et.ts \
|
||||
locale/bitcoin_eu_ES.ts \
|
||||
locale/bitcoin_fa_IR.ts \
|
||||
locale/bitcoin_fa.ts \
|
||||
locale/bitcoin_fi.ts \
|
||||
locale/bitcoin_fr_CA.ts \
|
||||
locale/bitcoin_fr.ts \
|
||||
locale/bitcoin_gl.ts \
|
||||
locale/bitcoin_gu_IN.ts \
|
||||
locale/bitcoin_he.ts \
|
||||
locale/bitcoin_hi_IN.ts \
|
||||
locale/bitcoin_hr.ts \
|
||||
locale/bitcoin_hu.ts \
|
||||
locale/bitcoin_id_ID.ts \
|
||||
locale/bitcoin_it.ts \
|
||||
locale/bitcoin_ja.ts \
|
||||
locale/bitcoin_ka.ts \
|
||||
locale/bitcoin_kk_KZ.ts \
|
||||
locale/bitcoin_ko_KR.ts \
|
||||
locale/bitcoin_ky.ts \
|
||||
locale/bitcoin_la.ts \
|
||||
locale/bitcoin_lt.ts \
|
||||
locale/bitcoin_lv_LV.ts \
|
||||
locale/bitcoin_ms_MY.ts \
|
||||
locale/bitcoin_nb.ts \
|
||||
locale/bitcoin_nl.ts \
|
||||
locale/bitcoin_pam.ts \
|
||||
locale/bitcoin_pl.ts \
|
||||
locale/bitcoin_pt_BR.ts \
|
||||
locale/bitcoin_pt_PT.ts \
|
||||
locale/bitcoin_ro_RO.ts \
|
||||
locale/bitcoin_ru.ts \
|
||||
locale/bitcoin_sah.ts \
|
||||
locale/bitcoin_sk.ts \
|
||||
locale/bitcoin_sl_SI.ts \
|
||||
locale/bitcoin_sq.ts \
|
||||
locale/bitcoin_sr.ts \
|
||||
locale/bitcoin_sv.ts \
|
||||
locale/bitcoin_th_TH.ts \
|
||||
locale/bitcoin_tr.ts \
|
||||
locale/bitcoin_uk.ts \
|
||||
locale/bitcoin_ur_PK.ts \
|
||||
locale/bitcoin_uz@Cyrl.ts \
|
||||
locale/bitcoin_vi.ts \
|
||||
locale/bitcoin_vi_VN.ts \
|
||||
locale/bitcoin_zh_CN.ts \
|
||||
locale/bitcoin_zh_HK.ts \
|
||||
locale/bitcoin_zh_TW.ts
|
||||
|
||||
QT_FORMS_UI = \
|
||||
forms/aboutdialog.ui \
|
||||
forms/addressbookpage.ui \
|
||||
forms/askpassphrasedialog.ui \
|
||||
forms/coincontroldialog.ui \
|
||||
forms/editaddressdialog.ui \
|
||||
forms/helpmessagedialog.ui \
|
||||
forms/intro.ui \
|
||||
forms/openuridialog.ui \
|
||||
forms/optionsdialog.ui \
|
||||
forms/overviewpage.ui \
|
||||
forms/receivecoinsdialog.ui \
|
||||
forms/receiverequestdialog.ui \
|
||||
forms/rpcconsole.ui \
|
||||
forms/sendcoinsdialog.ui \
|
||||
forms/sendcoinsentry.ui \
|
||||
forms/signverifymessagedialog.ui \
|
||||
forms/transactiondescdialog.ui
|
||||
|
||||
QT_MOC_CPP = \
|
||||
moc_addressbookpage.cpp \
|
||||
moc_addresstablemodel.cpp \
|
||||
moc_askpassphrasedialog.cpp \
|
||||
moc_bitcoinaddressvalidator.cpp \
|
||||
moc_bitcoinamountfield.cpp \
|
||||
moc_bitcoingui.cpp \
|
||||
moc_bitcoinunits.cpp \
|
||||
moc_clientmodel.cpp \
|
||||
moc_coincontroldialog.cpp \
|
||||
moc_coincontroltreewidget.cpp \
|
||||
moc_csvmodelwriter.cpp \
|
||||
moc_editaddressdialog.cpp \
|
||||
moc_guiutil.cpp \
|
||||
moc_intro.cpp \
|
||||
moc_macdockiconhandler.cpp \
|
||||
moc_macnotificationhandler.cpp \
|
||||
moc_monitoreddatamapper.cpp \
|
||||
moc_notificator.cpp \
|
||||
moc_openuridialog.cpp \
|
||||
moc_optionsdialog.cpp \
|
||||
moc_optionsmodel.cpp \
|
||||
moc_overviewpage.cpp \
|
||||
moc_paymentserver.cpp \
|
||||
moc_qvalidatedlineedit.cpp \
|
||||
moc_qvaluecombobox.cpp \
|
||||
moc_receivecoinsdialog.cpp \
|
||||
moc_receiverequestdialog.cpp \
|
||||
moc_recentrequeststablemodel.cpp \
|
||||
moc_rpcconsole.cpp \
|
||||
moc_sendcoinsdialog.cpp \
|
||||
moc_sendcoinsentry.cpp \
|
||||
moc_signverifymessagedialog.cpp \
|
||||
moc_splashscreen.cpp \
|
||||
moc_trafficgraphwidget.cpp \
|
||||
moc_transactiondesc.cpp \
|
||||
moc_transactiondescdialog.cpp \
|
||||
moc_transactionfilterproxy.cpp \
|
||||
moc_transactiontablemodel.cpp \
|
||||
moc_transactionview.cpp \
|
||||
moc_utilitydialog.cpp \
|
||||
moc_walletframe.cpp \
|
||||
moc_walletmodel.cpp \
|
||||
moc_walletview.cpp
|
||||
|
||||
BITCOIN_MM = \
|
||||
macdockiconhandler.mm \
|
||||
macnotificationhandler.mm
|
||||
|
||||
QT_MOC = \
|
||||
bitcoin.moc \
|
||||
intro.moc \
|
||||
overviewpage.moc \
|
||||
rpcconsole.moc
|
||||
|
||||
QT_QRC_CPP = qrc_bitcoin.cpp
|
||||
QT_QRC = bitcoin.qrc
|
||||
|
||||
PROTOBUF_CC = paymentrequest.pb.cc
|
||||
PROTOBUF_H = paymentrequest.pb.h
|
||||
PROTOBUF_PROTO = paymentrequest.proto
|
||||
|
||||
BITCOIN_QT_H = \
|
||||
addressbookpage.h \
|
||||
addresstablemodel.h \
|
||||
askpassphrasedialog.h \
|
||||
bitcoinaddressvalidator.h \
|
||||
bitcoinamountfield.h \
|
||||
bitcoingui.h \
|
||||
bitcoinunits.h \
|
||||
clientmodel.h \
|
||||
coincontroldialog.h \
|
||||
coincontroltreewidget.h \
|
||||
csvmodelwriter.h \
|
||||
editaddressdialog.h \
|
||||
guiconstants.h \
|
||||
guiutil.h \
|
||||
intro.h \
|
||||
macdockiconhandler.h \
|
||||
macnotificationhandler.h \
|
||||
monitoreddatamapper.h \
|
||||
notificator.h \
|
||||
openuridialog.h \
|
||||
optionsdialog.h \
|
||||
optionsmodel.h \
|
||||
overviewpage.h \
|
||||
paymentrequestplus.h \
|
||||
paymentserver.h \
|
||||
qvalidatedlineedit.h \
|
||||
qvaluecombobox.h \
|
||||
receivecoinsdialog.h \
|
||||
receiverequestdialog.h \
|
||||
recentrequeststablemodel.h \
|
||||
rpcconsole.h \
|
||||
sendcoinsdialog.h \
|
||||
sendcoinsentry.h \
|
||||
signverifymessagedialog.h \
|
||||
splashscreen.h \
|
||||
trafficgraphwidget.h \
|
||||
transactiondesc.h \
|
||||
transactiondescdialog.h \
|
||||
transactionfilterproxy.h \
|
||||
transactionrecord.h \
|
||||
transactiontablemodel.h \
|
||||
transactionview.h \
|
||||
utilitydialog.h \
|
||||
walletframe.h \
|
||||
walletmodel.h \
|
||||
walletmodeltransaction.h \
|
||||
walletview.h \
|
||||
winshutdownmonitor.h
|
||||
|
||||
RES_ICONS = \
|
||||
res/icons/add.png \
|
||||
res/icons/address-book.png \
|
||||
res/icons/bitcoin.ico \
|
||||
res/icons/bitcoin.png \
|
||||
res/icons/bitcoin_testnet.ico \
|
||||
res/icons/bitcoin_testnet.png \
|
||||
res/icons/clock1.png \
|
||||
res/icons/clock2.png \
|
||||
res/icons/clock3.png \
|
||||
res/icons/clock4.png \
|
||||
res/icons/clock5.png \
|
||||
res/icons/configure.png \
|
||||
res/icons/connect0_16.png \
|
||||
res/icons/connect1_16.png \
|
||||
res/icons/connect2_16.png \
|
||||
res/icons/connect3_16.png \
|
||||
res/icons/connect4_16.png \
|
||||
res/icons/debugwindow.png \
|
||||
res/icons/edit.png \
|
||||
res/icons/editcopy.png \
|
||||
res/icons/editpaste.png \
|
||||
res/icons/export.png \
|
||||
res/icons/filesave.png \
|
||||
res/icons/history.png \
|
||||
res/icons/key.png \
|
||||
res/icons/lock_closed.png \
|
||||
res/icons/lock_open.png \
|
||||
res/icons/overview.png \
|
||||
res/icons/qrcode.png \
|
||||
res/icons/quit.png \
|
||||
res/icons/receive.png \
|
||||
res/icons/remove.png \
|
||||
res/icons/send.png \
|
||||
res/icons/synced.png \
|
||||
res/icons/toolbar.png \
|
||||
res/icons/toolbar_testnet.png \
|
||||
res/icons/transaction0.png \
|
||||
res/icons/transaction2.png \
|
||||
res/icons/transaction_conflicted.png \
|
||||
res/icons/tx_inout.png \
|
||||
res/icons/tx_input.png \
|
||||
res/icons/tx_output.png \
|
||||
res/icons/tx_mined.png
|
||||
|
||||
BITCOIN_QT_CPP = \
|
||||
bitcoin.cpp \
|
||||
bitcoinaddressvalidator.cpp \
|
||||
bitcoinamountfield.cpp \
|
||||
bitcoingui.cpp \
|
||||
bitcoinunits.cpp \
|
||||
clientmodel.cpp \
|
||||
csvmodelwriter.cpp \
|
||||
guiutil.cpp \
|
||||
intro.cpp \
|
||||
monitoreddatamapper.cpp \
|
||||
notificator.cpp \
|
||||
optionsdialog.cpp \
|
||||
optionsmodel.cpp \
|
||||
qvalidatedlineedit.cpp \
|
||||
qvaluecombobox.cpp \
|
||||
rpcconsole.cpp \
|
||||
splashscreen.cpp \
|
||||
trafficgraphwidget.cpp \
|
||||
utilitydialog.cpp \
|
||||
winshutdownmonitor.cpp
|
||||
|
||||
if ENABLE_WALLET
|
||||
BITCOIN_QT_CPP += \
|
||||
addressbookpage.cpp \
|
||||
addresstablemodel.cpp \
|
||||
askpassphrasedialog.cpp \
|
||||
coincontroldialog.cpp \
|
||||
coincontroltreewidget.cpp \
|
||||
editaddressdialog.cpp \
|
||||
openuridialog.cpp \
|
||||
overviewpage.cpp \
|
||||
paymentrequestplus.cpp \
|
||||
paymentserver.cpp \
|
||||
receivecoinsdialog.cpp \
|
||||
receiverequestdialog.cpp \
|
||||
recentrequeststablemodel.cpp \
|
||||
sendcoinsdialog.cpp \
|
||||
sendcoinsentry.cpp \
|
||||
signverifymessagedialog.cpp \
|
||||
transactiondesc.cpp \
|
||||
transactiondescdialog.cpp \
|
||||
transactionfilterproxy.cpp \
|
||||
transactionrecord.cpp \
|
||||
transactiontablemodel.cpp \
|
||||
transactionview.cpp \
|
||||
walletframe.cpp \
|
||||
walletmodel.cpp \
|
||||
walletmodeltransaction.cpp \
|
||||
walletview.cpp
|
||||
endif
|
||||
|
||||
RES_IMAGES = \
|
||||
res/images/about.png \
|
||||
res/images/splash.png \
|
||||
res/images/splash_testnet.png
|
||||
|
||||
RES_MOVIES = $(wildcard res/movies/spinner-*.png)
|
||||
|
||||
BITCOIN_RC = res/bitcoin-qt-res.rc
|
||||
|
||||
libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \
|
||||
-I$(top_srcdir)/src/qt/forms $(QT_DBUS_INCLUDES)
|
||||
libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \
|
||||
$(QT_QRC) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
|
||||
|
||||
nodist_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \
|
||||
$(PROTOBUF_H) $(QT_QRC_CPP)
|
||||
|
||||
BUILT_SOURCES = $(nodist_libbitcoinqt_a_SOURCES)
|
||||
|
||||
#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 #
|
||||
bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \
|
||||
-I$(top_srcdir)/src/qt/forms
|
||||
bitcoin_qt_SOURCES = bitcoin.cpp
|
||||
if TARGET_DARWIN
|
||||
bitcoin_qt_SOURCES += $(BITCOIN_MM)
|
||||
endif
|
||||
if TARGET_WINDOWS
|
||||
bitcoin_qt_SOURCES += $(BITCOIN_RC)
|
||||
endif
|
||||
bitcoin_qt_LDADD = libbitcoinqt.a $(LIBBITCOIN_SERVER)
|
||||
if ENABLE_WALLET
|
||||
bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
|
||||
endif
|
||||
bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
|
||||
bitcoin_qt_LDFLAGS = $(QT_LDFLAGS)
|
||||
|
||||
# forms/foo.h -> forms/ui_foo.h
|
||||
QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h))))
|
||||
|
||||
#locale/foo.ts -> locale/foo.qm
|
||||
QT_QM=$(QT_TS:.ts=.qm)
|
||||
|
||||
.PHONY: FORCE
|
||||
.SECONDARY: $(QT_QM)
|
||||
|
||||
bitcoinstrings.cpp: FORCE
|
||||
$(MAKE) -C $(top_srcdir)/src qt/bitcoinstrings.cpp
|
||||
|
||||
translate: 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"
|
||||
@QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts locale/bitcoin_en.ts
|
||||
|
||||
$(QT_QRC_CPP): $(QT_QRC) $(QT_QM) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H)
|
||||
@cd $(abs_srcdir); test -f $(RCC) && QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin -o $(abs_builddir)/$@ $< || \
|
||||
echo error: could not build $@
|
||||
$(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,}
|
||||
$(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,}
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES) $(QT_QM) $(QT_FORMS_H) *.gcda *.gcno
|
||||
@@ -3,7 +3,7 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "addressbookpage.h"
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
case CT_NEW:
|
||||
if(inModel)
|
||||
{
|
||||
qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_NEW, but entry is already in model";
|
||||
qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_NEW, but entry is already in model";
|
||||
break;
|
||||
}
|
||||
parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex);
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
case CT_UPDATED:
|
||||
if(!inModel)
|
||||
{
|
||||
qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_UPDATED, but entry is not in model";
|
||||
qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_UPDATED, but entry is not in model";
|
||||
break;
|
||||
}
|
||||
lower->type = newEntryType;
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
case CT_DELETED:
|
||||
if(!inModel)
|
||||
{
|
||||
qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_DELETED, but entry is not in model";
|
||||
qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_DELETED, but entry is not in model";
|
||||
break;
|
||||
}
|
||||
parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
|
||||
|
||||
@@ -37,7 +37,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
|
||||
case Encrypt: // Ask passphrase x2
|
||||
ui->passLabel1->hide();
|
||||
ui->passEdit1->hide();
|
||||
ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>."));
|
||||
ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>."));
|
||||
setWindowTitle(tr("Encrypt wallet"));
|
||||
break;
|
||||
case Unlock: // Ask passphrase
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "bitcoingui.h"
|
||||
@@ -126,15 +126,15 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
|
||||
#if QT_VERSION < 0x050000
|
||||
void DebugMessageHandler(QtMsgType type, const char *msg)
|
||||
{
|
||||
Q_UNUSED(type);
|
||||
LogPrint("qt", "GUI: %s\n", msg);
|
||||
const char *category = (type == QtDebugMsg) ? "qt" : NULL;
|
||||
LogPrint(category, "GUI: %s\n", msg);
|
||||
}
|
||||
#else
|
||||
void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
|
||||
{
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(context);
|
||||
LogPrint("qt", "GUI: %s\n", qPrintable(msg));
|
||||
const char *category = (type == QtDebugMsg) ? "qt" : NULL;
|
||||
LogPrint(category, "GUI: %s\n", msg.toStdString());
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -459,6 +459,8 @@ WId BitcoinApplication::getMainWinId() const
|
||||
#ifndef BITCOIN_QT_TEST
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SetupEnvironment();
|
||||
|
||||
/// 1. Parse command-line options. These take precedence over anything else.
|
||||
// Command-line options take precedence:
|
||||
ParseParameters(argc, argv);
|
||||
@@ -473,6 +475,7 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
Q_INIT_RESOURCE(bitcoin);
|
||||
Q_INIT_RESOURCE(bitcoin_locale);
|
||||
BitcoinApplication app(argc, argv);
|
||||
#if QT_VERSION > 0x050100
|
||||
// Generate high-dpi pixmaps
|
||||
@@ -500,9 +503,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Show help message immediately after parsing command-line options (for "-lang") and setting locale,
|
||||
// but before showing splash screen.
|
||||
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
||||
if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
|
||||
{
|
||||
HelpMessageDialog help(NULL);
|
||||
HelpMessageDialog help(NULL, mapArgs.count("-version"));
|
||||
help.showOrPrint();
|
||||
return 1;
|
||||
}
|
||||
@@ -543,7 +546,7 @@ int main(int argc, char *argv[])
|
||||
if (!PaymentServer::ipcParseCommandLine(argc, argv))
|
||||
exit(0);
|
||||
#endif
|
||||
bool isaTestNet = Params().NetworkID() != CChainParams::MAIN;
|
||||
bool isaTestNet = Params().NetworkID() != CBaseChainParams::MAIN;
|
||||
// Allow for separate UI settings for testnets
|
||||
if (isaTestNet)
|
||||
QApplication::setApplicationName(QAPP_APP_NAME_TESTNET);
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
<file alias="tx_input">res/icons/tx_input.png</file>
|
||||
<file alias="tx_output">res/icons/tx_output.png</file>
|
||||
<file alias="tx_inout">res/icons/tx_inout.png</file>
|
||||
<file alias="unit_btc">res/icons/unit_btc.png</file>
|
||||
<file alias="unit_mbtc">res/icons/unit_mbtc.png</file>
|
||||
<file alias="unit_ubtc">res/icons/unit_ubtc.png</file>
|
||||
<file alias="lock_closed">res/icons/lock_closed.png</file>
|
||||
<file alias="lock_open">res/icons/lock_open.png</file>
|
||||
<file alias="key">res/icons/key.png</file>
|
||||
@@ -84,76 +87,4 @@
|
||||
<file alias="spinner-033">res/movies/spinner-033.png</file>
|
||||
<file alias="spinner-034">res/movies/spinner-034.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/translations">
|
||||
<file alias="ach">locale/bitcoin_ach.qm</file>
|
||||
<file alias="af_ZA">locale/bitcoin_af_ZA.qm</file>
|
||||
<file alias="ar">locale/bitcoin_ar.qm</file>
|
||||
<file alias="be_BY">locale/bitcoin_be_BY.qm</file>
|
||||
<file alias="bg">locale/bitcoin_bg.qm</file>
|
||||
<file alias="bs">locale/bitcoin_bs.qm</file>
|
||||
<file alias="ca_ES">locale/bitcoin_ca_ES.qm</file>
|
||||
<file alias="ca">locale/bitcoin_ca.qm</file>
|
||||
<file alias="ca@valencia">locale/bitcoin_ca@valencia.qm</file>
|
||||
<file alias="cmn">locale/bitcoin_cmn.qm</file>
|
||||
<file alias="cs">locale/bitcoin_cs.qm</file>
|
||||
<file alias="cy">locale/bitcoin_cy.qm</file>
|
||||
<file alias="da">locale/bitcoin_da.qm</file>
|
||||
<file alias="de">locale/bitcoin_de.qm</file>
|
||||
<file alias="el_GR">locale/bitcoin_el_GR.qm</file>
|
||||
<file alias="en">locale/bitcoin_en.qm</file>
|
||||
<file alias="eo">locale/bitcoin_eo.qm</file>
|
||||
<file alias="es_CL">locale/bitcoin_es_CL.qm</file>
|
||||
<file alias="es_DO">locale/bitcoin_es_DO.qm</file>
|
||||
<file alias="es_MX">locale/bitcoin_es_MX.qm</file>
|
||||
<file alias="es">locale/bitcoin_es.qm</file>
|
||||
<file alias="es_UY">locale/bitcoin_es_UY.qm</file>
|
||||
<file alias="et">locale/bitcoin_et.qm</file>
|
||||
<file alias="eu_ES">locale/bitcoin_eu_ES.qm</file>
|
||||
<file alias="fa_IR">locale/bitcoin_fa_IR.qm</file>
|
||||
<file alias="fa">locale/bitcoin_fa.qm</file>
|
||||
<file alias="fi">locale/bitcoin_fi.qm</file>
|
||||
<file alias="fr_CA">locale/bitcoin_fr_CA.qm</file>
|
||||
<file alias="fr">locale/bitcoin_fr.qm</file>
|
||||
<file alias="gl">locale/bitcoin_gl.qm</file>
|
||||
<file alias="gu_IN">locale/bitcoin_gu_IN.qm</file>
|
||||
<file alias="he">locale/bitcoin_he.qm</file>
|
||||
<file alias="hi_IN">locale/bitcoin_hi_IN.qm</file>
|
||||
<file alias="hr">locale/bitcoin_hr.qm</file>
|
||||
<file alias="hu">locale/bitcoin_hu.qm</file>
|
||||
<file alias="id_ID">locale/bitcoin_id_ID.qm</file>
|
||||
<file alias="it">locale/bitcoin_it.qm</file>
|
||||
<file alias="ja">locale/bitcoin_ja.qm</file>
|
||||
<file alias="ka">locale/bitcoin_ka.qm</file>
|
||||
<file alias="kk_KZ">locale/bitcoin_kk_KZ.qm</file>
|
||||
<file alias="ko_KR">locale/bitcoin_ko_KR.qm</file>
|
||||
<file alias="ky">locale/bitcoin_ky.qm</file>
|
||||
<file alias="la">locale/bitcoin_la.qm</file>
|
||||
<file alias="lt">locale/bitcoin_lt.qm</file>
|
||||
<file alias="lv_LV">locale/bitcoin_lv_LV.qm</file>
|
||||
<file alias="ms_MY">locale/bitcoin_ms_MY.qm</file>
|
||||
<file alias="nb">locale/bitcoin_nb.qm</file>
|
||||
<file alias="nl">locale/bitcoin_nl.qm</file>
|
||||
<file alias="pam">locale/bitcoin_pam.qm</file>
|
||||
<file alias="pl">locale/bitcoin_pl.qm</file>
|
||||
<file alias="pt_BR">locale/bitcoin_pt_BR.qm</file>
|
||||
<file alias="pt_PT">locale/bitcoin_pt_PT.qm</file>
|
||||
<file alias="ro_RO">locale/bitcoin_ro_RO.qm</file>
|
||||
<file alias="ru">locale/bitcoin_ru.qm</file>
|
||||
<file alias="sah">locale/bitcoin_sah.qm</file>
|
||||
<file alias="sk">locale/bitcoin_sk.qm</file>
|
||||
<file alias="sl_SI">locale/bitcoin_sl_SI.qm</file>
|
||||
<file alias="sq">locale/bitcoin_sq.qm</file>
|
||||
<file alias="sr">locale/bitcoin_sr.qm</file>
|
||||
<file alias="sv">locale/bitcoin_sv.qm</file>
|
||||
<file alias="th_TH">locale/bitcoin_th_TH.qm</file>
|
||||
<file alias="tr">locale/bitcoin_tr.qm</file>
|
||||
<file alias="uk">locale/bitcoin_uk.qm</file>
|
||||
<file alias="ur_PK">locale/bitcoin_ur_PK.qm</file>
|
||||
<file alias="uz@Cyrl">locale/bitcoin_uz@Cyrl.qm</file>
|
||||
<file alias="vi">locale/bitcoin_vi.qm</file>
|
||||
<file alias="vi_VN">locale/bitcoin_vi_VN.qm</file>
|
||||
<file alias="zh_CN">locale/bitcoin_zh_CN.qm</file>
|
||||
<file alias="zh_HK">locale/bitcoin_zh_HK.qm</file>
|
||||
<file alias="zh_TW">locale/bitcoin_zh_TW.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
75
src/qt/bitcoin_locale.qrc
Normal file
75
src/qt/bitcoin_locale.qrc
Normal file
@@ -0,0 +1,75 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="/translations">
|
||||
<file alias="ach">locale/bitcoin_ach.qm</file>
|
||||
<file alias="af_ZA">locale/bitcoin_af_ZA.qm</file>
|
||||
<file alias="ar">locale/bitcoin_ar.qm</file>
|
||||
<file alias="be_BY">locale/bitcoin_be_BY.qm</file>
|
||||
<file alias="bg">locale/bitcoin_bg.qm</file>
|
||||
<file alias="bs">locale/bitcoin_bs.qm</file>
|
||||
<file alias="ca_ES">locale/bitcoin_ca_ES.qm</file>
|
||||
<file alias="ca">locale/bitcoin_ca.qm</file>
|
||||
<file alias="ca@valencia">locale/bitcoin_ca@valencia.qm</file>
|
||||
<file alias="cmn">locale/bitcoin_cmn.qm</file>
|
||||
<file alias="cs">locale/bitcoin_cs.qm</file>
|
||||
<file alias="cy">locale/bitcoin_cy.qm</file>
|
||||
<file alias="da">locale/bitcoin_da.qm</file>
|
||||
<file alias="de">locale/bitcoin_de.qm</file>
|
||||
<file alias="el_GR">locale/bitcoin_el_GR.qm</file>
|
||||
<file alias="en">locale/bitcoin_en.qm</file>
|
||||
<file alias="eo">locale/bitcoin_eo.qm</file>
|
||||
<file alias="es_CL">locale/bitcoin_es_CL.qm</file>
|
||||
<file alias="es_DO">locale/bitcoin_es_DO.qm</file>
|
||||
<file alias="es_MX">locale/bitcoin_es_MX.qm</file>
|
||||
<file alias="es">locale/bitcoin_es.qm</file>
|
||||
<file alias="es_UY">locale/bitcoin_es_UY.qm</file>
|
||||
<file alias="et">locale/bitcoin_et.qm</file>
|
||||
<file alias="eu_ES">locale/bitcoin_eu_ES.qm</file>
|
||||
<file alias="fa_IR">locale/bitcoin_fa_IR.qm</file>
|
||||
<file alias="fa">locale/bitcoin_fa.qm</file>
|
||||
<file alias="fi">locale/bitcoin_fi.qm</file>
|
||||
<file alias="fr_CA">locale/bitcoin_fr_CA.qm</file>
|
||||
<file alias="fr">locale/bitcoin_fr.qm</file>
|
||||
<file alias="gl">locale/bitcoin_gl.qm</file>
|
||||
<file alias="gu_IN">locale/bitcoin_gu_IN.qm</file>
|
||||
<file alias="he">locale/bitcoin_he.qm</file>
|
||||
<file alias="hi_IN">locale/bitcoin_hi_IN.qm</file>
|
||||
<file alias="hr">locale/bitcoin_hr.qm</file>
|
||||
<file alias="hu">locale/bitcoin_hu.qm</file>
|
||||
<file alias="id_ID">locale/bitcoin_id_ID.qm</file>
|
||||
<file alias="it">locale/bitcoin_it.qm</file>
|
||||
<file alias="ja">locale/bitcoin_ja.qm</file>
|
||||
<file alias="ka">locale/bitcoin_ka.qm</file>
|
||||
<file alias="kk_KZ">locale/bitcoin_kk_KZ.qm</file>
|
||||
<file alias="ko_KR">locale/bitcoin_ko_KR.qm</file>
|
||||
<file alias="ky">locale/bitcoin_ky.qm</file>
|
||||
<file alias="la">locale/bitcoin_la.qm</file>
|
||||
<file alias="lt">locale/bitcoin_lt.qm</file>
|
||||
<file alias="lv_LV">locale/bitcoin_lv_LV.qm</file>
|
||||
<file alias="mn">locale/bitcoin_mn.qm</file>
|
||||
<file alias="ms_MY">locale/bitcoin_ms_MY.qm</file>
|
||||
<file alias="nb">locale/bitcoin_nb.qm</file>
|
||||
<file alias="nl">locale/bitcoin_nl.qm</file>
|
||||
<file alias="pam">locale/bitcoin_pam.qm</file>
|
||||
<file alias="pl">locale/bitcoin_pl.qm</file>
|
||||
<file alias="pt_BR">locale/bitcoin_pt_BR.qm</file>
|
||||
<file alias="pt_PT">locale/bitcoin_pt_PT.qm</file>
|
||||
<file alias="ro_RO">locale/bitcoin_ro_RO.qm</file>
|
||||
<file alias="ru">locale/bitcoin_ru.qm</file>
|
||||
<file alias="sah">locale/bitcoin_sah.qm</file>
|
||||
<file alias="sk">locale/bitcoin_sk.qm</file>
|
||||
<file alias="sl_SI">locale/bitcoin_sl_SI.qm</file>
|
||||
<file alias="sq">locale/bitcoin_sq.qm</file>
|
||||
<file alias="sr">locale/bitcoin_sr.qm</file>
|
||||
<file alias="sv">locale/bitcoin_sv.qm</file>
|
||||
<file alias="th_TH">locale/bitcoin_th_TH.qm</file>
|
||||
<file alias="tr">locale/bitcoin_tr.qm</file>
|
||||
<file alias="uk">locale/bitcoin_uk.qm</file>
|
||||
<file alias="ur_PK">locale/bitcoin_ur_PK.qm</file>
|
||||
<file alias="uz@Cyrl">locale/bitcoin_uz@Cyrl.qm</file>
|
||||
<file alias="vi">locale/bitcoin_vi.qm</file>
|
||||
<file alias="vi_VN">locale/bitcoin_vi_VN.qm</file>
|
||||
<file alias="zh_CN">locale/bitcoin_zh_CN.qm</file>
|
||||
<file alias="zh_HK">locale/bitcoin_zh_HK.qm</file>
|
||||
<file alias="zh_TW">locale/bitcoin_zh_TW.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -28,18 +28,18 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QIcon>
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
#include <QMimeData>
|
||||
#include <QProgressBar>
|
||||
#include <QProgressDialog>
|
||||
#include <QSettings>
|
||||
#include <QStackedWidget>
|
||||
#include <QStatusBar>
|
||||
@@ -155,10 +155,13 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
|
||||
QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
|
||||
frameBlocksLayout->setContentsMargins(3,0,3,0);
|
||||
frameBlocksLayout->setSpacing(3);
|
||||
unitDisplayControl = new UnitDisplayStatusBarControl();
|
||||
labelEncryptionIcon = new QLabel();
|
||||
labelConnectionsIcon = new QLabel();
|
||||
labelBlocksIcon = new QLabel();
|
||||
frameBlocksLayout->addStretch();
|
||||
frameBlocksLayout->addWidget(unitDisplayControl);
|
||||
frameBlocksLayout->addStretch();
|
||||
frameBlocksLayout->addWidget(labelEncryptionIcon);
|
||||
frameBlocksLayout->addStretch();
|
||||
frameBlocksLayout->addWidget(labelConnectionsIcon);
|
||||
@@ -188,7 +191,7 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
|
||||
|
||||
connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show()));
|
||||
|
||||
// prevents an oben debug window from becoming stuck/unusable on client shutdown
|
||||
// prevents an open debug window from becoming stuck/unusable on client shutdown
|
||||
connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
|
||||
|
||||
// Install event filter to be able to catch status tip events (QEvent::StatusTip)
|
||||
@@ -403,12 +406,15 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
|
||||
setNumConnections(clientModel->getNumConnections());
|
||||
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
|
||||
|
||||
setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers());
|
||||
connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
|
||||
setNumBlocks(clientModel->getNumBlocks());
|
||||
connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));
|
||||
|
||||
// Receive and report messages from client model
|
||||
connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
|
||||
|
||||
// Show progress dialog
|
||||
connect(clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
|
||||
|
||||
rpcConsole->setClientModel(clientModel);
|
||||
#ifdef ENABLE_WALLET
|
||||
if(walletFrame)
|
||||
@@ -416,6 +422,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
|
||||
walletFrame->setClientModel(clientModel);
|
||||
}
|
||||
#endif
|
||||
|
||||
this->unitDisplayControl->setOptionsModel(clientModel->getOptionsModel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,14 +553,13 @@ void BitcoinGUI::aboutClicked()
|
||||
if(!clientModel)
|
||||
return;
|
||||
|
||||
AboutDialog dlg(this);
|
||||
dlg.setModel(clientModel);
|
||||
HelpMessageDialog dlg(this, true);
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void BitcoinGUI::showHelpMessageClicked()
|
||||
{
|
||||
HelpMessageDialog *help = new HelpMessageDialog(this);
|
||||
HelpMessageDialog *help = new HelpMessageDialog(this, false);
|
||||
help->setAttribute(Qt::WA_DeleteOnClose);
|
||||
help->show();
|
||||
}
|
||||
@@ -617,7 +624,7 @@ void BitcoinGUI::setNumConnections(int count)
|
||||
labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
|
||||
}
|
||||
|
||||
void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
|
||||
void BitcoinGUI::setNumBlocks(int count)
|
||||
{
|
||||
// Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text)
|
||||
statusBar()->clearMessage();
|
||||
@@ -646,17 +653,10 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
|
||||
QDateTime currentDate = QDateTime::currentDateTime();
|
||||
int secs = lastBlockDate.secsTo(currentDate);
|
||||
|
||||
if(count < nTotalBlocks)
|
||||
{
|
||||
tooltip = tr("Processed %1 of %2 (estimated) blocks of transaction history.").arg(count).arg(nTotalBlocks);
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip = tr("Processed %1 blocks of transaction history.").arg(count);
|
||||
}
|
||||
tooltip = tr("Processed %1 blocks of transaction history.").arg(count);
|
||||
|
||||
// Set icon state: spinning if catching up, tick otherwise
|
||||
if(secs < 90*60 && count >= nTotalBlocks)
|
||||
if(secs < 90*60)
|
||||
{
|
||||
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
|
||||
labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
|
||||
@@ -956,6 +956,29 @@ void BitcoinGUI::detectShutdown()
|
||||
}
|
||||
}
|
||||
|
||||
void BitcoinGUI::showProgress(const QString &title, int nProgress)
|
||||
{
|
||||
if (nProgress == 0)
|
||||
{
|
||||
progressDialog = new QProgressDialog(title, "", 0, 100);
|
||||
progressDialog->setWindowModality(Qt::ApplicationModal);
|
||||
progressDialog->setMinimumDuration(0);
|
||||
progressDialog->setCancelButton(0);
|
||||
progressDialog->setAutoClose(false);
|
||||
progressDialog->setValue(0);
|
||||
}
|
||||
else if (nProgress == 100)
|
||||
{
|
||||
if (progressDialog)
|
||||
{
|
||||
progressDialog->close();
|
||||
progressDialog->deleteLater();
|
||||
}
|
||||
}
|
||||
else if (progressDialog)
|
||||
progressDialog->setValue(nProgress);
|
||||
}
|
||||
|
||||
static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style)
|
||||
{
|
||||
bool modal = (style & CClientUIInterface::MODAL);
|
||||
@@ -981,3 +1004,71 @@ void BitcoinGUI::unsubscribeFromCoreSignals()
|
||||
// Disconnect signals from client
|
||||
uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
|
||||
}
|
||||
|
||||
UnitDisplayStatusBarControl::UnitDisplayStatusBarControl():QLabel()
|
||||
{
|
||||
optionsModel = 0;
|
||||
createContextMenu();
|
||||
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
|
||||
}
|
||||
|
||||
/** So that it responds to left-button clicks */
|
||||
void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
onDisplayUnitsClicked(event->pos());
|
||||
}
|
||||
|
||||
/** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
|
||||
void UnitDisplayStatusBarControl::createContextMenu()
|
||||
{
|
||||
menu = new QMenu();
|
||||
foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits())
|
||||
{
|
||||
QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this);
|
||||
menuAction->setData(QVariant(u));
|
||||
menu->addAction(menuAction);
|
||||
}
|
||||
connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*)));
|
||||
|
||||
// what happens on right click.
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(onDisplayUnitsClicked(const QPoint&)));
|
||||
}
|
||||
|
||||
/** Lets the control know about the Options Model (and its signals) */
|
||||
void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *optionsModel)
|
||||
{
|
||||
if (optionsModel)
|
||||
{
|
||||
this->optionsModel = optionsModel;
|
||||
|
||||
// be aware of a display unit change reported by the OptionsModel object.
|
||||
connect(optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int)));
|
||||
|
||||
// initialize the display units label with the current value in the model.
|
||||
updateDisplayUnit(optionsModel->getDisplayUnit());
|
||||
}
|
||||
}
|
||||
|
||||
/** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
|
||||
void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits)
|
||||
{
|
||||
setPixmap(QIcon(":/icons/unit_" + BitcoinUnits::id(newUnits)).pixmap(31,STATUSBAR_ICONSIZE));
|
||||
}
|
||||
|
||||
/** Shows context menu with Display Unit options by the mouse coordinates */
|
||||
void UnitDisplayStatusBarControl::onDisplayUnitsClicked(const QPoint& point)
|
||||
{
|
||||
QPoint globalPos = mapToGlobal(point);
|
||||
menu->exec(globalPos);
|
||||
}
|
||||
|
||||
/** Tells underlying optionsModel to update its current display unit. */
|
||||
void UnitDisplayStatusBarControl::onMenuSelection(QAction* action)
|
||||
{
|
||||
if (action)
|
||||
{
|
||||
optionsModel->setDisplayUnit(action->data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,17 +6,22 @@
|
||||
#define BITCOINGUI_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bitcoin-config.h"
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include <QLabel>
|
||||
#include <QMainWindow>
|
||||
#include <QMap>
|
||||
#include <QMenu>
|
||||
#include <QPoint>
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
class ClientModel;
|
||||
class Notificator;
|
||||
class OptionsModel;
|
||||
class RPCConsole;
|
||||
class SendCoinsRecipient;
|
||||
class UnitDisplayStatusBarControl;
|
||||
class WalletFrame;
|
||||
class WalletModel;
|
||||
|
||||
@@ -24,8 +29,8 @@ class CWallet;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QLabel;
|
||||
class QProgressBar;
|
||||
class QProgressDialog;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/**
|
||||
@@ -68,11 +73,13 @@ private:
|
||||
ClientModel *clientModel;
|
||||
WalletFrame *walletFrame;
|
||||
|
||||
UnitDisplayStatusBarControl *unitDisplayControl;
|
||||
QLabel *labelEncryptionIcon;
|
||||
QLabel *labelConnectionsIcon;
|
||||
QLabel *labelBlocksIcon;
|
||||
QLabel *progressBarLabel;
|
||||
QProgressBar *progressBar;
|
||||
QProgressDialog *progressDialog;
|
||||
|
||||
QMenuBar *appMenuBar;
|
||||
QAction *overviewAction;
|
||||
@@ -130,7 +137,7 @@ public slots:
|
||||
/** Set number of connections shown in the UI */
|
||||
void setNumConnections(int count);
|
||||
/** Set number of blocks shown in the UI */
|
||||
void setNumBlocks(int count, int nTotalBlocks);
|
||||
void setNumBlocks(int count);
|
||||
|
||||
/** Notify the user of an event from the core network or transaction handling code.
|
||||
@param[in] title the message box / notification title
|
||||
@@ -191,6 +198,37 @@ private slots:
|
||||
|
||||
/** called by a timer to check if fRequestShutdown has been set **/
|
||||
void detectShutdown();
|
||||
|
||||
/** Show progress dialog e.g. for verifychain */
|
||||
void showProgress(const QString &title, int nProgress);
|
||||
};
|
||||
|
||||
class UnitDisplayStatusBarControl : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UnitDisplayStatusBarControl();
|
||||
/** Lets the control know about the Options Model (and its signals) */
|
||||
void setOptionsModel(OptionsModel *optionsModel);
|
||||
|
||||
protected:
|
||||
/** So that it responds to left-button clicks */
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
|
||||
private:
|
||||
OptionsModel *optionsModel;
|
||||
QMenu* menu;
|
||||
/** Shows context menu with Display Unit options by the mouse coordinates */
|
||||
void onDisplayUnitsClicked(const QPoint& point);
|
||||
/** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
|
||||
void createContextMenu();
|
||||
|
||||
private slots:
|
||||
/** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
|
||||
void updateDisplayUnit(int newUnits);
|
||||
/** Tells underlying optionsModel to update its current display unit. */
|
||||
void onMenuSelection(QAction* action);
|
||||
};
|
||||
|
||||
#endif // BITCOINGUI_H
|
||||
|
||||
@@ -22,31 +22,42 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"It is also recommended to set alertnotify so you are notified of problems;\n"
|
||||
"for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com\n"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"(default: 1, 1 = keep tx meta data e.g. account owner and payment request "
|
||||
"information, 2 = drop tx meta data)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!"
|
||||
"3DES:@STRENGTH)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"An error occurred while setting up the RPC port %u for listening on IPv4: %s"),
|
||||
"Allow JSON-RPC connections from specified source. Valid for <ip> are a "
|
||||
"single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or "
|
||||
"a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"An error occurred while setting up the RPC port %u for listening on IPv6, "
|
||||
"falling back to IPv4: %s"),
|
||||
"An error occurred while setting up the RPC address %s port %u for listening: "
|
||||
"%s"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Bind to given address and always listen on it. Use [host]:port notation for "
|
||||
"IPv6"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Bind to given address to listen for JSON-RPC connections. Use [host]:port "
|
||||
"notation for IPv6. This option can be specified multiple times (default: "
|
||||
"bind to all interfaces)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Cannot obtain a lock on data directory %s. Bitcoin Core is probably already "
|
||||
"running."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Continuously rate-limit free transactions to <n>*1000 bytes per minute "
|
||||
"(default:15)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"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."),
|
||||
"Delete all wallet transactions and only recover those part of the blockchain "
|
||||
"through -rescan on startup"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Distributed under the MIT/X11 software license, see the accompanying file "
|
||||
"COPYING or <http://www.opensource.org/licenses/mit-license.php>."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Enter regression test mode, which uses a special chain in which blocks can "
|
||||
"be solved instantly."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Error: Listening for incoming connections failed (listen returned error %d)"),
|
||||
"Error: Listening for incoming connections failed (listen returned error %s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Error: The transaction was rejected! This might happen if some of the coins "
|
||||
"in your wallet were already spent, such as if you used a copy of wallet.dat "
|
||||
@@ -55,6 +66,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Error: This transaction requires a transaction fee of at least %s because of "
|
||||
"its amount, complexity, or use of recently received funds!"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Execute command when a network tx respends wallet tx input (%s=respend TxID, "
|
||||
"%t=wallet TxID)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Execute command when a relevant alert is received or we see a really long "
|
||||
"fork (%s in cmd is replaced by message)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
@@ -64,14 +78,20 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Execute command when the best block changes (%s in cmd is replaced by block "
|
||||
"hash)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Fees smaller than this are considered zero fee (for transaction creation) "
|
||||
"(default:"),
|
||||
"Fees (in BTC/Kb) smaller than this are considered zero fee for relaying "
|
||||
"(default: %s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Fees (in BTC/Kb) smaller than this are considered zero fee for transaction "
|
||||
"creation (default: %s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Flush database activity from memory pool to disk log every <n> megabytes "
|
||||
"(default: 100)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"How thorough the block verification of -checkblocks is (0-4, default: 3)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"If paytxfee is not set, include enough fee so transactions are confirmed on "
|
||||
"average within n blocks (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"In this mode -genproclimit controls how many blocks are generated "
|
||||
"immediately."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
@@ -93,6 +113,10 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"This is a pre-release test build - use at your own risk - do not use for "
|
||||
"mining or merchant applications"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"This product includes software developed by the OpenSSL Project for use in "
|
||||
"the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software "
|
||||
"written by Eric Young and UPnP software written by Thomas Bernard."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Unable to bind to %s on this computer. Bitcoin Core is probably already "
|
||||
"running."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
@@ -117,11 +141,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as "
|
||||
"wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect "
|
||||
"you should restore from a backup."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"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."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "(default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "(default: wallet.dat)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "<category> can be:"),
|
||||
@@ -129,22 +148,19 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Accept command line and JSON-RPC commands"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1 if no -proxy or -connect)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Allow JSON-RPC connections from specified IP address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet.dat"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin Core Daemon"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin Core RPC client version"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -bind address: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -externalip address: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Clear list of wallet transactions (diagnostic tool; implies -rescan)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node(s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect through SOCKS proxy"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect to a node to retrieve peer addresses, and disconnect"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connection options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Copyright (C) 2009-%i The Bitcoin Core Developers"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Corrupted block database detected"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Could not parse -rpcbind value %s as network address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Debugging/Testing options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Disable safemode, override a real safe mode event (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Discover own IP address (default: 1 when listening and no -externalip)"),
|
||||
@@ -160,6 +176,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet requires new
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low!"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unsupported argument -tor found, use -onion."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Wallet locked, unable to create transaction!"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error: system error: "),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."),
|
||||
@@ -173,27 +190,28 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write file info"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write to coin database"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write transaction index"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write undo data"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Fee per kB to add to transactions you send"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Fees smaller than this are considered zero fee (for relaying) (default:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Fee (in BTC/kB) to add to transactions you send (default: %s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1 unless -connect)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Force safe mode (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 288, 0 = all)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "If <category> is not supplied, output all debugging information."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Importing..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000??.dat file"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Include IP addresses in debug output (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Information"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. Bitcoin Core is shutting down."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -onion address: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -minrelaytxfee=<amount>: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -mintxfee=<amount>: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Keep at most <n> unconnectable blocks in memory (default: %u)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Limit size of signature cache to <n> entries (default: 50000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "List commands"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on <port> (default: 8333 or testnet: 18333)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index..."),
|
||||
@@ -203,6 +221,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Maintain a full transaction index (default: 0
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maintain at most <n> connections to peers (default: 125)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Node relay options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Not enough file descriptors available."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Only accept block chain matching built-in checkpoints (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network <net> (IPv4, IPv6 or Tor)"),
|
||||
@@ -212,19 +231,16 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp (default:
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Print block on startup, if found in block index"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Print block tree on startup (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "RPC client options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "RPC server options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Randomly drop 1 of every <n> network messages"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Randomly fuzz 1 of every <n> network messages"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Rebuild block chain index from current blk000??.dat files"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Relay and mine data carrier transactions (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Run a thread to flush wallet periodically (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "SSL options: (see the Bitcoin Wiki for SSL setup instructions)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Select SOCKS version for -proxy (4 or 5, default: 5)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send command to Bitcoin Core"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send commands to node running on <ip> (default: 127.0.0.1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Server certificate file (default: server.cert)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Server private key (default: server.pem)"),
|
||||
@@ -245,21 +261,20 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Specify pid file (default: bitcoind.pid)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify wallet file (within data directory)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify your own public address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Spend unconfirmed change when sending transactions (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Start Bitcoin Core Daemon"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Stop running after importing blocks from disk (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "System error: "),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "This help message"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "This is experimental software."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "This is intended for regression testing tools and app development."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Threshold for disconnecting misbehaving peers (default: 100)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "To use the %s option"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amount too small"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amounts must be positive"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %d, %s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown -socks proxy version requested: %i"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Upgrade wallet to latest format"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Usage (deprecated, use bitcoin-cli):"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 1 when listening)"),
|
||||
@@ -267,7 +282,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Use the test network"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Wait for RPC server to start"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin to complete"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet options:"),
|
||||
@@ -277,6 +291,5 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete, upgrade re
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Zapping all transactions from wallet..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "on startup"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "version"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "wallet.dat corrupt, salvage failed"),
|
||||
};
|
||||
|
||||
@@ -34,6 +34,17 @@ bool BitcoinUnits::valid(int unit)
|
||||
}
|
||||
}
|
||||
|
||||
QString BitcoinUnits::id(int unit)
|
||||
{
|
||||
switch(unit)
|
||||
{
|
||||
case BTC: return QString("btc");
|
||||
case mBTC: return QString("mbtc");
|
||||
case uBTC: return QString("ubtc");
|
||||
default: return QString("???");
|
||||
}
|
||||
}
|
||||
|
||||
QString BitcoinUnits::name(int unit)
|
||||
{
|
||||
switch(unit)
|
||||
@@ -188,6 +199,16 @@ bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
|
||||
return ok;
|
||||
}
|
||||
|
||||
QString BitcoinUnits::getAmountColumnTitle(int unit)
|
||||
{
|
||||
QString amountTitle = QObject::tr("Amount");
|
||||
if (BitcoinUnits::valid(unit))
|
||||
{
|
||||
amountTitle += " ("+BitcoinUnits::name(unit) + ")";
|
||||
}
|
||||
return amountTitle;
|
||||
}
|
||||
|
||||
int BitcoinUnits::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
@@ -74,6 +74,8 @@ public:
|
||||
static QList<Unit> availableUnits();
|
||||
//! Is unit ID valid?
|
||||
static bool valid(int unit);
|
||||
//! Identifier, e.g. for image names
|
||||
static QString id(int unit);
|
||||
//! Short name
|
||||
static QString name(int unit);
|
||||
//! Longer description
|
||||
@@ -93,6 +95,8 @@ public:
|
||||
static QString formatHtmlWithUnit(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
|
||||
//! Parse string to coin amount
|
||||
static bool parse(int unit, const QString &value, qint64 *val_out);
|
||||
//! Gets title for amount column including current display unit if optionsModel reference available */
|
||||
static QString getAmountColumnTitle(int unit);
|
||||
///@}
|
||||
|
||||
//! @name AbstractListModel implementation
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "clientmodel.h"
|
||||
|
||||
#include "guiconstants.h"
|
||||
#include "peertablemodel.h"
|
||||
|
||||
#include "alert.h"
|
||||
#include "chainparams.h"
|
||||
@@ -22,11 +23,14 @@
|
||||
static const int64_t nClientStartupTime = GetTime();
|
||||
|
||||
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
|
||||
QObject(parent), optionsModel(optionsModel),
|
||||
cachedNumBlocks(0), cachedNumBlocksOfPeers(0),
|
||||
QObject(parent),
|
||||
optionsModel(optionsModel),
|
||||
peerTableModel(0),
|
||||
cachedNumBlocks(0),
|
||||
cachedReindexing(0), cachedImporting(0),
|
||||
numBlocksAtStartup(-1), pollTimer(0)
|
||||
{
|
||||
peerTableModel = new PeerTableModel(this);
|
||||
pollTimer = new QTimer(this);
|
||||
connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
|
||||
pollTimer->start(MODEL_UPDATE_DELAY);
|
||||
@@ -81,7 +85,7 @@ QDateTime ClientModel::getLastBlockDate() const
|
||||
if (chainActive.Tip())
|
||||
return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
|
||||
else
|
||||
return QDateTime::fromTime_t(Params().GenesisBlock().nTime); // Genesis block's time of current network
|
||||
return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network
|
||||
}
|
||||
|
||||
double ClientModel::getVerificationProgress() const
|
||||
@@ -101,19 +105,16 @@ void ClientModel::updateTimer()
|
||||
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
|
||||
// Periodically check and update with a timer.
|
||||
int newNumBlocks = getNumBlocks();
|
||||
int newNumBlocksOfPeers = getNumBlocksOfPeers();
|
||||
|
||||
// check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state
|
||||
if (cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers ||
|
||||
if (cachedNumBlocks != newNumBlocks ||
|
||||
cachedReindexing != fReindex || cachedImporting != fImporting)
|
||||
{
|
||||
cachedNumBlocks = newNumBlocks;
|
||||
cachedNumBlocksOfPeers = newNumBlocksOfPeers;
|
||||
cachedReindexing = fReindex;
|
||||
cachedImporting = fImporting;
|
||||
|
||||
// ensure we return the maximum of newNumBlocksOfPeers and newNumBlocks to not create weird displays in the GUI
|
||||
emit numBlocksChanged(newNumBlocks, std::max(newNumBlocksOfPeers, newNumBlocks));
|
||||
emit numBlocksChanged(newNumBlocks);
|
||||
}
|
||||
|
||||
emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
|
||||
@@ -141,14 +142,6 @@ void ClientModel::updateAlert(const QString &hash, int status)
|
||||
emit alertsChanged(getStatusBarWarnings());
|
||||
}
|
||||
|
||||
QString ClientModel::getNetworkName() const
|
||||
{
|
||||
QString netname(QString::fromStdString(Params().DataDir()));
|
||||
if(netname.isEmpty())
|
||||
netname = "main";
|
||||
return netname;
|
||||
}
|
||||
|
||||
bool ClientModel::inInitialBlockDownload() const
|
||||
{
|
||||
return IsInitialBlockDownload();
|
||||
@@ -166,11 +159,6 @@ enum BlockSource ClientModel::getBlockSource() const
|
||||
return BLOCK_SOURCE_NONE;
|
||||
}
|
||||
|
||||
int ClientModel::getNumBlocksOfPeers() const
|
||||
{
|
||||
return GetNumBlocksOfPeers();
|
||||
}
|
||||
|
||||
QString ClientModel::getStatusBarWarnings() const
|
||||
{
|
||||
return QString::fromStdString(GetWarnings("statusbar"));
|
||||
@@ -181,6 +169,11 @@ OptionsModel *ClientModel::getOptionsModel()
|
||||
return optionsModel;
|
||||
}
|
||||
|
||||
PeerTableModel *ClientModel::getPeerTableModel()
|
||||
{
|
||||
return peerTableModel;
|
||||
}
|
||||
|
||||
QString ClientModel::formatFullVersion() const
|
||||
{
|
||||
return QString::fromStdString(FormatFullVersion());
|
||||
@@ -207,6 +200,14 @@ QString ClientModel::formatClientStartupTime() const
|
||||
}
|
||||
|
||||
// Handlers for core signals
|
||||
static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress)
|
||||
{
|
||||
// emits signal "showProgress"
|
||||
QMetaObject::invokeMethod(clientmodel, "showProgress", Qt::QueuedConnection,
|
||||
Q_ARG(QString, QString::fromStdString(title)),
|
||||
Q_ARG(int, nProgress));
|
||||
}
|
||||
|
||||
static void NotifyBlocksChanged(ClientModel *clientmodel)
|
||||
{
|
||||
// This notification is too frequent. Don't trigger a signal.
|
||||
@@ -231,6 +232,7 @@ static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, Ch
|
||||
void ClientModel::subscribeToCoreSignals()
|
||||
{
|
||||
// Connect signals to client
|
||||
uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
|
||||
uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this));
|
||||
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
||||
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
||||
@@ -239,6 +241,7 @@ void ClientModel::subscribeToCoreSignals()
|
||||
void ClientModel::unsubscribeFromCoreSignals()
|
||||
{
|
||||
// Disconnect signals from client
|
||||
uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
|
||||
uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this));
|
||||
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
||||
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
class AddressTableModel;
|
||||
class OptionsModel;
|
||||
class PeerTableModel;
|
||||
class TransactionTableModel;
|
||||
|
||||
class CWallet;
|
||||
@@ -42,6 +43,7 @@ public:
|
||||
~ClientModel();
|
||||
|
||||
OptionsModel *getOptionsModel();
|
||||
PeerTableModel *getPeerTableModel();
|
||||
|
||||
//! Return number of connections, default is in- and outbound (total)
|
||||
int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const;
|
||||
@@ -54,14 +56,10 @@ public:
|
||||
double getVerificationProgress() const;
|
||||
QDateTime getLastBlockDate() const;
|
||||
|
||||
//! Return network (main, testnet3, regtest)
|
||||
QString getNetworkName() const;
|
||||
//! Return true if core is doing initial block download
|
||||
bool inInitialBlockDownload() const;
|
||||
//! Return true if core is importing blocks
|
||||
enum BlockSource getBlockSource() const;
|
||||
//! Return conservative estimate of total number of blocks, or 0 if unknown
|
||||
int getNumBlocksOfPeers() const;
|
||||
//! Return warnings to be displayed in status bar
|
||||
QString getStatusBarWarnings() const;
|
||||
|
||||
@@ -73,9 +71,9 @@ public:
|
||||
|
||||
private:
|
||||
OptionsModel *optionsModel;
|
||||
PeerTableModel *peerTableModel;
|
||||
|
||||
int cachedNumBlocks;
|
||||
int cachedNumBlocksOfPeers;
|
||||
bool cachedReindexing;
|
||||
bool cachedImporting;
|
||||
|
||||
@@ -88,13 +86,16 @@ private:
|
||||
|
||||
signals:
|
||||
void numConnectionsChanged(int count);
|
||||
void numBlocksChanged(int count, int countOfPeers);
|
||||
void numBlocksChanged(int count);
|
||||
void alertsChanged(const QString &warnings);
|
||||
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);
|
||||
|
||||
//! Fired when a message should be reported to the user
|
||||
void message(const QString &title, const QString &message, unsigned int style);
|
||||
|
||||
// Show progress dialog e.g. for verifychain
|
||||
void showProgress(const QString &title, int nProgress);
|
||||
|
||||
public slots:
|
||||
void updateTimer();
|
||||
void updateNumConnections(int numConnections);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "main.h"
|
||||
#include "wallet.h"
|
||||
|
||||
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QCursor>
|
||||
@@ -71,7 +73,7 @@ CoinControlDialog::CoinControlDialog(QWidget *parent) :
|
||||
QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this);
|
||||
QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this);
|
||||
QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this);
|
||||
QAction *clipboardLowOutputAction = new QAction(tr("Copy low output"), this);
|
||||
QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this);
|
||||
QAction *clipboardChangeAction = new QAction(tr("Copy change"), this);
|
||||
|
||||
connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(clipboardQuantity()));
|
||||
@@ -309,7 +311,7 @@ void CoinControlDialog::clipboardPriority()
|
||||
GUIUtil::setClipboard(ui->labelCoinControlPriority->text());
|
||||
}
|
||||
|
||||
// copy label "Low output" to clipboard
|
||||
// copy label "Dust" to clipboard
|
||||
void CoinControlDialog::clipboardLowOutput()
|
||||
{
|
||||
GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text());
|
||||
@@ -400,23 +402,24 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
|
||||
}
|
||||
|
||||
// return human readable label for priority number
|
||||
QString CoinControlDialog::getPriorityLabel(double dPriority)
|
||||
QString CoinControlDialog::getPriorityLabel(const CTxMemPool& pool, double dPriority)
|
||||
{
|
||||
if (AllowFree(dPriority)) // at least medium
|
||||
// confirmations -> textual description
|
||||
typedef std::map<unsigned int, QString> PriorityDescription;
|
||||
const static PriorityDescription priorityDescriptions = boost::assign::map_list_of
|
||||
(1, tr("highest"))(2, tr("higher"))(3, tr("high"))
|
||||
(5, tr("medium-high"))(6, tr("medium"))
|
||||
(10, tr("low-medium"))(15, tr("low"))
|
||||
(20, tr("lower"));
|
||||
|
||||
BOOST_FOREACH(const PriorityDescription::value_type& i, priorityDescriptions)
|
||||
{
|
||||
if (AllowFree(dPriority / 1000000)) return tr("highest");
|
||||
else if (AllowFree(dPriority / 100000)) return tr("higher");
|
||||
else if (AllowFree(dPriority / 10000)) return tr("high");
|
||||
else if (AllowFree(dPriority / 1000)) return tr("medium-high");
|
||||
else return tr("medium");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AllowFree(dPriority * 10)) return tr("low-medium");
|
||||
else if (AllowFree(dPriority * 100)) return tr("low");
|
||||
else if (AllowFree(dPriority * 1000)) return tr("lower");
|
||||
else return tr("lowest");
|
||||
double p = mempool.estimatePriority(i.first);
|
||||
if (p > 0 && dPriority >= p) return i.second;
|
||||
}
|
||||
// Note: if mempool hasn't accumulated enough history (estimatePriority
|
||||
// returns -1) we're conservative and classify as "lowest"
|
||||
return tr("lowest");
|
||||
}
|
||||
|
||||
// shows count of locked unspent outputs
|
||||
@@ -439,21 +442,17 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||
|
||||
// nPayAmount
|
||||
qint64 nPayAmount = 0;
|
||||
bool fLowOutput = false;
|
||||
bool fDust = false;
|
||||
CTransaction txDummy;
|
||||
CMutableTransaction txDummy;
|
||||
foreach(const qint64 &amount, CoinControlDialog::payAmounts)
|
||||
{
|
||||
nPayAmount += amount;
|
||||
|
||||
if (amount > 0)
|
||||
{
|
||||
if (amount < CENT)
|
||||
fLowOutput = true;
|
||||
|
||||
CTxOut txout(amount, (CScript)vector<unsigned char>(24, 0));
|
||||
txDummy.vout.push_back(txout);
|
||||
if (txout.IsDust(CTransaction::nMinRelayTxFee))
|
||||
if (txout.IsDust(::minRelayTxFee))
|
||||
fDust = true;
|
||||
}
|
||||
}
|
||||
@@ -522,40 +521,27 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||
|
||||
// Priority
|
||||
dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority)
|
||||
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority);
|
||||
|
||||
// Fee
|
||||
int64_t nFee = nTransactionFee * (1 + (int64_t)nBytes / 1000);
|
||||
sPriorityLabel = CoinControlDialog::getPriorityLabel(mempool, dPriority);
|
||||
|
||||
// Min Fee
|
||||
int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND);
|
||||
nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
|
||||
|
||||
nPayFee = max(nFee, nMinFee);
|
||||
double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
|
||||
if (dPriorityNeeded <= 0) // Not enough mempool history: never send free
|
||||
dPriorityNeeded = std::numeric_limits<double>::max();
|
||||
|
||||
if (nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE && dPriority >= dPriorityNeeded)
|
||||
nPayFee = 0;
|
||||
|
||||
if (nPayAmount > 0)
|
||||
{
|
||||
nChange = nAmount - nPayFee - nPayAmount;
|
||||
|
||||
// if sub-cent change is required, the fee must be raised to at least CTransaction::nMinTxFee
|
||||
if (nPayFee < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
|
||||
{
|
||||
if (nChange < CTransaction::nMinTxFee) // change < 0.0001 => simply move all change to fees
|
||||
{
|
||||
nPayFee += nChange;
|
||||
nChange = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nChange = nChange + nPayFee - CTransaction::nMinTxFee;
|
||||
nPayFee = CTransaction::nMinTxFee;
|
||||
}
|
||||
}
|
||||
|
||||
// Never create dust outputs; if we would, just add the dust to the fee.
|
||||
if (nChange > 0 && nChange < CENT)
|
||||
{
|
||||
CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0));
|
||||
if (txout.IsDust(CTransaction::nMinRelayTxFee))
|
||||
if (txout.IsDust(::minRelayTxFee))
|
||||
{
|
||||
nPayFee += nChange;
|
||||
nChange = 0;
|
||||
@@ -586,7 +572,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||
QLabel *l7 = dialog->findChild<QLabel *>("labelCoinControlLowOutput");
|
||||
QLabel *l8 = dialog->findChild<QLabel *>("labelCoinControlChange");
|
||||
|
||||
// enable/disable "low output" and "change"
|
||||
// enable/disable "dust" and "change"
|
||||
dialog->findChild<QLabel *>("labelCoinControlLowOutputText")->setEnabled(nPayAmount > 0);
|
||||
dialog->findChild<QLabel *>("labelCoinControlLowOutput") ->setEnabled(nPayAmount > 0);
|
||||
dialog->findChild<QLabel *>("labelCoinControlChangeText") ->setEnabled(nPayAmount > 0);
|
||||
@@ -599,35 +585,44 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||
l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee)); // After Fee
|
||||
l5->setText(((nBytes > 0) ? "~" : "") + QString::number(nBytes)); // Bytes
|
||||
l6->setText(sPriorityLabel); // Priority
|
||||
l7->setText((fLowOutput ? (fDust ? tr("Dust") : tr("yes")) : tr("no"))); // Low Output / Dust
|
||||
l7->setText(fDust ? tr("yes") : tr("no")); // Dust
|
||||
l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change
|
||||
if (nPayFee > 0)
|
||||
{
|
||||
l3->setText("~" + l3->text());
|
||||
l4->setText("~" + l4->text());
|
||||
if (nChange > 0)
|
||||
l8->setText("~" + l8->text());
|
||||
}
|
||||
|
||||
// turn labels "red"
|
||||
l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000
|
||||
l5->setStyleSheet((nBytes >= MAX_FREE_TRANSACTION_CREATE_SIZE) ? "color:red;" : "");// Bytes >= 1000
|
||||
l6->setStyleSheet((dPriority > 0 && !AllowFree(dPriority)) ? "color:red;" : ""); // Priority < "medium"
|
||||
l7->setStyleSheet((fLowOutput) ? "color:red;" : ""); // Low Output = "yes"
|
||||
l8->setStyleSheet((nChange > 0 && nChange < CENT) ? "color:red;" : ""); // Change < 0.01BTC
|
||||
l7->setStyleSheet((fDust) ? "color:red;" : ""); // Dust = "yes"
|
||||
|
||||
// tool tips
|
||||
QString toolTip1 = tr("This label turns red, if the transaction size is greater than 1000 bytes.") + "<br /><br />";
|
||||
toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee)) + "<br /><br />";
|
||||
toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK())) + "<br /><br />";
|
||||
toolTip1 += tr("Can vary +/- 1 byte per input.");
|
||||
|
||||
QString toolTip2 = tr("Transactions with higher priority are more likely to get included into a block.") + "<br /><br />";
|
||||
toolTip2 += tr("This label turns red, if the priority is smaller than \"medium\".") + "<br /><br />";
|
||||
toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee));
|
||||
toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK()));
|
||||
|
||||
QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)) + "<br /><br />";
|
||||
toolTip3 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee)) + "<br /><br />";
|
||||
toolTip3 += tr("Amounts below 0.546 times the minimum relay fee are shown as dust.");
|
||||
QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, ::minRelayTxFee.GetFee(546)));
|
||||
|
||||
QString toolTip4 = tr("This label turns red, if the change is smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)) + "<br /><br />";
|
||||
toolTip4 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee));
|
||||
// how many satoshis the estimated fee can vary per byte we guess wrong
|
||||
double dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000;
|
||||
QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
|
||||
|
||||
l3->setToolTip(toolTip4);
|
||||
l4->setToolTip(toolTip4);
|
||||
l5->setToolTip(toolTip1);
|
||||
l6->setToolTip(toolTip2);
|
||||
l7->setToolTip(toolTip3);
|
||||
l8->setToolTip(toolTip4);
|
||||
dialog->findChild<QLabel *>("labelCoinControlFeeText") ->setToolTip(l3->toolTip());
|
||||
dialog->findChild<QLabel *>("labelCoinControlAfterFeeText") ->setToolTip(l4->toolTip());
|
||||
dialog->findChild<QLabel *>("labelCoinControlBytesText") ->setToolTip(l5->toolTip());
|
||||
dialog->findChild<QLabel *>("labelCoinControlPriorityText") ->setToolTip(l6->toolTip());
|
||||
dialog->findChild<QLabel *>("labelCoinControlLowOutputText")->setToolTip(l7->toolTip());
|
||||
@@ -742,7 +737,7 @@ void CoinControlDialog::updateView()
|
||||
|
||||
// priority
|
||||
double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10
|
||||
itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority));
|
||||
itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPriority));
|
||||
itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPriority), 20, " "));
|
||||
dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1);
|
||||
nInputSum += nInputSize;
|
||||
@@ -775,7 +770,7 @@ void CoinControlDialog::updateView()
|
||||
itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")");
|
||||
itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum));
|
||||
itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " "));
|
||||
itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum));
|
||||
itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPrioritySum));
|
||||
itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPrioritySum), 20, " "));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Ui {
|
||||
}
|
||||
class WalletModel;
|
||||
class CCoinControl;
|
||||
class CTxMemPool;
|
||||
|
||||
class CoinControlDialog : public QDialog
|
||||
{
|
||||
@@ -32,7 +33,7 @@ public:
|
||||
|
||||
// static because also called from sendcoinsdialog
|
||||
static void updateLabels(WalletModel*, QDialog*);
|
||||
static QString getPriorityLabel(double);
|
||||
static QString getPriorityLabel(const CTxMemPool& pool, double);
|
||||
|
||||
static QList<qint64> payAmounts;
|
||||
static CCoinControl *coinControl;
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutDialog</class>
|
||||
<widget class="QDialog" name="AboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>593</width>
|
||||
<height>319</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About Bitcoin Core</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Ignored">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../bitcoin.qrc">:/images/about</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><b>Bitcoin Core</b> version</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="versionLabel">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0.3.666-beta</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="copyrightLabel">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Copyright &copy; 2009-YYYY The Bitcoin Core developers</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>
|
||||
This is experimental software.
|
||||
|
||||
Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../bitcoin.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -225,7 +225,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Low Output:</string>
|
||||
<string>Dust:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Bitcoin Core - Command-line options</string>
|
||||
<string notr="true">Bitcoin Core - Command-line options</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
@@ -54,17 +54,15 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="helpMessageLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Terminal</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
|
||||
@@ -242,6 +242,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="allowIncoming">
|
||||
<property name="toolTip">
|
||||
<string>Accept connections from outside</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow incoming connections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="connectSocks">
|
||||
<property name="toolTip">
|
||||
@@ -318,26 +328,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="socksVersionLabel">
|
||||
<property name="text">
|
||||
<string>SOCKS &Version:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>socksVersion</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QValueComboBox" name="socksVersion">
|
||||
<property name="toolTip">
|
||||
<string>SOCKS version of the proxy (e.g. 5)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_1_Network">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>573</width>
|
||||
<width>596</width>
|
||||
<height>342</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -46,204 +46,369 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Wallet</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Wallet</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelWalletStatus">
|
||||
<property name="toolTip">
|
||||
<string>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color: red; }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">(out of sync)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelWalletStatus">
|
||||
<property name="toolTip">
|
||||
<string>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color: red; }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">(out of sync)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelWatchonly">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Watchonly:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Available:</string>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<property name="horizontalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Available:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="labelBalance">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Your current spendable balance</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Pending:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelUnconfirmed">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelImmatureText">
|
||||
<property name="text">
|
||||
<string>Immature:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelImmature">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Mined balance that has not yet matured</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelTotalText">
|
||||
<property name="text">
|
||||
<string>Total:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="labelTotal">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Your current total balance</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="labelBalance">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
<property name="horizontalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Your current spendable balance</string>
|
||||
<property name="verticalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="labelWatchAvailable">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Your current balance in watchonly addresses</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelWatchPending">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Unconfirmed transactions to watchonly addresses</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelWatchImmature">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Mined balance in watchonly addresses that has not yet matured</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="Line" name="lineWatchBalance">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="labelWatchTotal">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Current total balance in watchonly addresses</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Pending:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelUnconfirmed">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelImmatureText">
|
||||
<property name="text">
|
||||
<string>Immature:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelImmature">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Mined balance that has not yet matured</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelTotalText">
|
||||
<property name="text">
|
||||
<string>Total:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="labelTotal">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Your current total balance</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
|
||||
@@ -113,14 +113,17 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<widget class="QLabel" name="label_berkeleyDBVersion">
|
||||
<property name="text">
|
||||
<string>Build date</string>
|
||||
<string>Using BerkeleyDB version</string>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="buildDate">
|
||||
<widget class="QLabel" name="berkeleyDBVersion">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
@@ -136,14 +139,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Startup time</string>
|
||||
<string>Build date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="startupTime">
|
||||
<widget class="QLabel" name="buildDate">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
@@ -159,6 +162,29 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Startup time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="startupTime">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="font">
|
||||
<font>
|
||||
@@ -171,14 +197,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="networkName">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
@@ -194,14 +220,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Number of connections</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="numberOfConnections">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
@@ -217,7 +243,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="font">
|
||||
<font>
|
||||
@@ -230,38 +256,15 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Current number of blocks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QLabel" name="numberOfBlocks">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Estimated total blocks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QLabel" name="totalBlocks">
|
||||
<widget class="QLabel" name="numberOfBlocks">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
@@ -556,7 +559,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>In:</string>
|
||||
<string>Received</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -636,7 +639,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Out:</string>
|
||||
<string>Sent</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -675,6 +678,281 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_peers">
|
||||
<attribute name="title">
|
||||
<string>&Peers</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="peerHeading">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select a peer to view detailed information.</string>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="QTableView" name="peerWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QWidget" name="detailWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Version:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QLabel" name="peerPingTime">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Last Receive:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>User Agent:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QLabel" name="peerVersion">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="peerConnTime">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>160</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>Ping Time:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="peerLastRecv">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Connection Time:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="peerBytesSent">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QLabel" name="peerSubversion">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Starting Height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLabel" name="peerBytesRecv">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Bytes Sent:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Bytes Received:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QLabel" name="peerHeight">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Ban Score:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QLabel" name="peerBanScore">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Direction:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="1">
|
||||
<widget class="QLabel" name="peerDirection">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="19" column="0">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>Sync Node:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="19" column="1">
|
||||
<widget class="QLabel" name="peerSyncNode">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Last Send:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Services:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>IP Address/port:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="peerLastSend">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="peerServices">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="peerAddr">
|
||||
<property name="text">
|
||||
<string>N/A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -417,7 +417,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Low Output:</string>
|
||||
<string>Dust:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<item>
|
||||
<widget class="QValidatedLineEdit" name="payTo">
|
||||
<property name="toolTip">
|
||||
<string>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
|
||||
<string>The Bitcoin address to send the payment to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<item>
|
||||
<widget class="QValidatedLineEdit" name="addressIn_SM">
|
||||
<property name="toolTip">
|
||||
<string>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
|
||||
<string>The Bitcoin address to sign the message with</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -255,7 +255,7 @@
|
||||
<item>
|
||||
<widget class="QValidatedLineEdit" name="addressIn_VM">
|
||||
<property name="toolTip">
|
||||
<string>The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
|
||||
<string>The Bitcoin address the message was signed with</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user