diff --git a/src/Makefile.am b/src/Makefile.am index 915ffd938..b1e27032c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,768 +1,772 @@ # Copyright (c) 2013-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. DIST_SUBDIRS = secp256k1 univalue AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS) $(SANITIZER_LDFLAGS) AM_CXXFLAGS = $(DEBUG_CXXFLAGS) $(HARDENED_CXXFLAGS) $(WARN_CXXFLAGS) $(NOWARN_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) $(SANITIZER_CXXFLAGS) AM_CPPFLAGS = $(DEBUG_CPPFLAGS) $(HARDENED_CPPFLAGS) AM_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_LIBRARIES = if EMBEDDED_UNIVALUE LIBUNIVALUE = univalue/libunivalue.la $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(wildcard univalue/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) else LIBUNIVALUE = $(UNIVALUE_LIBS) endif BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) BITCOIN_SEEDER_INCLUDES = -I$(srcdir)/seeder BITCOIN_SEEDER_INCLUDES += $(BITCOIN_INCLUDES) LIBBITCOIN_SERVER=libbitcoin_server.a LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO_BASE=crypto/libbitcoin_crypto_base.a LIBBITCOINQT=qt/libbitcoinqt.a LIBSECP256K1=secp256k1/libsecp256k1.la if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a endif if BUILD_BITCOIN_LIBS LIBBITCOINCONSENSUS=libbitcoinconsensus.la endif if BUILD_BITCOIN_SEEDER LIBBITCOIN_SEEDER=libbitcoin_seeder.a endif if ENABLE_WALLET LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_WALLET_TOOL=libbitcoin_wallet_tool.a endif LIBBITCOIN_CRYPTO= $(LIBBITCOIN_CRYPTO_BASE) if ENABLE_SSE41 LIBBITCOIN_CRYPTO_SSE41 = crypto/libbitcoin_crypto_sse41.a LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SSE41) endif if ENABLE_AVX2 LIBBITCOIN_CRYPTO_AVX2 = crypto/libbitcoin_crypto_avx2.a LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_AVX2) endif if ENABLE_SHANI LIBBITCOIN_CRYPTO_SHANI = crypto/libbitcoin_crypto_shani.a LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SHANI) endif $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES += \ $(LIBBITCOIN_CRYPTO) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_CLI) \ $(LIBBITCOIN_SEEDER) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_WALLET_TOOL) \ $(LIBBITCOIN_ZMQ) lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS) bin_PROGRAMS = noinst_PROGRAMS = TESTS = BENCHMARKS = if BUILD_BITCOIND bin_PROGRAMS += bitcoind endif if BUILD_BITCOIN_SEEDER bin_PROGRAMS += bitcoin-seeder endif if BUILD_BITCOIN_CLI bin_PROGRAMS += bitcoin-cli endif if BUILD_BITCOIN_TX bin_PROGRAMS += bitcoin-tx endif if ENABLE_WALLET if BUILD_BITCOIN_WALLET bin_PROGRAMS += bitcoin-wallet endif endif .PHONY: FORCE check-symbols check-security # bitcoin core # BITCOIN_CORE_H = \ addrdb.h \ addrman.h \ attributes.h \ avalanche.h \ banman.h \ base58.h \ bloom.h \ blockencodings.h \ blockfileinfo.h \ blockfilter.h \ blockindexworkcomparator.h \ blockstatus.h \ blockvalidity.h \ cashaddr.h \ cashaddrenc.h \ chain.h \ chainparams.h \ chainparamsbase.h \ chainparamsconstants.h \ chainparamsseeds.h \ checkpoints.h \ checkqueue.h \ clientversion.h \ coins.h \ compat.h \ compat/assumptions.h \ compat/byteswap.h \ compat/endian.h \ compat/sanity.h \ compat/setenv.h \ compressor.h \ config.h \ consensus/activation.h \ consensus/consensus.h \ consensus/tx_verify.h \ core_io.h \ core_memusage.h \ cuckoocache.h \ eventloop.h \ flatfile.h \ fs.h \ globals.h \ httprpc.h \ httpserver.h \ index/base.h \ index/txindex.h \ indirectmap.h \ init.h \ interfaces/chain.h \ interfaces/handler.h \ interfaces/node.h \ interfaces/wallet.h \ key.h \ key_io.h \ keystore.h \ dbwrapper.h \ limitedmap.h \ logging.h \ memusage.h \ merkleblock.h \ miner.h \ minerfund.h \ net.h \ net_processing.h \ netaddress.h \ netbase.h \ netmessagemaker.h \ node/transaction.h \ noui.h \ optional.h \ outputtype.h \ policy/fees.h \ policy/mempool.h \ policy/policy.h \ pow.h \ protocol.h \ psbt.h \ radix.h \ random.h \ rcu.h \ reverse_iterator.h \ reverselock.h \ rpc/blockchain.h \ rpc/client.h \ rpc/command.h \ rpc/jsonrpcrequest.h \ rpc/mining.h \ rpc/protocol.h \ rpc/rawtransaction.h \ rpc/server.h \ rpc/register.h \ rpc/util.h \ rwcollection.h \ scheduler.h \ script/descriptor.h \ script/ismine.h \ script/scriptcache.h \ script/sigcache.h \ script/sign.h \ script/standard.h \ shutdown.h \ streams.h \ support/allocators/secure.h \ support/allocators/zeroafterfree.h \ support/cleanse.h \ support/events.h \ support/lockedpool.h \ sync.h \ threadsafety.h \ threadinterrupt.h \ timedata.h \ torcontrol.h \ txdb.h \ txmempool.h \ ui_interface.h \ undo.h \ util/bitmanip.h \ util/bytevectorhash.h \ util/check.h \ util/macros.h \ util/moneystr.h \ util/system.h \ util/threadnames.h \ util/time.h \ validation.h \ validationinterface.h \ versionbits.h \ versionbitsinfo.h \ walletinitinterface.h \ wallet/coincontrol.h \ wallet/coinselection.h \ wallet/crypter.h \ wallet/db.h \ wallet/rpcdump.h \ wallet/fees.h \ wallet/psbtwallet.h \ wallet/rpcwallet.h \ wallet/wallet.h \ wallet/walletdb.h \ wallet/wallettool.h \ wallet/walletutil.h \ warnings.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ zmq/zmqnotificationinterface.h \ zmq/zmqpublishnotifier.h \ zmq/zmqrpc.h obj/build.h: FORCE @$(MKDIR_P) "$(builddir)/obj" @$(top_srcdir)/share/genbuild.sh "$(abs_top_builddir)/src/obj/build.h" \ "$(abs_top_srcdir)" libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: shared between bitcoind and bitcoin-qt libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ addrdb.cpp \ addrman.cpp \ avalanche.cpp \ banman.cpp \ bloom.cpp \ blockencodings.cpp \ blockfilter.cpp \ chain.cpp \ checkpoints.cpp \ config.cpp \ consensus/activation.cpp \ consensus/tx_verify.cpp \ flatfile.cpp \ globals.cpp \ httprpc.cpp \ httpserver.cpp \ index/base.cpp \ index/txindex.cpp \ init.cpp \ interfaces/chain.cpp \ interfaces/handler.cpp \ interfaces/node.cpp \ dbwrapper.cpp \ merkleblock.cpp \ miner.cpp \ minerfund.cpp \ net.cpp \ net_processing.cpp \ node/transaction.cpp \ noui.cpp \ outputtype.cpp \ policy/fees.cpp \ policy/mempool.cpp \ policy/policy.cpp \ pow.cpp \ rest.cpp \ rpc/abc.cpp \ rpc/avalanche.cpp \ rpc/blockchain.cpp \ rpc/command.cpp \ rpc/jsonrpcrequest.cpp \ rpc/mining.cpp \ rpc/misc.cpp \ rpc/net.cpp \ rpc/rawtransaction.cpp \ rpc/server.cpp \ script/scriptcache.cpp \ script/sigcache.cpp \ shutdown.cpp \ timedata.cpp \ torcontrol.cpp \ txdb.cpp \ txmempool.cpp \ ui_interface.cpp \ validation.cpp \ validationinterface.cpp \ versionbits.cpp \ $(BITCOIN_CORE_H) if !ENABLE_WALLET libbitcoin_server_a_SOURCES += dummywallet.cpp endif if ENABLE_ZMQ libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS) libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_zmq_a_SOURCES = \ zmq/zmqabstractnotifier.cpp \ zmq/zmqnotificationinterface.cpp \ zmq/zmqpublishnotifier.cpp \ zmq/zmqrpc.cpp endif # wallet: shared between bitcoind and bitcoin-qt, but only linked # when wallet enabled libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ interfaces/wallet.cpp \ wallet/coincontrol.cpp \ wallet/crypter.cpp \ wallet/coinselection.cpp \ wallet/db.cpp \ wallet/fees.cpp \ wallet/init.cpp \ wallet/psbtwallet.cpp \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ wallet/walletdb.cpp \ wallet/walletutil.cpp \ $(BITCOIN_CORE_H) libbitcoin_wallet_tool_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_wallet_tool_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_tool_a_SOURCES = \ wallet/wallettool.cpp \ $(BITCOIN_CORE_H) # crypto primitives library crypto_libbitcoin_crypto_base_a_CPPFLAGS = $(AM_CPPFLAGS) crypto_libbitcoin_crypto_base_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libbitcoin_crypto_base_a_SOURCES = \ crypto/aes.cpp \ crypto/aes.h \ crypto/chacha20.h \ crypto/chacha20.cpp \ crypto/common.h \ crypto/hmac_sha256.cpp \ crypto/hmac_sha256.h \ crypto/hmac_sha512.cpp \ crypto/hmac_sha512.h \ crypto/ripemd160.cpp \ crypto/ripemd160.h \ crypto/sha1.cpp \ crypto/sha1.h \ crypto/sha256.cpp \ crypto/sha256.h \ crypto/sha512.cpp \ crypto/sha512.h \ crypto/siphash.cpp \ crypto/siphash.h if USE_ASM crypto_libbitcoin_crypto_base_a_SOURCES += crypto/sha256_sse4.cpp endif crypto_libbitcoin_crypto_sse41_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libbitcoin_crypto_sse41_a_CPPFLAGS = $(AM_CPPFLAGS) crypto_libbitcoin_crypto_sse41_a_CXXFLAGS += $(SSE41_CXXFLAGS) crypto_libbitcoin_crypto_sse41_a_CPPFLAGS += -DENABLE_SSE41 crypto_libbitcoin_crypto_sse41_a_SOURCES = crypto/sha256_sse41.cpp crypto_libbitcoin_crypto_avx2_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libbitcoin_crypto_avx2_a_CPPFLAGS = $(AM_CPPFLAGS) crypto_libbitcoin_crypto_avx2_a_CXXFLAGS += $(AVX2_CXXFLAGS) crypto_libbitcoin_crypto_avx2_a_CPPFLAGS += -DENABLE_AVX2 crypto_libbitcoin_crypto_avx2_a_SOURCES = crypto/sha256_avx2.cpp crypto_libbitcoin_crypto_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libbitcoin_crypto_shani_a_CPPFLAGS = $(AM_CPPFLAGS) crypto_libbitcoin_crypto_shani_a_CXXFLAGS += $(SHANI_CXXFLAGS) crypto_libbitcoin_crypto_shani_a_CPPFLAGS += -DENABLE_SHANI crypto_libbitcoin_crypto_shani_a_SOURCES = crypto/sha256_shani.cpp # consensus: shared between all executables that validate any consensus rules. libbitcoin_consensus_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_consensus_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_consensus_a_SOURCES = \ amount.h \ arith_uint256.cpp \ arith_uint256.h \ consensus/merkle.cpp \ consensus/merkle.h \ consensus/params.h \ consensus/validation.h \ feerate.h \ hash.cpp \ hash.h \ prevector.h \ primitives/block.cpp \ primitives/block.h \ primitives/transaction.cpp \ primitives/transaction.h \ primitives/txid.h \ pubkey.cpp \ pubkey.h \ script/bitcoinconsensus.cpp \ script/bitfield.cpp \ script/bitfield.h \ script/sighashtype.h \ script/interpreter.cpp \ script/interpreter.h \ script/script.cpp \ script/script.h \ script/script_error.cpp \ script/script_error.h \ script/script_flags.h \ script/script_metrics.h \ script/sigencoding.cpp \ script/sigencoding.h \ serialize.h \ span.h \ tinyformat.h \ uint256.cpp \ uint256.h \ util/strencodings.cpp \ util/strencodings.h \ version.h # common: shared between bitcoind, and bitcoin-qt and non-server tools libbitcoin_common_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_common_a_SOURCES = \ amount.cpp \ base58.cpp \ cashaddr.cpp \ cashaddrenc.cpp \ chainparams.cpp \ config.cpp \ coins.cpp \ compressor.cpp \ eventloop.cpp \ feerate.cpp \ globals.cpp \ core_read.cpp \ core_write.cpp \ key.cpp \ key_io.cpp \ keystore.cpp \ netaddress.cpp \ netbase.cpp \ protocol.cpp \ psbt.cpp \ scheduler.cpp \ script/descriptor.cpp \ script/ismine.cpp \ script/sign.cpp \ script/standard.cpp \ versionbitsinfo.cpp \ warnings.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 = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_util_a_SOURCES = \ support/lockedpool.cpp \ chainparamsbase.cpp \ clientversion.cpp \ compat/glibc_sanity.cpp \ compat/glibcxx_sanity.cpp \ compat/strnlen.cpp \ fs.cpp \ logging.cpp \ random.cpp \ rcu.cpp \ rpc/protocol.cpp \ rpc/util.cpp \ support/cleanse.cpp \ sync.cpp \ threadinterrupt.cpp \ uint256.cpp \ uint256.h \ util/system.cpp \ util/moneystr.cpp \ util/strencodings.cpp \ util/threadnames.cpp \ util/time.cpp \ util/bytevectorhash.cpp \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp AM_LDFLAGS += $(COMPAT_LDFLAGS) endif # cli: shared between bitcoin-cli and bitcoin-qt libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_cli_a_SOURCES = \ rpc/client.cpp \ $(BITCOIN_CORE_H) # seeder library libbitcoin_seeder_a_CPPFLAGS = $(AM_CPPFLAGS) $(PIE_FLAGS) $(BITCOIN_SEEDER_INCLUDES) libbitcoin_seeder_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_seeder_a_SOURCES = \ seeder/bitcoin.cpp \ seeder/bitcoin.h \ seeder/db.cpp \ seeder/db.h \ seeder/dns.cpp \ seeder/dns.h \ seeder/util.h nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h # # bitcoind binary # bitcoind_SOURCES = bitcoind.cpp bitcoind_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) bitcoind_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoind_SOURCES += bitcoind-res.rc endif bitcoind_LDADD = \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_ZMQ) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ $(LIBSECP256K1) bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # bitcoin-cli binary # bitcoin_cli_SOURCES = bitcoin-cli.cpp bitcoin_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) bitcoin_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoin_cli_SOURCES += bitcoin-cli-res.rc endif bitcoin_cli_LDADD = \ $(LIBBITCOIN_CLI) \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS) # # bitcoin-seeder binary # bitcoin_seeder_SOURCES = seeder/main.cpp bitcoin_seeder_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_SEEDER_INCLUDES) bitcoin_seeder_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_seeder_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) bitcoin_seeder_LDADD = \ $(LIBBITCOIN_SEEDER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) \ $(LIBBITCOIN_CONSENSUS) bitcoin_seeder_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # # bitcoin-tx binary # bitcoin_tx_SOURCES = bitcoin-tx.cpp bitcoin_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) bitcoin_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoin_tx_SOURCES += bitcoin-tx-res.rc endif bitcoin_tx_LDADD = \ $(LIBUNIVALUE) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBSECP256K1) bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # # bitcoin-wallet binary # bitcoin_wallet_SOURCES = bitcoin-wallet.cpp bitcoin_wallet_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) bitcoin_wallet_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_wallet_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoin_wallet_SOURCES += bitcoin-wallet-res.rc endif bitcoin_wallet_LDADD = \ $(LIBBITCOIN_WALLET_TOOL) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_WALLET) \ + $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_ZMQ) \ $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ - $(LIBSECP256K1) + $(LIBSECP256K1) \ + $(LIBUNIVALUE) -bitcoin_wallet_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) +bitcoin_wallet_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(ZMQ_LIBS) # # bitcoinconsensus library # if BUILD_BITCOIN_LIBS include_HEADERS = script/bitcoinconsensus.h libbitcoinconsensus_la_SOURCES = $(crypto_libbitcoin_crypto_base_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) if GLIBC_BACK_COMPAT libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp endif libbitcoinconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1) libbitcoinconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL libbitcoinconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) endif # CTAES_DIST = crypto/ctaes/bench.c CTAES_DIST += crypto/ctaes/ctaes.c CTAES_DIST += crypto/ctaes/ctaes.h CTAES_DIST += crypto/ctaes/README.md CTAES_DIST += crypto/ctaes/test.c CLEANFILES = $(EXTRA_LIBRARIES) CLEANFILES += *.gcda *.gcno CLEANFILES += compat/*.gcda compat/*.gcno CLEANFILES += consensus/*.gcda consensus/*.gcno CLEANFILES += crypto/*.gcda crypto/*.gcno CLEANFILES += policy/*.gcda policy/*.gcno CLEANFILES += primitives/*.gcda primitives/*.gcno CLEANFILES += script/*.gcda script/*.gcno CLEANFILES += support/*.gcda support/*.gcno CLEANFILES += univalue/*.gcda univalue/*.gcno CLEANFILES += wallet/*.gcda wallet/*.gcno CLEANFILES += wallet/test/*.gcda wallet/test/*.gcno CLEANFILES += zmq/*.gcda zmq/*.gcno CLEANFILES += obj/build.h EXTRA_DIST = $(CTAES_DIST) config/bitcoin-config.h: config/stamp-h1 @$(MAKE) -C $(top_builddir) $(subdir)/$(@) config/stamp-h1: $(top_srcdir)/$(subdir)/config/bitcoin-config.h.in $(top_builddir)/config.status $(AM_V_at)$(MAKE) -C $(top_builddir) $(subdir)/$(@) $(top_srcdir)/$(subdir)/config/bitcoin-config.h.in: $(am__configure_deps) $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/bitcoin-config.h.in clean-local: -$(MAKE) -C secp256k1 clean -$(MAKE) -C univalue clean -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno -rm -rf test/__pycache__ .rc.o: @test -f $(WINDRES) ## FIXME: How to get the appropriate modulename_CPPFLAGS in here? $(AM_V_GEN) $(WINDRES) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) -DWINDRES_PREPROC -i $< -o $@ .mm.o: $(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) -c -o $@ $< check-symbols: $(bin_PROGRAMS) if GLIBC_BACK_COMPAT @echo "Checking glibc back compat..." $(AM_V_at) READELF=$(READELF) CPPFILT=$(CPPFILT) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py < $(bin_PROGRAMS) endif check-security: $(bin_PROGRAMS) if HARDEN @echo "Checking binary security..." $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS) endif if ENABLE_BIP70 %.pb.cc %.pb.h: %.proto @test -f $(PROTOC) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$( "$@.new" && mv -f "$@.new" "$@" @echo "Generated $@" diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index c7462d0e7..079ab3a30 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -1,234 +1,236 @@ // Copyright (c) 2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include +#include #include #include #include #include #include #include #include #include #include #include namespace interfaces { namespace { class LockImpl : public Chain::Lock { Optional getHeight() override { int height = ::ChainActive().Height(); if (height >= 0) { return height; } return nullopt; } Optional getBlockHeight(const BlockHash &hash) override { CBlockIndex *block = LookupBlockIndex(hash); if (block && ::ChainActive().Contains(block)) { return block->nHeight; } return nullopt; } int getBlockDepth(const BlockHash &hash) override { const Optional tip_height = getHeight(); const Optional height = getBlockHeight(hash); return tip_height && height ? *tip_height - *height + 1 : 0; } BlockHash getBlockHash(int height) override { CBlockIndex *block = ::ChainActive()[height]; assert(block != nullptr); return block->GetBlockHash(); } int64_t getBlockTime(int height) override { CBlockIndex *block = ::ChainActive()[height]; assert(block != nullptr); return block->GetBlockTime(); } int64_t getBlockMedianTimePast(int height) override { CBlockIndex *block = ::ChainActive()[height]; assert(block != nullptr); return block->GetMedianTimePast(); } bool haveBlockOnDisk(int height) override { CBlockIndex *block = ::ChainActive()[height]; return block && (block->nStatus.hasData() != 0) && block->nTx > 0; } Optional findFirstBlockWithTime(int64_t time, BlockHash *hash) override { CBlockIndex *block = ::ChainActive().FindEarliestAtLeast(time); if (block) { if (hash) { *hash = block->GetBlockHash(); } return block->nHeight; } return nullopt; } Optional findFirstBlockWithTimeAndHeight(int64_t time, int height) override { // TODO: Could update CChain::FindEarliestAtLeast() to take a height // parameter and use it with std::lower_bound() to make this // implementation more efficient and allow combining // findFirstBlockWithTime and findFirstBlockWithTimeAndHeight into // one method. for (CBlockIndex *block = ::ChainActive()[height]; block; block = ::ChainActive().Next(block)) { if (block->GetBlockTime() >= time) { return block->nHeight; } } return nullopt; } Optional findPruned(int start_height, Optional stop_height) override { if (::fPruneMode) { CBlockIndex *block = stop_height ? ::ChainActive()[*stop_height] : ::ChainActive().Tip(); while (block && block->nHeight >= start_height) { if (block->nStatus.hasData() == 0) { return block->nHeight; } block = block->pprev; } } return nullopt; } Optional findFork(const BlockHash &hash, Optional *height) override { const CBlockIndex *block = LookupBlockIndex(hash); const CBlockIndex *fork = block ? ::ChainActive().FindFork(block) : nullptr; if (height) { if (block) { *height = block->nHeight; } else { height->reset(); } } if (fork) { return fork->nHeight; } return nullopt; } bool isPotentialTip(const BlockHash &hash) override { if (::ChainActive().Tip()->GetBlockHash() == hash) { return true; } CBlockIndex *block = LookupBlockIndex(hash); return block && block->GetAncestor(::ChainActive().Height()) == ::ChainActive().Tip(); } CBlockLocator getLocator() override { return ::ChainActive().GetLocator(); } Optional findLocatorFork(const CBlockLocator &locator) override { LockAnnotation lock(::cs_main); if (CBlockIndex *fork = FindForkInGlobalIndex(::ChainActive(), locator)) { return fork->nHeight; } return nullopt; } bool contextualCheckTransactionForCurrentBlock( const Consensus::Params ¶ms, const CTransaction &tx, CValidationState &state) override { LockAnnotation lock(::cs_main); return ContextualCheckTransactionForCurrentBlock(params, tx, state); } }; class LockingStateImpl : public LockImpl, public UniqueLock { using UniqueLock::UniqueLock; }; class ChainImpl : public Chain { public: std::unique_ptr lock(bool try_lock) override { auto result = std::make_unique( ::cs_main, "cs_main", __FILE__, __LINE__, try_lock); if (try_lock && result && !*result) { return {}; } return result; } std::unique_ptr assumeLocked() override { return std::make_unique(); } bool findBlock(const BlockHash &hash, CBlock *block, int64_t *time, int64_t *time_max) override { CBlockIndex *index; { LOCK(cs_main); index = LookupBlockIndex(hash); if (!index) { return false; } if (time) { *time = index->GetBlockTime(); } if (time_max) { *time_max = index->GetBlockTimeMax(); } } if (block && !ReadBlockFromDisk(*block, index, Params().GetConsensus())) { block->SetNull(); } return true; } double guessVerificationProgress(const BlockHash &block_hash) override { LOCK(cs_main); return GuessVerificationProgress(Params().TxData(), LookupBlockIndex(block_hash)); } bool hasDescendantsInMempool(const TxId &txid) override { LOCK(::g_mempool.cs); auto it_mp = ::g_mempool.mapTx.find(txid); return it_mp != ::g_mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1; } void getTransactionAncestry(const TxId &txid, size_t &ancestors, size_t &descendants) override { ::g_mempool.GetTransactionAncestry(txid, ancestors, descendants); } bool checkChainLimits(CTransactionRef tx) override { LockPoints lp; CTxMemPoolEntry entry(tx, Amount(), 0, 0, false, 0, lp); CTxMemPool::setEntries ancestors; auto limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); auto limit_ancestor_size = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000; auto limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); auto limit_descendant_size = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000; std::string unused_error_string; LOCK(::g_mempool.cs); return ::g_mempool.CalculateMemPoolAncestors( entry, ancestors, limit_ancestor_count, limit_ancestor_size, limit_descendant_count, limit_descendant_size, unused_error_string); } bool getPruneMode() override { return ::fPruneMode; } + bool p2pEnabled() override { return g_connman != nullptr; } }; } // namespace std::unique_ptr MakeChain() { return std::make_unique(); } } // namespace interfaces diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index bac090079..e9a8d1ccd 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -1,203 +1,206 @@ // Copyright (c) 2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_INTERFACES_CHAIN_H #define BITCOIN_INTERFACES_CHAIN_H #include #include #include #include #include #include #include #include struct BlockHash; class CBlock; struct CBlockLocator; class CChainParams; class CScheduler; class CTransaction; class CValidationState; namespace Consensus { struct Params; } namespace interfaces { //! Interface for giving wallet processes access to blockchain state. class Chain { public: virtual ~Chain() {} //! Interface for querying locked chain state, used by legacy code that //! assumes state won't change between calls. New code should avoid using //! the Lock interface and instead call higher-level Chain methods //! that return more information so the chain doesn't need to stay locked //! between calls. class Lock { public: virtual ~Lock() {} //! Get current chain height, not including genesis block (returns 0 if //! chain only contains genesis block, nullopt if chain does not contain //! any blocks). virtual Optional getHeight() = 0; //! Get block height above genesis block. Returns 0 for genesis block, //! 1 for following block, and so on. Returns nullopt for a block not //! included in the current chain. virtual Optional getBlockHeight(const BlockHash &hash) = 0; //! Get block depth. Returns 1 for chain tip, 2 for preceding block, and //! so on. Returns 0 for a block not included in the current chain. virtual int getBlockDepth(const BlockHash &hash) = 0; //! Get block hash. Height must be valid or this function will abort. virtual BlockHash getBlockHash(int height) = 0; //! Get block time. Height must be valid or this function will abort. virtual int64_t getBlockTime(int height) = 0; //! Get block median time past. Height must be valid or this function //! will abort. virtual int64_t getBlockMedianTimePast(int height) = 0; //! Check that the block is available on disk (i.e. has not been //! pruned), and contains transactions. virtual bool haveBlockOnDisk(int height) = 0; //! Return height of the first block in the chain with timestamp equal //! or greater than the given time, or nullopt if there is no block with //! a high enough timestamp. Also return the block hash as an optional //! output parameter (to avoid the cost of a second lookup in case this //! information is needed.) virtual Optional findFirstBlockWithTime(int64_t time, BlockHash *hash) = 0; //! Return height of the first block in the chain with timestamp equal //! or greater than the given time and height equal or greater than the //! given height, or nullopt if there is no such block. //! //! Calling this with height 0 is equivalent to calling //! findFirstBlockWithTime, but less efficient because it requires a //! linear instead of a binary search. virtual Optional findFirstBlockWithTimeAndHeight(int64_t time, int height) = 0; //! Return height of last block in the specified range which is pruned, //! or nullopt if no block in the range is pruned. Range is inclusive. virtual Optional findPruned(int start_height = 0, Optional stop_height = nullopt) = 0; //! Return height of the highest block on the chain that is an ancestor //! of the specified block, or nullopt if no common ancestor is found. //! Also return the height of the specified block as an optional output //! parameter (to avoid the cost of a second hash lookup in case this //! information is desired). virtual Optional findFork(const BlockHash &hash, Optional *height) = 0; //! Return true if block hash points to the current chain tip, or to a //! possible descendant of the current chain tip that isn't currently //! connected. virtual bool isPotentialTip(const BlockHash &hash) = 0; //! Get locator for the current chain tip. virtual CBlockLocator getLocator() = 0; //! Return height of the latest block common to locator and chain, which //! is guaranteed to be an ancestor of the block used to create the //! locator. virtual Optional findLocatorFork(const CBlockLocator &locator) = 0; //! Check if transaction will be final given chain height current time. virtual bool contextualCheckTransactionForCurrentBlock( const Consensus::Params ¶ms, const CTransaction &tx, CValidationState &state) = 0; }; //! Return Lock interface. Chain is locked when this is called, and //! unlocked when the returned interface is freed. virtual std::unique_ptr lock(bool try_lock = false) = 0; //! Return Lock interface assuming chain is already locked. This //! method is temporary and is only used in a few places to avoid changing //! behavior while code is transitioned to use the Chain::Lock interface. virtual std::unique_ptr assumeLocked() = 0; //! Return whether node has the block and optionally return block metadata //! or contents. //! //! If a block pointer is provided to retrieve the block contents, and the //! block exists but doesn't have data (for example due to pruning), the //! block will be empty and all fields set to null. virtual bool findBlock(const BlockHash &hash, CBlock *block = nullptr, int64_t *time = nullptr, int64_t *max_time = nullptr) = 0; //! Estimate fraction of total transactions verified if blocks up to //! the specified block hash are verified. virtual double guessVerificationProgress(const BlockHash &block_hash) = 0; //! Check if transaction has descendants in mempool. virtual bool hasDescendantsInMempool(const TxId &txid) = 0; //! Calculate mempool ancestor and descendant counts for the given //! transaction. virtual void getTransactionAncestry(const TxId &txid, size_t &ancestors, size_t &descendants) = 0; //! Check chain limits. virtual bool checkChainLimits(CTransactionRef tx) = 0; //! Check if pruning is enabled. virtual bool getPruneMode() = 0; + + //! Check if p2p enabled. + virtual bool p2pEnabled() = 0; }; //! Interface to let node manage chain clients (wallets, or maybe tools for //! monitoring and analysis in the future). class ChainClient { public: virtual ~ChainClient() {} //! Register rpcs. virtual void registerRpcs() = 0; //! Check for errors before loading. virtual bool verify(const CChainParams &chainParams) = 0; //! Load saved state. virtual bool load(const CChainParams &chainParams) = 0; //! Start client execution and provide a scheduler. virtual void start(CScheduler &scheduler) = 0; //! Save state to disk. virtual void flush() = 0; //! Shut down client. virtual void stop() = 0; }; //! Return implementation of Chain interface. std::unique_ptr MakeChain(); //! Return implementation of ChainClient interface for a wallet client. This //! function will be undefined in builds where ENABLE_WALLET is false. //! //! Currently, wallets are the only chain clients. But in the future, other //! types of chain clients could be added, such as tools for monitoring, //! analysis, or fee estimation. These clients need to expose their own //! MakeXXXClient functions returning their implementations of the ChainClient //! interface. std::unique_ptr MakeWalletClient(Chain &chain, std::vector wallet_filenames); } // namespace interfaces #endif // BITCOIN_INTERFACES_CHAIN_H diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index 4e941bc3e..18091479a 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -1,32 +1,32 @@ # Copyright (c) 2017 The Bitcoin developers project(wallet) # Add Berkeley DB dependency. find_package(BerkeleyDB 5.3 REQUIRED COMPONENTS CXX) # Add event dependency. This is only required for evhttp_uridecode # in rpcwallet.cpp so it may be worth considering using an alternative. find_package(Event 2.0.22 REQUIRED COMPONENTS event) add_library(wallet ../interfaces/wallet.cpp coincontrol.cpp coinselection.cpp crypter.cpp db.cpp fees.cpp init.cpp psbtwallet.cpp rpcdump.cpp rpcwallet.cpp wallet.cpp walletdb.cpp walletutil.cpp ) -target_link_libraries(wallet script univalue Event::event BerkeleyDB::CXX) +target_link_libraries(wallet zmq server script univalue Event::event BerkeleyDB::CXX) # wallet-tool library add_library(wallet-tool wallettool.cpp) target_link_libraries(wallet-tool wallet) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5549159fd..f9ee2bb5e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1,4910 +1,4910 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include // for GetConsensus. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; static std::string urlDecode(const std::string &urlEncoded) { std::string res; if (!urlEncoded.empty()) { char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, nullptr); if (decoded) { res = std::string(decoded); free(decoded); } } return res; } bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name) { if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) { // wallet endpoint was used wallet_name = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size())); return true; } return false; } std::shared_ptr GetWalletForJSONRPCRequest(const JSONRPCRequest &request) { std::string wallet_name; if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) { std::shared_ptr pwallet = GetWallet(wallet_name); if (!pwallet) { throw JSONRPCError( RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded"); } return pwallet; } std::vector> wallets = GetWallets(); return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr; } std::string HelpRequiringPassphrase(CWallet *const pwallet) { return pwallet && pwallet->IsCrypted() ? "\nRequires wallet passphrase to be set with walletpassphrase " "call." : ""; } bool EnsureWalletIsAvailable(CWallet *const pwallet, bool avoidException) { if (pwallet) { return true; } if (avoidException) { return false; } if (!HasWallets()) { throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (wallet method is disabled " "because no wallet is loaded)"); } throw JSONRPCError(RPC_WALLET_NOT_SPECIFIED, "Wallet file not specified (must request wallet RPC " "through /wallet/ uri-path)."); } void EnsureWalletIsUnlocked(CWallet *const pwallet) { if (pwallet->IsLocked()) { throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with " "walletpassphrase first."); } } static void WalletTxToJSON(interfaces::Chain &chain, interfaces::Chain::Lock &locked_chain, const CWalletTx &wtx, UniValue &entry) { int confirms = wtx.GetDepthInMainChain(locked_chain); entry.pushKV("confirmations", confirms); if (wtx.IsCoinBase()) { entry.pushKV("generated", true); } if (confirms > 0) { entry.pushKV("blockhash", wtx.hashBlock.GetHex()); entry.pushKV("blockindex", wtx.nIndex); int64_t block_time; bool found_block = chain.findBlock(wtx.hashBlock, nullptr /* block */, &block_time); assert(found_block); entry.pushKV("blocktime", block_time); } else { entry.pushKV("trusted", wtx.IsTrusted(locked_chain)); } uint256 hash = wtx.GetId(); entry.pushKV("txid", hash.GetHex()); UniValue conflicts(UniValue::VARR); for (const uint256 &conflict : wtx.GetConflicts()) { conflicts.push_back(conflict.GetHex()); } entry.pushKV("walletconflicts", conflicts); entry.pushKV("time", wtx.GetTxTime()); entry.pushKV("timereceived", (int64_t)wtx.nTimeReceived); for (const std::pair &item : wtx.mapValue) { entry.pushKV(item.first, item.second); } } static std::string LabelFromValue(const UniValue &value) { std::string label = value.get_str(); if (label == "*") { throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name"); } return label; } static UniValue getnewaddress(const Config &config, const JSONRPCRequest &request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } if (request.fHelp || request.params.size() > 2) { throw std::runtime_error( RPCHelpMan{ "getnewaddress", "\nReturns a new Bitcoin address for receiving payments.\n" "If 'label' is specified, it is added to the address book \n" "so payments received with the address will be associated with " "'label'.\n", { {"label", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "The label name for the address to be linked to. If not " "provided, the default label \"\" is used. It can also be " "set to the empty string \"\" to represent the default " "label. The label does not need to exist, it will be " "created if there is no label by the given name."}, }} .ToString() + "\nResult:\n" "\"address\" (string) The new bitcoin address\n" "\nExamples:\n" + HelpExampleRpc("getnewaddress", "")); } // Belt and suspenders check for disabled private keys if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet"); } LOCK(pwallet->cs_wallet); if (!pwallet->CanGetAddresses()) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys"); } // Parse the label first so we don't generate a key if there's an error std::string label; if (!request.params[0].isNull()) { label = LabelFromValue(request.params[0]); } OutputType output_type = pwallet->m_default_address_type; if (!request.params[1].isNull()) { if (!ParseOutputType(request.params[1].get_str(), output_type)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str())); } } if (!pwallet->IsLocked()) { pwallet->TopUpKeyPool(); } // Generate a new key that is added to wallet CPubKey newKey; if (!pwallet->GetKeyFromPool(newKey)) { throw JSONRPCError( RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); } pwallet->LearnRelatedScripts(newKey, output_type); CTxDestination dest = GetDestinationForKey(newKey, output_type); pwallet->SetAddressBook(dest, label, "receive"); return EncodeDestination(dest, config); } static UniValue getrawchangeaddress(const Config &config, const JSONRPCRequest &request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } if (request.fHelp || request.params.size() > 1) { throw std::runtime_error( RPCHelpMan{ "getrawchangeaddress", "\nReturns a new Bitcoin address, for receiving change.\n" "This is for use with raw transactions, NOT normal use.\n", {}} .ToString() + "\nResult:\n" "\"address\" (string) The address\n" "\nExamples:\n" + HelpExampleCli("getrawchangeaddress", "") + HelpExampleRpc("getrawchangeaddress", "")); } // Belt and suspenders check for disabled private keys if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet"); } LOCK(pwallet->cs_wallet); if (!pwallet->CanGetAddresses(true)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys"); } if (!pwallet->IsLocked()) { pwallet->TopUpKeyPool(); } OutputType output_type = pwallet->m_default_change_type != OutputType::CHANGE_AUTO ? pwallet->m_default_change_type : pwallet->m_default_address_type; if (!request.params[0].isNull()) { if (!ParseOutputType(request.params[0].get_str(), output_type)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str())); } } CReserveKey reservekey(pwallet); CPubKey vchPubKey; if (!reservekey.GetReservedKey(vchPubKey, true)) { throw JSONRPCError( RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); } reservekey.KeepKey(); pwallet->LearnRelatedScripts(vchPubKey, output_type); CTxDestination dest = GetDestinationForKey(vchPubKey, output_type); return EncodeDestination(dest, config); } static UniValue setlabel(const Config &config, const JSONRPCRequest &request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } if (request.fHelp || request.params.size() != 2) { throw std::runtime_error( RPCHelpMan{ "setlabel", "\nSets the label associated with the given address.\n", { {"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address to be associated with a label."}, {"label", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The label to assign to the address."}, }} .ToString() + "\nExamples:\n" + HelpExampleCli("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"") + HelpExampleRpc( "setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")); } LOCK(pwallet->cs_wallet); CTxDestination dest = DecodeDestination(request.params[0].get_str(), config.GetChainParams()); if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); } std::string old_label = pwallet->mapAddressBook[dest].name; std::string label = LabelFromValue(request.params[1]); if (IsMine(*pwallet, dest)) { pwallet->SetAddressBook(dest, label, "receive"); } else { pwallet->SetAddressBook(dest, label, "send"); } return NullUniValue; } static CTransactionRef SendMoney(interfaces::Chain::Lock &locked_chain, CWallet *const pwallet, const CTxDestination &address, Amount nValue, bool fSubtractFeeFromAmount, mapValue_t mapValue) { Amount curBalance = pwallet->GetBalance(); // Check amount if (nValue <= Amount::zero()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount"); } if (nValue > curBalance) { throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); } - if (pwallet->GetBroadcastTransactions() && !g_connman) { + if (pwallet->GetBroadcastTransactions() && !pwallet->chain().p2pEnabled()) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } // Parse Bitcoin address CScript scriptPubKey = GetScriptForDestination(address); // Create and send the transaction CReserveKey reservekey(pwallet); Amount nFeeRequired; std::string strError; std::vector vecSend; int nChangePosRet = -1; CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount}; vecSend.push_back(recipient); CCoinControl coinControl; CTransactionRef tx; if (!pwallet->CreateTransaction(locked_chain, vecSend, tx, reservekey, nFeeRequired, nChangePosRet, strError, coinControl)) { if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance) { strError = strprintf("Error: This transaction requires a " "transaction fee of at least %s", FormatMoney(nFeeRequired)); } throw JSONRPCError(RPC_WALLET_ERROR, strError); } CValidationState state; if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, reservekey, g_connman.get(), state)) { strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state)); throw JSONRPCError(RPC_WALLET_ERROR, strError); } return tx; } static UniValue sendtoaddress(const Config &config, const JSONRPCRequest &request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } if (request.fHelp || request.params.size() < 2 || request.params.size() > 5) { throw std::runtime_error( RPCHelpMan{ "sendtoaddress", "\nSend an amount to a given address.\n" + HelpRequiringPassphrase(pwallet) + "\n", { {"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address to send to."}, {"amount", RPCArg::Type::AMOUNT, /* opt */ false, /* default_val */ "", "The amount in " + CURRENCY_UNIT + " to send. eg 0.1"}, {"comment", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "A comment used to store what the transaction is for.\n" " This is not part of the " "transaction, just kept in your wallet."}, {"comment_to", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "A comment to store the name of the person or " "organization\n" " to which you're sending the " "transaction. This is not part of the \n" " transaction, just kept in " "your wallet."}, {"subtractfeefromamount", RPCArg::Type::BOOL, /* opt */ true, /* default_val */ "false", "The fee will be deducted from the amount being sent.\n" " The recipient will receive " "less bitcoins than you enter in the amount field."}, }} .ToString() + "\nResult:\n" "\"txid\" (string) The transaction id.\n" "\nExamples:\n" + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1") + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvay" "dd\" 0.1 \"donation\" \"seans " "outpost\"") + HelpExampleCli( "sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true") + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvay" "dd\", 0.1, \"donation\", \"seans " "outpost\"")); } // Make sure the results are valid at least up to the most recent block // the user could have gotten from another RPC command prior to now pwallet->BlockUntilSyncedToCurrentChain(); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); CTxDestination dest = DecodeDestination(request.params[0].get_str(), config.GetChainParams()); if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); } // Amount Amount nAmount = AmountFromValue(request.params[1]); if (nAmount <= Amount::zero()) { throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); } // Wallet comments mapValue_t mapValue; if (!request.params[2].isNull() && !request.params[2].get_str().empty()) { mapValue["comment"] = request.params[2].get_str(); } if (!request.params[3].isNull() && !request.params[3].get_str().empty()) { mapValue["to"] = request.params[3].get_str(); } bool fSubtractFeeFromAmount = false; if (!request.params[4].isNull()) { fSubtractFeeFromAmount = request.params[4].get_bool(); } EnsureWalletIsUnlocked(pwallet); CTransactionRef tx = SendMoney(*locked_chain, pwallet, dest, nAmount, fSubtractFeeFromAmount, std::move(mapValue)); return tx->GetId().GetHex(); } static UniValue listaddressgroupings(const Config &config, const JSONRPCRequest &request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } if (request.fHelp || request.params.size() != 0) { throw std::runtime_error( RPCHelpMan{"listaddressgroupings", "\nLists groups of addresses which have had their " "common ownership\n" "made public by common use as inputs or as the " "resulting change\n" "in past transactions\n", {}} .ToString() + "\nResult:\n" "[\n" " [\n" " [\n" " \"address\", (string) The bitcoin address\n" " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"label\" (string, optional) The label\n" " ]\n" " ,...\n" " ]\n" " ,...\n" "]\n" "\nExamples:\n" + HelpExampleCli("listaddressgroupings", "") + HelpExampleRpc("listaddressgroupings", "")); } // Make sure the results are valid at least up to the most recent block // the user could have gotten from another RPC command prior to now pwallet->BlockUntilSyncedToCurrentChain(); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); UniValue jsonGroupings(UniValue::VARR); std::map balances = pwallet->GetAddressBalances(*locked_chain); for (const std::set &grouping : pwallet->GetAddressGroupings()) { UniValue jsonGrouping(UniValue::VARR); for (const CTxDestination &address : grouping) { UniValue addressInfo(UniValue::VARR); addressInfo.push_back(EncodeDestination(address, config)); addressInfo.push_back(ValueFromAmount(balances[address])); if (pwallet->mapAddressBook.find(address) != pwallet->mapAddressBook.end()) { addressInfo.push_back( pwallet->mapAddressBook.find(address)->second.name); } jsonGrouping.push_back(addressInfo); } jsonGroupings.push_back(jsonGrouping); } return jsonGroupings; } static UniValue signmessage(const Config &config, const JSONRPCRequest &request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } if (request.fHelp || request.params.size() != 2) { throw std::runtime_error( RPCHelpMan{"signmessage", "\nSign a message with the private key of an address" + HelpRequiringPassphrase(pwallet) + "\n", { {"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address to use for the private key."}, {"message", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The message to create a signature of."}, }} .ToString() + "\nResult:\n" "\"signature\" (string) The signature of the message " "encoded in base 64\n" "\nExamples:\n" "\nUnlock the wallet for 30 seconds\n" + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + "\nCreate the signature\n" + HelpExampleCli( "signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") + "\nVerify the signature\n" + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4" "XX\" \"signature\" \"my " "message\"") + "\nAs a JSON-RPC call\n" + HelpExampleRpc( "signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")); } auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); EnsureWalletIsUnlocked(pwallet); std::string strAddress = request.params[0].get_str(); std::string strMessage = request.params[1].get_str(); CTxDestination dest = DecodeDestination(strAddress, config.GetChainParams()); if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); } const CKeyID *keyID = boost::get(&dest); if (!keyID) { throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); } CKey key; if (!pwallet->GetKey(*keyID, key)) { throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); } CHashWriter ss(SER_GETHASH, 0); ss << strMessageMagic; ss << strMessage; std::vector vchSig; if (!key.SignCompact(ss.GetHash(), vchSig)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed"); } return EncodeBase64(vchSig.data(), vchSig.size()); } static UniValue getreceivedbyaddress(const Config &config, const JSONRPCRequest &request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { throw std::runtime_error( RPCHelpMan{ "getreceivedbyaddress", "\nReturns the total amount received by the given address in " "transactions with at least minconf confirmations.\n", { {"address", RPCArg::Type::STR, /* opt */ false, /* default_val */ "", "The bitcoin address for transactions."}, {"minconf", RPCArg::Type::NUM, /* opt */ true, /* default_val */ "1", "Only include transactions confirmed at least this many " "times."}, }} .ToString() + "\nResult:\n" "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n" "\nExamples:\n" "\nThe amount from transactions with at least 1 confirmation\n" + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") + "\nThe amount including unconfirmed transactions, zero " "confirmations\n" + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 0") + "\nThe amount with at least 6 confirmations\n" + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") + "\nAs a JSON-RPC call\n" + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")); } // Make sure the results are valid at least up to the most recent block // the user could have gotten from another RPC command prior to now pwallet->BlockUntilSyncedToCurrentChain(); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); // Bitcoin address CTxDestination dest = DecodeDestination(request.params[0].get_str(), config.GetChainParams()); if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); } CScript scriptPubKey = GetScriptForDestination(dest); if (!IsMine(*pwallet, scriptPubKey)) { throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet"); } // Minimum confirmations int nMinDepth = 1; if (!request.params[1].isNull()) { nMinDepth = request.params[1].get_int(); } // Tally Amount nAmount = Amount::zero(); for (const std::pair &pairWtx : pwallet->mapWallet) { const CWalletTx &wtx = pairWtx.second; CValidationState state; if (wtx.IsCoinBase() || !locked_chain->contextualCheckTransactionForCurrentBlock( config.GetChainParams().GetConsensus(), *wtx.tx, state)) { continue; } for (const CTxOut &txout : wtx.tx->vout) { if (txout.scriptPubKey == scriptPubKey) { if (wtx.GetDepthInMainChain(*locked_chain) >= nMinDepth) { nAmount += txout.nValue; } } } } return ValueFromAmount(nAmount); } static UniValue getreceivedbylabel(const Config &config, const JSONRPCRequest &request) { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet *const pwallet = wallet.get(); if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { return NullUniValue; } if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { throw std::runtime_error( RPCHelpMan{ "getreceivedbylabel", "\nReturns the total amount received by addresses with