aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am12
-rw-r--r--src/Makefile.bench.include2
-rw-r--r--src/Makefile.crc32c.include2
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.qttest.include2
-rw-r--r--src/Makefile.test.include1196
-rw-r--r--src/addrdb.cpp2
-rw-r--r--src/addrdb.h2
-rw-r--r--src/addrman.cpp2
-rw-r--r--src/attributes.h2
-rw-r--r--src/banman.cpp2
-rw-r--r--src/base58.cpp2
-rw-r--r--src/base58.h2
-rw-r--r--src/bench/base58.cpp2
-rw-r--r--src/bench/block_assemble.cpp2
-rw-r--r--src/bench/chacha20.cpp2
-rw-r--r--src/bench/chacha_poly_aead.cpp9
-rw-r--r--src/bench/coin_selection.cpp2
-rw-r--r--src/bench/crypto_hash.cpp54
-rw-r--r--src/bench/gcs_filter.cpp2
-rw-r--r--src/bench/hashpadding.cpp2
-rw-r--r--src/bench/lockedpool.cpp2
-rw-r--r--src/bench/mempool_eviction.cpp2
-rw-r--r--src/bench/mempool_stress.cpp2
-rw-r--r--src/bench/poly1305.cpp2
-rw-r--r--src/bench/prevector.cpp2
-rw-r--r--src/bench/rollingbloom.cpp2
-rw-r--r--src/bench/rpc_mempool.cpp2
-rw-r--r--src/bench/util_time.cpp2
-rw-r--r--src/bench/verify_script.cpp2
-rw-r--r--src/bench/wallet_balance.cpp8
-rw-r--r--src/bitcoin-cli.cpp70
-rw-r--r--src/bitcoin-tx.cpp20
-rw-r--r--src/bitcoin-wallet.cpp31
-rw-r--r--src/bitcoind.cpp27
-rw-r--r--src/blockencodings.cpp2
-rw-r--r--src/blockfilter.cpp2
-rw-r--r--src/bloom.cpp2
-rw-r--r--src/bloom.h2
-rw-r--r--src/chainparams.cpp2
-rw-r--r--src/chainparamsbase.cpp2
-rw-r--r--src/chainparamsbase.h2
-rw-r--r--src/clientversion.cpp2
-rw-r--r--src/clientversion.h2
-rw-r--r--src/coins.cpp2
-rw-r--r--src/compat.h2
-rw-r--r--src/compat/assumptions.h2
-rw-r--r--src/compat/glibc_compat.cpp2
-rw-r--r--src/compat/glibc_sanity.cpp2
-rw-r--r--src/consensus/params.h2
-rw-r--r--src/consensus/tx_verify.cpp2
-rw-r--r--src/consensus/tx_verify.h2
-rw-r--r--src/consensus/validation.h2
-rw-r--r--src/core_io.h7
-rw-r--r--src/core_read.cpp59
-rw-r--r--src/core_write.cpp33
-rw-r--r--src/crc32c/.appveyor.yml13
-rw-r--r--src/crc32c/AUTHORS2
-rw-r--r--src/crc32c/CMakeLists.txt43
-rw-r--r--src/crc32c/Crc32cConfig.cmake.in (renamed from src/crc32c/Crc32cConfig.cmake)4
-rw-r--r--src/crc32c/src/crc32c.cc6
-rw-r--r--src/crc32c/src/crc32c_arm64.cc23
-rw-r--r--src/crc32c/src/crc32c_arm64.h8
-rw-r--r--src/crc32c/src/crc32c_arm64_check.h (renamed from src/crc32c/src/crc32c_arm64_linux_check.h)26
-rw-r--r--src/crc32c/src/crc32c_benchmark.cc8
-rw-r--r--src/crc32c/src/crc32c_read_le.h16
-rw-r--r--src/crypto/chacha_poly_aead.h4
-rw-r--r--src/crypto/common.h2
-rw-r--r--src/crypto/muhash.cpp338
-rw-r--r--src/crypto/muhash.h130
-rw-r--r--src/crypto/sha256_shani.cpp2
-rw-r--r--src/crypto/sha256_sse4.cpp2
-rw-r--r--src/crypto/siphash.cpp2
-rw-r--r--src/crypto/siphash.h2
-rw-r--r--src/cuckoocache.h2
-rw-r--r--src/dbwrapper.h2
-rw-r--r--src/flatfile.cpp1
-rw-r--r--src/fs.cpp2
-rw-r--r--src/hash.cpp4
-rw-r--r--src/hash.h2
-rw-r--r--src/httprpc.h2
-rw-r--r--src/index/blockfilterindex.cpp3
-rw-r--r--src/index/blockfilterindex.h2
-rw-r--r--src/index/disktxpos.h2
-rw-r--r--src/index/txindex.cpp2
-rw-r--r--src/init.cpp85
-rw-r--r--src/init.h2
-rw-r--r--src/interfaces/chain.h29
-rw-r--r--src/interfaces/node.h7
-rw-r--r--src/key.cpp6
-rw-r--r--src/key_io.cpp12
-rw-r--r--src/logging.cpp2
-rw-r--r--src/logging.h4
-rw-r--r--src/mapport.cpp336
-rw-r--r--src/mapport.h30
-rw-r--r--src/merkleblock.cpp4
-rw-r--r--src/merkleblock.h2
-rw-r--r--src/miner.cpp2
-rw-r--r--src/miner.h2
-rw-r--r--src/net.cpp478
-rw-r--r--src/net.h1115
-rw-r--r--src/net_permissions.cpp2
-rw-r--r--src/net_processing.cpp540
-rw-r--r--src/net_processing.h118
-rw-r--r--src/netaddress.cpp86
-rw-r--r--src/netaddress.h26
-rw-r--r--src/netmessagemaker.h2
-rw-r--r--src/node/coinstats.cpp2
-rw-r--r--src/node/coinstats.h2
-rw-r--r--src/node/context.cpp1
-rw-r--r--src/node/context.h2
-rw-r--r--src/node/interfaces.cpp103
-rw-r--r--src/node/transaction.cpp2
-rw-r--r--src/node/utxo_snapshot.h2
-rw-r--r--src/noui.cpp2
-rw-r--r--src/noui.h2
-rw-r--r--src/optional.h18
-rw-r--r--src/outputtype.cpp2
-rw-r--r--src/outputtype.h8
-rw-r--r--src/policy/feerate.cpp2
-rw-r--r--src/policy/feerate.h2
-rw-r--r--src/policy/fees.cpp64
-rw-r--r--src/policy/fees.h16
-rw-r--r--src/policy/policy.cpp4
-rw-r--r--src/policy/policy.h43
-rw-r--r--src/policy/rbf.cpp2
-rw-r--r--src/policy/rbf.h2
-rw-r--r--src/primitives/block.h2
-rw-r--r--src/primitives/transaction.cpp2
-rw-r--r--src/primitives/transaction.h16
-rw-r--r--src/protocol.cpp3
-rw-r--r--src/protocol.h6
-rw-r--r--src/psbt.cpp7
-rw-r--r--src/pubkey.cpp2
-rw-r--r--src/pubkey.h2
-rw-r--r--src/qt/addressbookpage.cpp2
-rw-r--r--src/qt/addressbookpage.h2
-rw-r--r--src/qt/addresstablemodel.cpp14
-rw-r--r--src/qt/addresstablemodel.h2
-rw-r--r--src/qt/askpassphrasedialog.cpp2
-rw-r--r--src/qt/askpassphrasedialog.h2
-rw-r--r--src/qt/bantablemodel.cpp8
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/bitcoinaddressvalidator.h2
-rw-r--r--src/qt/bitcoinamountfield.cpp2
-rw-r--r--src/qt/bitcoinamountfield.h2
-rw-r--r--src/qt/bitcoingui.cpp12
-rw-r--r--src/qt/bitcoingui.h3
-rw-r--r--src/qt/bitcoinunits.cpp8
-rw-r--r--src/qt/clientmodel.h2
-rw-r--r--src/qt/coincontroldialog.cpp4
-rw-r--r--src/qt/coincontroldialog.h2
-rw-r--r--src/qt/createwalletdialog.cpp2
-rw-r--r--src/qt/editaddressdialog.cpp2
-rw-r--r--src/qt/editaddressdialog.h2
-rw-r--r--src/qt/forms/createwalletdialog.ui8
-rw-r--r--src/qt/forms/debugwindow.ui99
-rw-r--r--src/qt/forms/optionsdialog.ui19
-rw-r--r--src/qt/guiutil.cpp30
-rw-r--r--src/qt/guiutil.h22
-rw-r--r--src/qt/modaloverlay.h2
-rw-r--r--src/qt/notificator.cpp4
-rw-r--r--src/qt/openuridialog.h2
-rw-r--r--src/qt/optionsdialog.cpp28
-rw-r--r--src/qt/optionsdialog.h4
-rw-r--r--src/qt/optionsmodel.cpp45
-rw-r--r--src/qt/optionsmodel.h9
-rw-r--r--src/qt/overviewpage.cpp2
-rw-r--r--src/qt/overviewpage.h2
-rw-r--r--src/qt/paymentserver.cpp2
-rw-r--r--src/qt/paymentserver.h2
-rw-r--r--src/qt/peertablemodel.cpp33
-rw-r--r--src/qt/peertablemodel.h17
-rw-r--r--src/qt/qrimagewidget.cpp2
-rw-r--r--src/qt/qrimagewidget.h2
-rw-r--r--src/qt/qvalidatedlineedit.h2
-rw-r--r--src/qt/receivecoinsdialog.cpp2
-rw-r--r--src/qt/receivecoinsdialog.h2
-rw-r--r--src/qt/receiverequestdialog.cpp2
-rw-r--r--src/qt/receiverequestdialog.h2
-rw-r--r--src/qt/recentrequeststablemodel.cpp12
-rw-r--r--src/qt/recentrequeststablemodel.h2
-rwxr-xr-xsrc/qt/res/animation/makespinner.sh2
-rw-r--r--src/qt/rpcconsole.cpp40
-rw-r--r--src/qt/rpcconsole.h2
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/sendcoinsdialog.h2
-rw-r--r--src/qt/sendcoinsrecipient.h2
-rw-r--r--src/qt/signverifymessagedialog.cpp2
-rw-r--r--src/qt/signverifymessagedialog.h2
-rw-r--r--src/qt/splashscreen.h2
-rw-r--r--src/qt/test/addressbooktests.h2
-rw-r--r--src/qt/test/rpcnestedtests.cpp66
-rw-r--r--src/qt/test/rpcnestedtests.h2
-rw-r--r--src/qt/test/test_main.cpp2
-rw-r--r--src/qt/test/util.cpp2
-rw-r--r--src/qt/test/util.h2
-rw-r--r--src/qt/test/wallettests.h2
-rw-r--r--src/qt/trafficgraphwidget.cpp2
-rw-r--r--src/qt/transactiondescdialog.cpp2
-rw-r--r--src/qt/transactionfilterproxy.h2
-rw-r--r--src/qt/transactionrecord.cpp4
-rw-r--r--src/qt/transactionrecord.h2
-rw-r--r--src/qt/transactiontablemodel.cpp10
-rw-r--r--src/qt/transactiontablemodel.h2
-rw-r--r--src/qt/transactionview.cpp2
-rw-r--r--src/qt/transactionview.h2
-rw-r--r--src/qt/walletcontroller.cpp2
-rw-r--r--src/qt/walletframe.h2
-rw-r--r--src/randomenv.cpp2
-rw-r--r--src/rest.cpp2
-rw-r--r--src/rpc/blockchain.cpp32
-rw-r--r--src/rpc/blockchain.h4
-rw-r--r--src/rpc/mining.cpp38
-rw-r--r--src/rpc/net.cpp108
-rw-r--r--src/rpc/protocol.h1
-rw-r--r--src/rpc/rawtransaction.cpp17
-rw-r--r--src/rpc/rawtransaction_util.cpp2
-rw-r--r--src/rpc/rawtransaction_util.h2
-rw-r--r--src/rpc/request.cpp2
-rw-r--r--src/rpc/request.h2
-rw-r--r--src/rpc/server.h2
-rw-r--r--src/rpc/util.cpp16
-rw-r--r--src/rpc/util.h7
-rw-r--r--src/script/bitcoinconsensus.cpp7
-rw-r--r--src/script/descriptor.cpp4
-rw-r--r--src/script/interpreter.cpp4
-rw-r--r--src/script/interpreter.h2
-rw-r--r--src/script/keyorigin.h2
-rw-r--r--src/script/script.cpp2
-rw-r--r--src/script/script_error.h2
-rw-r--r--src/script/sigcache.cpp4
-rw-r--r--src/script/sigcache.h2
-rw-r--r--src/script/sign.cpp2
-rw-r--r--src/script/signingprovider.cpp10
-rw-r--r--src/script/standard.cpp11
-rw-r--r--src/script/standard.h6
-rw-r--r--src/shutdown.cpp91
-rw-r--r--src/shutdown.h19
-rw-r--r--src/streams.h2
-rw-r--r--src/support/lockedpool.cpp2
-rw-r--r--src/support/lockedpool.h2
-rw-r--r--src/sync.cpp32
-rw-r--r--src/sync.h10
-rw-r--r--src/test/addrman_tests.cpp2
-rw-r--r--src/test/amount_tests.cpp2
-rw-r--r--src/test/base58_tests.cpp2
-rw-r--r--src/test/blockencodings_tests.cpp2
-rw-r--r--src/test/blockfilter_tests.cpp2
-rw-r--r--src/test/checkqueue_tests.cpp8
-rw-r--r--src/test/coins_tests.cpp2
-rw-r--r--src/test/crypto_tests.cpp90
-rw-r--r--src/test/denialofservice_tests.cpp22
-rw-r--r--src/test/flatfile_tests.cpp2
-rw-r--r--src/test/fuzz/FuzzedDataProvider.h563
-rw-r--r--src/test/fuzz/addition_overflow.cpp2
-rw-r--r--src/test/fuzz/addrdb.cpp2
-rw-r--r--src/test/fuzz/addrman.cpp4
-rw-r--r--src/test/fuzz/asmap.cpp2
-rw-r--r--src/test/fuzz/asmap_direct.cpp2
-rw-r--r--src/test/fuzz/autofile.cpp2
-rw-r--r--src/test/fuzz/banman.cpp5
-rw-r--r--src/test/fuzz/base_encode_decode.cpp2
-rw-r--r--src/test/fuzz/bech32.cpp4
-rw-r--r--src/test/fuzz/block.cpp4
-rw-r--r--src/test/fuzz/block_header.cpp2
-rw-r--r--src/test/fuzz/blockfilter.cpp2
-rw-r--r--src/test/fuzz/bloom_filter.cpp2
-rw-r--r--src/test/fuzz/buffered_file.cpp2
-rw-r--r--src/test/fuzz/chain.cpp2
-rw-r--r--src/test/fuzz/checkqueue.cpp2
-rw-r--r--src/test/fuzz/coins_view.cpp4
-rw-r--r--src/test/fuzz/connman.cpp23
-rw-r--r--src/test/fuzz/crypto.cpp18
-rw-r--r--src/test/fuzz/crypto_aes256.cpp2
-rw-r--r--src/test/fuzz/crypto_aes256cbc.cpp2
-rw-r--r--src/test/fuzz/crypto_chacha20.cpp2
-rw-r--r--src/test/fuzz/crypto_chacha20_poly1305_aead.cpp2
-rw-r--r--src/test/fuzz/crypto_common.cpp2
-rw-r--r--src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp2
-rw-r--r--src/test/fuzz/crypto_poly1305.cpp2
-rw-r--r--src/test/fuzz/cuckoocache.cpp2
-rwxr-xr-xsrc/test/fuzz/danger_link_all.sh28
-rw-r--r--src/test/fuzz/data_stream.cpp25
-rw-r--r--src/test/fuzz/decode_tx.cpp4
-rw-r--r--src/test/fuzz/descriptor_parse.cpp4
-rw-r--r--src/test/fuzz/deserialize.cpp140
-rw-r--r--src/test/fuzz/eval_script.cpp4
-rw-r--r--src/test/fuzz/fee_rate.cpp2
-rw-r--r--src/test/fuzz/fees.cpp2
-rw-r--r--src/test/fuzz/flatfile.cpp2
-rw-r--r--src/test/fuzz/float.cpp2
-rw-r--r--src/test/fuzz/fuzz.cpp38
-rw-r--r--src/test/fuzz/fuzz.h27
-rw-r--r--src/test/fuzz/golomb_rice.cpp2
-rw-r--r--src/test/fuzz/hex.cpp4
-rw-r--r--src/test/fuzz/http_request.cpp2
-rw-r--r--src/test/fuzz/integer.cpp4
-rw-r--r--src/test/fuzz/key.cpp4
-rw-r--r--src/test/fuzz/key_io.cpp4
-rw-r--r--src/test/fuzz/kitchen_sink.cpp37
-rw-r--r--src/test/fuzz/load_external_block_file.cpp4
-rw-r--r--src/test/fuzz/locale.cpp2
-rw-r--r--src/test/fuzz/merkleblock.cpp2
-rw-r--r--src/test/fuzz/message.cpp4
-rw-r--r--src/test/fuzz/muhash.cpp53
-rw-r--r--src/test/fuzz/multiplication_overflow.cpp2
-rw-r--r--src/test/fuzz/net.cpp56
-rw-r--r--src/test/fuzz/net_permissions.cpp15
-rw-r--r--src/test/fuzz/netaddress.cpp2
-rw-r--r--src/test/fuzz/node_eviction.cpp44
-rw-r--r--src/test/fuzz/p2p_transport_deserializer.cpp6
-rw-r--r--src/test/fuzz/parse_hd_keypath.cpp4
-rw-r--r--src/test/fuzz/parse_iso8601.cpp4
-rw-r--r--src/test/fuzz/parse_numbers.cpp4
-rw-r--r--src/test/fuzz/parse_script.cpp4
-rw-r--r--src/test/fuzz/parse_univalue.cpp4
-rw-r--r--src/test/fuzz/policy_estimator.cpp8
-rw-r--r--src/test/fuzz/policy_estimator_io.cpp4
-rw-r--r--src/test/fuzz/pow.cpp4
-rw-r--r--src/test/fuzz/prevector.cpp2
-rw-r--r--src/test/fuzz/primitives_transaction.cpp2
-rw-r--r--src/test/fuzz/process_message.cpp53
-rw-r--r--src/test/fuzz/process_messages.cpp15
-rw-r--r--src/test/fuzz/protocol.cpp2
-rw-r--r--src/test/fuzz/psbt.cpp4
-rw-r--r--src/test/fuzz/random.cpp2
-rw-r--r--src/test/fuzz/rbf.cpp3
-rw-r--r--src/test/fuzz/rolling_bloom_filter.cpp2
-rw-r--r--src/test/fuzz/script.cpp22
-rw-r--r--src/test/fuzz/script_assets_test_minimizer.cpp4
-rw-r--r--src/test/fuzz/script_bitcoin_consensus.cpp2
-rw-r--r--src/test/fuzz/script_descriptor_cache.cpp2
-rw-r--r--src/test/fuzz/script_flags.cpp4
-rw-r--r--src/test/fuzz/script_interpreter.cpp2
-rw-r--r--src/test/fuzz/script_ops.cpp2
-rw-r--r--src/test/fuzz/script_sigcache.cpp6
-rw-r--r--src/test/fuzz/script_sign.cpp4
-rw-r--r--src/test/fuzz/scriptnum_ops.cpp2
-rw-r--r--src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp2
-rw-r--r--src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp2
-rw-r--r--src/test/fuzz/signature_checker.cpp4
-rw-r--r--src/test/fuzz/signet.cpp4
-rw-r--r--src/test/fuzz/span.cpp2
-rw-r--r--src/test/fuzz/spanparsing.cpp4
-rw-r--r--src/test/fuzz/string.cpp2
-rw-r--r--src/test/fuzz/strprintf.cpp2
-rw-r--r--src/test/fuzz/system.cpp2
-rw-r--r--src/test/fuzz/timedata.cpp2
-rw-r--r--src/test/fuzz/transaction.cpp6
-rw-r--r--src/test/fuzz/tx_in.cpp4
-rw-r--r--src/test/fuzz/tx_out.cpp4
-rw-r--r--src/test/fuzz/txrequest.cpp2
-rw-r--r--src/test/fuzz/util.h57
-rw-r--r--src/test/interfaces_tests.cpp51
-rw-r--r--src/test/key_tests.cpp22
-rw-r--r--src/test/merkle_tests.cpp2
-rw-r--r--src/test/miner_tests.cpp2
-rw-r--r--src/test/net_tests.cpp174
-rw-r--r--src/test/netbase_tests.cpp21
-rw-r--r--src/test/pow_tests.cpp2
-rw-r--r--src/test/raii_event_tests.cpp2
-rw-r--r--src/test/reverselock_tests.cpp10
-rw-r--r--src/test/sanity_tests.cpp2
-rw-r--r--src/test/script_standard_tests.cpp40
-rw-r--r--src/test/streams_tests.cpp2
-rw-r--r--src/test/sync_tests.cpp37
-rw-r--r--src/test/system_tests.cpp2
-rw-r--r--src/test/transaction_tests.cpp2
-rw-r--r--src/test/util/logging.cpp2
-rw-r--r--src/test/util/logging.h2
-rw-r--r--src/test/util/mining.cpp2
-rw-r--r--src/test/util/net.h31
-rw-r--r--src/test/util/setup_common.cpp78
-rw-r--r--src/test/util/setup_common.h19
-rw-r--r--src/test/util_tests.cpp8
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp14
-rw-r--r--src/test/validation_tests.cpp4
-rw-r--r--src/threadsafety.h2
-rw-r--r--src/torcontrol.cpp2
-rw-r--r--src/torcontrol.h2
-rw-r--r--src/uint256.cpp2
-rw-r--r--src/uint256.h2
-rw-r--r--src/util/asmap.h2
-rw-r--r--src/util/check.h22
-rw-r--r--src/util/error.cpp2
-rw-r--r--src/util/error.h2
-rw-r--r--src/util/fees.cpp2
-rw-r--r--src/util/fees.h2
-rw-r--r--src/util/golombrice.h2
-rw-r--r--src/util/memory.h2
-rw-r--r--src/util/message.cpp2
-rw-r--r--src/util/strencodings.h2
-rw-r--r--src/util/system.cpp27
-rw-r--r--src/util/system.h12
-rw-r--r--src/util/time.h4
-rw-r--r--src/util/translation.h2
-rw-r--r--src/validation.cpp23
-rw-r--r--src/validation.h4
-rw-r--r--src/version.h2
-rw-r--r--src/versionbitsinfo.cpp2
-rw-r--r--src/wallet/bdb.cpp45
-rw-r--r--src/wallet/bdb.h10
-rw-r--r--src/wallet/coinselection.cpp2
-rw-r--r--src/wallet/coinselection.h2
-rw-r--r--src/wallet/crypter.h2
-rw-r--r--src/wallet/db.cpp117
-rw-r--r--src/wallet/db.h8
-rw-r--r--src/wallet/dump.cpp282
-rw-r--r--src/wallet/dump.h17
-rw-r--r--src/wallet/feebumper.cpp8
-rw-r--r--src/wallet/fees.cpp4
-rw-r--r--src/wallet/interfaces.cpp6
-rw-r--r--src/wallet/load.h2
-rw-r--r--src/wallet/rpcwallet.cpp25
-rw-r--r--src/wallet/salvage.cpp5
-rw-r--r--src/wallet/sqlite.cpp45
-rw-r--r--src/wallet/sqlite.h4
-rw-r--r--src/wallet/test/coinselector_tests.cpp7
-rw-r--r--src/wallet/test/db_tests.cpp9
-rw-r--r--src/wallet/test/init_test_fixture.cpp4
-rw-r--r--src/wallet/test/init_test_fixture.h3
-rw-r--r--src/wallet/test/init_tests.cpp2
-rw-r--r--src/wallet/test/ismine_tests.cpp5
-rw-r--r--src/wallet/test/scriptpubkeyman_tests.cpp4
-rw-r--r--src/wallet/test/wallet_crypto_tests.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp4
-rw-r--r--src/wallet/test/wallet_test_fixture.h3
-rw-r--r--src/wallet/test/wallet_tests.cpp61
-rw-r--r--src/wallet/test/walletdb_tests.cpp2
-rw-r--r--src/wallet/wallet.cpp61
-rw-r--r--src/wallet/wallet.h2
-rw-r--r--src/wallet/walletdb.cpp10
-rw-r--r--src/wallet/wallettool.cpp112
-rw-r--r--src/wallet/wallettool.h4
-rw-r--r--src/wallet/walletutil.cpp59
-rw-r--r--src/wallet/walletutil.h5
-rw-r--r--src/walletinitinterface.h2
-rw-r--r--src/warnings.cpp2
-rw-r--r--src/warnings.h2
-rw-r--r--src/zmq/zmqabstractnotifier.cpp2
-rw-r--r--src/zmq/zmqabstractnotifier.h2
-rw-r--r--src/zmq/zmqnotificationinterface.cpp2
-rw-r--r--src/zmq/zmqnotificationinterface.h2
-rw-r--r--src/zmq/zmqpublishnotifier.h2
445 files changed, 5653 insertions, 4091 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 4a080ef1fb..1a0791dccd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -152,6 +152,7 @@ BITCOIN_CORE_H = \
key_io.h \
logging.h \
logging/timer.h \
+ mapport.h \
memusage.h \
merkleblock.h \
miner.h \
@@ -249,6 +250,7 @@ BITCOIN_CORE_H = \
wallet/context.h \
wallet/crypter.h \
wallet/db.h \
+ wallet/dump.h \
wallet/feebumper.h \
wallet/fees.h \
wallet/ismine.h \
@@ -298,6 +300,7 @@ libbitcoin_server_a_SOURCES = \
index/blockfilterindex.cpp \
index/txindex.cpp \
init.cpp \
+ mapport.cpp \
miner.cpp \
net.cpp \
net_processing.cpp \
@@ -361,6 +364,7 @@ libbitcoin_wallet_a_SOURCES = \
wallet/context.cpp \
wallet/crypter.cpp \
wallet/db.cpp \
+ wallet/dump.cpp \
wallet/feebumper.cpp \
wallet/fees.cpp \
wallet/interfaces.cpp \
@@ -406,6 +410,8 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \
crypto/hmac_sha512.h \
crypto/poly1305.h \
crypto/poly1305.cpp \
+ crypto/muhash.h \
+ crypto/muhash.cpp \
crypto/ripemd160.cpp \
crypto/ripemd160.h \
crypto/sha1.cpp \
@@ -594,7 +600,7 @@ bitcoin_bin_ldadd = \
$(LIBMEMENV) \
$(LIBSECP256K1)
-bitcoin_bin_ldadd += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(SQLITE_LIBS)
+bitcoin_bin_ldadd += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(SQLITE_LIBS)
bitcoind_SOURCES = $(bitcoin_daemon_sources)
bitcoind_CPPFLAGS = $(bitcoin_bin_cppflags)
@@ -740,13 +746,13 @@ endif
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)
+ $(AM_V_at) 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) OTOOL=$(OTOOL) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py $(bin_PROGRAMS)
+ $(AM_V_at) OBJDUMP=$(OBJDUMP) OTOOL=$(OTOOL) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py $(bin_PROGRAMS)
endif
if EMBEDDED_LEVELDB
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index beb3f8dfd2..56b8ca8ce6 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -74,7 +74,7 @@ bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
bench_bench_bitcoin_SOURCES += bench/wallet_balance.cpp
endif
-bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(SQLITE_LIBS)
+bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS)
bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES)
diff --git a/src/Makefile.crc32c.include b/src/Makefile.crc32c.include
index 802b3a2e4b..113272e65e 100644
--- a/src/Makefile.crc32c.include
+++ b/src/Makefile.crc32c.include
@@ -41,7 +41,7 @@ crc32c_libcrc32c_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
crc32c_libcrc32c_a_SOURCES =
crc32c_libcrc32c_a_SOURCES += crc32c/include/crc32c/crc32c.h
crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_arm64.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_arm64_linux_check.h
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_arm64_check.h
crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_internal.h
crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_prefetch.h
crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_read_le.h
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index f46310a603..3d41d203d3 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -320,7 +320,7 @@ if ENABLE_ZMQ
bitcoin_qt_ldadd += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
bitcoin_qt_ldadd += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
- $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
+ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(SQLITE_LIBS)
bitcoin_qt_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
bitcoin_qt_libtoolflags = $(AM_LIBTOOLFLAGS) --tag CXX
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index c05dd38737..a6a857d952 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -55,7 +55,7 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \
$(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
- $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
+ $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(SQLITE_LIBS)
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index f4c726b0b2..e9f9b73abe 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -2,171 +2,15 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-FUZZ_TARGETS = \
- test/fuzz/addition_overflow \
- test/fuzz/addr_info_deserialize \
- test/fuzz/addrdb \
- test/fuzz/address_deserialize \
- test/fuzz/addrman \
- test/fuzz/addrman_deserialize \
- test/fuzz/asmap \
- test/fuzz/asmap_direct \
- test/fuzz/autofile \
- test/fuzz/banentry_deserialize \
- test/fuzz/banman \
- test/fuzz/base_encode_decode \
- test/fuzz/bech32 \
- test/fuzz/block \
- test/fuzz/block_deserialize \
- test/fuzz/block_file_info_deserialize \
- test/fuzz/block_filter_deserialize \
- test/fuzz/block_header \
- test/fuzz/block_header_and_short_txids_deserialize \
- test/fuzz/blockfilter \
- test/fuzz/blockheader_deserialize \
- test/fuzz/blocklocator_deserialize \
- test/fuzz/blockmerkleroot \
- test/fuzz/blocktransactions_deserialize \
- test/fuzz/blocktransactionsrequest_deserialize \
- test/fuzz/blockundo_deserialize \
- test/fuzz/bloom_filter \
- test/fuzz/bloomfilter_deserialize \
- test/fuzz/buffered_file \
- test/fuzz/chain \
- test/fuzz/checkqueue \
- test/fuzz/coins_deserialize \
- test/fuzz/coins_view \
- test/fuzz/connman \
- test/fuzz/crypto \
- test/fuzz/crypto_aes256 \
- test/fuzz/crypto_aes256cbc \
- test/fuzz/crypto_chacha20 \
- test/fuzz/crypto_chacha20_poly1305_aead \
- test/fuzz/crypto_common \
- test/fuzz/crypto_hkdf_hmac_sha256_l32 \
- test/fuzz/crypto_poly1305 \
- test/fuzz/cuckoocache \
- test/fuzz/decode_tx \
- test/fuzz/descriptor_parse \
- test/fuzz/diskblockindex_deserialize \
- test/fuzz/eval_script \
- test/fuzz/fee_rate \
- test/fuzz/fee_rate_deserialize \
- test/fuzz/fees \
- test/fuzz/flat_file_pos_deserialize \
- test/fuzz/flatfile \
- test/fuzz/float \
- test/fuzz/golomb_rice \
- test/fuzz/hex \
- test/fuzz/http_request \
- test/fuzz/integer \
- test/fuzz/inv_deserialize \
- test/fuzz/key \
- test/fuzz/key_io \
- test/fuzz/key_origin_info_deserialize \
- test/fuzz/kitchen_sink \
- test/fuzz/load_external_block_file \
- test/fuzz/locale \
- test/fuzz/merkle_block_deserialize \
- test/fuzz/merkleblock \
- test/fuzz/message \
- test/fuzz/messageheader_deserialize \
- test/fuzz/multiplication_overflow \
- test/fuzz/net \
- test/fuzz/net_permissions \
- test/fuzz/netaddr_deserialize \
- test/fuzz/netaddress \
- test/fuzz/out_point_deserialize \
- test/fuzz/p2p_transport_deserializer \
- test/fuzz/parse_hd_keypath \
- test/fuzz/parse_iso8601 \
- test/fuzz/parse_numbers \
- test/fuzz/parse_script \
- test/fuzz/parse_univalue \
- test/fuzz/partial_merkle_tree_deserialize \
- test/fuzz/partially_signed_transaction_deserialize \
- test/fuzz/policy_estimator \
- test/fuzz/policy_estimator_io \
- test/fuzz/pow \
- test/fuzz/prefilled_transaction_deserialize \
- test/fuzz/prevector \
- test/fuzz/primitives_transaction \
- test/fuzz/process_message \
- test/fuzz/process_message_addr \
- test/fuzz/process_message_block \
- test/fuzz/process_message_blocktxn \
- test/fuzz/process_message_cmpctblock \
- test/fuzz/process_message_feefilter \
- test/fuzz/process_message_filteradd \
- test/fuzz/process_message_filterclear \
- test/fuzz/process_message_filterload \
- test/fuzz/process_message_getaddr \
- test/fuzz/process_message_getblocks \
- test/fuzz/process_message_getblocktxn \
- test/fuzz/process_message_getdata \
- test/fuzz/process_message_getheaders \
- test/fuzz/process_message_headers \
- test/fuzz/process_message_inv \
- test/fuzz/process_message_mempool \
- test/fuzz/process_message_notfound \
- test/fuzz/process_message_ping \
- test/fuzz/process_message_pong \
- test/fuzz/process_message_sendcmpct \
- test/fuzz/process_message_sendheaders \
- test/fuzz/process_message_tx \
- test/fuzz/process_message_verack \
- test/fuzz/process_message_version \
- test/fuzz/process_messages \
- test/fuzz/protocol \
- test/fuzz/psbt \
- test/fuzz/psbt_input_deserialize \
- test/fuzz/psbt_output_deserialize \
- test/fuzz/pub_key_deserialize \
- test/fuzz/random \
- test/fuzz/rbf \
- test/fuzz/rolling_bloom_filter \
- test/fuzz/script \
- test/fuzz/script_bitcoin_consensus \
- test/fuzz/script_descriptor_cache \
- test/fuzz/script_deserialize \
- test/fuzz/script_flags \
- test/fuzz/script_interpreter \
- test/fuzz/script_assets_test_minimizer \
- test/fuzz/script_ops \
- test/fuzz/script_sigcache \
- test/fuzz/script_sign \
- test/fuzz/scriptnum_ops \
- test/fuzz/secp256k1_ec_seckey_import_export_der \
- test/fuzz/secp256k1_ecdsa_signature_parse_der_lax \
- test/fuzz/service_deserialize \
- test/fuzz/signature_checker \
- test/fuzz/signet \
- test/fuzz/snapshotmetadata_deserialize \
- test/fuzz/span \
- test/fuzz/spanparsing \
- test/fuzz/string \
- test/fuzz/strprintf \
- test/fuzz/sub_net_deserialize \
- test/fuzz/system \
- test/fuzz/timedata \
- test/fuzz/transaction \
- test/fuzz/tx_in \
- test/fuzz/tx_in_deserialize \
- test/fuzz/tx_out \
- test/fuzz/txoutcompressor_deserialize \
- test/fuzz/txrequest \
- test/fuzz/txundo_deserialize \
- test/fuzz/uint160_deserialize \
- test/fuzz/uint256_deserialize
-
if ENABLE_FUZZ
-noinst_PROGRAMS += $(FUZZ_TARGETS:=)
+noinst_PROGRAMS += test/fuzz/fuzz
else
bin_PROGRAMS += test/test_bitcoin
endif
TEST_SRCDIR = test
TEST_BINARY=test/test_bitcoin$(EXEEXT)
+FUZZ_BINARY=test/fuzz/fuzz$(EXEEXT)
JSON_TEST_FILES = \
test/data/script_tests.json \
@@ -323,7 +167,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_test_bitcoin_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(SQLITE_LIBS)
+test_test_bitcoin_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS)
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) -static
if ENABLE_ZMQ
@@ -334,935 +178,106 @@ if ENABLE_FUZZ
FUZZ_SUITE_LDFLAGS_COMMON = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
-test_fuzz_addition_overflow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_addition_overflow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addition_overflow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addition_overflow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addition_overflow_SOURCES = test/fuzz/addition_overflow.cpp
-
-test_fuzz_addr_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDR_INFO_DESERIALIZE=1
-test_fuzz_addr_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addr_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addr_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addr_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_addrdb_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_addrdb_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addrdb_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addrdb_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addrdb_SOURCES = test/fuzz/addrdb.cpp
-
-test_fuzz_address_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRESS_DESERIALIZE=1
-test_fuzz_address_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_address_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_address_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_address_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_addrman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_addrman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addrman_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addrman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addrman_SOURCES = test/fuzz/addrman.cpp
-
-test_fuzz_addrman_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRMAN_DESERIALIZE=1
-test_fuzz_addrman_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addrman_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addrman_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addrman_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_asmap_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_asmap_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_asmap_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_asmap_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_asmap_SOURCES = test/fuzz/asmap.cpp
-
-test_fuzz_asmap_direct_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_asmap_direct_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_asmap_direct_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_asmap_direct_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_asmap_direct_SOURCES = test/fuzz/asmap_direct.cpp
-
-test_fuzz_autofile_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_autofile_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_autofile_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_autofile_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_autofile_SOURCES = test/fuzz/autofile.cpp
-
-test_fuzz_banentry_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBANENTRY_DESERIALIZE=1
-test_fuzz_banentry_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_banentry_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_banentry_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_banman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_banman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_banman_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_banman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_banman_SOURCES = test/fuzz/banman.cpp
-
-test_fuzz_base_encode_decode_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_base_encode_decode_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_base_encode_decode_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_base_encode_decode_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_base_encode_decode_SOURCES = test/fuzz/base_encode_decode.cpp
-
-test_fuzz_bech32_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_bech32_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_bech32_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bech32_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_bech32_SOURCES = test/fuzz/bech32.cpp
-
-test_fuzz_block_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_block_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_SOURCES = test/fuzz/block.cpp
-
-test_fuzz_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_DESERIALIZE=1
-test_fuzz_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_block_file_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_FILE_INFO_DESERIALIZE=1
-test_fuzz_block_file_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_file_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_file_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_file_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_block_filter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_FILTER_DESERIALIZE=1
-test_fuzz_block_filter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_filter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_filter_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_filter_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_block_header_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_block_header_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_header_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_header_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_header_SOURCES = test/fuzz/block_header.cpp
-
-test_fuzz_block_header_and_short_txids_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE=1
-test_fuzz_block_header_and_short_txids_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_header_and_short_txids_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_header_and_short_txids_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_header_and_short_txids_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blockfilter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_blockfilter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blockfilter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockfilter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blockfilter_SOURCES = test/fuzz/blockfilter.cpp
-
-test_fuzz_blockheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKHEADER_DESERIALIZE=1
-test_fuzz_blockheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blockheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockheader_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blockheader_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blocklocator_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKLOCATOR_DESERIALIZE=1
-test_fuzz_blocklocator_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blocklocator_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocklocator_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blocklocator_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blockmerkleroot_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKMERKLEROOT=1
-test_fuzz_blockmerkleroot_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blockmerkleroot_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockmerkleroot_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blockmerkleroot_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blocktransactions_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONS_DESERIALIZE=1
-test_fuzz_blocktransactions_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blocktransactions_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocktransactions_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blocktransactions_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blocktransactionsrequest_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONSREQUEST_DESERIALIZE=1
-test_fuzz_blocktransactionsrequest_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blocktransactionsrequest_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blocktransactionsrequest_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blockundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKUNDO_DESERIALIZE=1
-test_fuzz_blockundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blockundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockundo_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blockundo_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_bloom_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_bloom_filter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_bloom_filter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bloom_filter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_bloom_filter_SOURCES = test/fuzz/bloom_filter.cpp
-
-test_fuzz_bloomfilter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOOMFILTER_DESERIALIZE=1
-test_fuzz_bloomfilter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_bloomfilter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bloomfilter_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_bloomfilter_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_buffered_file_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_buffered_file_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_buffered_file_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_buffered_file_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_buffered_file_SOURCES = test/fuzz/buffered_file.cpp
-
-test_fuzz_chain_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_chain_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_chain_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_chain_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_chain_SOURCES = test/fuzz/chain.cpp
-
-test_fuzz_checkqueue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_checkqueue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_checkqueue_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_checkqueue_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_checkqueue_SOURCES = test/fuzz/checkqueue.cpp
-
-test_fuzz_coins_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DCOINS_DESERIALIZE=1
-test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_coins_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_coins_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_coins_view_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_coins_view_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_coins_view_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_coins_view_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_coins_view_SOURCES = test/fuzz/coins_view.cpp
-
-test_fuzz_connman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_connman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_connman_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_connman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_connman_SOURCES = test/fuzz/connman.cpp
-
-test_fuzz_crypto_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_SOURCES = test/fuzz/crypto.cpp
-
-test_fuzz_crypto_aes256_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_aes256_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_aes256_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_aes256_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_aes256_SOURCES = test/fuzz/crypto_aes256.cpp
-
-test_fuzz_crypto_aes256cbc_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_aes256cbc_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_aes256cbc_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_aes256cbc_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_aes256cbc_SOURCES = test/fuzz/crypto_aes256cbc.cpp
-
-test_fuzz_crypto_chacha20_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_chacha20_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_chacha20_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_chacha20_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_chacha20_SOURCES = test/fuzz/crypto_chacha20.cpp
-
-test_fuzz_crypto_chacha20_poly1305_aead_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_chacha20_poly1305_aead_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_chacha20_poly1305_aead_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_chacha20_poly1305_aead_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_chacha20_poly1305_aead_SOURCES = test/fuzz/crypto_chacha20_poly1305_aead.cpp
-
-test_fuzz_crypto_common_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_common_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_common_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_common_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_common_SOURCES = test/fuzz/crypto_common.cpp
-
-test_fuzz_crypto_hkdf_hmac_sha256_l32_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_SOURCES = test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
-
-test_fuzz_crypto_poly1305_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_poly1305_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_poly1305_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_poly1305_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_poly1305_SOURCES = test/fuzz/crypto_poly1305.cpp
-
-test_fuzz_cuckoocache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_cuckoocache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_cuckoocache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_cuckoocache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_cuckoocache_SOURCES = test/fuzz/cuckoocache.cpp
-
-test_fuzz_decode_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_decode_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_decode_tx_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_decode_tx_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_decode_tx_SOURCES = test/fuzz/decode_tx.cpp
-
-test_fuzz_descriptor_parse_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_descriptor_parse_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_descriptor_parse_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_descriptor_parse_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_descriptor_parse_SOURCES = test/fuzz/descriptor_parse.cpp
-
-test_fuzz_diskblockindex_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DDISKBLOCKINDEX_DESERIALIZE=1
-test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_diskblockindex_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_diskblockindex_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_eval_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_eval_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_eval_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_eval_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_eval_script_SOURCES = test/fuzz/eval_script.cpp
-
-test_fuzz_fee_rate_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_fee_rate_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_fee_rate_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fee_rate_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_fee_rate_SOURCES = test/fuzz/fee_rate.cpp
-
-test_fuzz_fee_rate_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFEE_RATE_DESERIALIZE=1
-test_fuzz_fee_rate_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_fee_rate_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fee_rate_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_fee_rate_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_fees_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_fees_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_fees_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fees_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_fees_SOURCES = test/fuzz/fees.cpp
-
-test_fuzz_flat_file_pos_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFLAT_FILE_POS_DESERIALIZE=1
-test_fuzz_flat_file_pos_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_flat_file_pos_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_flat_file_pos_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_flat_file_pos_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_flatfile_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_flatfile_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_flatfile_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_flatfile_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_flatfile_SOURCES = test/fuzz/flatfile.cpp
-
-test_fuzz_float_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_float_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_float_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_float_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_float_SOURCES = test/fuzz/float.cpp
-
-test_fuzz_golomb_rice_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_golomb_rice_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_golomb_rice_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_golomb_rice_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_golomb_rice_SOURCES = test/fuzz/golomb_rice.cpp
-
-test_fuzz_hex_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_hex_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_hex_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_hex_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_hex_SOURCES = test/fuzz/hex.cpp
-
-test_fuzz_http_request_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_http_request_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_http_request_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_http_request_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_http_request_SOURCES = test/fuzz/http_request.cpp
-
-test_fuzz_integer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_integer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_integer_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_integer_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_integer_SOURCES = test/fuzz/integer.cpp
-
-test_fuzz_inv_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DINV_DESERIALIZE=1
-test_fuzz_inv_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_inv_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_inv_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_inv_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_key_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_key_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_key_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_key_SOURCES = test/fuzz/key.cpp
-
-test_fuzz_key_io_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_key_io_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_key_io_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_io_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_key_io_SOURCES = test/fuzz/key_io.cpp
-
-test_fuzz_key_origin_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DKEY_ORIGIN_INFO_DESERIALIZE=1
-test_fuzz_key_origin_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_key_origin_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_origin_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_key_origin_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_kitchen_sink_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_kitchen_sink_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_kitchen_sink_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_kitchen_sink_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_kitchen_sink_SOURCES = test/fuzz/kitchen_sink.cpp
-
-test_fuzz_load_external_block_file_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_load_external_block_file_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_load_external_block_file_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_load_external_block_file_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_load_external_block_file_SOURCES = test/fuzz/load_external_block_file.cpp
-
-test_fuzz_locale_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_locale_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_locale_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_locale_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_locale_SOURCES = test/fuzz/locale.cpp
-
-test_fuzz_merkle_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMERKLE_BLOCK_DESERIALIZE=1
-test_fuzz_merkle_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_merkle_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_merkle_block_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_merkle_block_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_merkleblock_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_merkleblock_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_merkleblock_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_merkleblock_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_merkleblock_SOURCES = test/fuzz/merkleblock.cpp
-
-test_fuzz_message_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_message_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_message_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_message_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_message_SOURCES = test/fuzz/message.cpp
-
-test_fuzz_messageheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGEHEADER_DESERIALIZE=1
-test_fuzz_messageheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_messageheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_messageheader_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_messageheader_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_multiplication_overflow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_multiplication_overflow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_multiplication_overflow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_multiplication_overflow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_multiplication_overflow_SOURCES = test/fuzz/multiplication_overflow.cpp
-
-test_fuzz_net_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_net_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_net_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_net_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_net_SOURCES = test/fuzz/net.cpp
-
-test_fuzz_net_permissions_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_net_permissions_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_net_permissions_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_net_permissions_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_net_permissions_SOURCES = test/fuzz/net_permissions.cpp
-
-test_fuzz_netaddr_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DNETADDR_DESERIALIZE=1
-test_fuzz_netaddr_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_netaddr_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_netaddr_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_netaddress_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_netaddress_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_netaddress_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_netaddress_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_netaddress_SOURCES = test/fuzz/netaddress.cpp
-
-test_fuzz_out_point_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DOUT_POINT_DESERIALIZE=1
-test_fuzz_out_point_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_out_point_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_out_point_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_out_point_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_p2p_transport_deserializer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_p2p_transport_deserializer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_p2p_transport_deserializer_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_p2p_transport_deserializer_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_p2p_transport_deserializer_SOURCES = test/fuzz/p2p_transport_deserializer.cpp
-
-test_fuzz_parse_hd_keypath_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_hd_keypath_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_hd_keypath_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_hd_keypath_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_hd_keypath_SOURCES = test/fuzz/parse_hd_keypath.cpp
-
-test_fuzz_parse_iso8601_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_iso8601_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_iso8601_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_iso8601_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_iso8601_SOURCES = test/fuzz/parse_iso8601.cpp
-
-test_fuzz_parse_numbers_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_numbers_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_numbers_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_numbers_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_numbers_SOURCES = test/fuzz/parse_numbers.cpp
-
-test_fuzz_parse_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_script_SOURCES = test/fuzz/parse_script.cpp
-
-test_fuzz_parse_univalue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_univalue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_univalue_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_univalue_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_univalue_SOURCES = test/fuzz/parse_univalue.cpp
-
-test_fuzz_prevector_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_prevector_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_prevector_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_prevector_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_prevector_SOURCES = test/fuzz/prevector.cpp
-
-test_fuzz_partial_merkle_tree_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIAL_MERKLE_TREE_DESERIALIZE=1
-test_fuzz_partial_merkle_tree_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_partial_merkle_tree_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_partial_merkle_tree_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_partial_merkle_tree_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_partially_signed_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIALLY_SIGNED_TRANSACTION_DESERIALIZE=1
-test_fuzz_partially_signed_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_partially_signed_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_partially_signed_transaction_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_partially_signed_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_policy_estimator_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_policy_estimator_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_policy_estimator_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_policy_estimator_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_policy_estimator_SOURCES = test/fuzz/policy_estimator.cpp
-
-test_fuzz_policy_estimator_io_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_policy_estimator_io_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_policy_estimator_io_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_policy_estimator_io_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_policy_estimator_io_SOURCES = test/fuzz/policy_estimator_io.cpp
-
-test_fuzz_pow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_pow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_pow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_pow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_pow_SOURCES = test/fuzz/pow.cpp
-
-test_fuzz_prefilled_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPREFILLED_TRANSACTION_DESERIALIZE=1
-test_fuzz_prefilled_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_prefilled_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_prefilled_transaction_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_prefilled_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_primitives_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_primitives_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_primitives_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_primitives_transaction_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_primitives_transaction_SOURCES = test/fuzz/primitives_transaction.cpp
-
-test_fuzz_process_messages_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_process_messages_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_messages_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_messages_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_messages_SOURCES = test/fuzz/process_messages.cpp
-
-test_fuzz_process_message_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_process_message_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_addr_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=addr
-test_fuzz_process_message_addr_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_addr_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_addr_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_addr_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_block_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=block
-test_fuzz_process_message_block_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_block_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_block_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_block_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_blocktxn_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=blocktxn
-test_fuzz_process_message_blocktxn_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_blocktxn_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_blocktxn_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_blocktxn_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_cmpctblock_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=cmpctblock
-test_fuzz_process_message_cmpctblock_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_cmpctblock_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_cmpctblock_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_cmpctblock_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_feefilter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=feefilter
-test_fuzz_process_message_feefilter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_feefilter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_feefilter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_feefilter_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_filteradd_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filteradd
-test_fuzz_process_message_filteradd_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_filteradd_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filteradd_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_filteradd_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_filterclear_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filterclear
-test_fuzz_process_message_filterclear_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_filterclear_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filterclear_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_filterclear_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_filterload_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filterload
-test_fuzz_process_message_filterload_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_filterload_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filterload_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_filterload_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getaddr_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getaddr
-test_fuzz_process_message_getaddr_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getaddr_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getaddr_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getaddr_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getblocks_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getblocks
-test_fuzz_process_message_getblocks_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getblocks_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getblocks_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getblocks_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getblocktxn_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getblocktxn
-test_fuzz_process_message_getblocktxn_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getblocktxn_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getblocktxn_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getblocktxn_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getdata_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getdata
-test_fuzz_process_message_getdata_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getdata_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getdata_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getdata_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getheaders_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getheaders
-test_fuzz_process_message_getheaders_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getheaders_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getheaders_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getheaders_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_headers_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=headers
-test_fuzz_process_message_headers_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_headers_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_headers_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_headers_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_inv_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=inv
-test_fuzz_process_message_inv_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_inv_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_inv_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_inv_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_mempool_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=mempool
-test_fuzz_process_message_mempool_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_mempool_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_mempool_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_mempool_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_notfound_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=notfound
-test_fuzz_process_message_notfound_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_notfound_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_notfound_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_notfound_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_ping_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=ping
-test_fuzz_process_message_ping_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_ping_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_ping_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_ping_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_pong_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=pong
-test_fuzz_process_message_pong_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_pong_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_pong_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_pong_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_sendcmpct_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=sendcmpct
-test_fuzz_process_message_sendcmpct_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_sendcmpct_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_sendcmpct_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_sendcmpct_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_sendheaders_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=sendheaders
-test_fuzz_process_message_sendheaders_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_sendheaders_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_sendheaders_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_sendheaders_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=tx
-test_fuzz_process_message_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_tx_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_tx_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_tx_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_verack_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=verack
-test_fuzz_process_message_verack_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_verack_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_verack_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_verack_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_version_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=version
-test_fuzz_process_message_version_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_version_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_version_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_version_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_protocol_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_protocol_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_protocol_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_protocol_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_protocol_SOURCES = test/fuzz/protocol.cpp
-
-test_fuzz_psbt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_psbt_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_psbt_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_psbt_SOURCES = test/fuzz/psbt.cpp
-
-test_fuzz_psbt_input_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPSBT_INPUT_DESERIALIZE=1
-test_fuzz_psbt_input_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_psbt_input_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_input_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_psbt_input_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_psbt_output_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPSBT_OUTPUT_DESERIALIZE=1
-test_fuzz_psbt_output_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_psbt_output_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_output_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_psbt_output_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_pub_key_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPUB_KEY_DESERIALIZE=1
-test_fuzz_pub_key_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_pub_key_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_pub_key_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_pub_key_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_random_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_random_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_random_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_random_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_random_SOURCES = test/fuzz/random.cpp
-
-test_fuzz_rbf_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_rbf_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_rbf_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_rbf_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_rbf_SOURCES = test/fuzz/rbf.cpp
-
-test_fuzz_rolling_bloom_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_rolling_bloom_filter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_rolling_bloom_filter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_rolling_bloom_filter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_rolling_bloom_filter_SOURCES = test/fuzz/rolling_bloom_filter.cpp
-
-test_fuzz_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_SOURCES = test/fuzz/script.cpp
-
-test_fuzz_script_bitcoin_consensus_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_bitcoin_consensus_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_bitcoin_consensus_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_bitcoin_consensus_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_bitcoin_consensus_SOURCES = test/fuzz/script_bitcoin_consensus.cpp
-
-test_fuzz_script_descriptor_cache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_descriptor_cache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_descriptor_cache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_descriptor_cache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_descriptor_cache_SOURCES = test/fuzz/script_descriptor_cache.cpp
-
-test_fuzz_script_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSCRIPT_DESERIALIZE=1
-test_fuzz_script_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_flags_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_flags_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_flags_SOURCES = test/fuzz/script_flags.cpp
-
-test_fuzz_script_interpreter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_interpreter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_interpreter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_interpreter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_interpreter_SOURCES = test/fuzz/script_interpreter.cpp
-
-test_fuzz_script_assets_test_minimizer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_assets_test_minimizer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_assets_test_minimizer_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_assets_test_minimizer_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_assets_test_minimizer_SOURCES = test/fuzz/script_assets_test_minimizer.cpp
-
-test_fuzz_script_ops_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_ops_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_ops_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_ops_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_ops_SOURCES = test/fuzz/script_ops.cpp
-
-test_fuzz_script_sigcache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_sigcache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_sigcache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_sigcache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_sigcache_SOURCES = test/fuzz/script_sigcache.cpp
-
-test_fuzz_script_sign_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_sign_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_sign_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_sign_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_sign_SOURCES = test/fuzz/script_sign.cpp
-
-test_fuzz_scriptnum_ops_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_scriptnum_ops_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_scriptnum_ops_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_scriptnum_ops_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_scriptnum_ops_SOURCES = test/fuzz/scriptnum_ops.cpp
-
-test_fuzz_secp256k1_ec_seckey_import_export_der_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_secp256k1_ec_seckey_import_export_der_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_secp256k1_ec_seckey_import_export_der_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_secp256k1_ec_seckey_import_export_der_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_secp256k1_ec_seckey_import_export_der_SOURCES = test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
-
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_SOURCES = test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
-
-test_fuzz_service_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSERVICE_DESERIALIZE=1
-test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_service_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_service_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_service_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_signature_checker_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_signature_checker_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_signature_checker_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_signature_checker_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_signature_checker_SOURCES = test/fuzz/signature_checker.cpp
-
-test_fuzz_signet_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_signet_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_signet_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_signet_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_signet_SOURCES = test/fuzz/signet.cpp
-
-test_fuzz_snapshotmetadata_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSNAPSHOTMETADATA_DESERIALIZE=1
-test_fuzz_snapshotmetadata_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_snapshotmetadata_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_snapshotmetadata_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_snapshotmetadata_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_span_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_span_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_span_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_span_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_span_SOURCES = test/fuzz/span.cpp
-
-test_fuzz_spanparsing_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_spanparsing_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_spanparsing_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_spanparsing_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_spanparsing_SOURCES = test/fuzz/spanparsing.cpp
-
-test_fuzz_string_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_string_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_string_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_string_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_string_SOURCES = test/fuzz/string.cpp
-
-test_fuzz_strprintf_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_strprintf_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_strprintf_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_strprintf_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_strprintf_SOURCES = test/fuzz/strprintf.cpp
-
-test_fuzz_sub_net_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSUB_NET_DESERIALIZE=1
-test_fuzz_sub_net_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_sub_net_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_sub_net_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_sub_net_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_system_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_system_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_system_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_system_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_system_SOURCES = test/fuzz/system.cpp
-
-test_fuzz_timedata_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_timedata_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_timedata_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_timedata_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_timedata_SOURCES = test/fuzz/timedata.cpp
-
-test_fuzz_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_transaction_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_transaction_SOURCES = test/fuzz/transaction.cpp
-
-test_fuzz_tx_in_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_tx_in_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_tx_in_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_in_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_tx_in_SOURCES = test/fuzz/tx_in.cpp
-
-test_fuzz_tx_in_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTX_IN_DESERIALIZE=1
-test_fuzz_tx_in_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_tx_in_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_in_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_tx_in_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_tx_out_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_tx_out_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_tx_out_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_out_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_tx_out_SOURCES = test/fuzz/tx_out.cpp
-
-test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1
-test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_txoutcompressor_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_txoutcompressor_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_txoutcompressor_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_txrequest_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_txrequest_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_txrequest_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_txrequest_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_txrequest_SOURCES = test/fuzz/txrequest.cpp
-
-test_fuzz_txundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXUNDO_DESERIALIZE=1
-test_fuzz_txundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_txundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_txundo_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_txundo_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_uint160_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DUINT160_DESERIALIZE=1
-test_fuzz_uint160_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_uint160_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_uint160_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_uint160_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_uint256_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DUINT256_DESERIALIZE=1
-test_fuzz_uint256_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_uint256_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_uint256_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_uint256_deserialize_SOURCES = test/fuzz/deserialize.cpp
+test_fuzz_fuzz_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_fuzz_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_fuzz_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_fuzz_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
+test_fuzz_fuzz_SOURCES = \
+ test/fuzz/addition_overflow.cpp \
+ test/fuzz/addrdb.cpp \
+ test/fuzz/addrman.cpp \
+ test/fuzz/asmap.cpp \
+ test/fuzz/asmap_direct.cpp \
+ test/fuzz/autofile.cpp \
+ test/fuzz/banman.cpp \
+ test/fuzz/base_encode_decode.cpp \
+ test/fuzz/bech32.cpp \
+ test/fuzz/block.cpp \
+ test/fuzz/block_header.cpp \
+ test/fuzz/blockfilter.cpp \
+ test/fuzz/bloom_filter.cpp \
+ test/fuzz/buffered_file.cpp \
+ test/fuzz/chain.cpp \
+ test/fuzz/checkqueue.cpp \
+ test/fuzz/coins_view.cpp \
+ test/fuzz/connman.cpp \
+ test/fuzz/crypto.cpp \
+ test/fuzz/crypto_aes256.cpp \
+ test/fuzz/crypto_aes256cbc.cpp \
+ test/fuzz/crypto_chacha20.cpp \
+ test/fuzz/crypto_chacha20_poly1305_aead.cpp \
+ test/fuzz/crypto_common.cpp \
+ test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp \
+ test/fuzz/crypto_poly1305.cpp \
+ test/fuzz/cuckoocache.cpp \
+ test/fuzz/data_stream.cpp \
+ test/fuzz/decode_tx.cpp \
+ test/fuzz/descriptor_parse.cpp \
+ test/fuzz/deserialize.cpp \
+ test/fuzz/eval_script.cpp \
+ test/fuzz/fee_rate.cpp \
+ test/fuzz/fees.cpp \
+ test/fuzz/flatfile.cpp \
+ test/fuzz/float.cpp \
+ test/fuzz/golomb_rice.cpp \
+ test/fuzz/hex.cpp \
+ test/fuzz/http_request.cpp \
+ test/fuzz/integer.cpp \
+ test/fuzz/key.cpp \
+ test/fuzz/key_io.cpp \
+ test/fuzz/kitchen_sink.cpp \
+ test/fuzz/load_external_block_file.cpp \
+ test/fuzz/locale.cpp \
+ test/fuzz/merkleblock.cpp \
+ test/fuzz/message.cpp \
+ test/fuzz/muhash.cpp \
+ test/fuzz/multiplication_overflow.cpp \
+ test/fuzz/net.cpp \
+ test/fuzz/net_permissions.cpp \
+ test/fuzz/netaddress.cpp \
+ test/fuzz/node_eviction.cpp \
+ test/fuzz/p2p_transport_deserializer.cpp \
+ test/fuzz/parse_hd_keypath.cpp \
+ test/fuzz/parse_iso8601.cpp \
+ test/fuzz/parse_numbers.cpp \
+ test/fuzz/parse_script.cpp \
+ test/fuzz/parse_univalue.cpp \
+ test/fuzz/policy_estimator.cpp \
+ test/fuzz/policy_estimator_io.cpp \
+ test/fuzz/pow.cpp \
+ test/fuzz/prevector.cpp \
+ test/fuzz/primitives_transaction.cpp \
+ test/fuzz/process_message.cpp \
+ test/fuzz/process_messages.cpp \
+ test/fuzz/protocol.cpp \
+ test/fuzz/psbt.cpp \
+ test/fuzz/random.cpp \
+ test/fuzz/rbf.cpp \
+ test/fuzz/rolling_bloom_filter.cpp \
+ test/fuzz/script.cpp \
+ test/fuzz/script_assets_test_minimizer.cpp \
+ test/fuzz/script_bitcoin_consensus.cpp \
+ test/fuzz/script_descriptor_cache.cpp \
+ test/fuzz/script_flags.cpp \
+ test/fuzz/script_interpreter.cpp \
+ test/fuzz/script_ops.cpp \
+ test/fuzz/script_sigcache.cpp \
+ test/fuzz/script_sign.cpp \
+ test/fuzz/scriptnum_ops.cpp \
+ test/fuzz/secp256k1_ec_seckey_import_export_der.cpp \
+ test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp \
+ test/fuzz/signature_checker.cpp \
+ test/fuzz/signet.cpp \
+ test/fuzz/span.cpp \
+ test/fuzz/spanparsing.cpp \
+ test/fuzz/string.cpp \
+ test/fuzz/strprintf.cpp \
+ test/fuzz/system.cpp \
+ test/fuzz/timedata.cpp \
+ test/fuzz/transaction.cpp \
+ test/fuzz/tx_in.cpp \
+ test/fuzz/tx_out.cpp \
+ test/fuzz/txrequest.cpp
endif # ENABLE_FUZZ
@@ -1309,6 +324,11 @@ if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
endif
+if ENABLE_FUZZ_LINK_ALL
+all-local: $(FUZZ_BINARY)
+ bash ./test/fuzz/danger_link_all.sh
+endif
+
%.cpp.test: %.cpp
@echo Running tests: `cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1` from $<
$(AM_V_at)$(TEST_BINARY) --catch_system_errors=no -l test_suite -t "`cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" -- DEBUG_LOG_OUT > $<.log 2>&1 || (cat $<.log && false)
diff --git a/src/addrdb.cpp b/src/addrdb.cpp
index 27f22826a9..8f77ed35ce 100644
--- a/src/addrdb.cpp
+++ b/src/addrdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/addrdb.h b/src/addrdb.h
index 4ac0e3e1b5..8953ebb169 100644
--- a/src/addrdb.h
+++ b/src/addrdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 7636c6bad2..ed7fccc0ff 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -617,7 +617,7 @@ CAddrInfo CAddrMan::SelectTriedCollision_()
return CAddrInfo();
}
- CAddrInfo& newInfo = mapInfo[id_new];
+ const CAddrInfo& newInfo = mapInfo[id_new];
// which tried bucket to move the entry to
int tried_bucket = newInfo.GetTriedBucket(nKey, m_asmap);
diff --git a/src/attributes.h b/src/attributes.h
index 995c24e13f..9957bcd84b 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/banman.cpp b/src/banman.cpp
index 995fef3d07..49bf6c43dc 100644
--- a/src/banman.cpp
+++ b/src/banman.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/base58.cpp b/src/base58.cpp
index 780846c6c5..65e373283c 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/base58.h b/src/base58.h
index 60551a12ae..9ba5af73e0 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp
index 18cb5de196..6f6b4e3bfa 100644
--- a/src/bench/base58.cpp
+++ b/src/bench/base58.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index 99a7ad237b..af5a82f69f 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/chacha20.cpp b/src/bench/chacha20.cpp
index 913e0f8d57..a6f4eec4ca 100644
--- a/src/bench/chacha20.cpp
+++ b/src/bench/chacha20.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/chacha_poly_aead.cpp b/src/bench/chacha_poly_aead.cpp
index 3b1d3e697a..e994279a4d 100644
--- a/src/bench/chacha_poly_aead.cpp
+++ b/src/bench/chacha_poly_aead.cpp
@@ -31,12 +31,15 @@ static void CHACHA20_POLY1305_AEAD(benchmark::Bench& bench, size_t buffersize, b
uint32_t len = 0;
bench.batch(buffersize).unit("byte").run([&] {
// encrypt or decrypt the buffer with a static key
- assert(aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true));
+ const bool crypt_ok_1 = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true);
+ assert(crypt_ok_1);
if (include_decryption) {
// if we decrypt, include the GetLength
- assert(aead.GetLength(&len, seqnr_aad, aad_pos, in.data()));
- assert(aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true));
+ const bool get_length_ok = aead.GetLength(&len, seqnr_aad, aad_pos, in.data());
+ assert(get_length_ok);
+ const bool crypt_ok_2 = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true);
+ assert(crypt_ok_2);
}
// increase main sequence number
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index 99aafd8dfc..e50c4476bb 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index 65d16d47d8..30fe11be6b 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -4,6 +4,7 @@
#include <bench/bench.h>
+#include <crypto/muhash.h>
#include <crypto/ripemd160.h>
#include <crypto/sha1.h>
#include <crypto/sha256.h>
@@ -105,6 +106,54 @@ static void FastRandom_1bit(benchmark::Bench& bench)
});
}
+static void MuHash(benchmark::Bench& bench)
+{
+ MuHash3072 acc;
+ unsigned char key[32] = {0};
+ int i = 0;
+ bench.run([&] {
+ key[0] = ++i;
+ acc *= MuHash3072(key);
+ });
+}
+
+static void MuHashMul(benchmark::Bench& bench)
+{
+ MuHash3072 acc;
+ FastRandomContext rng(true);
+ MuHash3072 muhash{rng.randbytes(32)};
+
+ bench.run([&] {
+ acc *= muhash;
+ });
+}
+
+static void MuHashDiv(benchmark::Bench& bench)
+{
+ MuHash3072 acc;
+ FastRandomContext rng(true);
+ MuHash3072 muhash{rng.randbytes(32)};
+
+ for (size_t i = 0; i < bench.epochIterations(); ++i) {
+ acc *= muhash;
+ }
+
+ bench.run([&] {
+ acc /= muhash;
+ });
+}
+
+static void MuHashPrecompute(benchmark::Bench& bench)
+{
+ MuHash3072 acc;
+ FastRandomContext rng(true);
+ std::vector<unsigned char> key{rng.randbytes(32)};
+
+ bench.run([&] {
+ MuHash3072{key};
+ });
+}
+
BENCHMARK(RIPEMD160);
BENCHMARK(SHA1);
BENCHMARK(SHA256);
@@ -116,3 +165,8 @@ BENCHMARK(SipHash_32b);
BENCHMARK(SHA256D64_1024);
BENCHMARK(FastRandom_32bit);
BENCHMARK(FastRandom_1bit);
+
+BENCHMARK(MuHash);
+BENCHMARK(MuHashMul);
+BENCHMARK(MuHashDiv);
+BENCHMARK(MuHashPrecompute);
diff --git a/src/bench/gcs_filter.cpp b/src/bench/gcs_filter.cpp
index ef83242e41..607e4392b7 100644
--- a/src/bench/gcs_filter.cpp
+++ b/src/bench/gcs_filter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/hashpadding.cpp b/src/bench/hashpadding.cpp
index 309cae3723..753c8c2881 100644
--- a/src/bench/hashpadding.cpp
+++ b/src/bench/hashpadding.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/lockedpool.cpp b/src/bench/lockedpool.cpp
index 32b060a15a..b6d8824aba 100644
--- a/src/bench/lockedpool.cpp
+++ b/src/bench/lockedpool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp
index 1b9e428c9d..db9a5661fd 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp
index 89233e390c..9b862b735c 100644
--- a/src/bench/mempool_stress.cpp
+++ b/src/bench/mempool_stress.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/poly1305.cpp b/src/bench/poly1305.cpp
index d8db99e7d4..cdef97c0ea 100644
--- a/src/bench/poly1305.cpp
+++ b/src/bench/poly1305.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp
index 73af244ce0..dcd0e10285 100644
--- a/src/bench/prevector.cpp
+++ b/src/bench/prevector.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp
index 9b43951e6e..997ab56549 100644
--- a/src/bench/rollingbloom.cpp
+++ b/src/bench/rollingbloom.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp
index 1ff41765cf..f1eeef8885 100644
--- a/src/bench/rpc_mempool.cpp
+++ b/src/bench/rpc_mempool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/util_time.cpp b/src/bench/util_time.cpp
index fad179eb87..afc733482e 100644
--- a/src/bench/util_time.cpp
+++ b/src/bench/util_time.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp
index 9af0b502eb..e3f6b35a7d 100644
--- a/src/bench/verify_script.cpp
+++ b/src/bench/verify_script.cpp
@@ -24,7 +24,7 @@ static void VerifyScriptBench(benchmark::Bench& bench)
const int flags = SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH;
const int witnessversion = 0;
- // Keypair.
+ // Key pair.
CKey key;
static const std::array<unsigned char, 32> vchKey = {
{
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
index b3b73284d8..b385cec085 100644
--- a/src/bench/wallet_balance.cpp
+++ b/src/bench/wallet_balance.cpp
@@ -24,21 +24,19 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE;
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
- CWallet wallet{chain.get(), "", CreateMockWalletDatabase()};
+ CWallet wallet{test_setup.m_node.chain.get(), "", CreateMockWalletDatabase()};
{
wallet.SetupLegacyScriptPubKeyMan();
bool first_run;
if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
}
- auto handler = chain->handleNotifications({&wallet, [](CWallet*) {}});
+ auto handler = test_setup.m_node.chain->handleNotifications({&wallet, [](CWallet*) {}});
const Optional<std::string> address_mine{add_mine ? Optional<std::string>{getnewaddress(wallet)} : nullopt};
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);
for (int i = 0; i < 100; ++i) {
- generatetoaddress(test_setup.m_node, address_mine.get_value_or(ADDRESS_WATCHONLY));
+ generatetoaddress(test_setup.m_node, address_mine.value_or(ADDRESS_WATCHONLY));
generatetoaddress(test_setup.m_node, ADDRESS_WATCHONLY);
}
SyncWithValidationInterfaceQueue();
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index ef4641cb63..94043a6b45 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -59,7 +59,7 @@ static void SetupCliArgs(ArgsManager& argsman)
argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-generate", strprintf("Generate blocks immediately, equivalent to RPC generatenewaddress followed by RPC generatetoaddress. Optional positional integer arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000", DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-netinfo", "Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0).", ArgsManager::ALLOW_INT, OptionsCategory::OPTIONS);
+ argsman.AddArg("-netinfo", "Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0). Pass \"help\" for detailed help documentation.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
SetupChainParamsBaseOptions(argsman);
argsman.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -309,7 +309,8 @@ private:
}
return UNKNOWN_NETWORK;
}
- uint8_t m_details_level{0}; //!< Optional user-supplied arg to set dashboard details level
+ uint8_t m_details_level{0}; //!< Optional user-supplied arg to set dashboard details level
+ bool m_is_help_requested{false}; //!< Optional user-supplied arg to print help documentation
bool DetailsRequested() const { return m_details_level > 0 && m_details_level < 5; }
bool IsAddressSelected() const { return m_details_level == 2 || m_details_level == 4; }
bool IsVersionSelected() const { return m_details_level == 3 || m_details_level == 4; }
@@ -349,6 +350,62 @@ private:
const double milliseconds{round(1000 * seconds)};
return milliseconds > 999999 ? "-" : ToString(milliseconds);
}
+ const UniValue NetinfoHelp()
+ {
+ return std::string{
+ "-netinfo level|\"help\" \n\n"
+ "Returns a network peer connections dashboard with information from the remote server.\n"
+ "Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo.\n"
+ "An optional integer argument from 0 to 4 can be passed for different peers listings.\n"
+ "Pass \"help\" to see this detailed help documentation.\n"
+ "If more than one argument is passed, only the first one is read and parsed.\n"
+ "Suggestion: use with the Linux watch(1) command for a live dashboard; see example below.\n\n"
+ "Arguments:\n"
+ "1. level (integer 0-4, optional) Specify the info level of the peers dashboard (default 0):\n"
+ " 0 - Connection counts and local addresses\n"
+ " 1 - Like 0 but with a peers listing (without address or version columns)\n"
+ " 2 - Like 1 but with an address column\n"
+ " 3 - Like 1 but with a version column\n"
+ " 4 - Like 1 but with both address and version columns\n"
+ "2. help (string \"help\", optional) Print this help documentation instead of the dashboard.\n\n"
+ "Result:\n\n"
+ "* The peers listing in levels 1-4 displays all of the peers sorted by direction and minimum ping time:\n\n"
+ " Column Description\n"
+ " ------ -----------\n"
+ " <-> Direction\n"
+ " \"in\" - inbound connections are those initiated by the peer\n"
+ " \"out\" - outbound connections are those initiated by us\n"
+ " type Type of peer connection\n"
+ " \"full\" - full relay, the default\n"
+ " \"block\" - block relay; like full relay but does not relay transactions or addresses\n"
+ " net Network the peer connected through (\"ipv4\", \"ipv6\", \"onion\", \"i2p\", or \"cjdns\")\n"
+ " mping Minimum observed ping time, in milliseconds (ms)\n"
+ " ping Last observed ping time, in milliseconds (ms)\n"
+ " send Time since last message sent to the peer, in seconds\n"
+ " recv Time since last message received from the peer, in seconds\n"
+ " txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes\n"
+ " blk Time since last novel block passing initial validity checks received from the peer, in minutes\n"
+ " age Duration of connection to the peer, in minutes\n"
+ " asmap Mapped AS (Autonomous System) number in the BGP route to the peer, used for diversifying\n"
+ " peer selection (only displayed if the -asmap config option is set)\n"
+ " id Peer index, in increasing order of peer connections since node startup\n"
+ " address IP address and port of the peer\n"
+ " version Peer version and subversion concatenated, e.g. \"70016/Satoshi:21.0.0/\"\n\n"
+ "* The connection counts table displays the number of peers by direction, network, and the totals\n"
+ " for each, as well as a column for block relay peers.\n\n"
+ "* The local addresses table lists each local address broadcast by the node, the port, and the score.\n\n"
+ "Examples:\n\n"
+ "Connection counts and local addresses only\n"
+ "> bitcoin-cli -netinfo\n\n"
+ "Compact peers listing\n"
+ "> bitcoin-cli -netinfo 1\n\n"
+ "Full dashboard\n"
+ "> bitcoin-cli -netinfo 4\n\n"
+ "Full live dashboard, adjust --interval or --no-title as needed (Linux)\n"
+ "> watch --interval 1 --no-title bitcoin-cli -netinfo 4\n\n"
+ "See this help\n"
+ "> bitcoin-cli -netinfo help\n"};
+ }
const int64_t m_time_now{GetSystemTimeInSeconds()};
public:
@@ -361,6 +418,10 @@ public:
uint8_t n{0};
if (ParseUInt8(args.at(0), &n)) {
m_details_level = n;
+ } else if (args.at(0) == "help") {
+ m_is_help_requested = true;
+ } else {
+ throw std::runtime_error(strprintf("invalid -netinfo argument: %s", args.at(0)));
}
}
UniValue result(UniValue::VARR);
@@ -371,6 +432,9 @@ public:
UniValue ProcessReply(const UniValue& batch_in) override
{
+ if (m_is_help_requested) {
+ return JSONRPCReplyObj(NetinfoHelp(), NullUniValue, 1);
+ }
const std::vector<UniValue> batch{JSONRPCProcessBatchReply(batch_in)};
if (!batch[ID_PEERINFO]["error"].isNull()) return batch[ID_PEERINFO];
if (!batch[ID_NETWORKINFO]["error"].isNull()) return batch[ID_NETWORKINFO];
@@ -424,7 +488,7 @@ public:
// Report detailed peer connections list sorted by direction and minimum ping time.
if (DetailsRequested() && !m_peers.empty()) {
std::sort(m_peers.begin(), m_peers.end());
- result += strprintf("Peer connections sorted by direction and min ping\n<-> relay net mping ping send recv txn blk %*s ", m_max_age_length, "age");
+ result += strprintf("<-> relay net mping ping send recv txn blk %*s ", m_max_age_length, "age");
if (m_is_asmap_on) result += " asmap ";
result += strprintf("%*s %-*s%s\n", m_max_id_length, "id", IsAddressSelected() ? m_max_addr_length : 0, IsAddressSelected() ? "address" : "", IsVersionSelected() ? "version" : "");
for (const Peer& peer : m_peers) {
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index e22b3766cf..321d62fe4d 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -11,6 +11,7 @@
#include <consensus/consensus.h>
#include <core_io.h>
#include <key_io.h>
+#include <policy/policy.h>
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <script/script.h>
@@ -40,6 +41,7 @@ static void SetupBitcoinTxArgs(ArgsManager &argsman)
{
SetupHelpOptions(argsman);
+ argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-create", "Create new, empty TX.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-json", "Select JSON output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-txid", "Output only the hex-encoded transaction id of the resultant transaction.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -95,13 +97,16 @@ static int AppInitRawTx(int argc, char* argv[])
fCreateBlank = gArgs.GetBoolArg("-create", false);
- if (argc < 2 || HelpRequested(gArgs)) {
+ if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
// First part of help message is specific to this utility
- std::string strUsage = PACKAGE_NAME " bitcoin-tx utility version " + FormatFullVersion() + "\n\n" +
- "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n" +
- "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n" +
- "\n";
- strUsage += gArgs.GetHelpMessage();
+ std::string strUsage = PACKAGE_NAME " bitcoin-tx utility version " + FormatFullVersion() + "\n";
+ if (!gArgs.IsArgSet("-version")) {
+ strUsage += "\n"
+ "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n"
+ "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n"
+ "\n";
+ strUsage += gArgs.GetHelpMessage();
+ }
tfm::format(std::cout, "%s", strUsage);
@@ -192,8 +197,9 @@ static CAmount ExtractAndValidateValue(const std::string& strValue)
static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal)
{
int64_t newVersion;
- if (!ParseInt64(cmdVal, &newVersion) || newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION)
+ if (!ParseInt64(cmdVal, &newVersion) || newVersion < 1 || newVersion > TX_MAX_STANDARD_VERSION) {
throw std::runtime_error("Invalid TX version requested: '" + cmdVal + "'");
+ }
tx.nVersion = (int) newVersion;
}
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index b9c2fe2d34..3e8e5fc7bc 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -24,14 +24,20 @@ static void SetupWalletToolArgs(ArgsManager& argsman)
SetupHelpOptions(argsman);
SetupChainParamsBaseOptions(argsman);
+ argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-wallet=<wallet-name>", "Specify wallet name", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-dumpfile=<file name>", "When used with 'dump', writes out the records to this file. When used with 'createfromdump', loads the records into a new wallet.", ArgsManager::ALLOW_STRING, OptionsCategory::OPTIONS);
argsman.AddArg("-debug=<category>", "Output debugging information (default: 0).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-descriptors", "Create descriptors wallet. Only for 'create'", ArgsManager::ALLOW_BOOL, OptionsCategory::OPTIONS);
+ argsman.AddArg("-format=<format>", "The format of the wallet file to create. Either \"bdb\" or \"sqlite\". Only used with 'createfromdump'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("info", "Get wallet info", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
argsman.AddArg("create", "Create new wallet file", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
argsman.AddArg("salvage", "Attempt to recover private keys from a corrupt wallet. Warning: 'salvage' is experimental.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
+ argsman.AddArg("dump", "Print out all of the wallet key-value records", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
+ argsman.AddArg("createfromdump", "Create new wallet file from dumped records", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
}
static bool WalletAppInit(int argc, char* argv[])
@@ -42,16 +48,18 @@ static bool WalletAppInit(int argc, char* argv[])
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error_message);
return false;
}
- if (argc < 2 || HelpRequested(gArgs)) {
- std::string usage = strprintf("%s bitcoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n\n" +
- "bitcoin-wallet is an offline tool for creating and interacting with " PACKAGE_NAME " wallet files.\n" +
- "By default bitcoin-wallet will act on wallets in the default mainnet wallet directory in the datadir.\n" +
- "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n" +
- "Usage:\n" +
- " bitcoin-wallet [options] <command>\n\n" +
- gArgs.GetHelpMessage();
-
- tfm::format(std::cout, "%s", usage);
+ if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
+ std::string strUsage = strprintf("%s bitcoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n";
+ if (!gArgs.IsArgSet("-version")) {
+ strUsage += "\n"
+ "bitcoin-wallet is an offline tool for creating and interacting with " PACKAGE_NAME " wallet files.\n"
+ "By default bitcoin-wallet will act on wallets in the default mainnet wallet directory in the datadir.\n"
+ "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n"
+ "Usage:\n"
+ " bitcoin-wallet [options] <command>\n";
+ strUsage += "\n" + gArgs.GetHelpMessage();
+ }
+ tfm::format(std::cout, "%s", strUsage);
return false;
}
@@ -112,8 +120,9 @@ int main(int argc, char* argv[])
ECCVerifyHandle globalVerifyHandle;
ECC_Start();
- if (!WalletTool::ExecuteWalletToolFunc(method, name))
+ if (!WalletTool::ExecuteWalletToolFunc(gArgs, method, name)) {
return EXIT_FAILURE;
+ }
ECC_Stop();
return EXIT_SUCCESS;
}
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 455a82e390..b7bcb534ef 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -28,15 +28,6 @@
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
UrlDecodeFn* const URL_DECODE = urlDecode;
-static void WaitForShutdown(NodeContext& node)
-{
- while (!ShutdownRequested())
- {
- UninterruptibleSleep(std::chrono::milliseconds{200});
- }
- Interrupt(node);
-}
-
static bool AppInit(int argc, char* argv[])
{
NodeContext node;
@@ -57,11 +48,11 @@ static bool AppInit(int argc, char* argv[])
if (HelpRequested(args) || args.IsArgSet("-version")) {
std::string strUsage = PACKAGE_NAME " version " + FormatFullVersion() + "\n";
- if (args.IsArgSet("-version")) {
- strUsage += FormatParagraph(LicenseInfo()) + "\n";
- } else {
- strUsage += "\nUsage: bitcoind [options] Start " PACKAGE_NAME "\n";
- strUsage += "\n" + args.GetHelpMessage();
+ if (!args.IsArgSet("-version")) {
+ strUsage += FormatParagraph(LicenseInfo()) + "\n"
+ "\nUsage: bitcoind [options] Start " PACKAGE_NAME "\n"
+ "\n";
+ strUsage += args.GetHelpMessage();
}
tfm::format(std::cout, "%s", strUsage);
@@ -147,12 +138,10 @@ static bool AppInit(int argc, char* argv[])
PrintExceptionContinue(nullptr, "AppInit()");
}
- if (!fRet)
- {
- Interrupt(node);
- } else {
- WaitForShutdown(node);
+ if (fRet) {
+ WaitForShutdown();
}
+ Interrupt(node);
Shutdown(node);
return fRet;
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index a47709cd82..aa111b5939 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp
index 9a6fb4abd0..41fa0b6fa0 100644
--- a/src/blockfilter.cpp
+++ b/src/blockfilter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bloom.cpp b/src/bloom.cpp
index d182f0728e..d0128a26d7 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bloom.h b/src/bloom.h
index 24dc607cd9..fdaa8abfb2 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index fedb032db2..88cf5ef0a8 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -272,7 +272,7 @@ public:
bin = ParseHex("512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae");
vSeeds.emplace_back("178.128.221.177");
vSeeds.emplace_back("2a01:7c8:d005:390::5");
- vSeeds.emplace_back("ntv3mtqw5wt63red.onion:38333");
+ vSeeds.emplace_back("v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333");
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000019fd16269a");
consensus.defaultAssumeValid = uint256S("0x0000002a1de0f46379358c1fd09906f7ac59adf3712323ed90eb59e4c183c020"); // 9434
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 603969aaea..2c517b58f8 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 9b4ae2f7ab..d593cff722 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/clientversion.cpp b/src/clientversion.cpp
index aaf041602b..29c38e2d3b 100644
--- a/src/clientversion.cpp
+++ b/src/clientversion.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/clientversion.h b/src/clientversion.h
index c925b8f084..2da909f829 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/coins.cpp b/src/coins.cpp
index 5de2ed7810..14f58e956c 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compat.h b/src/compat.h
index 5fa6589792..dad14748a2 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compat/assumptions.h b/src/compat/assumptions.h
index 4b0b224c69..301c2d914c 100644
--- a/src/compat/assumptions.h
+++ b/src/compat/assumptions.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp
index d17de33e86..6d7a293f9b 100644
--- a/src/compat/glibc_compat.cpp
+++ b/src/compat/glibc_compat.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp
index 0367b9a53f..06d0dd6fba 100644
--- a/src/compat/glibc_sanity.cpp
+++ b/src/compat/glibc_sanity.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 0983595c6a..217cb019e1 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index 9e8e6530f1..f595f16eab 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/consensus/tx_verify.h b/src/consensus/tx_verify.h
index e2a9328df8..e78dc9f2a5 100644
--- a/src/consensus/tx_verify.h
+++ b/src/consensus/tx_verify.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index e007c481df..c4d305434a 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/core_io.h b/src/core_io.h
index aaee9c445d..5469a760ee 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -18,6 +18,7 @@ class CTransaction;
struct CMutableTransaction;
class uint256;
class UniValue;
+class CTxUndo;
// core_read.cpp
CScript ParseScript(const std::string& s);
@@ -29,7 +30,7 @@ bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header);
/**
* Parse a hex string into 256 bits
* @param[in] strHex a hex-formatted, 64-character string
- * @param[out] result the result of the parasing
+ * @param[out] result the result of the parsing
* @returns true if successful, false if not
*
* @see ParseHashV for an RPC-oriented version of this
@@ -45,6 +46,6 @@ std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
std::string SighashToStr(unsigned char sighash_type);
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
void ScriptToUniv(const CScript& script, UniValue& out, bool include_address);
-void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0);
+void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0, const CTxUndo* txundo = nullptr);
#endif // BITCOIN_CORE_IO_H
diff --git a/src/core_read.cpp b/src/core_read.cpp
index a2eebbd528..b5fc93886d 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -126,31 +126,72 @@ static bool CheckTxScriptsSanity(const CMutableTransaction& tx)
static bool DecodeTx(CMutableTransaction& tx, const std::vector<unsigned char>& tx_data, bool try_no_witness, bool try_witness)
{
+ // General strategy:
+ // - Decode both with extended serialization (which interprets the 0x0001 tag as a marker for
+ // the presence of witnesses) and with legacy serialization (which interprets the tag as a
+ // 0-input 1-output incomplete transaction).
+ // - Restricted by try_no_witness (which disables legacy if false) and try_witness (which
+ // disables extended if false).
+ // - Ignore serializations that do not fully consume the hex string.
+ // - If neither succeeds, fail.
+ // - If only one succeeds, return that one.
+ // - If both decode attempts succeed:
+ // - If only one passes the CheckTxScriptsSanity check, return that one.
+ // - If neither or both pass CheckTxScriptsSanity, return the extended one.
+
+ CMutableTransaction tx_extended, tx_legacy;
+ bool ok_extended = false, ok_legacy = false;
+
+ // Try decoding with extended serialization support, and remember if the result successfully
+ // consumes the entire input.
if (try_witness) {
CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION);
try {
- ssData >> tx;
- // If transaction looks sane, we don't try other mode even if requested
- if (ssData.empty() && (!try_no_witness || CheckTxScriptsSanity(tx))) {
- return true;
- }
+ ssData >> tx_extended;
+ if (ssData.empty()) ok_extended = true;
} catch (const std::exception&) {
// Fall through.
}
}
+ // Optimization: if extended decoding succeeded and the result passes CheckTxScriptsSanity,
+ // don't bother decoding the other way.
+ if (ok_extended && CheckTxScriptsSanity(tx_extended)) {
+ tx = std::move(tx_extended);
+ return true;
+ }
+
+ // Try decoding with legacy serialization, and remember if the result successfully consumes the entire input.
if (try_no_witness) {
CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
try {
- ssData >> tx;
- if (ssData.empty()) {
- return true;
- }
+ ssData >> tx_legacy;
+ if (ssData.empty()) ok_legacy = true;
} catch (const std::exception&) {
// Fall through.
}
}
+ // If legacy decoding succeeded and passes CheckTxScriptsSanity, that's our answer, as we know
+ // at this point that extended decoding either failed or doesn't pass the sanity check.
+ if (ok_legacy && CheckTxScriptsSanity(tx_legacy)) {
+ tx = std::move(tx_legacy);
+ return true;
+ }
+
+ // If extended decoding succeeded, and neither decoding passes sanity, return the extended one.
+ if (ok_extended) {
+ tx = std::move(tx_extended);
+ return true;
+ }
+
+ // If legacy decoding succeeded and extended didn't, return the legacy one.
+ if (ok_legacy) {
+ tx = std::move(tx_legacy);
+ return true;
+ }
+
+ // If none succeeded, we failed.
return false;
}
diff --git a/src/core_write.cpp b/src/core_write.cpp
index 3980d8cb2e..a3902863d6 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,9 @@
#include <script/standard.h>
#include <serialize.h>
#include <streams.h>
+#include <undo.h>
#include <univalue.h>
+#include <util/check.h>
#include <util/system.h>
#include <util/strencodings.h>
@@ -177,7 +179,7 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
out.pushKV("addresses", a);
}
-void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)
+void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo)
{
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
@@ -189,13 +191,20 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
entry.pushKV("weight", GetTransactionWeight(tx));
entry.pushKV("locktime", (int64_t)tx.nLockTime);
- UniValue vin(UniValue::VARR);
+ UniValue vin{UniValue::VARR};
+
+ // If available, use Undo data to calculate the fee. Note that txundo == nullptr
+ // for coinbase transactions and for transactions where undo data is unavailable.
+ const bool calculate_fee = txundo != nullptr;
+ CAmount amt_total_in = 0;
+ CAmount amt_total_out = 0;
+
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const CTxIn& txin = tx.vin[i];
UniValue in(UniValue::VOBJ);
- if (tx.IsCoinBase())
+ if (tx.IsCoinBase()) {
in.pushKV("coinbase", HexStr(txin.scriptSig));
- else {
+ } else {
in.pushKV("txid", txin.prevout.hash.GetHex());
in.pushKV("vout", (int64_t)txin.prevout.n);
UniValue o(UniValue::VOBJ);
@@ -210,6 +219,10 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
}
in.pushKV("txinwitness", txinwitness);
}
+ if (calculate_fee) {
+ const CTxOut& prev_txout = txundo->vprevout[i].out;
+ amt_total_in += prev_txout.nValue;
+ }
in.pushKV("sequence", (int64_t)txin.nSequence);
vin.push_back(in);
}
@@ -228,9 +241,19 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
out.pushKV("scriptPubKey", o);
vout.push_back(out);
+
+ if (calculate_fee) {
+ amt_total_out += txout.nValue;
+ }
}
entry.pushKV("vout", vout);
+ if (calculate_fee) {
+ const CAmount fee = amt_total_in - amt_total_out;
+ CHECK_NONFATAL(MoneyRange(fee));
+ entry.pushKV("fee", ValueFromAmount(fee));
+ }
+
if (!hashBlock.IsNull())
entry.pushKV("blockhash", hashBlock.GetHex());
diff --git a/src/crc32c/.appveyor.yml b/src/crc32c/.appveyor.yml
index 7345746750..b23e02e88a 100644
--- a/src/crc32c/.appveyor.yml
+++ b/src/crc32c/.appveyor.yml
@@ -8,9 +8,9 @@ environment:
matrix:
# AppVeyor currently has no custom job name feature.
# http://help.appveyor.com/discussions/questions/1623-can-i-provide-a-friendly-name-for-jobs
- - JOB: Visual Studio 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- CMAKE_GENERATOR: Visual Studio 15 2017
+ - JOB: Visual Studio 2019
+ APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+ CMAKE_GENERATOR: Visual Studio 16 2019
platform:
- x86
@@ -24,10 +24,11 @@ build_script:
- git submodule update --init --recursive
- mkdir build
- cd build
- - if "%platform%"=="x64" set CMAKE_GENERATOR=%CMAKE_GENERATOR% Win64
+ - if "%platform%"=="x86" (set CMAKE_GENERATOR_PLATFORM="Win32")
+ else (set CMAKE_GENERATOR_PLATFORM="%platform%")
- cmake --version
- - cmake .. -G "%CMAKE_GENERATOR%" -DCRC32C_USE_GLOG=0
- -DCMAKE_CONFIGURATION_TYPES="%CONFIGURATION%"
+ - cmake .. -G "%CMAKE_GENERATOR%" -A "%CMAKE_GENERATOR_PLATFORM%"
+ -DCMAKE_CONFIGURATION_TYPES="%CONFIGURATION%" -DCRC32C_USE_GLOG=0
- cmake --build . --config "%CONFIGURATION%"
- cd ..
diff --git a/src/crc32c/AUTHORS b/src/crc32c/AUTHORS
index 6f1f6871a6..ef9b4ea933 100644
--- a/src/crc32c/AUTHORS
+++ b/src/crc32c/AUTHORS
@@ -7,3 +7,5 @@ Google Inc.
Fangming Fang <Fangming.Fang@arm.com>
Vadim Skipin <vadim.skipin@gmail.com>
+Rodrigo Tobar <rtobar@icrar.org>
+Harry Mallon <hjmallon@gmail.com>
diff --git a/src/crc32c/CMakeLists.txt b/src/crc32c/CMakeLists.txt
index 111a3e3614..71692d5796 100644
--- a/src/crc32c/CMakeLists.txt
+++ b/src/crc32c/CMakeLists.txt
@@ -5,15 +5,21 @@
cmake_minimum_required(VERSION 3.1)
project(Crc32c VERSION 1.1.0 LANGUAGES C CXX)
-# This project can use C11, but will gracefully decay down to C89.
-set(CMAKE_C_STANDARD 11)
-set(CMAKE_C_STANDARD_REQUIRED OFF)
-set(CMAKE_C_EXTENSIONS OFF)
-
-# This project requires C++11.
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF)
+# C standard can be overridden when this is used as a sub-project.
+if(NOT CMAKE_C_STANDARD)
+ # This project can use C11, but will gracefully decay down to C89.
+ set(CMAKE_C_STANDARD 11)
+ set(CMAKE_C_STANDARD_REQUIRED OFF)
+ set(CMAKE_C_EXTENSIONS OFF)
+endif(NOT CMAKE_C_STANDARD)
+
+# C++ standard can be overridden when this is used as a sub-project.
+if(NOT CMAKE_CXX_STANDARD)
+ # This project requires C++11.
+ set(CMAKE_CXX_STANDARD 11)
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
+ set(CMAKE_CXX_EXTENSIONS OFF)
+endif(NOT CMAKE_CXX_STANDARD)
# https://github.com/izenecloud/cmake/blob/master/SetCompilerWarningAll.cmake
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
@@ -269,7 +275,7 @@ target_sources(crc32c
PRIVATE
"${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
"src/crc32c_arm64.h"
- "src/crc32c_arm64_linux_check.h"
+ "src/crc32c_arm64_check.h"
"src/crc32c_internal.h"
"src/crc32c_portable.cc"
"src/crc32c_prefetch.h"
@@ -405,19 +411,24 @@ if(CRC32C_INSTALL)
)
include(CMakePackageConfigHelpers)
+ configure_package_config_file(
+ "${PROJECT_NAME}Config.cmake.in"
+ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+ INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
+ )
write_basic_package_version_file(
- "${PROJECT_BINARY_DIR}/Crc32cConfigVersion.cmake"
- COMPATIBILITY SameMajorVersion
+ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
+ COMPATIBILITY SameMajorVersion
)
install(
EXPORT Crc32cTargets
NAMESPACE Crc32c::
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Crc32c"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
install(
FILES
- "Crc32cConfig.cmake"
- "${PROJECT_BINARY_DIR}/Crc32cConfigVersion.cmake"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Crc32c"
+ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
endif(CRC32C_INSTALL)
diff --git a/src/crc32c/Crc32cConfig.cmake b/src/crc32c/Crc32cConfig.cmake.in
index 4d6057ec26..c6b8fc7913 100644
--- a/src/crc32c/Crc32cConfig.cmake
+++ b/src/crc32c/Crc32cConfig.cmake.in
@@ -2,4 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. See the AUTHORS file for names of contributors.
+@PACKAGE_INIT@
+
include("${CMAKE_CURRENT_LIST_DIR}/Crc32cTargets.cmake")
+
+check_required_components(Crc32c)
diff --git a/src/crc32c/src/crc32c.cc b/src/crc32c/src/crc32c.cc
index 4d3018af47..804133bc17 100644
--- a/src/crc32c/src/crc32c.cc
+++ b/src/crc32c/src/crc32c.cc
@@ -8,7 +8,7 @@
#include <cstdint>
#include "./crc32c_arm64.h"
-#include "./crc32c_arm64_linux_check.h"
+#include "./crc32c_arm64_check.h"
#include "./crc32c_internal.h"
#include "./crc32c_sse42.h"
#include "./crc32c_sse42_check.h"
@@ -20,8 +20,8 @@ uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count) {
static bool can_use_sse42 = CanUseSse42();
if (can_use_sse42) return ExtendSse42(crc, data, count);
#elif HAVE_ARM64_CRC32C
- static bool can_use_arm_linux = CanUseArm64Linux();
- if (can_use_arm_linux) return ExtendArm64(crc, data, count);
+ static bool can_use_arm64_crc32 = CanUseArm64Crc32();
+ if (can_use_arm64_crc32) return ExtendArm64(crc, data, count);
#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
return ExtendPortable(crc, data, count);
diff --git a/src/crc32c/src/crc32c_arm64.cc b/src/crc32c/src/crc32c_arm64.cc
index b872245f95..1da04ed34a 100644
--- a/src/crc32c/src/crc32c_arm64.cc
+++ b/src/crc32c/src/crc32c_arm64.cc
@@ -64,7 +64,7 @@
namespace crc32c {
-uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
+uint32_t ExtendArm64(uint32_t crc, const uint8_t *data, size_t size) {
int64_t length = size;
uint32_t crc0, crc1, crc2, crc3;
uint64_t t0, t1, t2;
@@ -74,7 +74,6 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
const poly64_t k0 = 0x8d96551c, k1 = 0xbd6f81f8, k2 = 0xdcb17aa4;
crc = crc ^ kCRC32Xor;
- const uint8_t *p = reinterpret_cast<const uint8_t *>(buf);
while (length >= KBYTES) {
crc0 = crc;
@@ -83,14 +82,14 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
crc3 = 0;
// Process 1024 bytes in parallel.
- CRC32C1024BYTES(p);
+ CRC32C1024BYTES(data);
// Merge the 4 partial CRC32C values.
t2 = (uint64_t)vmull_p64(crc2, k2);
t1 = (uint64_t)vmull_p64(crc1, k1);
t0 = (uint64_t)vmull_p64(crc0, k0);
- crc = __crc32cd(crc3, *(uint64_t *)p);
- p += sizeof(uint64_t);
+ crc = __crc32cd(crc3, *(uint64_t *)data);
+ data += sizeof(uint64_t);
crc ^= __crc32cd(0, t2);
crc ^= __crc32cd(0, t1);
crc ^= __crc32cd(0, t0);
@@ -99,23 +98,23 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
}
while (length >= 8) {
- crc = __crc32cd(crc, *(uint64_t *)p);
- p += 8;
+ crc = __crc32cd(crc, *(uint64_t *)data);
+ data += 8;
length -= 8;
}
if (length & 4) {
- crc = __crc32cw(crc, *(uint32_t *)p);
- p += 4;
+ crc = __crc32cw(crc, *(uint32_t *)data);
+ data += 4;
}
if (length & 2) {
- crc = __crc32ch(crc, *(uint16_t *)p);
- p += 2;
+ crc = __crc32ch(crc, *(uint16_t *)data);
+ data += 2;
}
if (length & 1) {
- crc = __crc32cb(crc, *p);
+ crc = __crc32cb(crc, *data);
}
return crc ^ kCRC32Xor;
diff --git a/src/crc32c/src/crc32c_arm64.h b/src/crc32c/src/crc32c_arm64.h
index 100cd56ec8..e093687ddc 100644
--- a/src/crc32c/src/crc32c_arm64.h
+++ b/src/crc32c/src/crc32c_arm64.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
-// Linux-specific code checking the availability for ARM CRC32C instructions.
+// ARM-specific code
-#ifndef CRC32C_CRC32C_ARM_LINUX_H_
-#define CRC32C_CRC32C_ARM_LINUX_H_
+#ifndef CRC32C_CRC32C_ARM_H_
+#define CRC32C_CRC32C_ARM_H_
#include <cstddef>
#include <cstdint>
@@ -24,4 +24,4 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t* data, size_t count);
#endif // HAVE_ARM64_CRC32C
-#endif // CRC32C_CRC32C_ARM_LINUX_H_
+#endif // CRC32C_CRC32C_ARM_H_
diff --git a/src/crc32c/src/crc32c_arm64_linux_check.h b/src/crc32c/src/crc32c_arm64_check.h
index 1a20a757bb..62a07aba09 100644
--- a/src/crc32c/src/crc32c_arm64_linux_check.h
+++ b/src/crc32c/src/crc32c_arm64_check.h
@@ -2,12 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
-// ARM Linux-specific code checking for the availability of CRC32C instructions.
+// ARM-specific code checking for the availability of CRC32C instructions.
-#ifndef CRC32C_CRC32C_ARM_LINUX_CHECK_H_
-#define CRC32C_CRC32C_ARM_LINUX_CHECK_H_
-
-// X86-specific code checking for the availability of SSE4.2 instructions.
+#ifndef CRC32C_CRC32C_ARM_CHECK_H_
+#define CRC32C_CRC32C_ARM_CHECK_H_
#include <cstddef>
#include <cstdint>
@@ -18,6 +16,7 @@
#if HAVE_ARM64_CRC32C
+#ifdef __linux__
#if HAVE_STRONG_GETAUXVAL
#include <sys/auxv.h>
#elif HAVE_WEAK_GETAUXVAL
@@ -27,17 +26,28 @@ extern "C" unsigned long getauxval(unsigned long type) __attribute__((weak));
#define AT_HWCAP 16
#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
+#endif // defined (__linux__)
+
+#ifdef __APPLE__
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif // defined (__APPLE__)
namespace crc32c {
-inline bool CanUseArm64Linux() {
-#if HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
+inline bool CanUseArm64Crc32() {
+#if defined (__linux__) && (HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL)
// From 'arch/arm64/include/uapi/asm/hwcap.h' in Linux kernel source code.
constexpr unsigned long kHWCAP_PMULL = 1 << 4;
constexpr unsigned long kHWCAP_CRC32 = 1 << 7;
unsigned long hwcap = (&getauxval != nullptr) ? getauxval(AT_HWCAP) : 0;
return (hwcap & (kHWCAP_PMULL | kHWCAP_CRC32)) ==
(kHWCAP_PMULL | kHWCAP_CRC32);
+#elif defined(__APPLE__)
+ int val = 0;
+ size_t len = sizeof(val);
+ return sysctlbyname("hw.optional.armv8_crc32", &val, &len, nullptr, 0) == 0
+ && val != 0;
#else
return false;
#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
@@ -47,4 +57,4 @@ inline bool CanUseArm64Linux() {
#endif // HAVE_ARM64_CRC32C
-#endif // CRC32C_CRC32C_ARM_LINUX_CHECK_H_
+#endif // CRC32C_CRC32C_ARM_CHECK_H_
diff --git a/src/crc32c/src/crc32c_benchmark.cc b/src/crc32c/src/crc32c_benchmark.cc
index c464304b3f..51194b370a 100644
--- a/src/crc32c/src/crc32c_benchmark.cc
+++ b/src/crc32c/src/crc32c_benchmark.cc
@@ -16,7 +16,7 @@
#endif // CRC32C_TESTS_BUILT_WITH_GLOG
#include "./crc32c_arm64.h"
-#include "./crc32c_arm64_linux_check.h"
+#include "./crc32c_arm64_check.h"
#include "./crc32c_internal.h"
#include "./crc32c_sse42.h"
#include "./crc32c_sse42_check.h"
@@ -58,8 +58,8 @@ BENCHMARK_REGISTER_F(CRC32CBenchmark, Portable)
#if HAVE_ARM64_CRC32C
-BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmLinux)(benchmark::State& state) {
- if (!crc32c::CanUseArm64Linux()) {
+BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmCRC32C)(benchmark::State& state) {
+ if (!crc32c::CanUseArm64Crc32()) {
state.SkipWithError("ARM CRC32C instructions not available or not enabled");
return;
}
@@ -69,7 +69,7 @@ BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmLinux)(benchmark::State& state) {
crc = crc32c::ExtendArm64(crc, block_buffer_, block_size_);
state.SetBytesProcessed(state.iterations() * block_size_);
}
-BENCHMARK_REGISTER_F(CRC32CBenchmark, ArmLinux)
+BENCHMARK_REGISTER_F(CRC32CBenchmark, ArmCRC32C)
->RangeMultiplier(16)
->Range(256, 16777216); // Block size.
diff --git a/src/crc32c/src/crc32c_read_le.h b/src/crc32c/src/crc32c_read_le.h
index 3bd45fe3aa..673a2a0db7 100644
--- a/src/crc32c/src/crc32c_read_le.h
+++ b/src/crc32c/src/crc32c_read_le.h
@@ -32,14 +32,14 @@ inline uint32_t ReadUint32LE(const uint8_t* buffer) {
// Reads a little-endian 64-bit integer from a 64-bit-aligned buffer.
inline uint64_t ReadUint64LE(const uint8_t* buffer) {
#if BYTE_ORDER_BIG_ENDIAN
- return ((static_cast<uint32_t>(static_cast<uint8_t>(buffer[0]))) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[1])) << 8) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[2])) << 16) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[3])) << 24) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[4])) << 32) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[5])) << 40) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[6])) << 48) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[7])) << 56));
+ return ((static_cast<uint64_t>(static_cast<uint8_t>(buffer[0]))) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[1])) << 8) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[2])) << 16) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[3])) << 24) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[4])) << 32) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[5])) << 40) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[6])) << 48) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[7])) << 56));
#else // !BYTE_ORDER_BIG_ENDIAN
uint64_t result;
// This should be optimized to a single instruction.
diff --git a/src/crypto/chacha_poly_aead.h b/src/crypto/chacha_poly_aead.h
index b3ba781cdd..0afe8fcc14 100644
--- a/src/crypto/chacha_poly_aead.h
+++ b/src/crypto/chacha_poly_aead.h
@@ -17,12 +17,12 @@ static constexpr int AAD_PACKAGES_PER_ROUND = 21; /* 64 / 3 round down*/
/* A AEAD class for ChaCha20-Poly1305@bitcoin.
*
* ChaCha20 is a stream cipher designed by Daniel Bernstein and described in
- * <ref>[http://cr.yp.to/chacha/chacha-20080128.pdf ChaCha20]</ref>. It operates
+ * <ref>[https://cr.yp.to/chacha/chacha-20080128.pdf ChaCha20]</ref>. It operates
* by permuting 128 fixed bits, 128 or 256 bits of key, a 64 bit nonce and a 64
* bit counter into 64 bytes of output. This output is used as a keystream, with
* any unused bytes simply discarded.
*
- * Poly1305 <ref>[http://cr.yp.to/mac/poly1305-20050329.pdf Poly1305]</ref>, also
+ * Poly1305 <ref>[https://cr.yp.to/mac/poly1305-20050329.pdf Poly1305]</ref>, also
* by Daniel Bernstein, is a one-time Carter-Wegman MAC that computes a 128 bit
* integrity tag given a message and a single-use 256 bit secret key.
*
diff --git a/src/crypto/common.h b/src/crypto/common.h
index c1acf8b22e..dc12ed9942 100644
--- a/src/crypto/common.h
+++ b/src/crypto/common.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/muhash.cpp b/src/crypto/muhash.cpp
new file mode 100644
index 0000000000..fbd14f9325
--- /dev/null
+++ b/src/crypto/muhash.cpp
@@ -0,0 +1,338 @@
+// Copyright (c) 2017-2020 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 <crypto/muhash.h>
+
+#include <crypto/chacha20.h>
+#include <crypto/common.h>
+#include <hash.h>
+
+#include <cassert>
+#include <cstdio>
+#include <limits>
+
+namespace {
+
+using limb_t = Num3072::limb_t;
+using double_limb_t = Num3072::double_limb_t;
+constexpr int LIMB_SIZE = Num3072::LIMB_SIZE;
+constexpr int LIMBS = Num3072::LIMBS;
+/** 2^3072 - 1103717, the largest 3072-bit safe prime number, is used as the modulus. */
+constexpr limb_t MAX_PRIME_DIFF = 1103717;
+
+/** Extract the lowest limb of [c0,c1,c2] into n, and left shift the number by 1 limb. */
+inline void extract3(limb_t& c0, limb_t& c1, limb_t& c2, limb_t& n)
+{
+ n = c0;
+ c0 = c1;
+ c1 = c2;
+ c2 = 0;
+}
+
+/** [c0,c1] = a * b */
+inline void mul(limb_t& c0, limb_t& c1, const limb_t& a, const limb_t& b)
+{
+ double_limb_t t = (double_limb_t)a * b;
+ c1 = t >> LIMB_SIZE;
+ c0 = t;
+}
+
+/* [c0,c1,c2] += n * [d0,d1,d2]. c2 is 0 initially */
+inline void mulnadd3(limb_t& c0, limb_t& c1, limb_t& c2, limb_t& d0, limb_t& d1, limb_t& d2, const limb_t& n)
+{
+ double_limb_t t = (double_limb_t)d0 * n + c0;
+ c0 = t;
+ t >>= LIMB_SIZE;
+ t += (double_limb_t)d1 * n + c1;
+ c1 = t;
+ t >>= LIMB_SIZE;
+ c2 = t + d2 * n;
+}
+
+/* [c0,c1] *= n */
+inline void muln2(limb_t& c0, limb_t& c1, const limb_t& n)
+{
+ double_limb_t t = (double_limb_t)c0 * n;
+ c0 = t;
+ t >>= LIMB_SIZE;
+ t += (double_limb_t)c1 * n;
+ c1 = t;
+}
+
+/** [c0,c1,c2] += a * b */
+inline void muladd3(limb_t& c0, limb_t& c1, limb_t& c2, const limb_t& a, const limb_t& b)
+{
+ double_limb_t t = (double_limb_t)a * b;
+ limb_t th = t >> LIMB_SIZE;
+ limb_t tl = t;
+
+ c0 += tl;
+ th += (c0 < tl) ? 1 : 0;
+ c1 += th;
+ c2 += (c1 < th) ? 1 : 0;
+}
+
+/** [c0,c1,c2] += 2 * a * b */
+inline void muldbladd3(limb_t& c0, limb_t& c1, limb_t& c2, const limb_t& a, const limb_t& b)
+{
+ double_limb_t t = (double_limb_t)a * b;
+ limb_t th = t >> LIMB_SIZE;
+ limb_t tl = t;
+
+ c0 += tl;
+ limb_t tt = th + ((c0 < tl) ? 1 : 0);
+ c1 += tt;
+ c2 += (c1 < tt) ? 1 : 0;
+ c0 += tl;
+ th += (c0 < tl) ? 1 : 0;
+ c1 += th;
+ c2 += (c1 < th) ? 1 : 0;
+}
+
+/**
+ * Add limb a to [c0,c1]: [c0,c1] += a. Then extract the lowest
+ * limb of [c0,c1] into n, and left shift the number by 1 limb.
+ * */
+inline void addnextract2(limb_t& c0, limb_t& c1, const limb_t& a, limb_t& n)
+{
+ limb_t c2 = 0;
+
+ // add
+ c0 += a;
+ if (c0 < a) {
+ c1 += 1;
+
+ // Handle case when c1 has overflown
+ if (c1 == 0)
+ c2 = 1;
+ }
+
+ // extract
+ n = c0;
+ c0 = c1;
+ c1 = c2;
+}
+
+/** in_out = in_out^(2^sq) * mul */
+inline void square_n_mul(Num3072& in_out, const int sq, const Num3072& mul)
+{
+ for (int j = 0; j < sq; ++j) in_out.Square();
+ in_out.Multiply(mul);
+}
+
+} // namespace
+
+/** Indicates wether d is larger than the modulus. */
+bool Num3072::IsOverflow() const
+{
+ if (this->limbs[0] <= std::numeric_limits<limb_t>::max() - MAX_PRIME_DIFF) return false;
+ for (int i = 1; i < LIMBS; ++i) {
+ if (this->limbs[i] != std::numeric_limits<limb_t>::max()) return false;
+ }
+ return true;
+}
+
+void Num3072::FullReduce()
+{
+ limb_t c0 = MAX_PRIME_DIFF;
+ limb_t c1 = 0;
+ for (int i = 0; i < LIMBS; ++i) {
+ addnextract2(c0, c1, this->limbs[i], this->limbs[i]);
+ }
+}
+
+Num3072 Num3072::GetInverse() const
+{
+ // For fast exponentiation a sliding window exponentiation with repunit
+ // precomputation is utilized. See "Fast Point Decompression for Standard
+ // Elliptic Curves" (Brumley, Järvinen, 2008).
+
+ Num3072 p[12]; // p[i] = a^(2^(2^i)-1)
+ Num3072 out;
+
+ p[0] = *this;
+
+ for (int i = 0; i < 11; ++i) {
+ p[i + 1] = p[i];
+ for (int j = 0; j < (1 << i); ++j) p[i + 1].Square();
+ p[i + 1].Multiply(p[i]);
+ }
+
+ out = p[11];
+
+ square_n_mul(out, 512, p[9]);
+ square_n_mul(out, 256, p[8]);
+ square_n_mul(out, 128, p[7]);
+ square_n_mul(out, 64, p[6]);
+ square_n_mul(out, 32, p[5]);
+ square_n_mul(out, 8, p[3]);
+ square_n_mul(out, 2, p[1]);
+ square_n_mul(out, 1, p[0]);
+ square_n_mul(out, 5, p[2]);
+ square_n_mul(out, 3, p[0]);
+ square_n_mul(out, 2, p[0]);
+ square_n_mul(out, 4, p[0]);
+ square_n_mul(out, 4, p[1]);
+ square_n_mul(out, 3, p[0]);
+
+ return out;
+}
+
+void Num3072::Multiply(const Num3072& a)
+{
+ limb_t c0 = 0, c1 = 0, c2 = 0;
+ Num3072 tmp;
+
+ /* Compute limbs 0..N-2 of this*a into tmp, including one reduction. */
+ for (int j = 0; j < LIMBS - 1; ++j) {
+ limb_t d0 = 0, d1 = 0, d2 = 0;
+ mul(d0, d1, this->limbs[1 + j], a.limbs[LIMBS + j - (1 + j)]);
+ for (int i = 2 + j; i < LIMBS; ++i) muladd3(d0, d1, d2, this->limbs[i], a.limbs[LIMBS + j - i]);
+ mulnadd3(c0, c1, c2, d0, d1, d2, MAX_PRIME_DIFF);
+ for (int i = 0; i < j + 1; ++i) muladd3(c0, c1, c2, this->limbs[i], a.limbs[j - i]);
+ extract3(c0, c1, c2, tmp.limbs[j]);
+ }
+
+ /* Compute limb N-1 of a*b into tmp. */
+ assert(c2 == 0);
+ for (int i = 0; i < LIMBS; ++i) muladd3(c0, c1, c2, this->limbs[i], a.limbs[LIMBS - 1 - i]);
+ extract3(c0, c1, c2, tmp.limbs[LIMBS - 1]);
+
+ /* Perform a second reduction. */
+ muln2(c0, c1, MAX_PRIME_DIFF);
+ for (int j = 0; j < LIMBS; ++j) {
+ addnextract2(c0, c1, tmp.limbs[j], this->limbs[j]);
+ }
+
+ assert(c1 == 0);
+ assert(c0 == 0 || c0 == 1);
+
+ /* Perform up to two more reductions if the internal state has already
+ * overflown the MAX of Num3072 or if it is larger than the modulus or
+ * if both are the case.
+ * */
+ if (this->IsOverflow()) this->FullReduce();
+ if (c0) this->FullReduce();
+}
+
+void Num3072::Square()
+{
+ limb_t c0 = 0, c1 = 0, c2 = 0;
+ Num3072 tmp;
+
+ /* Compute limbs 0..N-2 of this*this into tmp, including one reduction. */
+ for (int j = 0; j < LIMBS - 1; ++j) {
+ limb_t d0 = 0, d1 = 0, d2 = 0;
+ for (int i = 0; i < (LIMBS - 1 - j) / 2; ++i) muldbladd3(d0, d1, d2, this->limbs[i + j + 1], this->limbs[LIMBS - 1 - i]);
+ if ((j + 1) & 1) muladd3(d0, d1, d2, this->limbs[(LIMBS - 1 - j) / 2 + j + 1], this->limbs[LIMBS - 1 - (LIMBS - 1 - j) / 2]);
+ mulnadd3(c0, c1, c2, d0, d1, d2, MAX_PRIME_DIFF);
+ for (int i = 0; i < (j + 1) / 2; ++i) muldbladd3(c0, c1, c2, this->limbs[i], this->limbs[j - i]);
+ if ((j + 1) & 1) muladd3(c0, c1, c2, this->limbs[(j + 1) / 2], this->limbs[j - (j + 1) / 2]);
+ extract3(c0, c1, c2, tmp.limbs[j]);
+ }
+
+ assert(c2 == 0);
+ for (int i = 0; i < LIMBS / 2; ++i) muldbladd3(c0, c1, c2, this->limbs[i], this->limbs[LIMBS - 1 - i]);
+ extract3(c0, c1, c2, tmp.limbs[LIMBS - 1]);
+
+ /* Perform a second reduction. */
+ muln2(c0, c1, MAX_PRIME_DIFF);
+ for (int j = 0; j < LIMBS; ++j) {
+ addnextract2(c0, c1, tmp.limbs[j], this->limbs[j]);
+ }
+
+ assert(c1 == 0);
+ assert(c0 == 0 || c0 == 1);
+
+ /* Perform up to two more reductions if the internal state has already
+ * overflown the MAX of Num3072 or if it is larger than the modulus or
+ * if both are the case.
+ * */
+ if (this->IsOverflow()) this->FullReduce();
+ if (c0) this->FullReduce();
+}
+
+void Num3072::SetToOne()
+{
+ this->limbs[0] = 1;
+ for (int i = 1; i < LIMBS; ++i) this->limbs[i] = 0;
+}
+
+void Num3072::Divide(const Num3072& a)
+{
+ if (this->IsOverflow()) this->FullReduce();
+
+ Num3072 inv{};
+ if (a.IsOverflow()) {
+ Num3072 b = a;
+ b.FullReduce();
+ inv = b.GetInverse();
+ } else {
+ inv = a.GetInverse();
+ }
+
+ this->Multiply(inv);
+ if (this->IsOverflow()) this->FullReduce();
+}
+
+Num3072 MuHash3072::ToNum3072(Span<const unsigned char> in) {
+ Num3072 out{};
+ uint256 hashed_in = (CHashWriter(SER_DISK, 0) << in).GetSHA256();
+ unsigned char tmp[BYTE_SIZE];
+ ChaCha20(hashed_in.data(), hashed_in.size()).Keystream(tmp, BYTE_SIZE);
+ for (int i = 0; i < LIMBS; ++i) {
+ if (sizeof(limb_t) == 4) {
+ out.limbs[i] = ReadLE32(tmp + 4 * i);
+ } else if (sizeof(limb_t) == 8) {
+ out.limbs[i] = ReadLE64(tmp + 8 * i);
+ }
+ }
+ return out;
+}
+
+MuHash3072::MuHash3072(Span<const unsigned char> in) noexcept
+{
+ m_numerator = ToNum3072(in);
+}
+
+void MuHash3072::Finalize(uint256& out) noexcept
+{
+ m_numerator.Divide(m_denominator);
+ m_denominator.SetToOne(); // Needed to keep the MuHash object valid
+
+ unsigned char data[384];
+ for (int i = 0; i < LIMBS; ++i) {
+ if (sizeof(limb_t) == 4) {
+ WriteLE32(data + i * 4, m_numerator.limbs[i]);
+ } else if (sizeof(limb_t) == 8) {
+ WriteLE64(data + i * 8, m_numerator.limbs[i]);
+ }
+ }
+
+ out = (CHashWriter(SER_DISK, 0) << data).GetSHA256();
+}
+
+MuHash3072& MuHash3072::operator*=(const MuHash3072& mul) noexcept
+{
+ m_numerator.Multiply(mul.m_numerator);
+ m_denominator.Multiply(mul.m_denominator);
+ return *this;
+}
+
+MuHash3072& MuHash3072::operator/=(const MuHash3072& div) noexcept
+{
+ m_numerator.Multiply(div.m_denominator);
+ m_denominator.Multiply(div.m_numerator);
+ return *this;
+}
+
+MuHash3072& MuHash3072::Insert(Span<const unsigned char> in) noexcept {
+ m_numerator.Multiply(ToNum3072(in));
+ return *this;
+}
+
+MuHash3072& MuHash3072::Remove(Span<const unsigned char> in) noexcept {
+ m_numerator.Divide(ToNum3072(in));
+ return *this;
+}
diff --git a/src/crypto/muhash.h b/src/crypto/muhash.h
new file mode 100644
index 0000000000..0c710007c4
--- /dev/null
+++ b/src/crypto/muhash.h
@@ -0,0 +1,130 @@
+// Copyright (c) 2017-2020 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_CRYPTO_MUHASH_H
+#define BITCOIN_CRYPTO_MUHASH_H
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#include <serialize.h>
+#include <uint256.h>
+
+#include <stdint.h>
+
+class Num3072
+{
+private:
+ void FullReduce();
+ bool IsOverflow() const;
+ Num3072 GetInverse() const;
+
+public:
+
+#ifdef HAVE___INT128
+ typedef unsigned __int128 double_limb_t;
+ typedef uint64_t limb_t;
+ static constexpr int LIMBS = 48;
+ static constexpr int LIMB_SIZE = 64;
+#else
+ typedef uint64_t double_limb_t;
+ typedef uint32_t limb_t;
+ static constexpr int LIMBS = 96;
+ static constexpr int LIMB_SIZE = 32;
+#endif
+ limb_t limbs[LIMBS];
+
+ // Sanity check for Num3072 constants
+ static_assert(LIMB_SIZE * LIMBS == 3072, "Num3072 isn't 3072 bits");
+ static_assert(sizeof(double_limb_t) == sizeof(limb_t) * 2, "bad size for double_limb_t");
+ static_assert(sizeof(limb_t) * 8 == LIMB_SIZE, "LIMB_SIZE is incorrect");
+
+ // Hard coded values in MuHash3072 constructor and Finalize
+ static_assert(sizeof(limb_t) == 4 || sizeof(limb_t) == 8, "bad size for limb_t");
+
+ void Multiply(const Num3072& a);
+ void Divide(const Num3072& a);
+ void SetToOne();
+ void Square();
+
+ Num3072() { this->SetToOne(); };
+
+ SERIALIZE_METHODS(Num3072, obj)
+ {
+ for (auto& limb : obj.limbs) {
+ READWRITE(limb);
+ }
+ }
+};
+
+/** A class representing MuHash sets
+ *
+ * MuHash is a hashing algorithm that supports adding set elements in any
+ * order but also deleting in any order. As a result, it can maintain a
+ * running sum for a set of data as a whole, and add/remove when data
+ * is added to or removed from it. A downside of MuHash is that computing
+ * an inverse is relatively expensive. This is solved by representing
+ * the running value as a fraction, and multiplying added elements into
+ * the numerator and removed elements into the denominator. Only when the
+ * final hash is desired, a single modular inverse and multiplication is
+ * needed to combine the two. The combination is also run on serialization
+ * to allow for space-efficient storage on disk.
+ *
+ * As the update operations are also associative, H(a)+H(b)+H(c)+H(d) can
+ * in fact be computed as (H(a)+H(b)) + (H(c)+H(d)). This implies that
+ * all of this is perfectly parallellizable: each thread can process an
+ * arbitrary subset of the update operations, allowing them to be
+ * efficiently combined later.
+ *
+ * Muhash does not support checking if an element is already part of the
+ * set. That is why this class does not enforce the use of a set as the
+ * data it represents because there is no efficient way to do so.
+ * It is possible to add elements more than once and also to remove
+ * elements that have not been added before. However, this implementation
+ * is intended to represent a set of elements.
+ *
+ * See also https://cseweb.ucsd.edu/~mihir/papers/inchash.pdf and
+ * https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-May/014337.html.
+ */
+class MuHash3072
+{
+private:
+ static constexpr size_t BYTE_SIZE = 384;
+
+ Num3072 m_numerator;
+ Num3072 m_denominator;
+
+ Num3072 ToNum3072(Span<const unsigned char> in);
+
+public:
+ /* The empty set. */
+ MuHash3072() noexcept {};
+
+ /* A singleton with variable sized data in it. */
+ explicit MuHash3072(Span<const unsigned char> in) noexcept;
+
+ /* Insert a single piece of data into the set. */
+ MuHash3072& Insert(Span<const unsigned char> in) noexcept;
+
+ /* Remove a single piece of data from the set. */
+ MuHash3072& Remove(Span<const unsigned char> in) noexcept;
+
+ /* Multiply (resulting in a hash for the union of the sets) */
+ MuHash3072& operator*=(const MuHash3072& mul) noexcept;
+
+ /* Divide (resulting in a hash for the difference of the sets) */
+ MuHash3072& operator/=(const MuHash3072& div) noexcept;
+
+ /* Finalize into a 32-byte hash. Does not change this object's value. */
+ void Finalize(uint256& out) noexcept;
+
+ SERIALIZE_METHODS(MuHash3072, obj)
+ {
+ READWRITE(obj.m_numerator);
+ READWRITE(obj.m_denominator);
+ }
+};
+
+#endif // BITCOIN_CRYPTO_MUHASH_H
diff --git a/src/crypto/sha256_shani.cpp b/src/crypto/sha256_shani.cpp
index 3473f6e39f..4f4d5b5837 100644
--- a/src/crypto/sha256_shani.cpp
+++ b/src/crypto/sha256_shani.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
diff --git a/src/crypto/sha256_sse4.cpp b/src/crypto/sha256_sse4.cpp
index 89f529a3ab..143752c7cf 100644
--- a/src/crypto/sha256_sse4.cpp
+++ b/src/crypto/sha256_sse4.cpp
@@ -1001,7 +1001,7 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
; This code is described in an Intel White-Paper:
; "Fast SHA-256 Implementations on Intel Architecture Processors"
;
-; To find it, surf to http://www.intel.com/p/en_US/embedded
+; To find it, surf to https://www.intel.com/p/en_US/embedded
; and search for that title.
; The paper is expected to be released roughly at the end of April, 2012
;
diff --git a/src/crypto/siphash.cpp b/src/crypto/siphash.cpp
index 2e0106b165..2e90c393e1 100644
--- a/src/crypto/siphash.cpp
+++ b/src/crypto/siphash.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/siphash.h b/src/crypto/siphash.h
index 6b38950f8e..b573526932 100644
--- a/src/crypto/siphash.h
+++ b/src/crypto/siphash.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/cuckoocache.h b/src/cuckoocache.h
index 2daf676c4a..1166466771 100644
--- a/src/cuckoocache.h
+++ b/src/cuckoocache.h
@@ -225,7 +225,7 @@ private:
* [0, 1) and simply multiply it by the size. Then we just shift the result down by
* 32-bits to get our bucket number. The result has non-uniformity the same as a
* mod, but it is much faster to compute. More about this technique can be found at
- * http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ .
+ * https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ .
*
* The resulting non-uniformity is also more equally distributed which would be
* advantageous for something like linear probing, though it shouldn't matter
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index 215b033708..33e4b366a1 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/flatfile.cpp b/src/flatfile.cpp
index 8a8f7b681c..11cf357f3d 100644
--- a/src/flatfile.cpp
+++ b/src/flatfile.cpp
@@ -92,6 +92,7 @@ bool FlatFileSeq::Flush(const FlatFilePos& pos, bool finalize)
fclose(file);
return error("%s: failed to commit file %d", __func__, pos.nFile);
}
+ DirectoryCommit(m_dir);
fclose(file);
return true;
diff --git a/src/fs.cpp b/src/fs.cpp
index eef9c81de9..7eb0f5ca9f 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/hash.cpp b/src/hash.cpp
index 3657b38639..cc46043c2b 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2018 The Bitcoin Core developers
+// Copyright (c) 2013-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,7 +15,7 @@ inline uint32_t ROTL32(uint32_t x, int8_t r)
unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vDataToHash)
{
- // The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
+ // The following is MurmurHash3 (x86_32), see https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
uint32_t h1 = nHashSeed;
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
diff --git a/src/hash.h b/src/hash.h
index 083ac12523..1456a899d8 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/httprpc.h b/src/httprpc.h
index a6a38fc95a..97af6f7bb1 100644
--- a/src/httprpc.h
+++ b/src/httprpc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp
index 65a5f03a8e..4f61bbeabd 100644
--- a/src/index/blockfilterindex.cpp
+++ b/src/index/blockfilterindex.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -51,7 +51,6 @@ struct DBVal {
struct DBHeightKey {
int height;
- DBHeightKey() : height(0) {}
explicit DBHeightKey(int height_in) : height(height_in) {}
template<typename Stream>
diff --git a/src/index/blockfilterindex.h b/src/index/blockfilterindex.h
index 317f8c0e40..a9c8188bb6 100644
--- a/src/index/blockfilterindex.h
+++ b/src/index/blockfilterindex.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/index/disktxpos.h b/src/index/disktxpos.h
index 69696b0ec5..3166053226 100644
--- a/src/index/disktxpos.h
+++ b/src/index/disktxpos.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 462ac5962f..6398b7edc8 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/init.cpp b/src/init.cpp
index 9137050323..9a63fe0e03 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -26,6 +26,7 @@
#include <interfaces/chain.h>
#include <interfaces/node.h>
#include <key.h>
+#include <mapport.h>
#include <miner.h>
#include <net.h>
#include <net_permissions.h>
@@ -85,7 +86,6 @@
#include <zmq/zmqrpc.h>
#endif
-static bool fFeeEstimatesInitialized = false;
static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
@@ -99,8 +99,6 @@ static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
#define MIN_CORE_FILEDESCRIPTORS 150
#endif
-static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
-
static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map";
/**
@@ -203,7 +201,7 @@ void Shutdown(NodeContext& node)
// using the other before destroying them.
if (node.peerman) UnregisterValidationInterface(node.peerman.get());
// Follow the lock order requirements:
- // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount
+ // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraFullOutboundCount
// which locks cs_vNodes.
// * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which
// locks cs_vNodes.
@@ -236,17 +234,8 @@ void Shutdown(NodeContext& node)
DumpMempool(*node.mempool);
}
- if (fFeeEstimatesInitialized)
- {
- ::feeEstimator.FlushUnconfirmed();
- fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
- CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, CLIENT_VERSION);
- if (!est_fileout.IsNull())
- ::feeEstimator.Write(est_fileout);
- else
- LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
- fFeeEstimatesInitialized = false;
- }
+ // Drop transactions we were still watching, and record fee estimations.
+ if (node.fee_estimator) node.fee_estimator->Flush();
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
if (node.chainman) {
@@ -304,6 +293,7 @@ void Shutdown(NodeContext& node)
globalVerifyHandle.reset();
ECC_Stop();
node.mempool.reset();
+ node.fee_estimator.reset();
node.chainman = nullptr;
node.scheduler.reset();
@@ -461,7 +451,7 @@ void SetupServerArgs(NodeContext& node)
argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
- argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet: %u signet: %u, regtest: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
+ argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port>. Nodes not using the default ports (default: %u, testnet: %u, signet: %u, regtest: %u) are unlikely to get incoming connections.", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
argsman.AddArg("-proxy=<ip:port>", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -479,6 +469,11 @@ void SetupServerArgs(NodeContext& node)
#else
hidden_args.emplace_back("-upnp");
#endif
+#ifdef USE_NATPMP
+ argsman.AddArg("-natpmp", strprintf("Use NAT-PMP to map the listening port (default: %s)", DEFAULT_NATPMP ? "1 when listening and no -proxy" : "0"), ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
+#else
+ hidden_args.emplace_back("-natpmp");
+#endif // USE_NATPMP
argsman.AddArg("-whitebind=<[permissions@]addr>", "Bind to the given address and add permission flags to the peers connecting to it. "
"Use [host]:port notation for IPv6. Allowed permissions: " + Join(NET_PERMISSIONS_DOC, ", ") + ". "
"Specify multiple permissions separated by commas (default: download,noban,mempool,relay). Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -519,7 +514,6 @@ void SetupServerArgs(NodeContext& node)
argsman.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-checkpoints", strprintf("Enable rejection of any forks from the known historical chain until block %s (default: %u)", defaultChainParams->Checkpoints().GetHeight(), DEFAULT_CHECKPOINTS_ENABLED), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", DEFAULT_STOPATHEIGHT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
@@ -824,10 +818,13 @@ void InitParameterInteraction(ArgsManager& args)
// to protect privacy, do not listen by default if a default proxy server is specified
if (args.SoftSetBoolArg("-listen", false))
LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__);
- // to protect privacy, do not use UPNP when a proxy is set. The user may still specify -listen=1
+ // to protect privacy, do not map ports when a proxy is set. The user may still specify -listen=1
// to listen locally, so don't rely on this happening through -listen below.
if (args.SoftSetBoolArg("-upnp", false))
LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__);
+ if (args.SoftSetBoolArg("-natpmp", false)) {
+ LogPrintf("%s: parameter interaction: -proxy set -> setting -natpmp=0\n", __func__);
+ }
// to protect privacy, do not discover addresses by default
if (args.SoftSetBoolArg("-discover", false))
LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__);
@@ -837,6 +834,9 @@ void InitParameterInteraction(ArgsManager& args)
// do not map ports or try to retrieve public IP when not listening (pointless)
if (args.SoftSetBoolArg("-upnp", false))
LogPrintf("%s: parameter interaction: -listen=0 -> setting -upnp=0\n", __func__);
+ if (args.SoftSetBoolArg("-natpmp", false)) {
+ LogPrintf("%s: parameter interaction: -listen=0 -> setting -natpmp=0\n", __func__);
+ }
if (args.SoftSetBoolArg("-discover", false))
LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__);
if (args.SoftSetBoolArg("-listenonion", false))
@@ -914,7 +914,7 @@ std::set<BlockFilterType> g_enabled_filter_types;
std::terminate();
};
-bool AppInitBasicSetup(ArgsManager& args)
+bool AppInitBasicSetup(const ArgsManager& args)
{
// ********************************************************* Step 1: setup
#ifdef _MSC_VER
@@ -928,6 +928,9 @@ bool AppInitBasicSetup(ArgsManager& args)
// Enable heap terminate-on-corruption
HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
#endif
+ if (!InitShutdownState()) {
+ return InitError(Untranslated("Initializing wait-for-shutdown state failed."));
+ }
if (!SetupNetworking()) {
return InitError(Untranslated("Initializing networking failed."));
@@ -1384,20 +1387,31 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
// is not yet setup and may end up being set up twice if we
// need to reindex later.
+ fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
+ fDiscover = args.GetBoolArg("-discover", true);
+ const bool ignores_incoming_txs{args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)};
+
assert(!node.banman);
node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, args.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
assert(!node.connman);
node.connman = MakeUnique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()), args.GetBoolArg("-networkactive", true));
+ assert(!node.fee_estimator);
+ // Don't initialize fee estimation with old data if we don't relay transactions,
+ // as they would never get updated.
+ if (!ignores_incoming_txs) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
+
assert(!node.mempool);
int check_ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
- node.mempool = MakeUnique<CTxMemPool>(&::feeEstimator, check_ratio);
+ node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);
assert(!node.chainman);
node.chainman = &g_chainman;
ChainstateManager& chainman = *Assert(node.chainman);
- node.peerman.reset(new PeerManager(chainparams, *node.connman, node.banman.get(), *node.scheduler, chainman, *node.mempool));
+ assert(!node.peerman);
+ node.peerman = std::make_unique<PeerManager>(chainparams, *node.connman, node.banman.get(),
+ *node.scheduler, chainman, *node.mempool, ignores_incoming_txs);
RegisterValidationInterface(node.peerman.get());
// sanitize comments per BIP-0014, format user agent and check total size
@@ -1473,11 +1487,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
}
}
- // see Step 2: parameter interactions for more information about these
- fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
- fDiscover = args.GetBoolArg("-discover", true);
- g_relay_txes = !args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
-
for (const std::string& strAddr : args.GetArgs("-externalip")) {
CService addrLocal;
if (Lookup(strAddr, addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
@@ -1518,12 +1527,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
RegisterValidationInterface(g_zmq_notification_interface);
}
#endif
- uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set
- uint64_t nMaxOutboundTimeframe = MAX_UPLOAD_TIMEFRAME;
-
- if (args.IsArgSet("-maxuploadtarget")) {
- nMaxOutboundLimit = args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET) * 1024 * 1024;
- }
// ********************************************************* Step 7: load block chain
@@ -1785,13 +1788,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
return false;
}
- fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
- CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
- // Allowed to fail as this file IS missing on first startup.
- if (!est_filein.IsNull())
- ::feeEstimator.Read(est_filein);
- fFeeEstimatesInitialized = true;
-
// ********************************************************* Step 8: start indexers
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
g_txindex = MakeUnique<TxIndex>(nTxIndexCache, false, fReindex);
@@ -1910,13 +1906,12 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
}
}
LogPrintf("nBestHeight = %d\n", chain_active_height);
+ if (node.peerman) node.peerman->SetBestHeight(chain_active_height);
Discover();
- // Map ports with UPnP
- if (args.GetBoolArg("-upnp", DEFAULT_UPNP)) {
- StartMapPort();
- }
+ // Map ports with UPnP or NAT-PMP.
+ StartMapPort(args.GetBoolArg("-upnp", DEFAULT_UPNP), gArgs.GetBoolArg("-natpmp", DEFAULT_NATPMP));
CConnman::Options connOptions;
connOptions.nLocalServices = nLocalServices;
@@ -1925,7 +1920,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
connOptions.m_max_outbound_block_relay = std::min(MAX_BLOCK_RELAY_ONLY_CONNECTIONS, connOptions.nMaxConnections-connOptions.m_max_outbound_full_relay);
connOptions.nMaxAddnode = MAX_ADDNODE_CONNECTIONS;
connOptions.nMaxFeeler = MAX_FEELER_CONNECTIONS;
- connOptions.nBestHeight = chain_active_height;
connOptions.uiInterface = &uiInterface;
connOptions.m_banman = node.banman.get();
connOptions.m_msgproc = node.peerman.get();
@@ -1933,8 +1927,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
connOptions.nReceiveFloodSize = 1000 * args.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
connOptions.m_added_nodes = args.GetArgs("-addnode");
- connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe;
- connOptions.nMaxOutboundLimit = nMaxOutboundLimit;
+ connOptions.nMaxOutboundLimit = 1024 * 1024 * args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET);
connOptions.m_peer_connect_timeout = peer_connect_timeout;
for (const std::string& bind_arg : args.GetArgs("-bind")) {
diff --git a/src/init.h b/src/init.h
index 679e875da1..c04d966d06 100644
--- a/src/init.h
+++ b/src/init.h
@@ -33,7 +33,7 @@ void InitParameterInteraction(ArgsManager& args);
* @note This can be done before daemonization. Do not call Shutdown() if this function fails.
* @pre Parameters should be parsed and config file should be read.
*/
-bool AppInitBasicSetup(ArgsManager& args);
+bool AppInitBasicSetup(const ArgsManager& args);
/**
* Initialization: parameter interaction.
* @note This can be done before daemonization. Do not call Shutdown() if this function fails.
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 85d09be0f3..1a49518d69 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -44,6 +44,10 @@ public:
FoundBlock& time(int64_t& time) { m_time = &time; return *this; }
FoundBlock& maxTime(int64_t& max_time) { m_max_time = &max_time; return *this; }
FoundBlock& mtpTime(int64_t& mtp_time) { m_mtp_time = &mtp_time; return *this; }
+ //! Return whether block is in the active (most-work) chain.
+ FoundBlock& inActiveChain(bool& in_active_chain) { m_in_active_chain = &in_active_chain; return *this; }
+ //! Return next block in the active chain if current block is in the active chain.
+ FoundBlock& nextBlock(const FoundBlock& next_block) { m_next_block = &next_block; return *this; }
//! Read block data from disk. If the block exists but doesn't have data
//! (for example due to pruning), the CBlock variable will be set to null.
FoundBlock& data(CBlock& data) { m_data = &data; return *this; }
@@ -53,6 +57,8 @@ public:
int64_t* m_time = nullptr;
int64_t* m_max_time = nullptr;
int64_t* m_mtp_time = nullptr;
+ bool* m_in_active_chain = nullptr;
+ const FoundBlock* m_next_block = nullptr;
CBlock* m_data = nullptr;
};
@@ -77,9 +83,9 @@ public:
//! wallet cache it, fee estimation being driven by node mempool, wallet
//! should be the consumer.
//!
-//! * The `guessVerificationProgress`, `getBlockHeight`, `getBlockHash`, etc
-//! methods can go away if rescan logic is moved on the node side, and wallet
-//! only register rescan request.
+//! * `guessVerificationProgress` and similar methods can go away if rescan
+//! logic moves out of the wallet, and the wallet just requests scans from the
+//! node (https://github.com/bitcoin/bitcoin/issues/11756)
class Chain
{
public:
@@ -90,11 +96,6 @@ public:
//! any blocks)
virtual Optional<int> 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<int> getBlockHeight(const uint256& hash) = 0;
-
//! Get block hash. Height must be valid or this function will abort.
virtual uint256 getBlockHash(int height) = 0;
@@ -102,13 +103,6 @@ public:
//! 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 and height equal or greater than the
- //! given height, or nullopt if there is no block with a high enough
- //! timestamp and height. 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<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 0;
-
//! Get locator for the current chain tip.
virtual CBlockLocator getTipLocator() = 0;
@@ -130,11 +124,6 @@ public:
//! information.
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block={}) = 0;
- //! Find next block if block is part of current chain. Also flag if
- //! there was a reorg and the specified block hash is no longer in the
- //! current chain, and optionally return block information.
- virtual bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next={}, bool* reorg=nullptr) = 0;
-
//! Find ancestor of block at specified height and optionally return
//! ancestor information.
virtual bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out={}) = 0;
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 5079be038e..15f7ef6256 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -82,7 +82,7 @@ public:
virtual bool shutdownRequested() = 0;
//! Map port.
- virtual void mapPort(bool use_upnp) = 0;
+ virtual void mapPort(bool use_upnp, bool use_natpmp) = 0;
//! Get proxy.
virtual bool getProxy(Network net, proxyType& proxy_info) = 0;
@@ -151,9 +151,6 @@ public:
//! Get network active.
virtual bool getNetworkActive() = 0;
- //! Estimate smart fee.
- virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) = 0;
-
//! Get dust relay fee.
virtual CFeeRate getDustRelayFee() = 0;
diff --git a/src/key.cpp b/src/key.cpp
index 868a8b9b0e..1e59b301cb 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Copyright (c) 2017 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -18,7 +18,7 @@ static secp256k1_context* secp256k1_context_sign = nullptr;
/**
* This parses a format loosely based on a DER encoding of the ECPrivateKey type from
- * section C.4 of SEC 1 <http://www.secg.org/sec1-v2.pdf>, with the following caveats:
+ * section C.4 of SEC 1 <https://www.secg.org/sec1-v2.pdf>, with the following caveats:
*
* * The octet-length of the SEQUENCE must be encoded as 1 or 2 octets. It is not
* required to be encoded as one octet if it is less than 256, as DER would require.
@@ -80,7 +80,7 @@ int ec_seckey_import_der(const secp256k1_context* ctx, unsigned char *out32, con
/**
* This serializes to a DER encoding of the ECPrivateKey type from section C.4 of SEC 1
- * <http://www.secg.org/sec1-v2.pdf>. The optional parameters and publicKey fields are
+ * <https://www.secg.org/sec1-v2.pdf>. The optional parameters and publicKey fields are
* included.
*
* seckey must point to an output buffer of length at least CKey::SIZE bytes.
diff --git a/src/key_io.cpp b/src/key_io.cpp
index d2f5be93f5..a270ede864 100644
--- a/src/key_io.cpp
+++ b/src/key_io.cpp
@@ -8,16 +8,12 @@
#include <bech32.h>
#include <util/strencodings.h>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-
+#include <algorithm>
#include <assert.h>
#include <string.h>
-#include <algorithm>
-namespace
-{
-class DestinationEncoder : public boost::static_visitor<std::string>
+namespace {
+class DestinationEncoder
{
private:
const CChainParams& m_params;
@@ -209,7 +205,7 @@ std::string EncodeExtKey(const CExtKey& key)
std::string EncodeDestination(const CTxDestination& dest)
{
- return boost::apply_visitor(DestinationEncoder(Params()), dest);
+ return std::visit(DestinationEncoder(Params()), dest);
}
CTxDestination DecodeDestination(const std::string& str)
diff --git a/src/logging.cpp b/src/logging.cpp
index 35e0754f20..4ddcf1d930 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -174,7 +174,7 @@ bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str)
return false;
}
-std::vector<LogCategory> BCLog::Logger::LogCategoriesList()
+std::vector<LogCategory> BCLog::Logger::LogCategoriesList() const
{
std::vector<LogCategory> ret;
for (const CLogCategoryDesc& category_desc : LogCategories) {
diff --git a/src/logging.h b/src/logging.h
index 7e646ef67a..9efecc7c12 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -135,9 +135,9 @@ namespace BCLog {
bool WillLogCategory(LogFlags category) const;
/** Returns a vector of the log categories */
- std::vector<LogCategory> LogCategoriesList();
+ std::vector<LogCategory> LogCategoriesList() const;
/** Returns a string with the log categories */
- std::string LogCategoriesString()
+ std::string LogCategoriesString() const
{
return Join(LogCategoriesList(), ", ", [&](const LogCategory& i) { return i.category; });
};
diff --git a/src/mapport.cpp b/src/mapport.cpp
new file mode 100644
index 0000000000..2df4ce45d2
--- /dev/null
+++ b/src/mapport.cpp
@@ -0,0 +1,336 @@
+// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#include <mapport.h>
+
+#include <clientversion.h>
+#include <logging.h>
+#include <net.h>
+#include <netaddress.h>
+#include <netbase.h>
+#include <threadinterrupt.h>
+#include <util/system.h>
+
+#ifdef USE_NATPMP
+#include <compat.h>
+#include <natpmp.h>
+#endif // USE_NATPMP
+
+#ifdef USE_UPNP
+#include <miniupnpc/miniupnpc.h>
+#include <miniupnpc/upnpcommands.h>
+#include <miniupnpc/upnperrors.h>
+// The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
+// with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
+static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed");
+#endif // USE_UPNP
+
+#include <atomic>
+#include <cassert>
+#include <chrono>
+#include <functional>
+#include <string>
+#include <thread>
+
+#if defined(USE_NATPMP) || defined(USE_UPNP)
+static CThreadInterrupt g_mapport_interrupt;
+static std::thread g_mapport_thread;
+static std::atomic_uint g_mapport_enabled_protos{MapPortProtoFlag::NONE};
+static std::atomic<MapPortProtoFlag> g_mapport_current_proto{MapPortProtoFlag::NONE};
+
+using namespace std::chrono_literals;
+static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD{20min};
+static constexpr auto PORT_MAPPING_RETRY_PERIOD{5min};
+
+#ifdef USE_NATPMP
+static uint16_t g_mapport_external_port = 0;
+static bool NatpmpInit(natpmp_t* natpmp)
+{
+ const int r_init = initnatpmp(natpmp, /* detect gateway automatically */ 0, /* forced gateway - NOT APPLIED*/ 0);
+ if (r_init == 0) return true;
+ LogPrintf("natpmp: initnatpmp() failed with %d error.\n", r_init);
+ return false;
+}
+
+static bool NatpmpDiscover(natpmp_t* natpmp, struct in_addr& external_ipv4_addr)
+{
+ const int r_send = sendpublicaddressrequest(natpmp);
+ if (r_send == 2 /* OK */) {
+ int r_read;
+ natpmpresp_t response;
+ do {
+ r_read = readnatpmpresponseorretry(natpmp, &response);
+ } while (r_read == NATPMP_TRYAGAIN);
+
+ if (r_read == 0) {
+ external_ipv4_addr = response.pnu.publicaddress.addr;
+ return true;
+ } else if (r_read == NATPMP_ERR_NOGATEWAYSUPPORT) {
+ LogPrintf("natpmp: The gateway does not support NAT-PMP.\n");
+ } else {
+ LogPrintf("natpmp: readnatpmpresponseorretry() for public address failed with %d error.\n", r_read);
+ }
+ } else {
+ LogPrintf("natpmp: sendpublicaddressrequest() failed with %d error.\n", r_send);
+ }
+
+ return false;
+}
+
+static bool NatpmpMapping(natpmp_t* natpmp, const struct in_addr& external_ipv4_addr, uint16_t private_port, bool& external_ip_discovered)
+{
+ const uint16_t suggested_external_port = g_mapport_external_port ? g_mapport_external_port : private_port;
+ const int r_send = sendnewportmappingrequest(natpmp, NATPMP_PROTOCOL_TCP, private_port, suggested_external_port, 3600 /*seconds*/);
+ if (r_send == 12 /* OK */) {
+ int r_read;
+ natpmpresp_t response;
+ do {
+ r_read = readnatpmpresponseorretry(natpmp, &response);
+ } while (r_read == NATPMP_TRYAGAIN);
+
+ if (r_read == 0) {
+ auto pm = response.pnu.newportmapping;
+ if (private_port == pm.privateport && pm.lifetime > 0) {
+ g_mapport_external_port = pm.mappedpublicport;
+ const CService external{external_ipv4_addr, pm.mappedpublicport};
+ if (!external_ip_discovered && fDiscover) {
+ AddLocal(external, LOCAL_MAPPED);
+ external_ip_discovered = true;
+ }
+ LogPrintf("natpmp: Port mapping successful. External address = %s\n", external.ToString());
+ return true;
+ } else {
+ LogPrintf("natpmp: Port mapping failed.\n");
+ }
+ } else if (r_read == NATPMP_ERR_NOGATEWAYSUPPORT) {
+ LogPrintf("natpmp: The gateway does not support NAT-PMP.\n");
+ } else {
+ LogPrintf("natpmp: readnatpmpresponseorretry() for port mapping failed with %d error.\n", r_read);
+ }
+ } else {
+ LogPrintf("natpmp: sendnewportmappingrequest() failed with %d error.\n", r_send);
+ }
+
+ return false;
+}
+
+static bool ProcessNatpmp()
+{
+ bool ret = false;
+ natpmp_t natpmp;
+ struct in_addr external_ipv4_addr;
+ if (NatpmpInit(&natpmp) && NatpmpDiscover(&natpmp, external_ipv4_addr)) {
+ bool external_ip_discovered = false;
+ const uint16_t private_port = GetListenPort();
+ do {
+ ret = NatpmpMapping(&natpmp, external_ipv4_addr, private_port, external_ip_discovered);
+ } while (ret && g_mapport_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD));
+ g_mapport_interrupt.reset();
+
+ const int r_send = sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, private_port, g_mapport_external_port, /* remove a port mapping */ 0);
+ g_mapport_external_port = 0;
+ if (r_send == 12 /* OK */) {
+ LogPrintf("natpmp: Port mapping removed successfully.\n");
+ } else {
+ LogPrintf("natpmp: sendnewportmappingrequest(0) failed with %d error.\n", r_send);
+ }
+ }
+
+ closenatpmp(&natpmp);
+ return ret;
+}
+#endif // USE_NATPMP
+
+#ifdef USE_UPNP
+static bool ProcessUpnp()
+{
+ bool ret = false;
+ std::string port = strprintf("%u", GetListenPort());
+ const char * multicastif = nullptr;
+ const char * minissdpdpath = nullptr;
+ struct UPNPDev * devlist = nullptr;
+ char lanaddr[64];
+
+ int error = 0;
+#if MINIUPNPC_API_VERSION < 14
+ devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
+#else
+ devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
+#endif
+
+ struct UPNPUrls urls;
+ struct IGDdatas data;
+ int r;
+
+ r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
+ if (r == 1)
+ {
+ if (fDiscover) {
+ char externalIPAddress[40];
+ r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
+ if (r != UPNPCOMMAND_SUCCESS) {
+ LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
+ } else {
+ if (externalIPAddress[0]) {
+ CNetAddr resolved;
+ if (LookupHost(externalIPAddress, resolved, false)) {
+ LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString());
+ AddLocal(resolved, LOCAL_MAPPED);
+ }
+ } else {
+ LogPrintf("UPnP: GetExternalIPAddress failed.\n");
+ }
+ }
+ }
+
+ std::string strDesc = PACKAGE_NAME " " + FormatFullVersion();
+
+ do {
+ r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
+
+ if (r != UPNPCOMMAND_SUCCESS) {
+ ret = false;
+ LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r));
+ break;
+ } else {
+ ret = true;
+ LogPrintf("UPnP Port Mapping successful.\n");
+ }
+ } while (g_mapport_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD));
+ g_mapport_interrupt.reset();
+
+ r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
+ LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
+ freeUPNPDevlist(devlist); devlist = nullptr;
+ FreeUPNPUrls(&urls);
+ } else {
+ LogPrintf("No valid UPnP IGDs found\n");
+ freeUPNPDevlist(devlist); devlist = nullptr;
+ if (r != 0)
+ FreeUPNPUrls(&urls);
+ }
+
+ return ret;
+}
+#endif // USE_UPNP
+
+static void ThreadMapPort()
+{
+ bool ok;
+ do {
+ ok = false;
+
+#ifdef USE_UPNP
+ // High priority protocol.
+ if (g_mapport_enabled_protos & MapPortProtoFlag::UPNP) {
+ g_mapport_current_proto = MapPortProtoFlag::UPNP;
+ ok = ProcessUpnp();
+ if (ok) continue;
+ }
+#endif // USE_UPNP
+
+#ifdef USE_NATPMP
+ // Low priority protocol.
+ if (g_mapport_enabled_protos & MapPortProtoFlag::NAT_PMP) {
+ g_mapport_current_proto = MapPortProtoFlag::NAT_PMP;
+ ok = ProcessNatpmp();
+ if (ok) continue;
+ }
+#endif // USE_NATPMP
+
+ g_mapport_current_proto = MapPortProtoFlag::NONE;
+ if (g_mapport_enabled_protos == MapPortProtoFlag::NONE) {
+ return;
+ }
+
+ } while (ok || g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD));
+}
+
+void StartThreadMapPort()
+{
+ if (!g_mapport_thread.joinable()) {
+ assert(!g_mapport_interrupt);
+ g_mapport_thread = std::thread(std::bind(&TraceThread<void (*)()>, "mapport", &ThreadMapPort));
+ }
+}
+
+static void DispatchMapPort()
+{
+ if (g_mapport_current_proto == MapPortProtoFlag::NONE && g_mapport_enabled_protos == MapPortProtoFlag::NONE) {
+ return;
+ }
+
+ if (g_mapport_current_proto == MapPortProtoFlag::NONE && g_mapport_enabled_protos != MapPortProtoFlag::NONE) {
+ StartThreadMapPort();
+ return;
+ }
+
+ if (g_mapport_current_proto != MapPortProtoFlag::NONE && g_mapport_enabled_protos == MapPortProtoFlag::NONE) {
+ InterruptMapPort();
+ StopMapPort();
+ return;
+ }
+
+ if (g_mapport_enabled_protos & g_mapport_current_proto) {
+ // Enabling another protocol does not cause switching from the currently used one.
+ return;
+ }
+
+ assert(g_mapport_thread.joinable());
+ assert(!g_mapport_interrupt);
+ // Interrupt a protocol-specific loop in the ThreadUpnp() or in the ThreadNatpmp()
+ // to force trying the next protocol in the ThreadMapPort() loop.
+ g_mapport_interrupt();
+}
+
+static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled)
+{
+ if (enabled) {
+ g_mapport_enabled_protos |= proto;
+ } else {
+ g_mapport_enabled_protos &= ~proto;
+ }
+}
+
+void StartMapPort(bool use_upnp, bool use_natpmp)
+{
+ MapPortProtoSetEnabled(MapPortProtoFlag::UPNP, use_upnp);
+ MapPortProtoSetEnabled(MapPortProtoFlag::NAT_PMP, use_natpmp);
+ DispatchMapPort();
+}
+
+void InterruptMapPort()
+{
+ g_mapport_enabled_protos = MapPortProtoFlag::NONE;
+ if (g_mapport_thread.joinable()) {
+ g_mapport_interrupt();
+ }
+}
+
+void StopMapPort()
+{
+ if (g_mapport_thread.joinable()) {
+ g_mapport_thread.join();
+ g_mapport_interrupt.reset();
+ }
+}
+
+#else // #if defined(USE_NATPMP) || defined(USE_UPNP)
+void StartMapPort(bool use_upnp, bool use_natpmp)
+{
+ // Intentionally left blank.
+}
+void InterruptMapPort()
+{
+ // Intentionally left blank.
+}
+void StopMapPort()
+{
+ // Intentionally left blank.
+}
+#endif // #if defined(USE_NATPMP) || defined(USE_UPNP)
diff --git a/src/mapport.h b/src/mapport.h
new file mode 100644
index 0000000000..279d65167f
--- /dev/null
+++ b/src/mapport.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2011-2020 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_MAPPORT_H
+#define BITCOIN_MAPPORT_H
+
+#ifdef USE_UPNP
+static constexpr bool DEFAULT_UPNP = USE_UPNP;
+#else
+static constexpr bool DEFAULT_UPNP = false;
+#endif // USE_UPNP
+
+#ifdef USE_NATPMP
+static constexpr bool DEFAULT_NATPMP = USE_NATPMP;
+#else
+static constexpr bool DEFAULT_NATPMP = false;
+#endif // USE_NATPMP
+
+enum MapPortProtoFlag : unsigned int {
+ NONE = 0x00,
+ UPNP = 0x01,
+ NAT_PMP = 0x02,
+};
+
+void StartMapPort(bool use_upnp, bool use_natpmp);
+void InterruptMapPort();
+void StopMapPort();
+
+#endif // BITCOIN_MAPPORT_H
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index b571d463c9..3ffe1465da 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -59,7 +59,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
//if we do not have this assert, we can hit a memory access violation when indexing into vTxid
assert(vTxid.size() != 0);
if (height == 0) {
- // hash at height 0 is the txids themself
+ // hash at height 0 is the txids themselves
return vTxid[pos];
} else {
// calculate left hash
diff --git a/src/merkleblock.h b/src/merkleblock.h
index b2d2828784..0e4ed72130 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/miner.cpp b/src/miner.cpp
index 41a835f70a..009ae6b13a 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -213,7 +213,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost
// - transaction finality (locktime)
// - premature witness (in case segwit transactions are added to mempool before
// segwit activation)
-bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
+bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package) const
{
for (CTxMemPool::txiter it : package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
diff --git a/src/miner.h b/src/miner.h
index bb7a30b184..9a2b7063f4 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -185,7 +185,7 @@ private:
* locktime, premature-witness, serialized size (if necessary)
* These checks should always succeed, and they're here
* only as an extra check in case of suboptimal node configuration */
- bool TestPackageTransactions(const CTxMemPool::setEntries& package);
+ bool TestPackageTransactions(const CTxMemPool::setEntries& package) const;
/** Return true if given transaction from mapTx has already been evaluated,
* or if the transaction's cached data in mapTx is incorrect. */
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set& mapModifiedTx, CTxMemPool::setEntries& failedTx) EXCLUSIVE_LOCKS_REQUIRED(m_mempool.cs);
diff --git a/src/net.cpp b/src/net.cpp
index 9c6d7b6375..4f74bbede4 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -16,6 +16,7 @@
#include <net_permissions.h>
#include <netbase.h>
#include <node/ui_interface.h>
+#include <optional.h>
#include <protocol.h>
#include <random.h>
#include <scheduler.h>
@@ -32,15 +33,6 @@
#include <poll.h>
#endif
-#ifdef USE_UPNP
-#include <miniupnpc/miniupnpc.h>
-#include <miniupnpc/upnpcommands.h>
-#include <miniupnpc/upnperrors.h>
-// The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
-// with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
-static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed");
-#endif
-
#include <algorithm>
#include <cstdint>
#include <unordered_map>
@@ -72,6 +64,9 @@ static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS{11};
static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS{5};
static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD = 1000; // "many" vs "few" peers
+/** The default timeframe for -maxuploadtarget. 1 day. */
+static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME{60 * 60 * 24};
+
// We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
#define FEELER_SLEEP_WINDOW 1
@@ -111,7 +106,6 @@ static const uint64_t RANDOMIZER_ID_ADDRCACHE = 0x1cf2e4ddd306dda9ULL; // SHA256
//
bool fDiscover = true;
bool fListen = true;
-bool g_relay_txes = !DEFAULT_BLOCKSONLY;
RecursiveMutex cs_mapLocalHost;
std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(cs_mapLocalHost);
static bool vfLimited[NET_MAX] GUARDED_BY(cs_mapLocalHost) = {};
@@ -478,7 +472,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
CAddress addr_bind = GetBindAddress(hSocket);
- CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type);
+ CNode* pnode = new CNode(id, nLocalServices, hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type);
pnode->AddRef();
// We're making a new connection, harvest entropy from the time (and our peer count)
@@ -504,9 +498,9 @@ void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNet
}
}
-std::string CNode::ConnectionTypeAsString() const
+std::string ConnectionTypeAsString(ConnectionType conn_type)
{
- switch (m_conn_type) {
+ switch (conn_type) {
case ConnectionType::INBOUND:
return "inbound";
case ConnectionType::MANUAL:
@@ -552,7 +546,7 @@ void CNode::SetAddrLocal(const CService& addrLocalIn) {
Network CNode::ConnectedThroughNetwork() const
{
- return IsInboundConn() && m_inbound_onion ? NET_ONION : addr.GetNetClass();
+ return m_inbound_onion ? NET_ONION : addr.GetNetClass();
}
#undef X
@@ -563,7 +557,7 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
X(nServices);
X(addr);
X(addrBind);
- stats.m_network = GetNetworkName(ConnectedThroughNetwork());
+ stats.m_network = ConnectedThroughNetwork();
stats.m_mapped_as = addr.GetMappedAS(m_asmap);
if (m_tx_relay != nullptr) {
LOCK(m_tx_relay->cs_filter);
@@ -584,8 +578,8 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
X(cleanSubVer);
}
stats.fInbound = IsInboundConn();
- stats.m_manual_connection = IsManualConn();
- X(nStartingHeight);
+ X(m_bip152_highbandwidth_to);
+ X(m_bip152_highbandwidth_from);
{
LOCK(cs_vSend);
X(mapSendBytesPerMsgCmd);
@@ -596,10 +590,8 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
X(mapRecvBytesPerMsgCmd);
X(nRecvBytes);
}
- X(m_legacyWhitelisted);
X(m_permissionFlags);
if (m_tx_relay != nullptr) {
- LOCK(m_tx_relay->cs_feeFilter);
stats.minFeeFilter = m_tx_relay->minFeeFilter;
} else {
stats.minFeeFilter = 0;
@@ -625,7 +617,7 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
CService addrLocalUnlocked = GetAddrLocal();
stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToString() : "";
- stats.m_conn_type_string = ConnectionTypeAsString();
+ X(m_conn_type);
}
#undef X
@@ -788,30 +780,30 @@ void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vec
CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, header, 0, hdr};
}
-size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_vSend)
+size_t CConnman::SocketSendData(CNode& node) const
{
- auto it = pnode->vSendMsg.begin();
+ auto it = node.vSendMsg.begin();
size_t nSentSize = 0;
- while (it != pnode->vSendMsg.end()) {
- const auto &data = *it;
- assert(data.size() > pnode->nSendOffset);
+ while (it != node.vSendMsg.end()) {
+ const auto& data = *it;
+ assert(data.size() > node.nSendOffset);
int nBytes = 0;
{
- LOCK(pnode->cs_hSocket);
- if (pnode->hSocket == INVALID_SOCKET)
+ LOCK(node.cs_hSocket);
+ if (node.hSocket == INVALID_SOCKET)
break;
- nBytes = send(pnode->hSocket, reinterpret_cast<const char*>(data.data()) + pnode->nSendOffset, data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
+ nBytes = send(node.hSocket, reinterpret_cast<const char*>(data.data()) + node.nSendOffset, data.size() - node.nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
}
if (nBytes > 0) {
- pnode->nLastSend = GetSystemTimeInSeconds();
- pnode->nSendBytes += nBytes;
- pnode->nSendOffset += nBytes;
+ node.nLastSend = GetSystemTimeInSeconds();
+ node.nSendBytes += nBytes;
+ node.nSendOffset += nBytes;
nSentSize += nBytes;
- if (pnode->nSendOffset == data.size()) {
- pnode->nSendOffset = 0;
- pnode->nSendSize -= data.size();
- pnode->fPauseSend = pnode->nSendSize > nSendBufferMaxSize;
+ if (node.nSendOffset == data.size()) {
+ node.nSendOffset = 0;
+ node.nSendSize -= data.size();
+ node.fPauseSend = node.nSendSize > nSendBufferMaxSize;
it++;
} else {
// could not send full message; stop sending more
@@ -821,10 +813,9 @@ size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pno
if (nBytes < 0) {
// error
int nErr = WSAGetLastError();
- if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
- {
+ if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) {
LogPrintf("socket send error %s\n", NetworkErrorString(nErr));
- pnode->CloseSocketDisconnect();
+ node.CloseSocketDisconnect();
}
}
// couldn't send anything at all
@@ -832,29 +823,14 @@ size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pno
}
}
- if (it == pnode->vSendMsg.end()) {
- assert(pnode->nSendOffset == 0);
- assert(pnode->nSendSize == 0);
+ if (it == node.vSendMsg.end()) {
+ assert(node.nSendOffset == 0);
+ assert(node.nSendSize == 0);
}
- pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
+ node.vSendMsg.erase(node.vSendMsg.begin(), it);
return nSentSize;
}
-struct NodeEvictionCandidate
-{
- NodeId id;
- int64_t nTimeConnected;
- int64_t nMinPingUsecTime;
- int64_t nLastBlockTime;
- int64_t nLastTXTime;
- bool fRelevantServices;
- bool fRelayTxes;
- bool fBloomFilter;
- uint64_t nKeyedNetGroup;
- bool prefer_evict;
- bool m_is_local;
-};
-
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
{
return a.nMinPingUsecTime > b.nMinPingUsecTime;
@@ -910,43 +886,8 @@ static void EraseLastKElements(std::vector<T> &elements, Comparator comparator,
elements.erase(elements.end() - eraseSize, elements.end());
}
-/** Try to find a connection to evict when the node is full.
- * Extreme care must be taken to avoid opening the node to attacker
- * triggered network partitioning.
- * The strategy used here is to protect a small number of peers
- * for each of several distinct characteristics which are difficult
- * to forge. In order to partition a node the attacker must be
- * simultaneously better at all of them than honest peers.
- */
-bool CConnman::AttemptToEvictConnection()
+[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
{
- std::vector<NodeEvictionCandidate> vEvictionCandidates;
- {
- LOCK(cs_vNodes);
-
- for (const CNode* node : vNodes) {
- if (node->HasPermission(PF_NOBAN))
- continue;
- if (!node->IsInboundConn())
- continue;
- if (node->fDisconnect)
- continue;
- bool peer_relay_txes = false;
- bool peer_filter_not_null = false;
- if (node->m_tx_relay != nullptr) {
- LOCK(node->m_tx_relay->cs_filter);
- peer_relay_txes = node->m_tx_relay->fRelayTxes;
- peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
- }
- NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
- node->nLastBlockTime, node->nLastTXTime,
- HasAllDesirableServiceFlags(node->nServices),
- peer_relay_txes, peer_filter_not_null, node->nKeyedNetGroup,
- node->m_prefer_evict, node->addr.IsLocal()};
- vEvictionCandidates.push_back(candidate);
- }
- }
-
// Protect connections with certain characteristics
// Deterministically select 4 peers to protect by netgroup.
@@ -984,7 +925,7 @@ bool CConnman::AttemptToEvictConnection()
total_protect_size -= initial_size - vEvictionCandidates.size();
EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, total_protect_size);
- if (vEvictionCandidates.empty()) return false;
+ if (vEvictionCandidates.empty()) return nullopt;
// If any remaining peers are preferred for eviction consider only them.
// This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
@@ -1016,10 +957,52 @@ bool CConnman::AttemptToEvictConnection()
vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
// Disconnect from the network group with the most connections
- NodeId evicted = vEvictionCandidates.front().id;
+ return vEvictionCandidates.front().id;
+}
+
+/** Try to find a connection to evict when the node is full.
+ * Extreme care must be taken to avoid opening the node to attacker
+ * triggered network partitioning.
+ * The strategy used here is to protect a small number of peers
+ * for each of several distinct characteristics which are difficult
+ * to forge. In order to partition a node the attacker must be
+ * simultaneously better at all of them than honest peers.
+ */
+bool CConnman::AttemptToEvictConnection()
+{
+ std::vector<NodeEvictionCandidate> vEvictionCandidates;
+ {
+
+ LOCK(cs_vNodes);
+ for (const CNode* node : vNodes) {
+ if (node->HasPermission(PF_NOBAN))
+ continue;
+ if (!node->IsInboundConn())
+ continue;
+ if (node->fDisconnect)
+ continue;
+ bool peer_relay_txes = false;
+ bool peer_filter_not_null = false;
+ if (node->m_tx_relay != nullptr) {
+ LOCK(node->m_tx_relay->cs_filter);
+ peer_relay_txes = node->m_tx_relay->fRelayTxes;
+ peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
+ }
+ NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
+ node->nLastBlockTime, node->nLastTXTime,
+ HasAllDesirableServiceFlags(node->nServices),
+ peer_relay_txes, peer_filter_not_null, node->nKeyedNetGroup,
+ node->m_prefer_evict, node->addr.IsLocal()};
+ vEvictionCandidates.push_back(candidate);
+ }
+ }
+ const Optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
+ if (!node_id_to_evict) {
+ return false;
+ }
LOCK(cs_vNodes);
for (CNode* pnode : vNodes) {
- if (pnode->GetId() == evicted) {
+ if (pnode->GetId() == *node_id_to_evict) {
pnode->fDisconnect = true;
return true;
}
@@ -1044,14 +1027,12 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
NetPermissionFlags permissionFlags = NetPermissionFlags::PF_NONE;
hListenSocket.AddSocketPermissionFlags(permissionFlags);
AddWhitelistPermissionFlags(permissionFlags, addr);
- bool legacyWhitelisted = false;
if (NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::PF_ISIMPLICIT)) {
NetPermissions::ClearFlag(permissionFlags, PF_ISIMPLICIT);
if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permissionFlags, PF_FORCERELAY);
if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permissionFlags, PF_RELAY);
NetPermissions::AddFlag(permissionFlags, PF_MEMPOOL);
NetPermissions::AddFlag(permissionFlags, PF_NOBAN);
- legacyWhitelisted = true;
}
{
@@ -1124,11 +1105,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
}
const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
- CNode* pnode = new CNode(id, nodeServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", ConnectionType::INBOUND, inbound_onion);
+ CNode* pnode = new CNode(id, nodeServices, hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", ConnectionType::INBOUND, inbound_onion);
pnode->AddRef();
pnode->m_permissionFlags = permissionFlags;
- // If this flag is present, the user probably expect that RPC and QT report it as whitelisted (backward compatibility)
- pnode->m_legacyWhitelisted = legacyWhitelisted;
pnode->m_prefer_evict = discouraged;
m_msgproc->InitializeNode(pnode);
@@ -1143,6 +1122,27 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
RandAddEvent((uint32_t)id);
}
+bool CConnman::AddConnection(const std::string& address, ConnectionType conn_type)
+{
+ if (conn_type != ConnectionType::OUTBOUND_FULL_RELAY && conn_type != ConnectionType::BLOCK_RELAY) return false;
+
+ const int max_connections = conn_type == ConnectionType::OUTBOUND_FULL_RELAY ? m_max_outbound_full_relay : m_max_outbound_block_relay;
+
+ // Count existing connections
+ int existing_connections = WITH_LOCK(cs_vNodes,
+ return std::count_if(vNodes.begin(), vNodes.end(), [conn_type](CNode* node) { return node->m_conn_type == conn_type; }););
+
+ // Max connections of specified type already exist
+ if (existing_connections >= max_connections) return false;
+
+ // Max total outbound connections already exist
+ CSemaphoreGrant grant(*semOutbound, true);
+ if (!grant) return false;
+
+ OpenNetworkConnection(CAddress(), false, &grant, address.c_str(), conn_type);
+ return true;
+}
+
void CConnman::DisconnectNodes()
{
{
@@ -1216,7 +1216,7 @@ void CConnman::NotifyNumConnectionsChanged()
}
}
-void CConnman::InactivityCheck(CNode *pnode)
+void CConnman::InactivityCheck(CNode *pnode) const
{
int64_t nTime = GetSystemTimeInSeconds();
if (nTime - pnode->nTimeConnected > m_peer_connect_timeout)
@@ -1231,7 +1231,7 @@ void CConnman::InactivityCheck(CNode *pnode)
LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
pnode->fDisconnect = true;
}
- else if (nTime - pnode->nLastRecv > (pnode->GetCommonVersion() > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
+ else if (nTime - pnode->nLastRecv > TIMEOUT_INTERVAL)
{
LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
pnode->fDisconnect = true;
@@ -1516,16 +1516,10 @@ void CConnman::SocketHandler()
}
}
- //
- // Send
- //
- if (sendSet)
- {
- LOCK(pnode->cs_vSend);
- size_t nBytes = SocketSendData(pnode);
- if (nBytes) {
- RecordBytesSent(nBytes);
- }
+ if (sendSet) {
+ // Send data
+ size_t bytes_sent = WITH_LOCK(pnode->cs_vSend, return SocketSendData(*pnode));
+ if (bytes_sent) RecordBytesSent(bytes_sent);
}
InactivityCheck(pnode);
@@ -1556,121 +1550,6 @@ void CConnman::WakeMessageHandler()
condMsgProc.notify_one();
}
-
-
-
-
-
-#ifdef USE_UPNP
-static CThreadInterrupt g_upnp_interrupt;
-static std::thread g_upnp_thread;
-static void ThreadMapPort()
-{
- std::string port = strprintf("%u", GetListenPort());
- const char * multicastif = nullptr;
- const char * minissdpdpath = nullptr;
- struct UPNPDev * devlist = nullptr;
- char lanaddr[64];
-
- int error = 0;
-#if MINIUPNPC_API_VERSION < 14
- devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
-#else
- devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
-#endif
-
- struct UPNPUrls urls;
- struct IGDdatas data;
- int r;
-
- r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
- if (r == 1)
- {
- if (fDiscover) {
- char externalIPAddress[40];
- r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
- if (r != UPNPCOMMAND_SUCCESS) {
- LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
- } else {
- if (externalIPAddress[0]) {
- CNetAddr resolved;
- if (LookupHost(externalIPAddress, resolved, false)) {
- LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString());
- AddLocal(resolved, LOCAL_UPNP);
- }
- } else {
- LogPrintf("UPnP: GetExternalIPAddress failed.\n");
- }
- }
- }
-
- std::string strDesc = PACKAGE_NAME " " + FormatFullVersion();
-
- do {
- r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
-
- if (r != UPNPCOMMAND_SUCCESS) {
- LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r));
- } else {
- LogPrintf("UPnP Port Mapping successful.\n");
- }
- } while (g_upnp_interrupt.sleep_for(std::chrono::minutes(20)));
-
- r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
- LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
- freeUPNPDevlist(devlist); devlist = nullptr;
- FreeUPNPUrls(&urls);
- } else {
- LogPrintf("No valid UPnP IGDs found\n");
- freeUPNPDevlist(devlist); devlist = nullptr;
- if (r != 0)
- FreeUPNPUrls(&urls);
- }
-}
-
-void StartMapPort()
-{
- if (!g_upnp_thread.joinable()) {
- assert(!g_upnp_interrupt);
- g_upnp_thread = std::thread((std::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort)));
- }
-}
-
-void InterruptMapPort()
-{
- if(g_upnp_thread.joinable()) {
- g_upnp_interrupt();
- }
-}
-
-void StopMapPort()
-{
- if(g_upnp_thread.joinable()) {
- g_upnp_thread.join();
- g_upnp_interrupt.reset();
- }
-}
-
-#else
-void StartMapPort()
-{
- // Intentionally left blank.
-}
-void InterruptMapPort()
-{
- // Intentionally left blank.
-}
-void StopMapPort()
-{
- // Intentionally left blank.
-}
-#endif
-
-
-
-
-
-
void CConnman::ThreadDNSAddressSeed()
{
FastRandomContext rng;
@@ -1826,18 +1705,32 @@ void CConnman::SetTryNewOutboundPeer(bool flag)
// Also exclude peers that haven't finished initial connection handshake yet
// (so that we don't decide we're over our desired connection limit, and then
// evict some peer that has finished the handshake)
-int CConnman::GetExtraOutboundCount()
+int CConnman::GetExtraFullOutboundCount()
{
- int nOutbound = 0;
+ int full_outbound_peers = 0;
{
LOCK(cs_vNodes);
for (const CNode* pnode : vNodes) {
- if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsOutboundOrBlockRelayConn()) {
- ++nOutbound;
+ if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
+ ++full_outbound_peers;
}
}
}
- return std::max(nOutbound - m_max_outbound_full_relay - m_max_outbound_block_relay, 0);
+ return std::max(full_outbound_peers - m_max_outbound_full_relay, 0);
+}
+
+int CConnman::GetExtraBlockRelayCount()
+{
+ int block_relay_peers = 0;
+ {
+ LOCK(cs_vNodes);
+ for (const CNode* pnode : vNodes) {
+ if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
+ ++block_relay_peers;
+ }
+ }
+ }
+ return std::max(block_relay_peers - m_max_outbound_block_relay, 0);
}
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
@@ -1868,6 +1761,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// Minimum time before next feeler connection (in microseconds).
int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL);
+ int64_t nNextExtraBlockRelay = PoissonNextSend(nStart*1000*1000, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
while (!interruptNet)
{
ProcessAddrFetch();
@@ -1940,8 +1834,9 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// until we hit our block-relay-only peer limit.
// GetTryNewOutboundPeer() gets set when a stale tip is detected, so we
// try opening an additional OUTBOUND_FULL_RELAY connection. If none of
- // these conditions are met, check the nNextFeeler timer to decide if
- // we should open a FEELER.
+ // these conditions are met, check to see if it's time to try an extra
+ // block-relay-only peer (to confirm our tip is current, see below) or the nNextFeeler
+ // timer to decide if we should open a FEELER.
if (!m_anchors.empty() && (nOutboundBlockRelay < m_max_outbound_block_relay)) {
conn_type = ConnectionType::BLOCK_RELAY;
@@ -1952,6 +1847,30 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
conn_type = ConnectionType::BLOCK_RELAY;
} else if (GetTryNewOutboundPeer()) {
// OUTBOUND_FULL_RELAY
+ } else if (nTime > nNextExtraBlockRelay && m_start_extra_block_relay_peers) {
+ // Periodically connect to a peer (using regular outbound selection
+ // methodology from addrman) and stay connected long enough to sync
+ // headers, but not much else.
+ //
+ // Then disconnect the peer, if we haven't learned anything new.
+ //
+ // The idea is to make eclipse attacks very difficult to pull off,
+ // because every few minutes we're finding a new peer to learn headers
+ // from.
+ //
+ // This is similar to the logic for trying extra outbound (full-relay)
+ // peers, except:
+ // - we do this all the time on a poisson timer, rather than just when
+ // our tip is stale
+ // - we potentially disconnect our next-youngest block-relay-only peer, if our
+ // newest block-relay-only peer delivers a block more recently.
+ // See the eviction logic in net_processing.cpp.
+ //
+ // Because we can promote these connections to block-relay-only
+ // connections, they do not get their own ConnectionType enum
+ // (similar to how we deal with extra outbound peers).
+ nNextExtraBlockRelay = PoissonNextSend(nTime, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
+ conn_type = ConnectionType::BLOCK_RELAY;
} else if (nTime > nNextFeeler) {
nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL);
conn_type = ConnectionType::FEELER;
@@ -2037,7 +1956,11 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
continue;
}
- // do not allow non-default ports, unless after 50 invalid addresses selected already
+ // Do not allow non-default ports, unless after 50 invalid
+ // addresses selected already. This is to prevent malicious peers
+ // from advertising themselves as a service on another host and
+ // port, causing a DoS attack as nodes around the network attempt
+ // to connect to it fruitlessly.
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
continue;
@@ -2806,8 +2729,8 @@ void CConnman::RecordBytesSent(uint64_t bytes)
LOCK(cs_totalBytesSent);
nTotalBytesSent += bytes;
- uint64_t now = GetTime();
- if (nMaxOutboundCycleStartTime + nMaxOutboundTimeframe < now)
+ const auto now = GetTime<std::chrono::seconds>();
+ if (nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME < now)
{
// timeframe expired, reset cycle
nMaxOutboundCycleStartTime = now;
@@ -2818,48 +2741,29 @@ void CConnman::RecordBytesSent(uint64_t bytes)
nMaxOutboundTotalBytesSentInCycle += bytes;
}
-void CConnman::SetMaxOutboundTarget(uint64_t limit)
-{
- LOCK(cs_totalBytesSent);
- nMaxOutboundLimit = limit;
-}
-
uint64_t CConnman::GetMaxOutboundTarget()
{
LOCK(cs_totalBytesSent);
return nMaxOutboundLimit;
}
-uint64_t CConnman::GetMaxOutboundTimeframe()
+std::chrono::seconds CConnman::GetMaxOutboundTimeframe()
{
- LOCK(cs_totalBytesSent);
- return nMaxOutboundTimeframe;
+ return MAX_UPLOAD_TIMEFRAME;
}
-uint64_t CConnman::GetMaxOutboundTimeLeftInCycle()
+std::chrono::seconds CConnman::GetMaxOutboundTimeLeftInCycle()
{
LOCK(cs_totalBytesSent);
if (nMaxOutboundLimit == 0)
- return 0;
+ return 0s;
- if (nMaxOutboundCycleStartTime == 0)
- return nMaxOutboundTimeframe;
-
- uint64_t cycleEndTime = nMaxOutboundCycleStartTime + nMaxOutboundTimeframe;
- uint64_t now = GetTime();
- return (cycleEndTime < now) ? 0 : cycleEndTime - GetTime();
-}
+ if (nMaxOutboundCycleStartTime.count() == 0)
+ return MAX_UPLOAD_TIMEFRAME;
-void CConnman::SetMaxOutboundTimeframe(uint64_t timeframe)
-{
- LOCK(cs_totalBytesSent);
- if (nMaxOutboundTimeframe != timeframe)
- {
- // reset measure-cycle in case of changing
- // the timeframe
- nMaxOutboundCycleStartTime = GetTime();
- }
- nMaxOutboundTimeframe = timeframe;
+ const std::chrono::seconds cycleEndTime = nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME;
+ const auto now = GetTime<std::chrono::seconds>();
+ return (cycleEndTime < now) ? 0s : cycleEndTime - now;
}
bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit)
@@ -2871,8 +2775,8 @@ bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit)
if (historicalBlockServingLimit)
{
// keep a large enough buffer to at least relay each block once
- uint64_t timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
- uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SERIALIZED_SIZE;
+ const std::chrono::seconds timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
+ const uint64_t buffer = timeLeftInCycle / std::chrono::minutes{10} * MAX_BLOCK_SERIALIZED_SIZE;
if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
return true;
}
@@ -2908,36 +2812,22 @@ ServiceFlags CConnman::GetLocalServices() const
return nLocalServices;
}
-void CConnman::SetBestHeight(int height)
-{
- nBestHeight.store(height, std::memory_order_release);
-}
-
-int CConnman::GetBestHeight() const
-{
- return nBestHeight.load(std::memory_order_acquire);
-}
-
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
-CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
+CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
: nTimeConnected(GetSystemTimeInSeconds()),
- addr(addrIn),
- addrBind(addrBindIn),
- nKeyedNetGroup(nKeyedNetGroupIn),
- // Don't relay addr messages to peers that we connect to as block-relay-only
- // peers (to prevent adversaries from inferring these links from addr
- // traffic).
- id(idIn),
- nLocalHostNonce(nLocalHostNonceIn),
- m_conn_type(conn_type_in),
- nLocalServices(nLocalServicesIn),
- nMyStartingHeight(nMyStartingHeightIn),
- m_inbound_onion(inbound_onion)
-{
+ addr(addrIn),
+ addrBind(addrBindIn),
+ nKeyedNetGroup(nKeyedNetGroupIn),
+ id(idIn),
+ nLocalHostNonce(nLocalHostNonceIn),
+ m_conn_type(conn_type_in),
+ nLocalServices(nLocalServicesIn),
+ m_inbound_onion(inbound_onion)
+{
+ if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND);
hSocket = hSocketIn;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
- hashContinue = uint256();
if (conn_type_in != ConnectionType::BLOCK_RELAY) {
m_tx_relay = MakeUnique<TxRelay>();
}
@@ -2997,7 +2887,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
// If write queue empty, attempt "optimistic write"
if (optimisticSend == true)
- nBytesSent = SocketSendData(pnode);
+ nBytesSent = SocketSendData(*pnode);
}
if (nBytesSent)
RecordBytesSent(nBytesSent);
diff --git a/src/net.h b/src/net.h
index 21ee5e7808..4f1a6b89a9 100644
--- a/src/net.h
+++ b/src/net.h
@@ -24,14 +24,16 @@
#include <sync.h>
#include <threadinterrupt.h>
#include <uint256.h>
+#include <util/check.h>
#include <atomic>
+#include <condition_variable>
#include <cstdint>
#include <deque>
#include <map>
-#include <thread>
#include <memory>
-#include <condition_variable>
+#include <thread>
+#include <vector>
class CScheduler;
class CNode;
@@ -47,6 +49,8 @@ static const bool DEFAULT_WHITELISTFORCERELAY = false;
static const int TIMEOUT_INTERVAL = 20 * 60;
/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/
static const int FEELER_INTERVAL = 120;
+/** Run the extra block-relay-only connection loop once every 5 minutes. **/
+static const int EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL = 300;
/** The maximum number of addresses from our addrman to return in response to a getaddr message. */
static constexpr size_t MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable). */
@@ -63,18 +67,10 @@ static const int MAX_BLOCK_RELAY_ONLY_CONNECTIONS = 2;
static const int MAX_FEELER_CONNECTIONS = 1;
/** -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
/** The maximum number of peer connections to maintain. */
static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125;
/** The default for -maxuploadtarget. 0 = Unlimited */
-static const uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0;
-/** The default timeframe for -maxuploadtarget. 1 day. */
-static const uint64_t MAX_UPLOAD_TIMEFRAME = 60 * 60 * 24;
+static constexpr uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0;
/** Default for blocks only*/
static const bool DEFAULT_BLOCKSONLY = false;
/** -peertimeout default */
@@ -178,463 +174,17 @@ enum class ConnectionType {
ADDR_FETCH,
};
-class NetEventsInterface;
-class CConnman
-{
-public:
-
- enum NumConnections {
- CONNECTIONS_NONE = 0,
- CONNECTIONS_IN = (1U << 0),
- CONNECTIONS_OUT = (1U << 1),
- CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT),
- };
-
- struct Options
- {
- ServiceFlags nLocalServices = NODE_NONE;
- int nMaxConnections = 0;
- int m_max_outbound_full_relay = 0;
- int m_max_outbound_block_relay = 0;
- int nMaxAddnode = 0;
- int nMaxFeeler = 0;
- int nBestHeight = 0;
- CClientUIInterface* uiInterface = nullptr;
- NetEventsInterface* m_msgproc = nullptr;
- BanMan* m_banman = nullptr;
- unsigned int nSendBufferMaxSize = 0;
- unsigned int nReceiveFloodSize = 0;
- uint64_t nMaxOutboundTimeframe = 0;
- uint64_t nMaxOutboundLimit = 0;
- int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT;
- std::vector<std::string> vSeedNodes;
- std::vector<NetWhitelistPermissions> vWhitelistedRange;
- std::vector<NetWhitebindPermissions> vWhiteBinds;
- std::vector<CService> vBinds;
- std::vector<CService> onion_binds;
- bool m_use_addrman_outgoing = true;
- std::vector<std::string> m_specified_outgoing;
- std::vector<std::string> m_added_nodes;
- std::vector<bool> m_asmap;
- };
-
- void Init(const Options& connOptions) {
- nLocalServices = connOptions.nLocalServices;
- nMaxConnections = connOptions.nMaxConnections;
- m_max_outbound_full_relay = std::min(connOptions.m_max_outbound_full_relay, connOptions.nMaxConnections);
- m_max_outbound_block_relay = connOptions.m_max_outbound_block_relay;
- m_use_addrman_outgoing = connOptions.m_use_addrman_outgoing;
- nMaxAddnode = connOptions.nMaxAddnode;
- nMaxFeeler = connOptions.nMaxFeeler;
- m_max_outbound = m_max_outbound_full_relay + m_max_outbound_block_relay + nMaxFeeler;
- nBestHeight = connOptions.nBestHeight;
- clientInterface = connOptions.uiInterface;
- m_banman = connOptions.m_banman;
- m_msgproc = connOptions.m_msgproc;
- nSendBufferMaxSize = connOptions.nSendBufferMaxSize;
- nReceiveFloodSize = connOptions.nReceiveFloodSize;
- m_peer_connect_timeout = connOptions.m_peer_connect_timeout;
- {
- LOCK(cs_totalBytesSent);
- nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe;
- nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
- }
- vWhitelistedRange = connOptions.vWhitelistedRange;
- {
- LOCK(cs_vAddedNodes);
- vAddedNodes = connOptions.m_added_nodes;
- }
- m_onion_binds = connOptions.onion_binds;
- }
-
- CConnman(uint64_t seed0, uint64_t seed1, bool network_active = true);
- ~CConnman();
- bool Start(CScheduler& scheduler, const Options& options);
-
- void StopThreads();
- void StopNodes();
- void Stop()
- {
- StopThreads();
- StopNodes();
- };
-
- void Interrupt();
- bool GetNetworkActive() const { return fNetworkActive; };
- bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };
- void SetNetworkActive(bool active);
- void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* strDest, ConnectionType conn_type);
- bool CheckIncomingNonce(uint64_t nonce);
-
- bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func);
-
- void PushMessage(CNode* pnode, CSerializedNetMsg&& msg);
-
- using NodeFn = std::function<void(CNode*)>;
- void ForEachNode(const NodeFn& func)
- {
- LOCK(cs_vNodes);
- for (auto&& node : vNodes) {
- if (NodeFullyConnected(node))
- func(node);
- }
- };
-
- void ForEachNode(const NodeFn& func) const
- {
- LOCK(cs_vNodes);
- for (auto&& node : vNodes) {
- if (NodeFullyConnected(node))
- func(node);
- }
- };
-
- template<typename Callable, typename CallableAfter>
- void ForEachNodeThen(Callable&& pre, CallableAfter&& post)
- {
- LOCK(cs_vNodes);
- for (auto&& node : vNodes) {
- if (NodeFullyConnected(node))
- pre(node);
- }
- post();
- };
-
- template<typename Callable, typename CallableAfter>
- void ForEachNodeThen(Callable&& pre, CallableAfter&& post) const
- {
- LOCK(cs_vNodes);
- for (auto&& node : vNodes) {
- if (NodeFullyConnected(node))
- pre(node);
- }
- post();
- };
-
- // Addrman functions
- void SetServices(const CService &addr, ServiceFlags nServices);
- void MarkAddressGood(const CAddress& addr);
- bool AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
- std::vector<CAddress> GetAddresses(size_t max_addresses, size_t max_pct);
- /**
- * Cache is used to minimize topology leaks, so it should
- * be used for all non-trusted calls, for example, p2p.
- * A non-malicious call (from RPC or a peer with addr permission) should
- * call the function without a parameter to avoid using the cache.
- */
- std::vector<CAddress> GetAddresses(CNode& requestor, size_t max_addresses, size_t max_pct);
-
- // This allows temporarily exceeding m_max_outbound_full_relay, with the goal of finding
- // a peer that is better than all our current peers.
- void SetTryNewOutboundPeer(bool flag);
- bool GetTryNewOutboundPeer();
-
- // Return the number of outbound peers we have in excess of our target (eg,
- // if we previously called SetTryNewOutboundPeer(true), and have since set
- // to false, we may have extra peers that we wish to disconnect). This may
- // return a value less than (num_outbound_connections - num_outbound_slots)
- // in cases where some outbound connections are not yet fully connected, or
- // not yet fully disconnected.
- int GetExtraOutboundCount();
-
- bool AddNode(const std::string& node);
- bool RemoveAddedNode(const std::string& node);
- std::vector<AddedNodeInfo> GetAddedNodeInfo();
-
- size_t GetNodeCount(NumConnections num);
- void GetNodeStats(std::vector<CNodeStats>& vstats);
- bool DisconnectNode(const std::string& node);
- bool DisconnectNode(const CSubNet& subnet);
- bool DisconnectNode(const CNetAddr& addr);
- bool DisconnectNode(NodeId id);
-
- //! Used to convey which local services we are offering peers during node
- //! connection.
- //!
- //! The data returned by this is used in CNode construction,
- //! which is used to advertise which services we are offering
- //! that peer during `net_processing.cpp:PushNodeVersion()`.
- ServiceFlags GetLocalServices() const;
-
- //!set the max outbound target in bytes
- void SetMaxOutboundTarget(uint64_t limit);
- uint64_t GetMaxOutboundTarget();
-
- //!set the timeframe for the max outbound target
- void SetMaxOutboundTimeframe(uint64_t timeframe);
- uint64_t GetMaxOutboundTimeframe();
-
- //! check if the outbound target is reached
- //! if param historicalBlockServingLimit is set true, the function will
- //! response true if the limit for serving historical blocks has been reached
- bool OutboundTargetReached(bool historicalBlockServingLimit);
-
- //! response the bytes left in the current max outbound cycle
- //! in case of no limit, it will always response 0
- uint64_t GetOutboundTargetBytesLeft();
-
- //! response the time in second left in the current max outbound cycle
- //! in case of no limit, it will always response 0
- uint64_t GetMaxOutboundTimeLeftInCycle();
-
- uint64_t GetTotalBytesRecv();
- uint64_t GetTotalBytesSent();
-
- void SetBestHeight(int height);
- int GetBestHeight() const;
-
- /** Get a unique deterministic randomizer. */
- CSipHasher GetDeterministicRandomizer(uint64_t id) const;
-
- unsigned int GetReceiveFloodSize() const;
-
- void WakeMessageHandler();
-
- /** Attempts to obfuscate tx time through exponentially distributed emitting.
- Works assuming that a single interval is used.
- Variable intervals will result in privacy decrease.
- */
- int64_t PoissonNextSendInbound(int64_t now, int average_interval_seconds);
-
- void SetAsmap(std::vector<bool> asmap) { addrman.m_asmap = std::move(asmap); }
-
-private:
- struct ListenSocket {
- public:
- SOCKET socket;
- inline void AddSocketPermissionFlags(NetPermissionFlags& flags) const { NetPermissions::AddFlag(flags, m_permissions); }
- ListenSocket(SOCKET socket_, NetPermissionFlags permissions_) : socket(socket_), m_permissions(permissions_) {}
- private:
- NetPermissionFlags m_permissions;
- };
-
- bool BindListenPort(const CService& bindAddr, bilingual_str& strError, NetPermissionFlags permissions);
- bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions);
- bool InitBinds(
- const std::vector<CService>& binds,
- const std::vector<NetWhitebindPermissions>& whiteBinds,
- const std::vector<CService>& onion_binds);
-
- void ThreadOpenAddedConnections();
- void AddAddrFetch(const std::string& strDest);
- void ProcessAddrFetch();
- void ThreadOpenConnections(std::vector<std::string> connect);
- void ThreadMessageHandler();
- void AcceptConnection(const ListenSocket& hListenSocket);
- void DisconnectNodes();
- void NotifyNumConnectionsChanged();
- void InactivityCheck(CNode *pnode);
- bool GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
- void SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
- void SocketHandler();
- void ThreadSocketHandler();
- void ThreadDNSAddressSeed();
-
- uint64_t CalculateKeyedNetGroup(const CAddress& ad) const;
-
- CNode* FindNode(const CNetAddr& ip);
- CNode* FindNode(const CSubNet& subNet);
- CNode* FindNode(const std::string& addrName);
- CNode* FindNode(const CService& addr);
-
- /**
- * Determine whether we're already connected to a given address, in order to
- * avoid initiating duplicate connections.
- */
- bool AlreadyConnectedToAddress(const CAddress& addr);
-
- bool AttemptToEvictConnection();
- CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type);
- void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const;
-
- void DeleteNode(CNode* pnode);
-
- NodeId GetNewNodeId();
-
- size_t SocketSendData(CNode *pnode) const;
- void DumpAddresses();
-
- // Network stats
- void RecordBytesRecv(uint64_t bytes);
- void RecordBytesSent(uint64_t bytes);
-
- /**
- * Return vector of current BLOCK_RELAY peers.
- */
- std::vector<CAddress> GetCurrentBlockRelayOnlyConns() const;
-
- // Whether the node should be passed out in ForEach* callbacks
- static bool NodeFullyConnected(const CNode* pnode);
-
- // Network usage totals
- RecursiveMutex cs_totalBytesRecv;
- RecursiveMutex cs_totalBytesSent;
- uint64_t nTotalBytesRecv GUARDED_BY(cs_totalBytesRecv) {0};
- uint64_t nTotalBytesSent GUARDED_BY(cs_totalBytesSent) {0};
-
- // outbound limit & stats
- uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent) {0};
- uint64_t nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent) {0};
- uint64_t nMaxOutboundLimit GUARDED_BY(cs_totalBytesSent);
- uint64_t nMaxOutboundTimeframe GUARDED_BY(cs_totalBytesSent);
-
- // P2P timeout in seconds
- int64_t m_peer_connect_timeout;
-
- // Whitelisted ranges. Any node connecting from these is automatically
- // whitelisted (as well as those connecting to whitelisted binds).
- std::vector<NetWhitelistPermissions> vWhitelistedRange;
-
- unsigned int nSendBufferMaxSize{0};
- unsigned int nReceiveFloodSize{0};
-
- std::vector<ListenSocket> vhListenSocket;
- std::atomic<bool> fNetworkActive{true};
- bool fAddressesInitialized{false};
- CAddrMan addrman;
- std::deque<std::string> m_addr_fetches GUARDED_BY(m_addr_fetches_mutex);
- RecursiveMutex m_addr_fetches_mutex;
- std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes);
- RecursiveMutex cs_vAddedNodes;
- std::vector<CNode*> vNodes GUARDED_BY(cs_vNodes);
- std::list<CNode*> vNodesDisconnected;
- mutable RecursiveMutex cs_vNodes;
- std::atomic<NodeId> nLastNodeId{0};
- unsigned int nPrevNodeCount{0};
-
- /**
- * Cache responses to addr requests to minimize privacy leak.
- * Attack example: scraping addrs in real-time may allow an attacker
- * to infer new connections of the victim by detecting new records
- * with fresh timestamps (per self-announcement).
- */
- struct CachedAddrResponse {
- std::vector<CAddress> m_addrs_response_cache;
- std::chrono::microseconds m_cache_entry_expiration{0};
- };
-
- /**
- * Addr responses stored in different caches
- * per (network, local socket) prevent cross-network node identification.
- * If a node for example is multi-homed under Tor and IPv6,
- * a single cache (or no cache at all) would let an attacker
- * to easily detect that it is the same node by comparing responses.
- * Indexing by local socket prevents leakage when a node has multiple
- * listening addresses on the same network.
- *
- * The used memory equals to 1000 CAddress records (or around 40 bytes) per
- * distinct Network (up to 5) we have/had an inbound peer from,
- * resulting in at most ~196 KB. Every separate local socket may
- * add up to ~196 KB extra.
- */
- std::map<uint64_t, CachedAddrResponse> m_addr_response_caches;
-
- /**
- * Services this instance offers.
- *
- * This data is replicated in each CNode instance we create during peer
- * connection (in ConnectNode()) under a member also called
- * nLocalServices.
- *
- * This data is not marked const, but after being set it should not
- * change. See the note in CNode::nLocalServices documentation.
- *
- * \sa CNode::nLocalServices
- */
- ServiceFlags nLocalServices;
-
- std::unique_ptr<CSemaphore> semOutbound;
- std::unique_ptr<CSemaphore> semAddnode;
- int nMaxConnections;
-
- // How many full-relay (tx, block, addr) outbound peers we want
- int m_max_outbound_full_relay;
-
- // How many block-relay only outbound peers we want
- // We do not relay tx or addr messages with these peers
- int m_max_outbound_block_relay;
-
- int nMaxAddnode;
- int nMaxFeeler;
- int m_max_outbound;
- bool m_use_addrman_outgoing;
- std::atomic<int> nBestHeight;
- CClientUIInterface* clientInterface;
- NetEventsInterface* m_msgproc;
- /** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
- BanMan* m_banman;
-
- /**
- * Addresses that were saved during the previous clean shutdown. We'll
- * attempt to make block-relay-only connections to them.
- */
- std::vector<CAddress> m_anchors;
-
- /** SipHasher seeds for deterministic randomness */
- const uint64_t nSeed0, nSeed1;
-
- /** flag for waking the message processor. */
- bool fMsgProcWake GUARDED_BY(mutexMsgProc);
-
- std::condition_variable condMsgProc;
- Mutex mutexMsgProc;
- std::atomic<bool> flagInterruptMsgProc{false};
-
- CThreadInterrupt interruptNet;
-
- std::thread threadDNSAddressSeed;
- std::thread threadSocketHandler;
- std::thread threadOpenAddedConnections;
- std::thread threadOpenConnections;
- std::thread threadMessageHandler;
-
- /** flag for deciding to connect to an extra outbound peer,
- * in excess of m_max_outbound_full_relay
- * This takes the place of a feeler connection */
- std::atomic_bool m_try_another_outbound_peer;
-
- std::atomic<int64_t> m_next_send_inv_to_incoming{0};
-
- /**
- * A vector of -bind=<address>:<port>=onion arguments each of which is
- * an address and port that are designated for incoming Tor connections.
- */
- std::vector<CService> m_onion_binds;
-
- friend struct CConnmanTest;
- friend struct ConnmanTestMsg;
-};
+/** Convert ConnectionType enum to a string value */
+std::string ConnectionTypeAsString(ConnectionType conn_type);
void Discover();
-void StartMapPort();
-void InterruptMapPort();
-void StopMapPort();
uint16_t GetListenPort();
-/**
- * Interface for message handling
- */
-class NetEventsInterface
-{
-public:
- virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
- virtual bool SendMessages(CNode* pnode) = 0;
- virtual void InitializeNode(CNode* pnode) = 0;
- virtual void FinalizeNode(const CNode& node, bool& update_connection_time) = 0;
-
-protected:
- /**
- * Protected destructor so that instances can only be deleted by derived classes.
- * If that restriction is no longer desired, this should be made public and virtual.
- */
- ~NetEventsInterface() = default;
-};
-
enum
{
LOCAL_NONE, // unknown
LOCAL_IF, // address a local interface listens on
LOCAL_BIND, // address explicit bound to
- LOCAL_UPNP, // address reported by UPnP
+ LOCAL_MAPPED, // address reported by UPnP or NAT-PMP
LOCAL_MANUAL, // address explicitly specified (-externalip=)
LOCAL_MAX
@@ -664,7 +214,6 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
extern bool fDiscover;
extern bool fListen;
-extern bool g_relay_txes;
/** Subversion as sent to the P2P network in `version` messages */
extern std::string strSubVersion;
@@ -696,14 +245,14 @@ public:
int nVersion;
std::string cleanSubVer;
bool fInbound;
- bool m_manual_connection;
- int nStartingHeight;
+ bool m_bip152_highbandwidth_to;
+ bool m_bip152_highbandwidth_from;
+ int m_starting_height;
uint64_t nSendBytes;
mapMsgCmdSize mapSendBytesPerMsgCmd;
uint64_t nRecvBytes;
mapMsgCmdSize mapRecvBytesPerMsgCmd;
NetPermissionFlags m_permissionFlags;
- bool m_legacyWhitelisted;
int64_t m_ping_usec;
int64_t m_ping_wait_usec;
int64_t m_min_ping_usec;
@@ -714,14 +263,13 @@ public:
CAddress addr;
// Bind address of our side of the connection
CAddress addrBind;
- // Name of the network the peer connected through
- std::string m_network;
+ // Network the peer connected through
+ Network m_network;
uint32_t m_mapped_as;
- std::string m_conn_type_string;
+ ConnectionType m_conn_type;
};
-
/** Transport protocol agnostic message container.
* Ideally it should only contain receive time, payload,
* command and size.
@@ -846,16 +394,18 @@ public:
std::unique_ptr<TransportDeserializer> m_deserializer;
std::unique_ptr<TransportSerializer> m_serializer;
- // socket
+ NetPermissionFlags m_permissionFlags{PF_NONE};
std::atomic<ServiceFlags> nServices{NODE_NONE};
SOCKET hSocket GUARDED_BY(cs_hSocket);
- size_t nSendSize{0}; // total size of all vSendMsg entries
- size_t nSendOffset{0}; // offset inside the first vSendMsg already sent
+ /** Total size of all vSendMsg entries */
+ size_t nSendSize GUARDED_BY(cs_vSend){0};
+ /** Offset inside the first vSendMsg already sent */
+ size_t nSendOffset GUARDED_BY(cs_vSend){0};
uint64_t nSendBytes GUARDED_BY(cs_vSend){0};
std::deque<std::vector<unsigned char>> vSendMsg GUARDED_BY(cs_vSend);
- RecursiveMutex cs_vSend;
- RecursiveMutex cs_hSocket;
- RecursiveMutex cs_vRecv;
+ Mutex cs_vSend;
+ Mutex cs_hSocket;
+ Mutex cs_vRecv;
RecursiveMutex cs_vProcessMsg;
std::list<CNetMessage> vProcessMsg GUARDED_BY(cs_vProcessMsg);
@@ -884,8 +434,6 @@ public:
bool HasPermission(NetPermissionFlags permission) const {
return NetPermissions::HasFlag(m_permissionFlags, permission);
}
- // This boolean is unusued in actual processing, only present for backward compatibility at RPC/QT level
- bool m_legacyWhitelisted{false};
bool fClient{false}; // set by version message
bool m_limited_node{false}; //after BIP159, set by version message
/**
@@ -947,6 +495,9 @@ public:
/* Whether we send addr messages over this connection */
bool RelayAddrsWithConn() const
{
+ // Don't relay addr messages to peers that we connect to as block-relay-only
+ // peers (to prevent adversaries from inferring these links from addr
+ // traffic).
return m_conn_type != ConnectionType::BLOCK_RELAY;
}
@@ -977,13 +528,10 @@ public:
*/
Network ConnectedThroughNetwork() const;
-protected:
- mapMsgCmdSize mapSendBytesPerMsgCmd;
- mapMsgCmdSize mapRecvBytesPerMsgCmd GUARDED_BY(cs_vRecv);
-
-public:
- uint256 hashContinue;
- std::atomic<int> nStartingHeight{-1};
+ // We selected peer as (compact blocks) high-bandwidth peer (BIP152)
+ std::atomic<bool> m_bip152_highbandwidth_to{false};
+ // Peer selected us as (compact blocks) high-bandwidth peer (BIP152)
+ std::atomic<bool> m_bip152_highbandwidth_from{false};
// flood relay
std::vector<CAddress> vAddrToSend;
@@ -992,12 +540,6 @@ public:
std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0};
std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0};
- // List of block ids we still have announce.
- // There is no final sorting before sending, as they are always sent immediately
- // and in the order requested.
- std::vector<uint256> vInventoryBlockToSend GUARDED_BY(cs_inventory);
- Mutex cs_inventory;
-
struct TxRelay {
mutable RecursiveMutex cs_filter;
// We use fRelayTxes for two purposes -
@@ -1015,12 +557,11 @@ public:
// Used for BIP35 mempool sending
bool fSendMempool GUARDED_BY(cs_tx_inventory){false};
// Last time a "MEMPOOL" request was serviced.
- std::atomic<std::chrono::seconds> m_last_mempool_req{std::chrono::seconds{0}};
+ std::atomic<std::chrono::seconds> m_last_mempool_req{0s};
std::chrono::microseconds nNextInvSend{0};
- RecursiveMutex cs_feeFilter;
- // Minimum fee rate with which to filter inv's to this node
- CAmount minFeeFilter GUARDED_BY(cs_feeFilter){0};
+ /** Minimum fee rate with which to filter inv's to this node */
+ std::atomic<CAmount> minFeeFilter{0};
CAmount lastSentFeeFilter{0};
int64_t nextSendTimeFeeFilter{0};
};
@@ -1028,9 +569,6 @@ public:
// m_tx_relay == nullptr if we're not relaying transactions with this peer
std::unique_ptr<TxRelay> m_tx_relay;
- // Used for headers announcements - unfiltered blocks to relay
- std::vector<uint256> vBlockHashesToAnnounce GUARDED_BY(cs_inventory);
-
/** UNIX epoch time of the last block received from this peer that we had
* not yet seen (e.g. not already received from another peer), that passed
* preliminary validity checks and was saved to disk, even if we don't
@@ -1048,7 +586,7 @@ public:
// The pong reply we're expecting, or 0 if no pong expected.
std::atomic<uint64_t> nPingNonceSent{0};
/** When the last ping was sent, or 0 if no ping was ever sent */
- std::atomic<std::chrono::microseconds> m_ping_start{std::chrono::microseconds{0}};
+ std::atomic<std::chrono::microseconds> m_ping_start{0us};
// Last measured round-trip time.
std::atomic<int64_t> nPingUsecTime{0};
// Best measured round-trip time.
@@ -1056,50 +594,11 @@ public:
// Whether a ping is requested.
std::atomic<bool> fPingQueued{false};
- CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in, bool inbound_onion = false);
+ CNode(NodeId id, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion = false);
~CNode();
CNode(const CNode&) = delete;
CNode& operator=(const CNode&) = delete;
-private:
- const NodeId id;
- const uint64_t nLocalHostNonce;
- const ConnectionType m_conn_type;
- std::atomic<int> m_greatest_common_version{INIT_PROTO_VERSION};
-
- //! Services offered to this peer.
- //!
- //! This is supplied by the parent CConnman during peer connection
- //! (CConnman::ConnectNode()) from its attribute of the same name.
- //!
- //! This is const because there is no protocol defined for renegotiating
- //! services initially offered to a peer. The set of local services we
- //! offer should not change after initialization.
- //!
- //! An interesting example of this is NODE_NETWORK and initial block
- //! download: a node which starts up from scratch doesn't have any blocks
- //! to serve, but still advertises NODE_NETWORK because it will eventually
- //! fulfill this role after IBD completes. P2P code is written in such a
- //! way that it can gracefully handle peers who don't make good on their
- //! service advertisements.
- const ServiceFlags nLocalServices;
-
- const int nMyStartingHeight;
- NetPermissionFlags m_permissionFlags{ PF_NONE };
- std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread
-
- mutable RecursiveMutex cs_addrName;
- std::string addrName GUARDED_BY(cs_addrName);
-
- // Our address, as reported by the peer
- CService addrLocal GUARDED_BY(cs_addrLocal);
- mutable RecursiveMutex cs_addrLocal;
-
- //! Whether this peer connected via our Tor onion service.
- const bool m_inbound_onion{false};
-
-public:
-
NodeId GetId() const {
return id;
}
@@ -1108,10 +607,6 @@ public:
return nLocalHostNonce;
}
- int GetMyStartingHeight() const {
- return nMyStartingHeight;
- }
-
int GetRefCount() const
{
assert(nRefCount >= 0);
@@ -1131,6 +626,7 @@ public:
void SetCommonVersion(int greatest_common_version)
{
+ Assume(m_greatest_common_version == INIT_PROTO_VERSION);
m_greatest_common_version = greatest_common_version;
}
int GetCommonVersion() const
@@ -1153,26 +649,29 @@ public:
nRefCount--;
}
-
-
void AddAddressKnown(const CAddress& _addr)
{
assert(m_addr_known);
m_addr_known->insert(_addr.GetKey());
}
- void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand)
+ /**
+ * Whether the peer supports the address. For example, a peer that does not
+ * implement BIP155 cannot receive Tor v3 addresses because it requires
+ * ADDRv2 (BIP155) encoding.
+ */
+ bool IsAddrCompatible(const CAddress& addr) const
{
- // Whether the peer supports the address in `_addr`. For example,
- // nodes that do not implement BIP155 cannot receive Tor v3 addresses
- // because they require ADDRv2 (BIP155) encoding.
- const bool addr_format_supported = m_wants_addrv2 || _addr.IsAddrV1Compatible();
+ return m_wants_addrv2 || addr.IsAddrV1Compatible();
+ }
+ void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand)
+ {
// Known checking here is only to save space from duplicates.
// SendMessages will filter it again for knowns that were added
// after addresses were pushed.
assert(m_addr_known);
- if (_addr.IsValid() && !m_addr_known->contains(_addr.GetKey()) && addr_format_supported) {
+ if (_addr.IsValid() && !m_addr_known->contains(_addr.GetKey()) && IsAddrCompatible(_addr)) {
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr;
} else {
@@ -1181,7 +680,6 @@ public:
}
}
-
void AddKnownTx(const uint256& hash)
{
if (m_tx_relay != nullptr) {
@@ -1212,7 +710,505 @@ public:
//! Sets the addrName only if it was not previously set
void MaybeSetAddrName(const std::string& addrNameIn);
- std::string ConnectionTypeAsString() const;
+ std::string ConnectionTypeAsString() const { return ::ConnectionTypeAsString(m_conn_type); }
+
+ /** Whether this peer is an inbound onion, e.g. connected via our Tor onion service. */
+ bool IsInboundOnion() const { return m_inbound_onion; }
+
+private:
+ const NodeId id;
+ const uint64_t nLocalHostNonce;
+ const ConnectionType m_conn_type;
+ std::atomic<int> m_greatest_common_version{INIT_PROTO_VERSION};
+
+ //! Services offered to this peer.
+ //!
+ //! This is supplied by the parent CConnman during peer connection
+ //! (CConnman::ConnectNode()) from its attribute of the same name.
+ //!
+ //! This is const because there is no protocol defined for renegotiating
+ //! services initially offered to a peer. The set of local services we
+ //! offer should not change after initialization.
+ //!
+ //! An interesting example of this is NODE_NETWORK and initial block
+ //! download: a node which starts up from scratch doesn't have any blocks
+ //! to serve, but still advertises NODE_NETWORK because it will eventually
+ //! fulfill this role after IBD completes. P2P code is written in such a
+ //! way that it can gracefully handle peers who don't make good on their
+ //! service advertisements.
+ const ServiceFlags nLocalServices;
+
+ std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread
+
+ mutable RecursiveMutex cs_addrName;
+ std::string addrName GUARDED_BY(cs_addrName);
+
+ // Our address, as reported by the peer
+ CService addrLocal GUARDED_BY(cs_addrLocal);
+ mutable RecursiveMutex cs_addrLocal;
+
+ //! Whether this peer is an inbound onion, e.g. connected via our Tor onion service.
+ const bool m_inbound_onion{false};
+
+ mapMsgCmdSize mapSendBytesPerMsgCmd GUARDED_BY(cs_vSend);
+ mapMsgCmdSize mapRecvBytesPerMsgCmd GUARDED_BY(cs_vRecv);
+};
+
+/**
+ * Interface for message handling
+ */
+class NetEventsInterface
+{
+public:
+ virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
+ virtual bool SendMessages(CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_sendProcessing) = 0;
+ virtual void InitializeNode(CNode* pnode) = 0;
+ virtual void FinalizeNode(const CNode& node, bool& update_connection_time) = 0;
+
+protected:
+ /**
+ * Protected destructor so that instances can only be deleted by derived classes.
+ * If that restriction is no longer desired, this should be made public and virtual.
+ */
+ ~NetEventsInterface() = default;
+};
+
+class CConnman
+{
+public:
+
+ enum NumConnections {
+ CONNECTIONS_NONE = 0,
+ CONNECTIONS_IN = (1U << 0),
+ CONNECTIONS_OUT = (1U << 1),
+ CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT),
+ };
+
+ struct Options
+ {
+ ServiceFlags nLocalServices = NODE_NONE;
+ int nMaxConnections = 0;
+ int m_max_outbound_full_relay = 0;
+ int m_max_outbound_block_relay = 0;
+ int nMaxAddnode = 0;
+ int nMaxFeeler = 0;
+ CClientUIInterface* uiInterface = nullptr;
+ NetEventsInterface* m_msgproc = nullptr;
+ BanMan* m_banman = nullptr;
+ unsigned int nSendBufferMaxSize = 0;
+ unsigned int nReceiveFloodSize = 0;
+ uint64_t nMaxOutboundLimit = 0;
+ int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT;
+ std::vector<std::string> vSeedNodes;
+ std::vector<NetWhitelistPermissions> vWhitelistedRange;
+ std::vector<NetWhitebindPermissions> vWhiteBinds;
+ std::vector<CService> vBinds;
+ std::vector<CService> onion_binds;
+ bool m_use_addrman_outgoing = true;
+ std::vector<std::string> m_specified_outgoing;
+ std::vector<std::string> m_added_nodes;
+ std::vector<bool> m_asmap;
+ };
+
+ void Init(const Options& connOptions) {
+ nLocalServices = connOptions.nLocalServices;
+ nMaxConnections = connOptions.nMaxConnections;
+ m_max_outbound_full_relay = std::min(connOptions.m_max_outbound_full_relay, connOptions.nMaxConnections);
+ m_max_outbound_block_relay = connOptions.m_max_outbound_block_relay;
+ m_use_addrman_outgoing = connOptions.m_use_addrman_outgoing;
+ nMaxAddnode = connOptions.nMaxAddnode;
+ nMaxFeeler = connOptions.nMaxFeeler;
+ m_max_outbound = m_max_outbound_full_relay + m_max_outbound_block_relay + nMaxFeeler;
+ clientInterface = connOptions.uiInterface;
+ m_banman = connOptions.m_banman;
+ m_msgproc = connOptions.m_msgproc;
+ nSendBufferMaxSize = connOptions.nSendBufferMaxSize;
+ nReceiveFloodSize = connOptions.nReceiveFloodSize;
+ m_peer_connect_timeout = connOptions.m_peer_connect_timeout;
+ {
+ LOCK(cs_totalBytesSent);
+ nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
+ }
+ vWhitelistedRange = connOptions.vWhitelistedRange;
+ {
+ LOCK(cs_vAddedNodes);
+ vAddedNodes = connOptions.m_added_nodes;
+ }
+ m_onion_binds = connOptions.onion_binds;
+ }
+
+ CConnman(uint64_t seed0, uint64_t seed1, bool network_active = true);
+ ~CConnman();
+ bool Start(CScheduler& scheduler, const Options& options);
+
+ void StopThreads();
+ void StopNodes();
+ void Stop()
+ {
+ StopThreads();
+ StopNodes();
+ };
+
+ void Interrupt();
+ bool GetNetworkActive() const { return fNetworkActive; };
+ bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };
+ void SetNetworkActive(bool active);
+ void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* strDest, ConnectionType conn_type);
+ bool CheckIncomingNonce(uint64_t nonce);
+
+ bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func);
+
+ void PushMessage(CNode* pnode, CSerializedNetMsg&& msg);
+
+ using NodeFn = std::function<void(CNode*)>;
+ void ForEachNode(const NodeFn& func)
+ {
+ LOCK(cs_vNodes);
+ for (auto&& node : vNodes) {
+ if (NodeFullyConnected(node))
+ func(node);
+ }
+ };
+
+ void ForEachNode(const NodeFn& func) const
+ {
+ LOCK(cs_vNodes);
+ for (auto&& node : vNodes) {
+ if (NodeFullyConnected(node))
+ func(node);
+ }
+ };
+
+ template<typename Callable, typename CallableAfter>
+ void ForEachNodeThen(Callable&& pre, CallableAfter&& post)
+ {
+ LOCK(cs_vNodes);
+ for (auto&& node : vNodes) {
+ if (NodeFullyConnected(node))
+ pre(node);
+ }
+ post();
+ };
+
+ template<typename Callable, typename CallableAfter>
+ void ForEachNodeThen(Callable&& pre, CallableAfter&& post) const
+ {
+ LOCK(cs_vNodes);
+ for (auto&& node : vNodes) {
+ if (NodeFullyConnected(node))
+ pre(node);
+ }
+ post();
+ };
+
+ // Addrman functions
+ void SetServices(const CService &addr, ServiceFlags nServices);
+ void MarkAddressGood(const CAddress& addr);
+ bool AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
+ std::vector<CAddress> GetAddresses(size_t max_addresses, size_t max_pct);
+ /**
+ * Cache is used to minimize topology leaks, so it should
+ * be used for all non-trusted calls, for example, p2p.
+ * A non-malicious call (from RPC or a peer with addr permission) should
+ * call the function without a parameter to avoid using the cache.
+ */
+ std::vector<CAddress> GetAddresses(CNode& requestor, size_t max_addresses, size_t max_pct);
+
+ // This allows temporarily exceeding m_max_outbound_full_relay, with the goal of finding
+ // a peer that is better than all our current peers.
+ void SetTryNewOutboundPeer(bool flag);
+ bool GetTryNewOutboundPeer();
+
+ void StartExtraBlockRelayPeers() {
+ LogPrint(BCLog::NET, "net: enabling extra block-relay-only peers\n");
+ m_start_extra_block_relay_peers = true;
+ }
+
+ // Return the number of outbound peers we have in excess of our target (eg,
+ // if we previously called SetTryNewOutboundPeer(true), and have since set
+ // to false, we may have extra peers that we wish to disconnect). This may
+ // return a value less than (num_outbound_connections - num_outbound_slots)
+ // in cases where some outbound connections are not yet fully connected, or
+ // not yet fully disconnected.
+ int GetExtraFullOutboundCount();
+ // Count the number of block-relay-only peers we have over our limit.
+ int GetExtraBlockRelayCount();
+
+ bool AddNode(const std::string& node);
+ bool RemoveAddedNode(const std::string& node);
+ std::vector<AddedNodeInfo> GetAddedNodeInfo();
+
+ /**
+ * Attempts to open a connection. Currently only used from tests.
+ *
+ * @param[in] address Address of node to try connecting to
+ * @param[in] conn_type ConnectionType::OUTBOUND or ConnectionType::BLOCK_RELAY
+ * @return bool Returns false if there are no available
+ * slots for this connection:
+ * - conn_type not a supported ConnectionType
+ * - Max total outbound connection capacity filled
+ * - Max connection capacity for type is filled
+ */
+ bool AddConnection(const std::string& address, ConnectionType conn_type);
+
+ size_t GetNodeCount(NumConnections num);
+ void GetNodeStats(std::vector<CNodeStats>& vstats);
+ bool DisconnectNode(const std::string& node);
+ bool DisconnectNode(const CSubNet& subnet);
+ bool DisconnectNode(const CNetAddr& addr);
+ bool DisconnectNode(NodeId id);
+
+ //! Used to convey which local services we are offering peers during node
+ //! connection.
+ //!
+ //! The data returned by this is used in CNode construction,
+ //! which is used to advertise which services we are offering
+ //! that peer during `net_processing.cpp:PushNodeVersion()`.
+ ServiceFlags GetLocalServices() const;
+
+ uint64_t GetMaxOutboundTarget();
+ std::chrono::seconds GetMaxOutboundTimeframe();
+
+ //! check if the outbound target is reached
+ //! if param historicalBlockServingLimit is set true, the function will
+ //! response true if the limit for serving historical blocks has been reached
+ bool OutboundTargetReached(bool historicalBlockServingLimit);
+
+ //! response the bytes left in the current max outbound cycle
+ //! in case of no limit, it will always response 0
+ uint64_t GetOutboundTargetBytesLeft();
+
+ //! returns the time left in the current max outbound cycle
+ //! in case of no limit, it will always return 0
+ std::chrono::seconds GetMaxOutboundTimeLeftInCycle();
+
+ uint64_t GetTotalBytesRecv();
+ uint64_t GetTotalBytesSent();
+
+ /** Get a unique deterministic randomizer. */
+ CSipHasher GetDeterministicRandomizer(uint64_t id) const;
+
+ unsigned int GetReceiveFloodSize() const;
+
+ void WakeMessageHandler();
+
+ /** Attempts to obfuscate tx time through exponentially distributed emitting.
+ Works assuming that a single interval is used.
+ Variable intervals will result in privacy decrease.
+ */
+ int64_t PoissonNextSendInbound(int64_t now, int average_interval_seconds);
+
+ void SetAsmap(std::vector<bool> asmap) { addrman.m_asmap = std::move(asmap); }
+
+private:
+ struct ListenSocket {
+ public:
+ SOCKET socket;
+ inline void AddSocketPermissionFlags(NetPermissionFlags& flags) const { NetPermissions::AddFlag(flags, m_permissions); }
+ ListenSocket(SOCKET socket_, NetPermissionFlags permissions_) : socket(socket_), m_permissions(permissions_) {}
+ private:
+ NetPermissionFlags m_permissions;
+ };
+
+ bool BindListenPort(const CService& bindAddr, bilingual_str& strError, NetPermissionFlags permissions);
+ bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions);
+ bool InitBinds(
+ const std::vector<CService>& binds,
+ const std::vector<NetWhitebindPermissions>& whiteBinds,
+ const std::vector<CService>& onion_binds);
+
+ void ThreadOpenAddedConnections();
+ void AddAddrFetch(const std::string& strDest);
+ void ProcessAddrFetch();
+ void ThreadOpenConnections(std::vector<std::string> connect);
+ void ThreadMessageHandler();
+ void AcceptConnection(const ListenSocket& hListenSocket);
+ void DisconnectNodes();
+ void NotifyNumConnectionsChanged();
+ void InactivityCheck(CNode *pnode) const;
+ bool GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
+ void SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
+ void SocketHandler();
+ void ThreadSocketHandler();
+ void ThreadDNSAddressSeed();
+
+ uint64_t CalculateKeyedNetGroup(const CAddress& ad) const;
+
+ CNode* FindNode(const CNetAddr& ip);
+ CNode* FindNode(const CSubNet& subNet);
+ CNode* FindNode(const std::string& addrName);
+ CNode* FindNode(const CService& addr);
+
+ /**
+ * Determine whether we're already connected to a given address, in order to
+ * avoid initiating duplicate connections.
+ */
+ bool AlreadyConnectedToAddress(const CAddress& addr);
+
+ bool AttemptToEvictConnection();
+ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type);
+ void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const;
+
+ void DeleteNode(CNode* pnode);
+
+ NodeId GetNewNodeId();
+
+ size_t SocketSendData(CNode& node) const EXCLUSIVE_LOCKS_REQUIRED(node.cs_vSend);
+ void DumpAddresses();
+
+ // Network stats
+ void RecordBytesRecv(uint64_t bytes);
+ void RecordBytesSent(uint64_t bytes);
+
+ /**
+ * Return vector of current BLOCK_RELAY peers.
+ */
+ std::vector<CAddress> GetCurrentBlockRelayOnlyConns() const;
+
+ // Whether the node should be passed out in ForEach* callbacks
+ static bool NodeFullyConnected(const CNode* pnode);
+
+ // Network usage totals
+ RecursiveMutex cs_totalBytesRecv;
+ RecursiveMutex cs_totalBytesSent;
+ uint64_t nTotalBytesRecv GUARDED_BY(cs_totalBytesRecv) {0};
+ uint64_t nTotalBytesSent GUARDED_BY(cs_totalBytesSent) {0};
+
+ // outbound limit & stats
+ uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent) {0};
+ std::chrono::seconds nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent) {0};
+ uint64_t nMaxOutboundLimit GUARDED_BY(cs_totalBytesSent);
+
+ // P2P timeout in seconds
+ int64_t m_peer_connect_timeout;
+
+ // Whitelisted ranges. Any node connecting from these is automatically
+ // whitelisted (as well as those connecting to whitelisted binds).
+ std::vector<NetWhitelistPermissions> vWhitelistedRange;
+
+ unsigned int nSendBufferMaxSize{0};
+ unsigned int nReceiveFloodSize{0};
+
+ std::vector<ListenSocket> vhListenSocket;
+ std::atomic<bool> fNetworkActive{true};
+ bool fAddressesInitialized{false};
+ CAddrMan addrman;
+ std::deque<std::string> m_addr_fetches GUARDED_BY(m_addr_fetches_mutex);
+ RecursiveMutex m_addr_fetches_mutex;
+ std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes);
+ RecursiveMutex cs_vAddedNodes;
+ std::vector<CNode*> vNodes GUARDED_BY(cs_vNodes);
+ std::list<CNode*> vNodesDisconnected;
+ mutable RecursiveMutex cs_vNodes;
+ std::atomic<NodeId> nLastNodeId{0};
+ unsigned int nPrevNodeCount{0};
+
+ /**
+ * Cache responses to addr requests to minimize privacy leak.
+ * Attack example: scraping addrs in real-time may allow an attacker
+ * to infer new connections of the victim by detecting new records
+ * with fresh timestamps (per self-announcement).
+ */
+ struct CachedAddrResponse {
+ std::vector<CAddress> m_addrs_response_cache;
+ std::chrono::microseconds m_cache_entry_expiration{0};
+ };
+
+ /**
+ * Addr responses stored in different caches
+ * per (network, local socket) prevent cross-network node identification.
+ * If a node for example is multi-homed under Tor and IPv6,
+ * a single cache (or no cache at all) would let an attacker
+ * to easily detect that it is the same node by comparing responses.
+ * Indexing by local socket prevents leakage when a node has multiple
+ * listening addresses on the same network.
+ *
+ * The used memory equals to 1000 CAddress records (or around 40 bytes) per
+ * distinct Network (up to 5) we have/had an inbound peer from,
+ * resulting in at most ~196 KB. Every separate local socket may
+ * add up to ~196 KB extra.
+ */
+ std::map<uint64_t, CachedAddrResponse> m_addr_response_caches;
+
+ /**
+ * Services this instance offers.
+ *
+ * This data is replicated in each CNode instance we create during peer
+ * connection (in ConnectNode()) under a member also called
+ * nLocalServices.
+ *
+ * This data is not marked const, but after being set it should not
+ * change. See the note in CNode::nLocalServices documentation.
+ *
+ * \sa CNode::nLocalServices
+ */
+ ServiceFlags nLocalServices;
+
+ std::unique_ptr<CSemaphore> semOutbound;
+ std::unique_ptr<CSemaphore> semAddnode;
+ int nMaxConnections;
+
+ // How many full-relay (tx, block, addr) outbound peers we want
+ int m_max_outbound_full_relay;
+
+ // How many block-relay only outbound peers we want
+ // We do not relay tx or addr messages with these peers
+ int m_max_outbound_block_relay;
+
+ int nMaxAddnode;
+ int nMaxFeeler;
+ int m_max_outbound;
+ bool m_use_addrman_outgoing;
+ CClientUIInterface* clientInterface;
+ NetEventsInterface* m_msgproc;
+ /** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
+ BanMan* m_banman;
+
+ /**
+ * Addresses that were saved during the previous clean shutdown. We'll
+ * attempt to make block-relay-only connections to them.
+ */
+ std::vector<CAddress> m_anchors;
+
+ /** SipHasher seeds for deterministic randomness */
+ const uint64_t nSeed0, nSeed1;
+
+ /** flag for waking the message processor. */
+ bool fMsgProcWake GUARDED_BY(mutexMsgProc);
+
+ std::condition_variable condMsgProc;
+ Mutex mutexMsgProc;
+ std::atomic<bool> flagInterruptMsgProc{false};
+
+ CThreadInterrupt interruptNet;
+
+ std::thread threadDNSAddressSeed;
+ std::thread threadSocketHandler;
+ std::thread threadOpenAddedConnections;
+ std::thread threadOpenConnections;
+ std::thread threadMessageHandler;
+
+ /** flag for deciding to connect to an extra outbound peer,
+ * in excess of m_max_outbound_full_relay
+ * This takes the place of a feeler connection */
+ std::atomic_bool m_try_another_outbound_peer;
+
+ /** flag for initiating extra block-relay-only peer connections.
+ * this should only be enabled after initial chain sync has occurred,
+ * as these connections are intended to be short-lived and low-bandwidth.
+ */
+ std::atomic_bool m_start_extra_block_relay_peers{false};
+
+ std::atomic<int64_t> m_next_send_inv_to_incoming{0};
+
+ /**
+ * A vector of -bind=<address>:<port>=onion arguments each of which is
+ * an address and port that are designated for incoming Tor connections.
+ */
+ std::vector<CService> m_onion_binds;
+
+ friend struct CConnmanTest;
+ friend struct ConnmanTestMsg;
};
/** Return a timestamp in the future (in microseconds) for exponentially distributed events. */
@@ -1224,4 +1220,21 @@ inline std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now,
return std::chrono::microseconds{PoissonNextSend(now.count(), average_interval.count())};
}
+struct NodeEvictionCandidate
+{
+ NodeId id;
+ int64_t nTimeConnected;
+ int64_t nMinPingUsecTime;
+ int64_t nLastBlockTime;
+ int64_t nLastTXTime;
+ bool fRelevantServices;
+ bool fRelayTxes;
+ bool fBloomFilter;
+ uint64_t nKeyedNetGroup;
+ bool prefer_evict;
+ bool m_is_local;
+};
+
+[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates);
+
#endif // BITCOIN_NET_H
diff --git a/src/net_permissions.cpp b/src/net_permissions.cpp
index d40fdfb113..1fdcd97593 100644
--- a/src/net_permissions.cpp
+++ b/src/net_permissions.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index ec5400c3d8..8f1cb952f2 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -376,17 +376,14 @@ struct CNodeState {
//! Whether this peer is an inbound connection
bool m_is_inbound;
- //! Whether this peer is a manual connection
- bool m_is_manual_connection;
-
//! A rolling bloom filter of all announced tx CInvs to this peer.
CRollingBloomFilter m_recently_announced_invs = CRollingBloomFilter{INVENTORY_MAX_RECENT_RELAY, 0.000001};
//! Whether this peer relays txs via wtxid
bool m_wtxid_relay{false};
- CNodeState(CAddress addrIn, bool is_inbound, bool is_manual)
- : address(addrIn), m_is_inbound(is_inbound), m_is_manual_connection(is_manual)
+ CNodeState(CAddress addrIn, bool is_inbound)
+ : address(addrIn), m_is_inbound(is_inbound)
{
pindexBestKnownBlock = nullptr;
hashLastUnknownBlock.SetNull();
@@ -422,58 +419,6 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
return &it->second;
}
-/**
- * Data structure for an individual peer. This struct is not protected by
- * cs_main since it does not contain validation-critical data.
- *
- * Memory is owned by shared pointers and this object is destructed when
- * the refcount drops to zero.
- *
- * TODO: move most members from CNodeState to this structure.
- * TODO: move remaining application-layer data members from CNode to this structure.
- */
-struct Peer {
- /** Same id as the CNode object for this peer */
- const NodeId m_id{0};
-
- /** Protects misbehavior data members */
- Mutex m_misbehavior_mutex;
- /** Accumulated misbehavior score for this peer */
- int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0};
- /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
- bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
-
- /** Set of txids to reconsider once their parent transactions have been accepted **/
- std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
-
- /** Protects m_getdata_requests **/
- Mutex m_getdata_requests_mutex;
- /** Work queue of items requested by this peer **/
- std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
-
- explicit Peer(NodeId id) : m_id(id) {}
-};
-
-using PeerRef = std::shared_ptr<Peer>;
-
-/**
- * Map of all Peer objects, keyed by peer id. This map is protected
- * by the global g_peer_mutex. Once a shared pointer reference is
- * taken, the lock may be released. Individual fields are protected by
- * their own locks.
- */
-Mutex g_peer_mutex;
-static std::map<NodeId, PeerRef> g_peer_map GUARDED_BY(g_peer_mutex);
-
-/** Get a shared pointer to the Peer object.
- * May return nullptr if the Peer object can't be found. */
-static PeerRef GetPeerRef(NodeId id)
-{
- LOCK(g_peer_mutex);
- auto it = g_peer_map.find(id);
- return it != g_peer_map.end() ? it->second : nullptr;
-}
-
static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
nPreferredDownload -= state->fPreferredDownload;
@@ -484,32 +429,6 @@ static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUS
nPreferredDownload += state->fPreferredDownload;
}
-static void PushNodeVersion(CNode& pnode, CConnman& connman, int64_t nTime)
-{
- // Note that pnode->GetLocalServices() is a reflection of the local
- // services we were offering when the CNode object was created for this
- // peer.
- ServiceFlags nLocalNodeServices = pnode.GetLocalServices();
- uint64_t nonce = pnode.GetLocalNonce();
- int nNodeStartingHeight = pnode.GetMyStartingHeight();
- NodeId nodeid = pnode.GetId();
- CAddress addr = pnode.addr;
-
- CAddress addrYou = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ?
- addr :
- CAddress(CService(), addr.nServices);
- CAddress addrMe = CAddress(CService(), nLocalNodeServices);
-
- connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
- nonce, strSubVersion, nNodeStartingHeight, ::g_relay_txes && pnode.m_tx_relay != nullptr));
-
- if (fLogIPs) {
- LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
- } else {
- LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid);
- }
-}
-
// Returns a bool indicating whether we requested this block.
// Also used if a block was /not/ received and timed out or started with another peer
static bool MarkBlockAsReceived(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
@@ -635,11 +554,15 @@ static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connma
// blocks using compact encodings.
connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [&connman, nCMPCTBLOCKVersion](CNode* pnodeStop){
connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/false, nCMPCTBLOCKVersion));
+ // save BIP152 bandwidth state: we select peer to be low-bandwidth
+ pnodeStop->m_bip152_highbandwidth_to = false;
return true;
});
lNodesAnnouncingHeaderAndIDs.pop_front();
}
connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/true, nCMPCTBLOCKVersion));
+ // save BIP152 bandwidth state: we select peer to be high-bandwidth
+ pfrom->m_bip152_highbandwidth_to = true;
lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId());
return true;
});
@@ -760,6 +683,32 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec
} // namespace
+void PeerManager::PushNodeVersion(CNode& pnode, int64_t nTime)
+{
+ // Note that pnode->GetLocalServices() is a reflection of the local
+ // services we were offering when the CNode object was created for this
+ // peer.
+ ServiceFlags nLocalNodeServices = pnode.GetLocalServices();
+ uint64_t nonce = pnode.GetLocalNonce();
+ const int nNodeStartingHeight{m_best_height};
+ NodeId nodeid = pnode.GetId();
+ CAddress addr = pnode.addr;
+
+ CAddress addrYou = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ?
+ addr :
+ CAddress(CService(), addr.nServices);
+ CAddress addrMe = CAddress(CService(), nLocalNodeServices);
+
+ m_connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
+ nonce, strSubVersion, nNodeStartingHeight, !m_ignore_incoming_txs && pnode.m_tx_relay != nullptr));
+
+ if (fLogIPs) {
+ LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
+ } else {
+ LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid);
+ }
+}
+
void PeerManager::AddTxAnnouncement(const CNode& node, const GenTxid& gtxid, std::chrono::microseconds current_time)
{
AssertLockHeld(::cs_main); // For m_txrequest
@@ -802,16 +751,16 @@ void PeerManager::InitializeNode(CNode *pnode) {
NodeId nodeid = pnode->GetId();
{
LOCK(cs_main);
- mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, pnode->IsInboundConn(), pnode->IsManualConn()));
+ mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, pnode->IsInboundConn()));
assert(m_txrequest.Count(nodeid) == 0);
}
{
PeerRef peer = std::make_shared<Peer>(nodeid);
- LOCK(g_peer_mutex);
- g_peer_map.emplace_hint(g_peer_map.end(), nodeid, std::move(peer));
+ LOCK(m_peer_mutex);
+ m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer));
}
if (!pnode->IsInboundConn()) {
- PushNodeVersion(*pnode, m_connman, GetTime());
+ PushNodeVersion(*pnode, GetTime());
}
}
@@ -842,11 +791,14 @@ void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) {
LOCK(cs_main);
int misbehavior{0};
{
- PeerRef peer = GetPeerRef(nodeid);
+ // We remove the PeerRef from g_peer_map here, but we don't always
+ // destruct the Peer. Sometimes another thread is still holding a
+ // PeerRef, so the refcount is >= 1. Be careful not to do any
+ // processing here that assumes Peer won't be changed before it's
+ // destructed.
+ PeerRef peer = RemovePeer(nodeid);
assert(peer != nullptr);
misbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->m_misbehavior_score);
- LOCK(g_peer_mutex);
- g_peer_map.erase(nodeid);
}
CNodeState *state = State(nodeid);
assert(state != nullptr);
@@ -887,7 +839,26 @@ void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) {
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
}
-bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
+PeerRef PeerManager::GetPeerRef(NodeId id) const
+{
+ LOCK(m_peer_mutex);
+ auto it = m_peer_map.find(id);
+ return it != m_peer_map.end() ? it->second : nullptr;
+}
+
+PeerRef PeerManager::RemovePeer(NodeId id)
+{
+ PeerRef ret;
+ LOCK(m_peer_mutex);
+ auto it = m_peer_map.find(id);
+ if (it != m_peer_map.end()) {
+ ret = std::move(it->second);
+ m_peer_map.erase(it);
+ }
+ return ret;
+}
+
+bool PeerManager::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
{
LOCK(cs_main);
CNodeState* state = State(nodeid);
@@ -903,7 +874,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
PeerRef peer = GetPeerRef(nodeid);
if (peer == nullptr) return false;
- stats.m_misbehavior_score = WITH_LOCK(peer->m_misbehavior_mutex, return peer->m_misbehavior_score);
+ stats.m_starting_height = peer->m_starting_height;
return true;
}
@@ -1085,8 +1056,8 @@ bool PeerManager::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationSt
}
// Discourage outbound (but not inbound) peers if on an invalid chain.
- // Exempt HB compact block peers and manual connections.
- if (!via_compact_block && !node_state->m_is_inbound && !node_state->m_is_manual_connection) {
+ // Exempt HB compact block peers. Manual connections are always protected from discouragement.
+ if (!via_compact_block && !node_state->m_is_inbound) {
Misbehaving(nodeid, 100, message);
return true;
}
@@ -1159,13 +1130,15 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para
}
PeerManager::PeerManager(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool)
+ CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
+ bool ignore_incoming_txs)
: m_chainparams(chainparams),
m_connman(connman),
m_banman(banman),
m_chainman(chainman),
m_mempool(pool),
- m_stale_tip_check_time(0)
+ m_stale_tip_check_time(0),
+ m_ignore_incoming_txs(ignore_incoming_txs)
{
// Initialize global variables that cannot be constructed at startup.
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
@@ -1321,35 +1294,39 @@ void PeerManager::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_
* Update our best height and announce any block hashes which weren't previously
* in ::ChainActive() to our peers.
*/
-void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
- const int nNewHeight = pindexNew->nHeight;
- m_connman.SetBestHeight(nNewHeight);
-
+void PeerManager::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
+{
+ m_best_height = pindexNew->nHeight;
SetServiceFlagsIBDCache(!fInitialDownload);
- if (!fInitialDownload) {
- // Find the hashes of all blocks that weren't previously in the best chain.
- std::vector<uint256> vHashes;
- const CBlockIndex *pindexToAnnounce = pindexNew;
- while (pindexToAnnounce != pindexFork) {
- vHashes.push_back(pindexToAnnounce->GetBlockHash());
- pindexToAnnounce = pindexToAnnounce->pprev;
- if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
- // Limit announcements in case of a huge reorganization.
- // Rely on the peer's synchronization mechanism in that case.
- break;
- }
+
+ // Don't relay inventory during initial block download.
+ if (fInitialDownload) return;
+
+ // Find the hashes of all blocks that weren't previously in the best chain.
+ std::vector<uint256> vHashes;
+ const CBlockIndex *pindexToAnnounce = pindexNew;
+ while (pindexToAnnounce != pindexFork) {
+ vHashes.push_back(pindexToAnnounce->GetBlockHash());
+ pindexToAnnounce = pindexToAnnounce->pprev;
+ if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
+ // Limit announcements in case of a huge reorganization.
+ // Rely on the peer's synchronization mechanism in that case.
+ break;
}
- // Relay inventory, but don't relay old inventory during initial block download.
- m_connman.ForEachNode([nNewHeight, &vHashes](CNode* pnode) {
- LOCK(pnode->cs_inventory);
- if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) {
- for (const uint256& hash : reverse_iterate(vHashes)) {
- pnode->vBlockHashesToAnnounce.push_back(hash);
- }
+ }
+
+ {
+ LOCK(m_peer_mutex);
+ for (auto& it : m_peer_map) {
+ Peer& peer = *it.second;
+ LOCK(peer.m_block_inv_mutex);
+ for (const uint256& hash : reverse_iterate(vHashes)) {
+ peer.m_blocks_for_headers_relay.push_back(hash);
}
- });
- m_connman.WakeMessageHandler();
+ }
}
+
+ m_connman.WakeMessageHandler();
}
/**
@@ -1443,7 +1420,23 @@ void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman&
});
}
-static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman& connman)
+/**
+ * Relay (gossip) an address to a few randomly chosen nodes.
+ * We choose the same nodes within a given 24h window (if the list of connected
+ * nodes does not change) and we don't relay to nodes that already know an
+ * address. So within 24h we will likely relay a given address once. This is to
+ * prevent a peer from unjustly giving their address better propagation by sending
+ * it to us repeatedly.
+ * @param[in] originator The peer that sent us the address. We don't want to relay it back.
+ * @param[in] addr Address to relay.
+ * @param[in] fReachable Whether the address' network is reachable. We relay unreachable
+ * addresses less.
+ * @param[in] connman Connection manager to choose nodes to relay to.
+ */
+static void RelayAddress(const CNode& originator,
+ const CAddress& addr,
+ bool fReachable,
+ const CConnman& connman)
{
if (!fReachable && !addr.IsRelayable()) return;
@@ -1460,8 +1453,8 @@ static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman&
std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
assert(nRelayNodes <= best.size());
- auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) {
- if (pnode->RelayAddrsWithConn()) {
+ auto sortfunc = [&best, &hasher, nRelayNodes, &originator, &addr](CNode* pnode) {
+ if (pnode->RelayAddrsWithConn() && pnode != &originator && pnode->IsAddrCompatible(addr)) {
uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
for (unsigned int i = 0; i < nRelayNodes; i++) {
if (hashKey > best[i].first) {
@@ -1482,7 +1475,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman&
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
}
-void static ProcessGetBlockData(CNode& pfrom, const CChainParams& chainparams, const CInv& inv, CConnman& connman)
+void static ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, const CInv& inv, CConnman& connman)
{
bool send = false;
std::shared_ptr<const CBlock> a_recent_block;
@@ -1622,16 +1615,18 @@ void static ProcessGetBlockData(CNode& pfrom, const CChainParams& chainparams, c
}
}
- // Trigger the peer node to send a getblocks request for the next batch of inventory
- if (inv.hash == pfrom.hashContinue)
{
- // Send immediately. This must send even if redundant,
- // and we want it right after the last block so they don't
- // wait for other stuff first.
- std::vector<CInv> vInv;
- vInv.push_back(CInv(MSG_BLOCK, ::ChainActive().Tip()->GetBlockHash()));
- connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
- pfrom.hashContinue.SetNull();
+ LOCK(peer.m_block_inv_mutex);
+ // Trigger the peer node to send a getblocks request for the next batch of inventory
+ if (inv.hash == peer.m_continuation_block) {
+ // Send immediately. This must send even if redundant,
+ // and we want it right after the last block so they don't
+ // wait for other stuff first.
+ std::vector<CInv> vInv;
+ vInv.push_back(CInv(MSG_BLOCK, ::ChainActive().Tip()->GetBlockHash()));
+ connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
+ peer.m_continuation_block.SetNull();
+ }
}
}
}
@@ -1731,7 +1726,7 @@ void static ProcessGetData(CNode& pfrom, Peer& peer, const CChainParams& chainpa
if (it != peer.m_getdata_requests.end() && !pfrom.fPauseSend) {
const CInv &inv = *it++;
if (inv.IsGenBlkMsg()) {
- ProcessGetBlockData(pfrom, chainparams, inv, connman);
+ ProcessGetBlockData(pfrom, peer, chainparams, inv, connman);
}
// else: If the first item on the queue is an unknown type, we erase it
// and continue processing the queue on the next call.
@@ -1781,7 +1776,9 @@ void PeerManager::SendBlockTransactions(CNode& pfrom, const CBlock& block, const
m_connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCKTXN, resp));
}
-void PeerManager::ProcessHeadersMessage(CNode& pfrom, const std::vector<CBlockHeader>& headers, bool via_compact_block)
+void PeerManager::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
+ const std::vector<CBlockHeader>& headers,
+ bool via_compact_block)
{
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
size_t nCount = headers.size();
@@ -1871,7 +1868,8 @@ void PeerManager::ProcessHeadersMessage(CNode& pfrom, const std::vector<CBlockHe
// Headers message had its maximum size; the peer may have more headers.
// TODO: optimize: if pindexLast is an ancestor of ::ChainActive().Tip or pindexBestHeader, continue
// from there instead.
- LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom.GetId(), pfrom.nStartingHeight);
+ LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
+ pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexLast), uint256()));
}
@@ -2274,20 +2272,13 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
const std::atomic<bool>& interruptMsgProc)
{
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom.GetId());
- if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0)
- {
- LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
- return;
- }
PeerRef peer = GetPeerRef(pfrom.GetId());
if (peer == nullptr) return;
if (msg_type == NetMsgType::VERSION) {
- // Each connection can only send one version message
- if (pfrom.nVersion != 0)
- {
- Misbehaving(pfrom.GetId(), 1, "redundant version message");
+ if (pfrom.nVersion != 0) {
+ LogPrint(BCLog::NET, "redundant version message from peer=%d\n", pfrom.GetId());
return;
}
@@ -2299,7 +2290,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
ServiceFlags nServices;
int nVersion;
std::string cleanSubVer;
- int nStartingHeight = -1;
+ int starting_height = -1;
bool fRelay = true;
vRecv >> nVersion >> nServiceInt >> nTime >> addrMe;
@@ -2330,7 +2321,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
cleanSubVer = SanitizeString(strSubVer);
}
if (!vRecv.empty()) {
- vRecv >> nStartingHeight;
+ vRecv >> starting_height;
}
if (!vRecv.empty())
vRecv >> fRelay;
@@ -2347,9 +2338,9 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
SeenLocal(addrMe);
}
- // Be shy and don't send version until we hear
- if (pfrom.IsInboundConn())
- PushNodeVersion(pfrom, m_connman, GetAdjustedTime());
+ // Inbound peers send us their version message when they connect.
+ // We send our version message in response.
+ if (pfrom.IsInboundConn()) PushNodeVersion(pfrom, GetAdjustedTime());
// Change version
const int greatest_common_version = std::min(nVersion, PROTOCOL_VERSION);
@@ -2362,10 +2353,16 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::WTXIDRELAY));
}
- m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
-
// Signal ADDRv2 support (BIP155).
- m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
+ if (greatest_common_version >= 70016) {
+ // BIP155 defines addrv2 and sendaddrv2 for all protocol versions, but some
+ // implementations reject messages they don't know. As a courtesy, don't send
+ // it to nodes with a version before 70016, as no software is known to support
+ // BIP155 that doesn't announce at least that protocol version number.
+ m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
+ }
+
+ m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
pfrom.nServices = nServices;
pfrom.SetAddrLocal(addrMe);
@@ -2373,7 +2370,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
LOCK(pfrom.cs_SubVer);
pfrom.cleanSubVer = cleanSubVer;
}
- pfrom.nStartingHeight = nStartingHeight;
+ peer->m_starting_height = starting_height;
// set nodes not relaying blocks and tx and not serving (parts) of the historical blockchain as "clients"
pfrom.fClient = (!(nServices & NODE_NETWORK) && !(nServices & NODE_NETWORK_LIMITED));
@@ -2407,8 +2404,8 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// empty and no one will know who we are, so these mechanisms are
// important to help us connect to the network.
//
- // We skip this for BLOCK_RELAY peers to avoid potentially leaking
- // information about our BLOCK_RELAY connections via address relay.
+ // We skip this for block-relay-only peers to avoid potentially leaking
+ // information about our block-relay-only connections via address relay.
if (fListen && !::ChainstateActive().IsInitialBlockDownload())
{
CAddress addr = GetLocalAddress(&pfrom.addr, pfrom.GetLocalServices());
@@ -2453,7 +2450,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
LogPrint(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n",
cleanSubVer, pfrom.nVersion,
- pfrom.nStartingHeight, addrMe.ToString(), pfrom.GetId(),
+ peer->m_starting_height, addrMe.ToString(), pfrom.GetId(),
remoteAddr);
int64_t nTimeOffset = nTime - GetTime();
@@ -2475,7 +2472,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
if (pfrom.nVersion == 0) {
// Must have a version message before anything else
- Misbehaving(pfrom.GetId(), 1, "non-version message before version handshake");
+ LogPrint(BCLog::NET, "non-version message before version handshake. Message \"%s\" from peer=%d\n", SanitizeString(msg_type), pfrom.GetId());
return;
}
@@ -2487,9 +2484,9 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
if (!pfrom.IsInboundConn()) {
LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
- pfrom.nVersion.load(), pfrom.nStartingHeight,
+ pfrom.nVersion.load(), peer->m_starting_height,
pfrom.GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom.addr.ToString()) : ""),
- pfrom.m_tx_relay == nullptr ? "block-relay" : "full-relay");
+ pfrom.ConnectionTypeAsString());
}
if (pfrom.GetCommonVersion() >= SENDHEADERS_VERSION) {
@@ -2516,8 +2513,41 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
- // Feature negotiation of wtxidrelay should happen between VERSION and
- // VERACK, to avoid relay problems from switching after a connection is up
+ if (msg_type == NetMsgType::SENDHEADERS) {
+ LOCK(cs_main);
+ State(pfrom.GetId())->fPreferHeaders = true;
+ return;
+ }
+
+ if (msg_type == NetMsgType::SENDCMPCT) {
+ bool fAnnounceUsingCMPCTBLOCK = false;
+ uint64_t nCMPCTBLOCKVersion = 0;
+ vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
+ if (nCMPCTBLOCKVersion == 1 || ((pfrom.GetLocalServices() & NODE_WITNESS) && nCMPCTBLOCKVersion == 2)) {
+ LOCK(cs_main);
+ // fProvidesHeaderAndIDs is used to "lock in" version of compact blocks we send (fWantsCmpctWitness)
+ if (!State(pfrom.GetId())->fProvidesHeaderAndIDs) {
+ State(pfrom.GetId())->fProvidesHeaderAndIDs = true;
+ State(pfrom.GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
+ }
+ if (State(pfrom.GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) { // ignore later version announces
+ State(pfrom.GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
+ // save whether peer selects us as BIP152 high-bandwidth peer
+ // (receiving sendcmpct(1) signals high-bandwidth, sendcmpct(0) low-bandwidth)
+ pfrom.m_bip152_highbandwidth_from = fAnnounceUsingCMPCTBLOCK;
+ }
+ if (!State(pfrom.GetId())->fSupportsDesiredCmpctVersion) {
+ if (pfrom.GetLocalServices() & NODE_WITNESS)
+ State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
+ else
+ State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
+ }
+ }
+ return;
+ }
+
+ // Feature negotiation of wtxidrelay must happen between VERSION and VERACK
+ // to avoid relay problems from switching after a connection is up.
if (msg_type == NetMsgType::WTXIDRELAY) {
if (pfrom.fSuccessfullyConnected) {
// Disconnect peers that send wtxidrelay message after VERACK; this
@@ -2535,6 +2565,17 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
+ if (msg_type == NetMsgType::SENDADDRV2) {
+ if (pfrom.fSuccessfullyConnected) {
+ // Disconnect peers that send SENDADDRV2 message after VERACK; this
+ // must be negotiated between VERSION and VERACK.
+ pfrom.fDisconnect = true;
+ return;
+ }
+ pfrom.m_wants_addrv2 = true;
+ return;
+ }
+
if (!pfrom.fSuccessfullyConnected) {
LogPrint(BCLog::NET, "Unsupported message \"%s\" prior to verack from peer=%d\n", SanitizeString(msg_type), pfrom.GetId());
return;
@@ -2588,7 +2629,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
if (addr.nTime > nSince && !pfrom.fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
{
// Relay to a limited number of other nodes
- RelayAddress(addr, fReachable, m_connman);
+ RelayAddress(pfrom, addr, fReachable, m_connman);
}
// Do not store addresses outside our network
if (fReachable)
@@ -2602,40 +2643,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
- if (msg_type == NetMsgType::SENDADDRV2) {
- pfrom.m_wants_addrv2 = true;
- return;
- }
-
- if (msg_type == NetMsgType::SENDHEADERS) {
- LOCK(cs_main);
- State(pfrom.GetId())->fPreferHeaders = true;
- return;
- }
-
- if (msg_type == NetMsgType::SENDCMPCT) {
- bool fAnnounceUsingCMPCTBLOCK = false;
- uint64_t nCMPCTBLOCKVersion = 0;
- vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
- if (nCMPCTBLOCKVersion == 1 || ((pfrom.GetLocalServices() & NODE_WITNESS) && nCMPCTBLOCKVersion == 2)) {
- LOCK(cs_main);
- // fProvidesHeaderAndIDs is used to "lock in" version of compact blocks we send (fWantsCmpctWitness)
- if (!State(pfrom.GetId())->fProvidesHeaderAndIDs) {
- State(pfrom.GetId())->fProvidesHeaderAndIDs = true;
- State(pfrom.GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
- }
- if (State(pfrom.GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) // ignore later version announces
- State(pfrom.GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
- if (!State(pfrom.GetId())->fSupportsDesiredCmpctVersion) {
- if (pfrom.GetLocalServices() & NODE_WITNESS)
- State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
- else
- State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
- }
- }
- return;
- }
-
if (msg_type == NetMsgType::INV) {
std::vector<CInv> vInv;
vRecv >> vInv;
@@ -2647,7 +2654,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// We won't accept tx inv's if we're in blocks-only mode, or this is a
// block-relay-only peer
- bool fBlocksOnly = !g_relay_txes || (pfrom.m_tx_relay == nullptr);
+ bool fBlocksOnly = m_ignore_incoming_txs || (pfrom.m_tx_relay == nullptr);
// Allow peers with relay permission to send data other than blocks in blocks only mode
if (pfrom.HasPermission(PF_RELAY)) {
@@ -2789,13 +2796,12 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
break;
}
- WITH_LOCK(pfrom.cs_inventory, pfrom.vInventoryBlockToSend.push_back(pindex->GetBlockHash()));
- if (--nLimit <= 0)
- {
+ WITH_LOCK(peer->m_block_inv_mutex, peer->m_blocks_for_inv_relay.push_back(pindex->GetBlockHash()));
+ if (--nLimit <= 0) {
// When this block is requested, we'll send an inv that'll
// trigger the peer to getblocks the next batch of inventory.
LogPrint(BCLog::NET, " getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
- pfrom.hashContinue = pindex->GetBlockHash();
+ WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
break;
}
}
@@ -2924,7 +2930,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// Stop processing the transaction early if
// 1) We are in blocks only mode and peer has no relay permission
// 2) This peer is a block-relay-only peer
- if ((!g_relay_txes && !pfrom.HasPermission(PF_RELAY)) || (pfrom.m_tx_relay == nullptr))
+ if ((m_ignore_incoming_txs && !pfrom.HasPermission(PF_RELAY)) || (pfrom.m_tx_relay == nullptr))
{
LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom.GetId());
pfrom.fDisconnect = true;
@@ -3319,7 +3325,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// the peer if the header turns out to be for an invalid block.
// Note that if a peer tries to build on an invalid chain, that
// will be detected and the peer will be disconnected/discouraged.
- return ProcessHeadersMessage(pfrom, {cmpctblock.header}, /*via_compact_block=*/true);
+ return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.header}, /*via_compact_block=*/true);
}
if (fBlockReconstructed) {
@@ -3462,7 +3468,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
}
- return ProcessHeadersMessage(pfrom, headers, /*via_compact_block=*/false);
+ return ProcessHeadersMessage(pfrom, *peer, headers, /*via_compact_block=*/false);
}
if (msg_type == NetMsgType::BLOCK)
@@ -3706,7 +3712,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
vRecv >> newFeeFilter;
if (MoneyRange(newFeeFilter)) {
if (pfrom.m_tx_relay != nullptr) {
- LOCK(pfrom.m_tx_relay->cs_feeFilter);
pfrom.m_tx_relay->minFeeFilter = newFeeFilter;
}
LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom.GetId());
@@ -3786,7 +3791,7 @@ bool PeerManager::MaybeDiscourageAndDisconnect(CNode& pnode)
}
// Normal case: Disconnect the peer and discourage all nodes sharing the address
- LogPrintf("Disconnecting and discouraging peer %d!\n", peer_id);
+ LogPrint(BCLog::NET, "Disconnecting and discouraging peer %d!\n", peer_id);
if (m_banman) m_banman->Discourage(pnode.addr);
m_connman.DisconnectNode(pnode.addr);
return true;
@@ -3922,11 +3927,54 @@ void PeerManager::ConsiderEviction(CNode& pto, int64_t time_in_seconds)
void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds)
{
- // Check whether we have too many outbound peers
- int extra_peers = m_connman.GetExtraOutboundCount();
- if (extra_peers > 0) {
- // If we have more outbound peers than we target, disconnect one.
- // Pick the outbound peer that least recently announced
+ // If we have any extra block-relay-only peers, disconnect the youngest unless
+ // it's given us a block -- in which case, compare with the second-youngest, and
+ // out of those two, disconnect the peer who least recently gave us a block.
+ // The youngest block-relay-only peer would be the extra peer we connected
+ // to temporarily in order to sync our tip; see net.cpp.
+ // Note that we use higher nodeid as a measure for most recent connection.
+ if (m_connman.GetExtraBlockRelayCount() > 0) {
+ std::pair<NodeId, int64_t> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
+
+ m_connman.ForEachNode([&](CNode* pnode) {
+ if (!pnode->IsBlockOnlyConn() || pnode->fDisconnect) return;
+ if (pnode->GetId() > youngest_peer.first) {
+ next_youngest_peer = youngest_peer;
+ youngest_peer.first = pnode->GetId();
+ youngest_peer.second = pnode->nLastBlockTime;
+ }
+ });
+ NodeId to_disconnect = youngest_peer.first;
+ if (youngest_peer.second > next_youngest_peer.second) {
+ // Our newest block-relay-only peer gave us a block more recently;
+ // disconnect our second youngest.
+ to_disconnect = next_youngest_peer.first;
+ }
+ m_connman.ForNode(to_disconnect, [&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ AssertLockHeld(::cs_main);
+ // Make sure we're not getting a block right now, and that
+ // we've been connected long enough for this eviction to happen
+ // at all.
+ // Note that we only request blocks from a peer if we learn of a
+ // valid headers chain with at least as much work as our tip.
+ CNodeState *node_state = State(pnode->GetId());
+ if (node_state == nullptr ||
+ (time_in_seconds - pnode->nTimeConnected >= MINIMUM_CONNECT_TIME && node_state->nBlocksInFlight == 0)) {
+ pnode->fDisconnect = true;
+ LogPrint(BCLog::NET, "disconnecting extra block-relay-only peer=%d (last block received at time %d)\n", pnode->GetId(), pnode->nLastBlockTime);
+ return true;
+ } else {
+ LogPrint(BCLog::NET, "keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
+ pnode->GetId(), pnode->nTimeConnected, node_state->nBlocksInFlight);
+ }
+ return false;
+ });
+ }
+
+ // Check whether we have too many outbound-full-relay peers
+ if (m_connman.GetExtraFullOutboundCount() > 0) {
+ // If we have more outbound-full-relay peers than we target, disconnect one.
+ // Pick the outbound-full-relay peer that least recently announced
// us a new block, with ties broken by choosing the more recent
// connection (higher node id)
NodeId worst_peer = -1;
@@ -3935,14 +3983,13 @@ void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds)
m_connman.ForEachNode([&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
AssertLockHeld(::cs_main);
- // Ignore non-outbound peers, or nodes marked for disconnect already
- if (!pnode->IsOutboundOrBlockRelayConn() || pnode->fDisconnect) return;
+ // Only consider outbound-full-relay peers that are not already
+ // marked for disconnection
+ if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
CNodeState *state = State(pnode->GetId());
if (state == nullptr) return; // shouldn't be possible, but just in case
// Don't evict our protected peers
if (state->m_chain_sync.m_protect) return;
- // Don't evict our block-relay-only peers.
- if (pnode->m_tx_relay == nullptr) return;
if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
worst_peer = pnode->GetId();
oldest_block_announcement = state->m_last_block_announcement;
@@ -3998,6 +4045,11 @@ void PeerManager::CheckForStaleTipAndEvictPeers()
}
m_stale_tip_check_time = time_in_seconds + STALE_CHECK_INTERVAL;
}
+
+ if (!m_initial_sync_finished && CanDirectFetch(m_chainparams.GetConsensus())) {
+ m_connman.StartExtraBlockRelayPeers();
+ m_initial_sync_finished = true;
+ }
}
namespace {
@@ -4023,6 +4075,7 @@ public:
bool PeerManager::SendMessages(CNode* pto)
{
+ PeerRef peer = GetPeerRef(pto->GetId());
const Consensus::Params& consensusParams = m_chainparams.GetConsensus();
// We must call MaybeDiscourageAndDisconnect first, to ensure that we'll
@@ -4074,6 +4127,15 @@ bool PeerManager::SendMessages(CNode* pto)
auto current_time = GetTime<std::chrono::microseconds>();
if (pto->RelayAddrsWithConn() && !::ChainstateActive().IsInitialBlockDownload() && pto->m_next_local_addr_send < current_time) {
+ // If we've sent before, clear the bloom filter for the peer, so that our
+ // self-announcement will actually go out.
+ // This might be unnecessary if the bloom filter has already rolled
+ // over since our last self-announcement, but there is only a small
+ // bandwidth cost that we can incur by doing this (which happens
+ // once a day on average).
+ if (pto->m_next_local_addr_send != 0us) {
+ pto->m_addr_known->reset();
+ }
AdvertiseLocal(pto);
pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
@@ -4139,7 +4201,7 @@ bool PeerManager::SendMessages(CNode* pto)
got back an empty response. */
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
- LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), pto->nStartingHeight);
+ LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), peer->m_starting_height);
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexStart), uint256()));
}
}
@@ -4155,11 +4217,11 @@ bool PeerManager::SendMessages(CNode* pto)
// If no header would connect, or if we have too many
// blocks, or if the peer doesn't want headers, just
// add all to the inv queue.
- LOCK(pto->cs_inventory);
+ LOCK(peer->m_block_inv_mutex);
std::vector<CBlock> vHeaders;
bool fRevertToInv = ((!state.fPreferHeaders &&
- (!state.fPreferHeaderAndIDs || pto->vBlockHashesToAnnounce.size() > 1)) ||
- pto->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE);
+ (!state.fPreferHeaderAndIDs || peer->m_blocks_for_headers_relay.size() > 1)) ||
+ peer->m_blocks_for_headers_relay.size() > MAX_BLOCKS_TO_ANNOUNCE);
const CBlockIndex *pBestIndex = nullptr; // last header queued for delivery
ProcessBlockAvailability(pto->GetId()); // ensure pindexBestKnownBlock is up-to-date
@@ -4168,7 +4230,7 @@ bool PeerManager::SendMessages(CNode* pto)
// Try to find first header that our peer doesn't have, and
// then send all headers past that one. If we come across any
// headers that aren't on ::ChainActive(), give up.
- for (const uint256 &hash : pto->vBlockHashesToAnnounce) {
+ for (const uint256& hash : peer->m_blocks_for_headers_relay) {
const CBlockIndex* pindex = LookupBlockIndex(hash);
assert(pindex);
if (::ChainActive()[pindex->nHeight] != pindex) {
@@ -4185,7 +4247,7 @@ bool PeerManager::SendMessages(CNode* pto)
// which should be caught by the prior check), but one
// way this could happen is by using invalidateblock /
// reconsiderblock repeatedly on the tip, causing it to
- // be added multiple times to vBlockHashesToAnnounce.
+ // be added multiple times to m_blocks_for_headers_relay.
// Robustly deal with this rare situation by reverting
// to an inv.
fRevertToInv = true;
@@ -4257,10 +4319,10 @@ bool PeerManager::SendMessages(CNode* pto)
}
if (fRevertToInv) {
// If falling back to using an inv, just try to inv the tip.
- // The last entry in vBlockHashesToAnnounce was our tip at some point
+ // The last entry in m_blocks_for_headers_relay was our tip at some point
// in the past.
- if (!pto->vBlockHashesToAnnounce.empty()) {
- const uint256 &hashToAnnounce = pto->vBlockHashesToAnnounce.back();
+ if (!peer->m_blocks_for_headers_relay.empty()) {
+ const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
const CBlockIndex* pindex = LookupBlockIndex(hashToAnnounce);
assert(pindex);
@@ -4274,13 +4336,13 @@ bool PeerManager::SendMessages(CNode* pto)
// If the peer's chain has this block, don't inv it back.
if (!PeerHasHeader(&state, pindex)) {
- pto->vInventoryBlockToSend.push_back(hashToAnnounce);
+ peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
LogPrint(BCLog::NET, "%s: sending inv peer=%d hash=%s\n", __func__,
pto->GetId(), hashToAnnounce.ToString());
}
}
}
- pto->vBlockHashesToAnnounce.clear();
+ peer->m_blocks_for_headers_relay.clear();
}
//
@@ -4288,18 +4350,18 @@ bool PeerManager::SendMessages(CNode* pto)
//
std::vector<CInv> vInv;
{
- LOCK(pto->cs_inventory);
- vInv.reserve(std::max<size_t>(pto->vInventoryBlockToSend.size(), INVENTORY_BROADCAST_MAX));
+ LOCK(peer->m_block_inv_mutex);
+ vInv.reserve(std::max<size_t>(peer->m_blocks_for_inv_relay.size(), INVENTORY_BROADCAST_MAX));
// Add blocks
- for (const uint256& hash : pto->vInventoryBlockToSend) {
+ for (const uint256& hash : peer->m_blocks_for_inv_relay) {
vInv.push_back(CInv(MSG_BLOCK, hash));
if (vInv.size() == MAX_INV_SZ) {
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
}
}
- pto->vInventoryBlockToSend.clear();
+ peer->m_blocks_for_inv_relay.clear();
if (pto->m_tx_relay != nullptr) {
LOCK(pto->m_tx_relay->cs_tx_inventory);
@@ -4325,11 +4387,7 @@ bool PeerManager::SendMessages(CNode* pto)
if (fSendTrickle && pto->m_tx_relay->fSendMempool) {
auto vtxinfo = m_mempool.infoAll();
pto->m_tx_relay->fSendMempool = false;
- CFeeRate filterrate;
- {
- LOCK(pto->m_tx_relay->cs_feeFilter);
- filterrate = CFeeRate(pto->m_tx_relay->minFeeFilter);
- }
+ const CFeeRate filterrate{pto->m_tx_relay->minFeeFilter.load()};
LOCK(pto->m_tx_relay->cs_filter);
@@ -4363,11 +4421,7 @@ bool PeerManager::SendMessages(CNode* pto)
for (std::set<uint256>::iterator it = pto->m_tx_relay->setInventoryTxToSend.begin(); it != pto->m_tx_relay->setInventoryTxToSend.end(); it++) {
vInvTx.push_back(it);
}
- CFeeRate filterrate;
- {
- LOCK(pto->m_tx_relay->cs_feeFilter);
- filterrate = CFeeRate(pto->m_tx_relay->minFeeFilter);
- }
+ const CFeeRate filterrate{pto->m_tx_relay->minFeeFilter.load()};
// Topologically and fee-rate sort the inventory we send for privacy and priority reasons.
// A heap is used so that not all items need sorting if only a few are being sent.
CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, state.m_wtxid_relay);
@@ -4528,7 +4582,7 @@ bool PeerManager::SendMessages(CNode* pto)
}
//
- // Message: getdata (non-blocks)
+ // Message: getdata (transactions)
//
std::vector<std::pair<NodeId, GenTxid>> expired;
auto requestable = m_txrequest.GetRequestable(pto->GetId(), current_time, &expired);
diff --git a/src/net_processing.h b/src/net_processing.h
index 87eee566de..322fabbe11 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -32,10 +32,73 @@ static const bool DEFAULT_PEERBLOCKFILTERS = false;
/** Threshold for marking a node to be discouraged, e.g. disconnected and added to the discouragement filter. */
static const int DISCOURAGEMENT_THRESHOLD{100};
+struct CNodeStateStats {
+ int nSyncHeight = -1;
+ int nCommonHeight = -1;
+ int m_starting_height = -1;
+ std::vector<int> vHeightInFlight;
+};
+
+/**
+ * Data structure for an individual peer. This struct is not protected by
+ * cs_main since it does not contain validation-critical data.
+ *
+ * Memory is owned by shared pointers and this object is destructed when
+ * the refcount drops to zero.
+ *
+ * Mutexes inside this struct must not be held when locking m_peer_mutex.
+ *
+ * TODO: move most members from CNodeState to this structure.
+ * TODO: move remaining application-layer data members from CNode to this structure.
+ */
+struct Peer {
+ /** Same id as the CNode object for this peer */
+ const NodeId m_id{0};
+
+ /** Protects misbehavior data members */
+ Mutex m_misbehavior_mutex;
+ /** Accumulated misbehavior score for this peer */
+ int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0};
+ /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
+ bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
+
+ /** Protects block inventory data members */
+ Mutex m_block_inv_mutex;
+ /** List of blocks that we'll announce via an `inv` message.
+ * There is no final sorting before sending, as they are always sent
+ * immediately and in the order requested. */
+ std::vector<uint256> m_blocks_for_inv_relay GUARDED_BY(m_block_inv_mutex);
+ /** Unfiltered list of blocks that we'd like to announce via a `headers`
+ * message. If we can't announce via a `headers` message, we'll fall back to
+ * announcing via `inv`. */
+ std::vector<uint256> m_blocks_for_headers_relay GUARDED_BY(m_block_inv_mutex);
+ /** The final block hash that we sent in an `inv` message to this peer.
+ * When the peer requests this block, we send an `inv` message to trigger
+ * the peer to request the next sequence of block hashes.
+ * Most peers use headers-first syncing, which doesn't use this mechanism */
+ uint256 m_continuation_block GUARDED_BY(m_block_inv_mutex) {};
+
+ /** This peer's reported block height when we connected */
+ std::atomic<int> m_starting_height{-1};
+
+ /** Set of txids to reconsider once their parent transactions have been accepted **/
+ std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
+
+ /** Protects m_getdata_requests **/
+ Mutex m_getdata_requests_mutex;
+ /** Work queue of items requested by this peer **/
+ std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
+
+ explicit Peer(NodeId id) : m_id(id) {}
+};
+
+using PeerRef = std::shared_ptr<Peer>;
+
class PeerManager final : public CValidationInterface, public NetEventsInterface {
public:
PeerManager(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool);
+ CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
+ bool ignore_incoming_txs);
/**
* Overridden from CValidationInterface.
@@ -94,7 +157,24 @@ public:
*/
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message);
+ /** Get statistics from node state */
+ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats);
+
+ /** Set the best height */
+ void SetBestHeight(int height) { m_best_height = height; };
+
+ /** Whether this node ignores txs received over p2p. */
+ bool IgnoresIncomingTxs() { return m_ignore_incoming_txs; };
+
private:
+ /** Get a shared pointer to the Peer object.
+ * May return an empty shared_ptr if the Peer object can't be found. */
+ PeerRef GetPeerRef(NodeId id) const;
+
+ /** Get a shared pointer to the Peer object and remove it from m_peer_map.
+ * May return an empty shared_ptr if the Peer object can't be found. */
+ PeerRef RemovePeer(NodeId id);
+
/**
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
*
@@ -124,7 +204,9 @@ private:
void ProcessOrphanTx(std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans);
/** Process a single headers message from a peer. */
- void ProcessHeadersMessage(CNode& pfrom, const std::vector<CBlockHeader>& headers, bool via_compact_block);
+ void ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
+ const std::vector<CBlockHeader>& headers,
+ bool via_compact_block);
void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req);
@@ -134,6 +216,9 @@ private:
void AddTxAnnouncement(const CNode& node, const GenTxid& gtxid, std::chrono::microseconds current_time)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+ /** Send a version message to a peer */
+ void PushNodeVersion(CNode& pnode, int64_t nTime);
+
const CChainParams& m_chainparams;
CConnman& m_connman;
/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
@@ -142,18 +227,29 @@ private:
CTxMemPool& m_mempool;
TxRequestTracker m_txrequest GUARDED_BY(::cs_main);
+ /** The height of the best chain */
+ std::atomic<int> m_best_height{-1};
+
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
-};
-struct CNodeStateStats {
- int m_misbehavior_score = 0;
- int nSyncHeight = -1;
- int nCommonHeight = -1;
- std::vector<int> vHeightInFlight;
-};
+ /** Whether this node is running in blocks only mode */
+ const bool m_ignore_incoming_txs;
-/** Get statistics from node state */
-bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
+ /** Whether we've completed initial sync yet, for determining when to turn
+ * on extra block-relay-only peers. */
+ bool m_initial_sync_finished{false};
+
+ /** Protects m_peer_map. This mutex must not be locked while holding a lock
+ * on any of the mutexes inside a Peer object. */
+ mutable Mutex m_peer_mutex;
+ /**
+ * Map of all Peer objects, keyed by peer id. This map is protected
+ * by the m_peer_mutex. Once a shared pointer reference is
+ * taken, the lock may be released. Individual fields are protected by
+ * their own locks.
+ */
+ std::map<NodeId, PeerRef> m_peer_map GUARDED_BY(m_peer_mutex);
+};
/** Relay transaction to every node */
void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 35e9161f58..85e46fd373 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -437,6 +437,11 @@ bool CNetAddr::IsValid() const
return false;
}
+ // CJDNS addresses always start with 0xfc
+ if (IsCJDNS() && (m_addr[0] != 0xFC)) {
+ return false;
+ }
+
// documentation IPv6 address
if (IsRFC3849())
return false;
@@ -1063,15 +1068,24 @@ CSubNet::CSubNet(const CNetAddr& addr, const CNetAddr& mask) : CSubNet()
CSubNet::CSubNet(const CNetAddr& addr) : CSubNet()
{
- valid = addr.IsIPv4() || addr.IsIPv6();
- if (!valid) {
+ switch (addr.m_net) {
+ case NET_IPV4:
+ case NET_IPV6:
+ valid = true;
+ assert(addr.m_addr.size() <= sizeof(netmask));
+ memset(netmask, 0xFF, addr.m_addr.size());
+ break;
+ case NET_ONION:
+ case NET_I2P:
+ case NET_CJDNS:
+ valid = true;
+ break;
+ case NET_INTERNAL:
+ case NET_UNROUTABLE:
+ case NET_MAX:
return;
}
- assert(addr.m_addr.size() <= sizeof(netmask));
-
- memset(netmask, 0xFF, addr.m_addr.size());
-
network = addr;
}
@@ -1083,6 +1097,21 @@ bool CSubNet::Match(const CNetAddr &addr) const
{
if (!valid || !addr.IsValid() || network.m_net != addr.m_net)
return false;
+
+ switch (network.m_net) {
+ case NET_IPV4:
+ case NET_IPV6:
+ break;
+ case NET_ONION:
+ case NET_I2P:
+ case NET_CJDNS:
+ case NET_INTERNAL:
+ return addr == network;
+ case NET_UNROUTABLE:
+ case NET_MAX:
+ return false;
+ }
+
assert(network.m_addr.size() == addr.m_addr.size());
for (size_t x = 0; x < addr.m_addr.size(); ++x) {
if ((addr.m_addr[x] & netmask[x]) != network.m_addr[x]) {
@@ -1094,18 +1123,35 @@ bool CSubNet::Match(const CNetAddr &addr) const
std::string CSubNet::ToString() const
{
- assert(network.m_addr.size() <= sizeof(netmask));
+ std::string suffix;
- uint8_t cidr = 0;
+ switch (network.m_net) {
+ case NET_IPV4:
+ case NET_IPV6: {
+ assert(network.m_addr.size() <= sizeof(netmask));
- for (size_t i = 0; i < network.m_addr.size(); ++i) {
- if (netmask[i] == 0x00) {
- break;
+ uint8_t cidr = 0;
+
+ for (size_t i = 0; i < network.m_addr.size(); ++i) {
+ if (netmask[i] == 0x00) {
+ break;
+ }
+ cidr += NetmaskBits(netmask[i]);
}
- cidr += NetmaskBits(netmask[i]);
+
+ suffix = strprintf("/%u", cidr);
+ break;
+ }
+ case NET_ONION:
+ case NET_I2P:
+ case NET_CJDNS:
+ case NET_INTERNAL:
+ case NET_UNROUTABLE:
+ case NET_MAX:
+ break;
}
- return network.ToString() + strprintf("/%u", cidr);
+ return network.ToString() + suffix;
}
bool CSubNet::IsValid() const
@@ -1115,7 +1161,19 @@ bool CSubNet::IsValid() const
bool CSubNet::SanityCheck() const
{
- if (!(network.IsIPv4() || network.IsIPv6())) return false;
+ switch (network.m_net) {
+ case NET_IPV4:
+ case NET_IPV6:
+ break;
+ case NET_ONION:
+ case NET_I2P:
+ case NET_CJDNS:
+ return true;
+ case NET_INTERNAL:
+ case NET_UNROUTABLE:
+ case NET_MAX:
+ return false;
+ }
for (size_t x = 0; x < network.m_addr.size(); ++x) {
if (network.m_addr[x] & ~netmask[x]) return false;
diff --git a/src/netaddress.h b/src/netaddress.h
index 29b2eaafeb..b9eade7fd5 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -462,11 +462,33 @@ class CSubNet
bool SanityCheck() const;
public:
+ /**
+ * Construct an invalid subnet (empty, `Match()` always returns false).
+ */
CSubNet();
+
+ /**
+ * Construct from a given network start and number of bits (CIDR mask).
+ * @param[in] addr Network start. Must be IPv4 or IPv6, otherwise an invalid subnet is
+ * created.
+ * @param[in] mask CIDR mask, must be in [0, 32] for IPv4 addresses and in [0, 128] for
+ * IPv6 addresses. Otherwise an invalid subnet is created.
+ */
CSubNet(const CNetAddr& addr, uint8_t mask);
+
+ /**
+ * Construct from a given network start and mask.
+ * @param[in] addr Network start. Must be IPv4 or IPv6, otherwise an invalid subnet is
+ * created.
+ * @param[in] mask Network mask, must be of the same type as `addr` and not contain 0-bits
+ * followed by 1-bits. Otherwise an invalid subnet is created.
+ */
CSubNet(const CNetAddr& addr, const CNetAddr& mask);
- //constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
+ /**
+ * Construct a single-host subnet.
+ * @param[in] addr The sole address to be contained in the subnet, can also be non-IPv[46].
+ */
explicit CSubNet(const CNetAddr& addr);
bool Match(const CNetAddr &addr) const;
@@ -483,7 +505,7 @@ class CSubNet
READWRITE(obj.network);
if (obj.network.IsIPv4()) {
// Before commit 102867c587f5f7954232fb8ed8e85cda78bb4d32, CSubNet used the last 4 bytes of netmask
- // to store the relevant bytes for an IPv4 mask. For compatiblity reasons, keep doing so in
+ // to store the relevant bytes for an IPv4 mask. For compatibility reasons, keep doing so in
// serialized form.
unsigned char dummy[12] = {0};
READWRITE(dummy);
diff --git a/src/netmessagemaker.h b/src/netmessagemaker.h
index ffb3fe2f29..89fb4758f9 100644
--- a/src/netmessagemaker.h
+++ b/src/netmessagemaker.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp
index fb46ea1731..02e50c4dbe 100644
--- a/src/node/coinstats.cpp
+++ b/src/node/coinstats.cpp
@@ -112,7 +112,7 @@ bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, CoinStatsHashType hash_t
}
// The legacy hash serializes the hashBlock
-static void PrepareHash(CHashWriter& ss, CCoinsStats& stats)
+static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
{
ss << stats.hashBlock;
}
diff --git a/src/node/coinstats.h b/src/node/coinstats.h
index 2a7441c10e..7c56bfc2ad 100644
--- a/src/node/coinstats.h
+++ b/src/node/coinstats.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/node/context.cpp b/src/node/context.cpp
index 49d0c37235..958221a913 100644
--- a/src/node/context.cpp
+++ b/src/node/context.cpp
@@ -8,6 +8,7 @@
#include <interfaces/chain.h>
#include <net.h>
#include <net_processing.h>
+#include <policy/fees.h>
#include <scheduler.h>
#include <txmempool.h>
diff --git a/src/node/context.h b/src/node/context.h
index 3228831ed1..9b611bf8f5 100644
--- a/src/node/context.h
+++ b/src/node/context.h
@@ -12,6 +12,7 @@
class ArgsManager;
class BanMan;
+class CBlockPolicyEstimator;
class CConnman;
class CScheduler;
class CTxMemPool;
@@ -36,6 +37,7 @@ class WalletClient;
struct NodeContext {
std::unique_ptr<CConnman> connman;
std::unique_ptr<CTxMemPool> mempool;
+ std::unique_ptr<CBlockPolicyEstimator> fee_estimator;
std::unique_ptr<PeerManager> peerman;
ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
std::unique_ptr<BanMan> banman;
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index a8c8be05fb..e07eaa33d8 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -12,6 +12,7 @@
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
+#include <mapport.h>
#include <net.h>
#include <net_processing.h>
#include <netaddress.h>
@@ -93,15 +94,7 @@ public:
}
}
bool shutdownRequested() override { return ShutdownRequested(); }
- void mapPort(bool use_upnp) override
- {
- if (use_upnp) {
- StartMapPort();
- } else {
- InterruptMapPort();
- StopMapPort();
- }
- }
+ void mapPort(bool use_upnp, bool use_natpmp) override { StartMapPort(use_upnp, use_natpmp); }
bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); }
size_t getNodeCount(CConnman::NumConnections flags) override
{
@@ -121,11 +114,13 @@ public:
}
// Try to retrieve the CNodeStateStats for each node.
- TRY_LOCK(::cs_main, lockMain);
- if (lockMain) {
- for (auto& node_stats : stats) {
- std::get<1>(node_stats) =
- GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
+ if (m_context->peerman) {
+ TRY_LOCK(::cs_main, lockMain);
+ if (lockMain) {
+ for (auto& node_stats : stats) {
+ std::get<1>(node_stats) =
+ m_context->peerman->GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
+ }
}
}
return true;
@@ -221,15 +216,6 @@ public:
}
}
bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
- CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
- {
- FeeCalculation fee_calc;
- CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative);
- if (returned_target) {
- *returned_target = fee_calc.returnedTarget;
- }
- return result;
- }
CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
{
@@ -312,7 +298,7 @@ public:
util::Ref m_context_ref;
};
-bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock)
+bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active)
{
if (!index) return false;
if (block.m_hash) *block.m_hash = index->GetBlockHash();
@@ -320,6 +306,8 @@ bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<Rec
if (block.m_time) *block.m_time = index->GetBlockTime();
if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax();
if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
+ if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index;
+ if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active);
if (block.m_data) {
REVERSE_LOCK(lock);
if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull();
@@ -422,48 +410,33 @@ public:
Optional<int> getHeight() override
{
LOCK(::cs_main);
- int height = ::ChainActive().Height();
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ int height = active.Height();
if (height >= 0) {
return height;
}
return nullopt;
}
- Optional<int> getBlockHeight(const uint256& hash) override
- {
- LOCK(::cs_main);
- CBlockIndex* block = LookupBlockIndex(hash);
- if (block && ::ChainActive().Contains(block)) {
- return block->nHeight;
- }
- return nullopt;
- }
uint256 getBlockHash(int height) override
{
LOCK(::cs_main);
- CBlockIndex* block = ::ChainActive()[height];
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ CBlockIndex* block = active[height];
assert(block);
return block->GetBlockHash();
}
bool haveBlockOnDisk(int height) override
{
LOCK(cs_main);
- CBlockIndex* block = ::ChainActive()[height];
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ CBlockIndex* block = active[height];
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
}
- Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
- {
- LOCK(cs_main);
- CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
- if (block) {
- if (hash) *hash = block->GetBlockHash();
- return block->nHeight;
- }
- return nullopt;
- }
CBlockLocator getTipLocator() override
{
LOCK(cs_main);
- return ::ChainActive().GetLocator();
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ return active.GetLocator();
}
bool checkFinalTx(const CTransaction& tx) override
{
@@ -473,7 +446,8 @@ public:
Optional<int> findLocatorFork(const CBlockLocator& locator) override
{
LOCK(cs_main);
- if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ if (CBlockIndex* fork = FindForkInGlobalIndex(active, locator)) {
return fork->nHeight;
}
return nullopt;
@@ -481,47 +455,45 @@ public:
bool findBlock(const uint256& hash, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- return FillBlock(LookupBlockIndex(hash), block, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ return FillBlock(LookupBlockIndex(hash), block, lock, active);
}
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- return FillBlock(ChainActive().FindEarliestAtLeast(min_time, min_height), block, lock);
- }
- bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next, bool* reorg) override {
- WAIT_LOCK(cs_main, lock);
- CBlockIndex* block = ChainActive()[block_height];
- if (block && block->GetBlockHash() != block_hash) block = nullptr;
- if (reorg) *reorg = !block;
- return FillBlock(block ? ChainActive()[block_height + 1] : nullptr, next, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active);
}
bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
{
WAIT_LOCK(cs_main, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
if (const CBlockIndex* block = LookupBlockIndex(block_hash)) {
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
- return FillBlock(ancestor, ancestor_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active);
}
}
- return FillBlock(nullptr, ancestor_out, lock);
+ return FillBlock(nullptr, ancestor_out, lock, active);
}
bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
{
WAIT_LOCK(cs_main, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
const CBlockIndex* block = LookupBlockIndex(block_hash);
const CBlockIndex* ancestor = LookupBlockIndex(ancestor_hash);
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
- return FillBlock(ancestor, ancestor_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active);
}
bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
{
WAIT_LOCK(cs_main, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
const CBlockIndex* block1 = LookupBlockIndex(block_hash1);
const CBlockIndex* block2 = LookupBlockIndex(block_hash2);
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
// Using & instead of && below to avoid short circuiting and leaving
// output uninitialized.
- return FillBlock(ancestor, ancestor_out, lock) & FillBlock(block1, block1_out, lock) & FillBlock(block2, block2_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active) & FillBlock(block1, block1_out, lock, active) & FillBlock(block2, block2_out, lock, active);
}
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
double guessVerificationProgress(const uint256& block_hash) override
@@ -601,11 +573,13 @@ public:
}
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
{
- return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative);
+ if (!m_node.fee_estimator) return {};
+ return m_node.fee_estimator->estimateSmartFee(num_blocks, calc, conservative);
}
unsigned int estimateMaxBlocks() override
{
- return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+ if (!m_node.fee_estimator) return 0;
+ return m_node.fee_estimator->HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
}
CFeeRate mempoolMinFee() override
{
@@ -639,7 +613,8 @@ public:
{
if (!old_tip.IsNull()) {
LOCK(::cs_main);
- if (old_tip == ::ChainActive().Tip()->GetBlockHash()) return;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ if (old_tip == active.Tip()->GetBlockHash()) return;
}
SyncWithValidationInterfaceQueue();
}
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 97d5aad8e4..d3bb9687a8 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h
index c8b4d60fd0..fe78cb46bd 100644
--- a/src/node/utxo_snapshot.h
+++ b/src/node/utxo_snapshot.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/noui.cpp b/src/noui.cpp
index 3c82512fac..6fe5c5638c 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/noui.h b/src/noui.h
index 8ec5708328..cf273ffb33 100644
--- a/src/noui.h
+++ b/src/noui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2019 The Bitcoin Core developers
+// Copyright (c) 2013-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/optional.h b/src/optional.h
index a382cd7b77..583c56eabd 100644
--- a/src/optional.h
+++ b/src/optional.h
@@ -1,26 +1,20 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 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_OPTIONAL_H
#define BITCOIN_OPTIONAL_H
+#include <optional>
#include <utility>
-#include <boost/optional.hpp>
-
//! Substitute for C++17 std::optional
+//! DEPRECATED use std::optional in new code.
template <typename T>
-using Optional = boost::optional<T>;
-
-//! Substitute for C++17 std::make_optional
-template <typename T>
-Optional<T> MakeOptional(bool condition, T&& value)
-{
- return boost::make_optional(condition, std::forward<T>(value));
-}
+using Optional = std::optional<T>;
//! Substitute for C++17 std::nullopt
-static auto& nullopt = boost::none;
+//! DEPRECATED use std::nullopt in new code.
+static auto& nullopt = std::nullopt;
#endif // BITCOIN_OPTIONAL_H
diff --git a/src/outputtype.cpp b/src/outputtype.cpp
index e978852826..d96fb282c5 100644
--- a/src/outputtype.cpp
+++ b/src/outputtype.cpp
@@ -19,8 +19,6 @@ static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy";
static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit";
static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32";
-const std::array<OutputType, 3> OUTPUT_TYPES = {OutputType::LEGACY, OutputType::P2SH_SEGWIT, OutputType::BECH32};
-
bool ParseOutputType(const std::string& type, OutputType& output_type)
{
if (type == OUTPUT_TYPE_STRING_LEGACY) {
diff --git a/src/outputtype.h b/src/outputtype.h
index bb7f39323b..88422e5824 100644
--- a/src/outputtype.h
+++ b/src/outputtype.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -20,7 +20,11 @@ enum class OutputType {
BECH32,
};
-extern const std::array<OutputType, 3> OUTPUT_TYPES;
+static constexpr auto OUTPUT_TYPES = std::array{
+ OutputType::LEGACY,
+ OutputType::P2SH_SEGWIT,
+ OutputType::BECH32,
+};
[[nodiscard]] bool ParseOutputType(const std::string& str, OutputType& output_type);
const std::string& FormatOutputType(OutputType type);
diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp
index 04e0e117a5..3da85fedf9 100644
--- a/src/policy/feerate.cpp
+++ b/src/policy/feerate.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
index 7c5660ac8a..86ae507957 100644
--- a/src/policy/feerate.h
+++ b/src/policy/feerate.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 0f31093dbb..7da171d2e1 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -1,28 +1,29 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 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 <policy/fees.h>
#include <clientversion.h>
+#include <fs.h>
+#include <logging.h>
#include <streams.h>
#include <txmempool.h>
#include <util/system.h>
-static constexpr double INF_FEERATE = 1e99;
-
-std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon) {
- static const std::map<FeeEstimateHorizon, std::string> horizon_strings = {
- {FeeEstimateHorizon::SHORT_HALFLIFE, "short"},
- {FeeEstimateHorizon::MED_HALFLIFE, "medium"},
- {FeeEstimateHorizon::LONG_HALFLIFE, "long"},
- };
- auto horizon_string = horizon_strings.find(horizon);
+static const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat";
- if (horizon_string == horizon_strings.end()) return "unknown";
+static constexpr double INF_FEERATE = 1e99;
- return horizon_string->second;
+std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
+{
+ switch (horizon) {
+ case FeeEstimateHorizon::SHORT_HALFLIFE: return "short";
+ case FeeEstimateHorizon::MED_HALFLIFE: return "medium";
+ case FeeEstimateHorizon::LONG_HALFLIFE: return "long";
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
}
/**
@@ -489,6 +490,7 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
{
static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
size_t bucketIndex = 0;
+
for (double bucketBoundary = MIN_BUCKET_FEERATE; bucketBoundary <= MAX_BUCKET_FEERATE; bucketBoundary *= FEE_SPACING, bucketIndex++) {
buckets.push_back(bucketBoundary);
bucketMap[bucketBoundary] = bucketIndex;
@@ -500,6 +502,13 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
feeStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));
shortStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
longStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE));
+
+ // If the fee estimation file is present, read recorded estimations
+ fs::path est_filepath = GetDataDir() / FEE_ESTIMATES_FILENAME;
+ CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
+ if (est_file.IsNull() || !Read(est_file)) {
+ LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", est_filepath.string());
+ }
}
CBlockPolicyEstimator::~CBlockPolicyEstimator()
@@ -632,7 +641,7 @@ CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget) const
CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThreshold, FeeEstimateHorizon horizon, EstimationResult* result) const
{
- TxConfirmStats* stats;
+ TxConfirmStats* stats = nullptr;
double sufficientTxs = SUFFICIENT_FEETXS;
switch (horizon) {
case FeeEstimateHorizon::SHORT_HALFLIFE: {
@@ -648,10 +657,8 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr
stats = longStats.get();
break;
}
- default: {
- throw std::out_of_range("CBlockPolicyEstimator::estimateRawFee unknown FeeEstimateHorizon");
- }
- }
+ } // no default case, so the compiler can warn about missing cases
+ assert(stats);
LOCK(m_cs_fee_estimator);
// Return failure if trying to analyze a target we're not tracking
@@ -681,10 +688,8 @@ unsigned int CBlockPolicyEstimator::HighestTargetTracked(FeeEstimateHorizon hori
case FeeEstimateHorizon::LONG_HALFLIFE: {
return longStats->GetMaxConfirms();
}
- default: {
- throw std::out_of_range("CBlockPolicyEstimator::HighestTargetTracked unknown FeeEstimateHorizon");
- }
- }
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
}
unsigned int CBlockPolicyEstimator::BlockSpan() const
@@ -856,6 +861,15 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
return CFeeRate(llround(median));
}
+void CBlockPolicyEstimator::Flush() {
+ FlushUnconfirmed();
+
+ fs::path est_filepath = GetDataDir() / FEE_ESTIMATES_FILENAME;
+ CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
+ if (est_file.IsNull() || !Write(est_file)) {
+ LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", est_filepath.string());
+ }
+}
bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
{
@@ -888,8 +902,9 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
LOCK(m_cs_fee_estimator);
int nVersionRequired, nVersionThatWrote;
filein >> nVersionRequired >> nVersionThatWrote;
- if (nVersionRequired > CLIENT_VERSION)
- return error("CBlockPolicyEstimator::Read(): up-version (%d) fee estimate file", nVersionRequired);
+ if (nVersionRequired > CLIENT_VERSION) {
+ throw std::runtime_error(strprintf("up-version (%d) fee estimate file", nVersionRequired));
+ }
// Read fee estimates file into temporary variables so existing data
// structures aren't corrupted if there is an exception.
@@ -907,8 +922,9 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
std::vector<double> fileBuckets;
filein >> fileBuckets;
size_t numBuckets = fileBuckets.size();
- if (numBuckets <= 1 || numBuckets > 1000)
+ if (numBuckets <= 1 || numBuckets > 1000) {
throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
+ }
std::unique_ptr<TxConfirmStats> fileFeeStats(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));
std::unique_ptr<TxConfirmStats> fileShortStats(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 8ea8816dc3..c444d71a31 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -11,6 +11,7 @@
#include <random.h>
#include <sync.h>
+#include <array>
#include <map>
#include <memory>
#include <string>
@@ -25,9 +26,15 @@ class TxConfirmStats;
/* Identifier for each of the 3 different TxConfirmStats which will track
* history over different time horizons. */
enum class FeeEstimateHorizon {
- SHORT_HALFLIFE = 0,
- MED_HALFLIFE = 1,
- LONG_HALFLIFE = 2
+ SHORT_HALFLIFE,
+ MED_HALFLIFE,
+ LONG_HALFLIFE,
+};
+
+static constexpr auto ALL_FEE_ESTIMATE_HORIZONS = std::array{
+ FeeEstimateHorizon::SHORT_HALFLIFE,
+ FeeEstimateHorizon::MED_HALFLIFE,
+ FeeEstimateHorizon::LONG_HALFLIFE,
};
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon);
@@ -215,6 +222,9 @@ public:
/** Calculation of highest target that estimates are tracked for */
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const;
+ /** Drop still unconfirmed transactions and record current estimations, if the fee estimation file is present. */
+ void Flush();
+
private:
mutable RecursiveMutex m_cs_fee_estimator;
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 4e33fd6cb5..2b5fd4179d 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -75,7 +75,7 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
{
- if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
+ if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version";
return false;
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 726a14a27e..f2a3f35546 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -90,25 +90,32 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType);
- /**
- * Check for standard transaction types
- * @return True if all outputs (scriptPubKeys) use only standard transaction forms
- */
+
+
+// Changing the default transaction version requires a two step process: first
+// adapting relay policy by bumping TX_MAX_STANDARD_VERSION, and then later
+// allowing the new transaction version in the wallet/RPC.
+static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{2};
+
+/**
+* Check for standard transaction types
+* @return True if all outputs (scriptPubKeys) use only standard transaction forms
+*/
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
- /**
- * Check for standard transaction types
- * @param[in] mapInputs Map of previous transactions that have outputs we're spending
- * @param[in] taproot_active Whether or taproot consensus rules are active (used to decide whether spends of them are permitted)
- * @return True if all inputs (scriptSigs) use only standard transaction forms
- */
+/**
+* Check for standard transaction types
+* @param[in] mapInputs Map of previous transactions that have outputs we're spending
+* @param[in] taproot_active Whether or taproot consensus rules are active (used to decide whether spends of them are permitted)
+* @return True if all inputs (scriptSigs) use only standard transaction forms
+*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, bool taproot_active);
- /**
- * Check if the transaction is over standard P2WSH resources limit:
- * 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements
- * These limits are adequate for multisignatures up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL.
- *
- * Also enforce a maximum stack item size limit and no annexes for tapscript spends.
- */
+/**
+* Check if the transaction is over standard P2WSH resources limit:
+* 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements
+* These limits are adequate for multisignatures up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL.
+*
+* Also enforce a maximum stack item size limit and no annexes for tapscript spends.
+*/
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
/** Compute the virtual transaction size (weight reinterpreted as bytes). */
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index 4b55934891..8125b41c41 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index f84e6e5286..e078070c1c 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/primitives/block.h b/src/primitives/block.h
index fd8fc8b868..2d10853607 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index e6183cf2f4..245206b906 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -77,8 +77,6 @@ uint256 CTransaction::ComputeWitnessHash() const
return SerializeHash(*this, SER_GETHASH, 0);
}
-/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
-CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash{}, m_witness_hash{} {}
CTransaction::CTransaction(const CMutableTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
CTransaction::CTransaction(CMutableTransaction&& tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 00544f64fe..6bf36ee854 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -262,12 +262,6 @@ public:
// Default transaction version.
static const int32_t CURRENT_VERSION=2;
- // Changing the default transaction version requires a two step process: first
- // adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date
- // bumping the default CURRENT_VERSION at which point both CURRENT_VERSION and
- // MAX_STANDARD_VERSION will be equal.
- static const int32_t MAX_STANDARD_VERSION=2;
-
// 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,
@@ -287,12 +281,9 @@ private:
uint256 ComputeWitnessHash() const;
public:
- /** Construct a CTransaction that qualifies as IsNull() */
- CTransaction();
-
/** Convert a CMutableTransaction into a CTransaction. */
- explicit CTransaction(const CMutableTransaction &tx);
- CTransaction(CMutableTransaction &&tx);
+ explicit CTransaction(const CMutableTransaction& tx);
+ CTransaction(CMutableTransaction&& tx);
template <typename Stream>
inline void Serialize(Stream& s) const {
@@ -393,7 +384,6 @@ struct CMutableTransaction
};
typedef std::shared_ptr<const CTransaction> CTransactionRef;
-static inline CTransactionRef MakeTransactionRef() { return std::make_shared<const CTransaction>(); }
template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }
/** A generic txid reference (txid or wtxid). */
diff --git a/src/protocol.cpp b/src/protocol.cpp
index dc8f795a0c..56e738eaa8 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -203,7 +203,6 @@ static std::string serviceFlagToStr(size_t bit)
switch ((ServiceFlags)service_flag) {
case NODE_NONE: abort(); // impossible
case NODE_NETWORK: return "NETWORK";
- case NODE_GETUTXO: return "GETUTXO";
case NODE_BLOOM: return "BLOOM";
case NODE_WITNESS: return "WITNESS";
case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
diff --git a/src/protocol.h b/src/protocol.h
index 309fac621c..f183db0501 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -273,10 +273,6 @@ enum ServiceFlags : uint64_t {
// NODE_NETWORK means that the node is capable of serving the complete block chain. It is currently
// set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light clients.
NODE_NETWORK = (1 << 0),
- // NODE_GETUTXO means the node is capable of responding to the getutxo protocol request.
- // Bitcoin Core does not support this but a patch set called Bitcoin XT does.
- // See BIP 64 for details on how this is implemented.
- NODE_GETUTXO = (1 << 1),
// NODE_BLOOM means the node is capable and willing to handle bloom-filtered connections.
// Bitcoin Core nodes used to support this by default, without advertising this bit,
// but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
diff --git a/src/psbt.cpp b/src/psbt.cpp
index 3fb743e5db..4db57d3cd0 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -3,6 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <psbt.h>
+
+#include <util/check.h>
#include <util/strencodings.h>
@@ -207,7 +209,8 @@ size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt) {
void UpdatePSBTOutput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index)
{
- const CTxOut& out = psbt.tx->vout.at(index);
+ CMutableTransaction& tx = *Assert(psbt.tx);
+ const CTxOut& out = tx.vout.at(index);
PSBTOutput& psbt_out = psbt.outputs.at(index);
// Fill a SignatureData with output info
@@ -217,7 +220,7 @@ void UpdatePSBTOutput(const SigningProvider& provider, PartiallySignedTransactio
// Construct a would-be spend of this output, to update sigdata with.
// Note that ProduceSignature is used to fill in metadata (not actual signatures),
// so provider does not need to provide any private keys (it can be a HidingSigningProvider).
- MutableTransactionSignatureCreator creator(psbt.tx.get_ptr(), /* index */ 0, out.nValue, SIGHASH_ALL);
+ MutableTransactionSignatureCreator creator(&tx, /* index */ 0, out.nValue, SIGHASH_ALL);
ProduceSignature(provider, creator, out.scriptPubKey, sigdata);
// Put redeem_script, witness_script, key paths, into PSBTOutput.
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index 4d734fc891..fc1624af25 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Copyright (c) 2017 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/pubkey.h b/src/pubkey.h
index d60520ac44..12514fc3c9 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Copyright (c) 2017 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index aa4ec04497..0fa52359a8 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h
index 3d303a6f68..c6a364ccbd 100644
--- a/src/qt/addressbookpage.h
+++ b/src/qt/addressbookpage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 665c8e6053..bb444f22b3 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -11,7 +11,6 @@
#include <wallet/wallet.h>
#include <algorithm>
-#include <typeinfo>
#include <QFont>
#include <QDebug>
@@ -82,8 +81,9 @@ public:
{
for (const auto& address : wallet.getAddresses())
{
- if (pk_hash_only && address.dest.type() != typeid(PKHash))
+ if (pk_hash_only && !std::holds_alternative<PKHash>(address.dest)) {
continue;
+ }
AddressTableEntry::Type addressType = translateTransactionType(
QString::fromStdString(address.purpose), address.is_mine);
cachedAddressTable.append(AddressTableEntry(addressType,
@@ -177,13 +177,17 @@ AddressTableModel::~AddressTableModel()
int AddressTableModel::rowCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
+ if (parent.isValid()) {
+ return 0;
+ }
return priv->size();
}
int AddressTableModel::columnCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
+ if (parent.isValid()) {
+ return 0;
+ }
return columns.length();
}
@@ -257,7 +261,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
} else if(index.column() == Address) {
CTxDestination newAddress = DecodeDestination(value.toString().toStdString());
// Refuse to set invalid address, set error status and return false
- if(boost::get<CNoDestination>(&newAddress))
+ if(std::get_if<CNoDestination>(&newAddress))
{
editStatus = INVALID_ADDRESS;
return false;
diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h
index 73316cadc4..6cc14654ef 100644
--- a/src/qt/addresstablemodel.h
+++ b/src/qt/addresstablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index 3be8b664dd..c2349b78f9 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h
index f3ba882277..66031b08d3 100644
--- a/src/qt/askpassphrasedialog.h
+++ b/src/qt/askpassphrasedialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 2676de96d7..a01a7bc386 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -98,13 +98,17 @@ BanTableModel::~BanTableModel()
int BanTableModel::rowCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
+ if (parent.isValid()) {
+ return 0;
+ }
return priv->size();
}
int BanTableModel::columnCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
+ if (parent.isValid()) {
+ return 0;
+ }
return columns.length();
}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 4e1b239bc7..8efb0e35d0 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -77,7 +77,7 @@ static void RegisterMetaTypes()
#ifdef ENABLE_WALLET
qRegisterMetaType<WalletModel*>();
#endif
- // Register typedefs (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType)
+ // Register typedefs (see https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType)
// IMPORTANT: if CAmount is no longer a typedef use the normal variant above (see https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType-1)
qRegisterMetaType<CAmount>("CAmount");
qRegisterMetaType<size_t>("size_t");
diff --git a/src/qt/bitcoinaddressvalidator.h b/src/qt/bitcoinaddressvalidator.h
index 52c06828a3..ae698c72a6 100644
--- a/src/qt/bitcoinaddressvalidator.h
+++ b/src/qt/bitcoinaddressvalidator.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2014 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index a953c991bc..2af3502be3 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h
index d3e61aac29..c60d9a2c90 100644
--- a/src/qt/bitcoinamountfield.h
+++ b/src/qt/bitcoinamountfield.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 20120285d8..f2a49e5a76 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -615,10 +615,10 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
OptionsModel* optionsModel = _clientModel->getOptionsModel();
if (optionsModel && trayIcon) {
// be aware of the tray icon disable state change reported by the OptionsModel object.
- connect(optionsModel, &OptionsModel::hideTrayIconChanged, this, &BitcoinGUI::setTrayIconVisible);
+ connect(optionsModel, &OptionsModel::showTrayIconChanged, trayIcon, &QSystemTrayIcon::setVisible);
// initialize the disable state of the tray icon with the current value in the model.
- setTrayIconVisible(optionsModel->getHideTrayIcon());
+ trayIcon->setVisible(optionsModel->getShowTrayIcon());
}
} else {
// Disable possibility to show main window via action
@@ -1387,14 +1387,6 @@ void BitcoinGUI::showProgress(const QString &title, int nProgress)
}
}
-void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon)
-{
- if (trayIcon)
- {
- trayIcon->setVisible(!fHideTrayIcon);
- }
-}
-
void BitcoinGUI::showModalOverlay()
{
if (modalOverlay && (progressBar->isVisible() || modalOverlay->isLayerVisible()))
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 17458c5777..147f19e68d 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -318,9 +318,6 @@ public Q_SLOTS:
/** Show progress dialog e.g. for verifychain */
void showProgress(const QString &title, int nProgress);
- /** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */
- void setTrayIconVisible(bool);
-
void showModalOverlay();
};
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index fd55c547fc..9660ba99f7 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,6 +8,8 @@
#include <cassert>
+static constexpr auto MAX_DIGITS_BTC = 16;
+
BitcoinUnits::BitcoinUnits(QObject *parent):
QAbstractListModel(parent),
unitlist(availableUnits())
@@ -108,7 +110,9 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator
qint64 n_abs = (n > 0 ? n : -n);
qint64 quotient = n_abs / coin;
QString quotient_str = QString::number(quotient);
- if (justify) quotient_str = quotient_str.rightJustified(16 - num_decimals, ' ');
+ if (justify) {
+ quotient_str = quotient_str.rightJustified(MAX_DIGITS_BTC - num_decimals, ' ');
+ }
// Use SI-style thin space separators as these are locale independent and can't be
// confused with the decimal marker.
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 7f12cce1d9..7ac4cc040b 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 7c72858501..08abef7866 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -455,7 +455,7 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *
else if(ExtractDestination(out.txout.scriptPubKey, address))
{
CPubKey pubkey;
- PKHash *pkhash = boost::get<PKHash>(&address);
+ PKHash* pkhash = std::get_if<PKHash>(&address);
if (pkhash && model->wallet().getPubKey(out.txout.scriptPubKey, ToKeyID(*pkhash), pubkey))
{
nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h
index 3de7fd6d54..6ceb3de61d 100644
--- a/src/qt/coincontroldialog.h
+++ b/src/qt/coincontroldialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp
index 3945159c26..70f080f4de 100644
--- a/src/qt/createwalletdialog.cpp
+++ b/src/qt/createwalletdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp
index e0af9a20a8..cd25f856a2 100644
--- a/src/qt/editaddressdialog.cpp
+++ b/src/qt/editaddressdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h
index 3be63156fd..f7ad80bb2d 100644
--- a/src/qt/editaddressdialog.h
+++ b/src/qt/editaddressdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/forms/createwalletdialog.ui b/src/qt/forms/createwalletdialog.ui
index ea713e1abd..0b33c2cb8d 100644
--- a/src/qt/forms/createwalletdialog.ui
+++ b/src/qt/forms/createwalletdialog.ui
@@ -60,7 +60,7 @@
<rect>
<x>20</x>
<y>50</y>
- <width>171</width>
+ <width>220</width>
<height>22</height>
</rect>
</property>
@@ -79,7 +79,7 @@
<rect>
<x>20</x>
<y>90</y>
- <width>130</width>
+ <width>220</width>
<height>21</height>
</rect>
</property>
@@ -98,7 +98,7 @@
<rect>
<x>20</x>
<y>115</y>
- <width>171</width>
+ <width>220</width>
<height>22</height>
</rect>
</property>
@@ -130,7 +130,7 @@
<rect>
<x>20</x>
<y>155</y>
- <width>171</width>
+ <width>220</width>
<height>22</height>
</rect>
</property>
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index 139c8e161e..bce578a158 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -1077,14 +1077,17 @@
</widget>
</item>
<item row="1" column="0">
- <widget class="QLabel" name="label_23">
+ <widget class="QLabel" name="peerConnectionTypeLabel">
+ <property name="toolTip">
+ <string>The type of peer connection:&lt;ul&gt;&lt;li&gt;Inbound: initiated by peer&lt;/li&gt;&lt;li&gt;Outbound Full Relay: default&lt;/li&gt;&lt;li&gt;Outbound Block Relay: does not relay transactions or addresses&lt;/li&gt;&lt;li&gt;Outbound Manual: added using RPC %1 or %2/%3 configuration options&lt;/li&gt;&lt;li&gt;Outbound Feeler: short-lived, for testing addresses&lt;/li&gt;&lt;li&gt;Outbound Address Fetch: short-lived, for soliciting addresses&lt;/li&gt;&lt;/ul&gt;</string>
+ </property>
<property name="text">
- <string>Direction</string>
+ <string>Connection Type</string>
</property>
</widget>
</item>
<item row="1" column="1">
- <widget class="QLabel" name="peerDirection">
+ <widget class="QLabel" name="peerConnectionType">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
@@ -1100,13 +1103,39 @@
</widget>
</item>
<item row="2" column="0">
+ <widget class="QLabel" name="peerNetworkLabel">
+ <property name="toolTip">
+ <string>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</string>
+ </property>
+ <property name="text">
+ <string>Network</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="peerNetwork">
+ <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="3" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Version</string>
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="3" column="1">
<widget class="QLabel" name="peerVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1122,14 +1151,14 @@
</property>
</widget>
</item>
- <item row="3" column="0">
+ <item row="4" column="0">
<widget class="QLabel" name="label_28">
<property name="text">
<string>User Agent</string>
</property>
</widget>
</item>
- <item row="3" column="1">
+ <item row="4" column="1">
<widget class="QLabel" name="peerSubversion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1145,14 +1174,14 @@
</property>
</widget>
</item>
- <item row="4" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Services</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="5" column="1">
<widget class="QLabel" name="peerServices">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1168,14 +1197,14 @@
</property>
</widget>
</item>
- <item row="5" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="label_29">
<property name="text">
<string>Starting Block</string>
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="6" column="1">
<widget class="QLabel" name="peerHeight">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1191,14 +1220,14 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Synced Headers</string>
</property>
</widget>
</item>
- <item row="6" column="1">
+ <item row="7" column="1">
<widget class="QLabel" name="peerSyncHeight">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1214,14 +1243,14 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Synced Blocks</string>
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="8" column="1">
<widget class="QLabel" name="peerCommonHeight">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1237,14 +1266,14 @@
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Connection Time</string>
</property>
</widget>
</item>
- <item row="8" column="1">
+ <item row="9" column="1">
<widget class="QLabel" name="peerConnTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1260,14 +1289,14 @@
</property>
</widget>
</item>
- <item row="9" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Last Send</string>
</property>
</widget>
</item>
- <item row="9" column="1">
+ <item row="10" column="1">
<widget class="QLabel" name="peerLastSend">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1283,14 +1312,14 @@
</property>
</widget>
</item>
- <item row="10" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Last Receive</string>
</property>
</widget>
</item>
- <item row="10" column="1">
+ <item row="11" column="1">
<widget class="QLabel" name="peerLastRecv">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1306,14 +1335,14 @@
</property>
</widget>
</item>
- <item row="11" column="0">
+ <item row="12" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>Sent</string>
</property>
</widget>
</item>
- <item row="11" column="1">
+ <item row="12" column="1">
<widget class="QLabel" name="peerBytesSent">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1329,14 +1358,14 @@
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="13" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Received</string>
</property>
</widget>
</item>
- <item row="12" column="1">
+ <item row="13" column="1">
<widget class="QLabel" name="peerBytesRecv">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1352,14 +1381,14 @@
</property>
</widget>
</item>
- <item row="13" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Ping Time</string>
</property>
</widget>
</item>
- <item row="13" column="1">
+ <item row="14" column="1">
<widget class="QLabel" name="peerPingTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1375,7 +1404,7 @@
</property>
</widget>
</item>
- <item row="14" column="0">
+ <item row="15" column="0">
<widget class="QLabel" name="peerPingWaitLabel">
<property name="toolTip">
<string>The duration of a currently outstanding ping.</string>
@@ -1385,7 +1414,7 @@
</property>
</widget>
</item>
- <item row="14" column="1">
+ <item row="15" column="1">
<widget class="QLabel" name="peerPingWait">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1401,14 +1430,14 @@
</property>
</widget>
</item>
- <item row="15" column="0">
+ <item row="16" column="0">
<widget class="QLabel" name="peerMinPingLabel">
<property name="text">
<string>Min Ping</string>
</property>
</widget>
</item>
- <item row="15" column="1">
+ <item row="16" column="1">
<widget class="QLabel" name="peerMinPing">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1424,14 +1453,14 @@
</property>
</widget>
</item>
- <item row="16" column="0">
+ <item row="17" column="0">
<widget class="QLabel" name="label_timeoffset">
<property name="text">
<string>Time Offset</string>
</property>
</widget>
</item>
- <item row="16" column="1">
+ <item row="17" column="1">
<widget class="QLabel" name="timeoffset">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1447,7 +1476,7 @@
</property>
</widget>
</item>
- <item row="17" column="0">
+ <item row="18" column="0">
<widget class="QLabel" name="peerMappedASLabel">
<property name="toolTip">
<string>The mapped Autonomous System used for diversifying peer selection.</string>
@@ -1457,7 +1486,7 @@
</property>
</widget>
</item>
- <item row="17" column="1">
+ <item row="18" column="1">
<widget class="QLabel" name="peerMappedAS">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1473,7 +1502,7 @@
</property>
</widget>
</item>
- <item row="18" column="0">
+ <item row="19" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index 045c2d3539..8181cc47e2 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -260,6 +260,16 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="mapPortNatpmp">
+ <property name="toolTip">
+ <string>Automatically open the Bitcoin client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random.</string>
+ </property>
+ <property name="text">
+ <string>Map port using NA&amp;T-PMP</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QCheckBox" name="allowIncoming">
<property name="toolTip">
<string>Accept connections from outside.</string>
@@ -568,12 +578,15 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_Window">
<item>
- <widget class="QCheckBox" name="hideTrayIcon">
+ <widget class="QCheckBox" name="showTrayIcon">
<property name="toolTip">
- <string>Hide the icon from the system tray.</string>
+ <string>Show the icon in the system tray.</string>
</property>
<property name="text">
- <string>&amp;Hide tray icon</string>
+ <string>&amp;Show tray icon</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
</property>
</widget>
</item>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 53ffb27f50..430ecd322f 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -655,7 +655,7 @@ bool SetStartOnSystemStartup(bool fAutoStart)
#elif defined(Q_OS_LINUX)
// Follow the Desktop Application Autostart Spec:
-// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
+// https://specifications.freedesktop.org/autostart-spec/autostart-spec-latest.html
fs::path static GetAutostartDir()
{
@@ -749,6 +749,34 @@ QString boostPathToQString(const fs::path &path)
return QString::fromStdString(path.string());
}
+QString NetworkToQString(Network net)
+{
+ switch (net) {
+ case NET_UNROUTABLE: return QObject::tr("Unroutable");
+ case NET_IPV4: return "IPv4";
+ case NET_IPV6: return "IPv6";
+ case NET_ONION: return "Onion";
+ case NET_I2P: return "I2P";
+ case NET_CJDNS: return "CJDNS";
+ case NET_INTERNAL: return QObject::tr("Internal");
+ case NET_MAX: assert(false);
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
+}
+
+QString ConnectionTypeToQString(ConnectionType conn_type)
+{
+ switch (conn_type) {
+ case ConnectionType::INBOUND: return QObject::tr("Inbound");
+ case ConnectionType::OUTBOUND_FULL_RELAY: return QObject::tr("Outbound Full Relay");
+ case ConnectionType::BLOCK_RELAY: return QObject::tr("Outbound Block Relay");
+ case ConnectionType::MANUAL: return QObject::tr("Outbound Manual");
+ case ConnectionType::FEELER: return QObject::tr("Outbound Feeler");
+ case ConnectionType::ADDR_FETCH: return QObject::tr("Outbound Address Fetch");
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
+}
+
QString formatDurationStr(int secs)
{
QStringList strList;
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index d7bd124884..c471b888f7 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -7,16 +7,18 @@
#include <amount.h>
#include <fs.h>
+#include <net.h>
+#include <netaddress.h>
#include <QEvent>
#include <QHeaderView>
#include <QItemDelegate>
+#include <QLabel>
#include <QMessageBox>
#include <QObject>
#include <QProgressBar>
#include <QString>
#include <QTableView>
-#include <QLabel>
class QValidatedLineEdit;
class SendCoinsRecipient;
@@ -218,22 +220,28 @@ namespace GUIUtil
bool GetStartOnSystemStartup();
bool SetStartOnSystemStartup(bool fAutoStart);
- /* Convert QString to OS specific boost path through UTF-8 */
+ /** Convert QString to OS specific boost path through UTF-8 */
fs::path qstringToBoostPath(const QString &path);
- /* Convert OS specific boost path to QString through UTF-8 */
+ /** Convert OS specific boost path to QString through UTF-8 */
QString boostPathToQString(const fs::path &path);
- /* Convert seconds into a QString with days, hours, mins, secs */
+ /** Convert enum Network to QString */
+ QString NetworkToQString(Network net);
+
+ /** Convert enum ConnectionType to QString */
+ QString ConnectionTypeToQString(ConnectionType conn_type);
+
+ /** Convert seconds into a QString with days, hours, mins, secs */
QString formatDurationStr(int secs);
- /* Format CNodeStats.nServices bitmask into a user-readable string */
+ /** Format CNodeStats.nServices bitmask into a user-readable string */
QString formatServicesStr(quint64 mask);
- /* Format a CNodeStats.m_ping_usec into a user-readable string or display N/A, if 0*/
+ /** Format a CNodeStats.m_ping_usec into a user-readable string or display N/A, if 0 */
QString formatPingTime(int64_t ping_usec);
- /* Format a CNodeCombinedStats.nTimeOffset into a user-readable string. */
+ /** Format a CNodeCombinedStats.nTimeOffset into a user-readable string */
QString formatTimeOffset(int64_t nTimeOffset);
QString formatNiceTimeOffset(qint64 secs);
diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h
index 7b07777641..1d8af5cbf6 100644
--- a/src/qt/modaloverlay.h
+++ b/src/qt/modaloverlay.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp
index d518a2065c..b097ef080c 100644
--- a/src/qt/notificator.cpp
+++ b/src/qt/notificator.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -66,7 +66,7 @@ Notificator::~Notificator()
#ifdef USE_DBUS
-// Loosely based on http://www.qtcentre.org/archive/index.php/t-25879.html
+// Loosely based on https://www.qtcentre.org/archive/index.php/t-25879.html
class FreedesktopImage
{
public:
diff --git a/src/qt/openuridialog.h b/src/qt/openuridialog.h
index 667af2ec75..efe4b86f37 100644
--- a/src/qt/openuridialog.h
+++ b/src/qt/openuridialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index ae6aeb7709..416b9c83c9 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -24,6 +24,7 @@
#include <QIntValidator>
#include <QLocale>
#include <QMessageBox>
+#include <QSettings>
#include <QSystemTrayIcon>
#include <QTimer>
@@ -50,6 +51,13 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
#ifndef USE_UPNP
ui->mapPortUpnp->setEnabled(false);
#endif
+#ifndef USE_NATPMP
+ ui->mapPortNatpmp->setEnabled(false);
+#endif
+ connect(this, &QDialog::accepted, [this](){
+ QSettings settings;
+ model->node().mapPort(settings.value("fUseUPnP").toBool(), settings.value("fUseNatpmp").toBool());
+ });
ui->proxyIp->setEnabled(false);
ui->proxyPort->setEnabled(false);
@@ -130,8 +138,8 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
connect(ui->proxyPortTor, &QLineEdit::textChanged, this, &OptionsDialog::updateProxyValidationState);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
- ui->hideTrayIcon->setChecked(true);
- ui->hideTrayIcon->setEnabled(false);
+ ui->showTrayIcon->setChecked(false);
+ ui->showTrayIcon->setEnabled(false);
ui->minimizeToTray->setChecked(false);
ui->minimizeToTray->setEnabled(false);
}
@@ -214,6 +222,7 @@ void OptionsDialog::setMapper()
/* Network */
mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP);
+ mapper->addMapping(ui->mapPortNatpmp, OptionsModel::MapPortNatpmp);
mapper->addMapping(ui->allowIncoming, OptionsModel::Listen);
mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
@@ -227,7 +236,7 @@ void OptionsDialog::setMapper()
/* Window */
#ifndef Q_OS_MAC
if (QSystemTrayIcon::isSystemTrayAvailable()) {
- mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon);
+ mapper->addMapping(ui->showTrayIcon, OptionsModel::ShowTrayIcon);
mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
}
mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
@@ -286,17 +295,14 @@ void OptionsDialog::on_cancelButton_clicked()
reject();
}
-void OptionsDialog::on_hideTrayIcon_stateChanged(int fState)
+void OptionsDialog::on_showTrayIcon_stateChanged(int state)
{
- if(fState)
- {
+ if (state == Qt::Checked) {
+ ui->minimizeToTray->setEnabled(true);
+ } else {
ui->minimizeToTray->setChecked(false);
ui->minimizeToTray->setEnabled(false);
}
- else
- {
- ui->minimizeToTray->setEnabled(true);
- }
}
void OptionsDialog::togglePruneWarning(bool enabled)
diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h
index 568c8b6fd0..1cc96035c6 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -57,7 +57,7 @@ private Q_SLOTS:
void on_okButton_clicked();
void on_cancelButton_clicked();
- void on_hideTrayIcon_stateChanged(int fState);
+ void on_showTrayIcon_stateChanged(int state);
void togglePruneWarning(bool enabled);
void showRestartWarning(bool fPersistent = false);
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 1603b12a73..1e0391a35c 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -13,11 +13,12 @@
#include <qt/guiutil.h>
#include <interfaces/node.h>
-#include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS
+#include <mapport.h>
#include <net.h>
#include <netbase.h>
-#include <txdb.h> // for -dbcache defaults
+#include <txdb.h> // for -dbcache defaults
#include <util/string.h>
+#include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS
#include <QDebug>
#include <QSettings>
@@ -54,14 +55,15 @@ void OptionsModel::Init(bool resetSettings)
// These are Qt-only settings:
// Window
- if (!settings.contains("fHideTrayIcon"))
+ if (!settings.contains("fHideTrayIcon")) {
settings.setValue("fHideTrayIcon", false);
- fHideTrayIcon = settings.value("fHideTrayIcon").toBool();
- Q_EMIT hideTrayIconChanged(fHideTrayIcon);
+ }
+ m_show_tray_icon = !settings.value("fHideTrayIcon").toBool();
+ Q_EMIT showTrayIconChanged(m_show_tray_icon);
if (!settings.contains("fMinimizeToTray"))
settings.setValue("fMinimizeToTray", false);
- fMinimizeToTray = settings.value("fMinimizeToTray").toBool() && !fHideTrayIcon;
+ fMinimizeToTray = settings.value("fMinimizeToTray").toBool() && m_show_tray_icon;
if (!settings.contains("fMinimizeOnClose"))
settings.setValue("fMinimizeOnClose", false);
@@ -122,6 +124,13 @@ void OptionsModel::Init(bool resetSettings)
if (!gArgs.SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool()))
addOverriddenOption("-upnp");
+ if (!settings.contains("fUseNatpmp")) {
+ settings.setValue("fUseNatpmp", DEFAULT_NATPMP);
+ }
+ if (!gArgs.SoftSetBoolArg("-natpmp", settings.value("fUseNatpmp").toBool())) {
+ addOverriddenOption("-natpmp");
+ }
+
if (!settings.contains("fListen"))
settings.setValue("fListen", DEFAULT_LISTEN);
if (!gArgs.SoftSetBoolArg("-listen", settings.value("fListen").toBool()))
@@ -272,8 +281,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
{
case StartAtStartup:
return GUIUtil::GetStartOnSystemStartup();
- case HideTrayIcon:
- return fHideTrayIcon;
+ case ShowTrayIcon:
+ return m_show_tray_icon;
case MinimizeToTray:
return fMinimizeToTray;
case MapPortUPnP:
@@ -281,7 +290,13 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return settings.value("fUseUPnP");
#else
return false;
-#endif
+#endif // USE_UPNP
+ case MapPortNatpmp:
+#ifdef USE_NATPMP
+ return settings.value("fUseNatpmp");
+#else
+ return false;
+#endif // USE_NATPMP
case MinimizeOnClose:
return fMinimizeOnClose;
@@ -342,10 +357,10 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
case StartAtStartup:
successful = GUIUtil::SetStartOnSystemStartup(value.toBool());
break;
- case HideTrayIcon:
- fHideTrayIcon = value.toBool();
- settings.setValue("fHideTrayIcon", fHideTrayIcon);
- Q_EMIT hideTrayIconChanged(fHideTrayIcon);
+ case ShowTrayIcon:
+ m_show_tray_icon = value.toBool();
+ settings.setValue("fHideTrayIcon", !m_show_tray_icon);
+ Q_EMIT showTrayIconChanged(m_show_tray_icon);
break;
case MinimizeToTray:
fMinimizeToTray = value.toBool();
@@ -353,7 +368,9 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
break;
case MapPortUPnP: // core option - can be changed on-the-fly
settings.setValue("fUseUPnP", value.toBool());
- node().mapPort(value.toBool());
+ break;
+ case MapPortNatpmp: // core option - can be changed on-the-fly
+ settings.setValue("fUseNatpmp", value.toBool());
break;
case MinimizeOnClose:
fMinimizeOnClose = value.toBool();
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 3d9e7bbb80..f7171951a1 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -45,9 +45,10 @@ public:
enum OptionID {
StartAtStartup, // bool
- HideTrayIcon, // bool
+ ShowTrayIcon, // bool
MinimizeToTray, // bool
MapPortUPnP, // bool
+ MapPortNatpmp, // bool
MinimizeOnClose, // bool
ProxyUse, // bool
ProxyIP, // QString
@@ -78,7 +79,7 @@ public:
void setDisplayUnit(const QVariant &value);
/* Explicit getters */
- bool getHideTrayIcon() const { return fHideTrayIcon; }
+ bool getShowTrayIcon() const { return m_show_tray_icon; }
bool getMinimizeToTray() const { return fMinimizeToTray; }
bool getMinimizeOnClose() const { return fMinimizeOnClose; }
int getDisplayUnit() const { return nDisplayUnit; }
@@ -100,7 +101,7 @@ public:
private:
interfaces::Node* m_node = nullptr;
/* Qt-only settings */
- bool fHideTrayIcon;
+ bool m_show_tray_icon;
bool fMinimizeToTray;
bool fMinimizeOnClose;
QString language;
@@ -118,7 +119,7 @@ private:
Q_SIGNALS:
void displayUnitChanged(int unit);
void coinControlFeaturesChanged(bool);
- void hideTrayIconChanged(bool);
+ void showTrayIconChanged(bool);
};
#endif // BITCOIN_QT_OPTIONSMODEL_H
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index 1297eb8b75..cca4dce624 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h
index 4cf673b6a6..578ef601fb 100644
--- a/src/qt/overviewpage.h
+++ b/src/qt/overviewpage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 86d681aa6f..96f6202874 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index eaf2bafe59..08b83244ab 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 5220f8e138..bad81d894c 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -29,14 +29,16 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine
return pLeft->nodeid < pRight->nodeid;
case PeerTableModel::Address:
return pLeft->addrName.compare(pRight->addrName) < 0;
- case PeerTableModel::Subversion:
- return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
+ case PeerTableModel::Network:
+ return pLeft->m_network < pRight->m_network;
case PeerTableModel::Ping:
return pLeft->m_min_ping_usec < pRight->m_min_ping_usec;
case PeerTableModel::Sent:
return pLeft->nSendBytes < pRight->nSendBytes;
case PeerTableModel::Received:
return pLeft->nRecvBytes < pRight->nRecvBytes;
+ case PeerTableModel::Subversion:
+ return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
}
return false;
@@ -104,7 +106,6 @@ PeerTableModel::PeerTableModel(interfaces::Node& node, QObject* parent) :
m_node(node),
timer(nullptr)
{
- columns << tr("NodeId") << tr("Node/Service") << tr("Ping") << tr("Sent") << tr("Received") << tr("User Agent");
priv.reset(new PeerTablePriv());
// set up timer for auto refresh
@@ -133,13 +134,17 @@ void PeerTableModel::stopAutoRefresh()
int PeerTableModel::rowCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
+ if (parent.isValid()) {
+ return 0;
+ }
return priv->size();
}
int PeerTableModel::columnCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
+ if (parent.isValid()) {
+ return 0;
+ }
return columns.length();
}
@@ -158,17 +163,21 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const
case Address:
// prepend to peer address down-arrow symbol for inbound connection and up-arrow for outbound connection
return QString(rec->nodeStats.fInbound ? "↓ " : "↑ ") + QString::fromStdString(rec->nodeStats.addrName);
- case Subversion:
- return QString::fromStdString(rec->nodeStats.cleanSubVer);
+ case Network:
+ return GUIUtil::NetworkToQString(rec->nodeStats.m_network);
case Ping:
return GUIUtil::formatPingTime(rec->nodeStats.m_min_ping_usec);
case Sent:
return GUIUtil::formatBytes(rec->nodeStats.nSendBytes);
case Received:
return GUIUtil::formatBytes(rec->nodeStats.nRecvBytes);
+ case Subversion:
+ return QString::fromStdString(rec->nodeStats.cleanSubVer);
}
} else if (role == Qt::TextAlignmentRole) {
switch (index.column()) {
+ case Network:
+ return QVariant(Qt::AlignCenter);
case Ping:
case Sent:
case Received:
@@ -176,6 +185,11 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const
default:
return QVariant();
}
+ } else if (role == StatsRole) {
+ switch (index.column()) {
+ case NetNodeId: return QVariant::fromValue(rec);
+ default: return QVariant();
+ }
}
return QVariant();
@@ -211,11 +225,6 @@ QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent
return QModelIndex();
}
-const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx)
-{
- return priv->index(idx);
-}
-
void PeerTableModel::refresh()
{
Q_EMIT layoutAboutToBeChanged();
diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h
index 99de772ac0..7bff239507 100644
--- a/src/qt/peertablemodel.h
+++ b/src/qt/peertablemodel.h
@@ -28,6 +28,7 @@ struct CNodeCombinedStats {
CNodeStateStats nodeStateStats;
bool fNodeStateStatsAvailable;
};
+Q_DECLARE_METATYPE(CNodeCombinedStats*)
class NodeLessThan
{
@@ -52,7 +53,6 @@ class PeerTableModel : public QAbstractTableModel
public:
explicit PeerTableModel(interfaces::Node& node, QObject* parent);
~PeerTableModel();
- const CNodeCombinedStats *getNodeStats(int idx);
int getRowByNodeId(NodeId nodeid);
void startAutoRefresh();
void stopAutoRefresh();
@@ -60,10 +60,15 @@ public:
enum ColumnIndex {
NetNodeId = 0,
Address = 1,
- Ping = 2,
- Sent = 3,
- Received = 4,
- Subversion = 5
+ Network = 2,
+ Ping = 3,
+ Sent = 4,
+ Received = 5,
+ Subversion = 6
+ };
+
+ enum {
+ StatsRole = Qt::UserRole,
};
/** @name Methods overridden from QAbstractTableModel
@@ -82,7 +87,7 @@ public Q_SLOTS:
private:
interfaces::Node& m_node;
- QStringList columns;
+ const QStringList columns{tr("Peer Id"), tr("Address"), tr("Network"), tr("Ping"), tr("Sent"), tr("Received"), tr("User Agent")};
std::unique_ptr<PeerTablePriv> priv;
QTimer *timer;
};
diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp
index 141f4abb3b..490826cbbb 100644
--- a/src/qt/qrimagewidget.cpp
+++ b/src/qt/qrimagewidget.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/qrimagewidget.h b/src/qt/qrimagewidget.h
index a031bd7632..5dbba074a1 100644
--- a/src/qt/qrimagewidget.h
+++ b/src/qt/qrimagewidget.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h
index 2c72b2ecda..b32305f5e1 100644
--- a/src/qt/qvalidatedlineedit.h
+++ b/src/qt/qvalidatedlineedit.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index d374d610ee..1a9cd78d1e 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h
index 27455e2906..9b89bd6a8b 100644
--- a/src/qt/receivecoinsdialog.h
+++ b/src/qt/receivecoinsdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index d385c42821..bef3edc5fe 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h
index 846478643d..c861680761 100644
--- a/src/qt/receiverequestdialog.h
+++ b/src/qt/receiverequestdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp
index 3e20368a36..18b913774b 100644
--- a/src/qt/recentrequeststablemodel.cpp
+++ b/src/qt/recentrequeststablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -36,15 +36,17 @@ RecentRequestsTableModel::~RecentRequestsTableModel()
int RecentRequestsTableModel::rowCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
-
+ if (parent.isValid()) {
+ return 0;
+ }
return list.length();
}
int RecentRequestsTableModel::columnCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
-
+ if (parent.isValid()) {
+ return 0;
+ }
return columns.length();
}
diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h
index c0bd3461bb..b817b64e77 100644
--- a/src/qt/recentrequeststablemodel.h
+++ b/src/qt/recentrequeststablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/res/animation/makespinner.sh b/src/qt/res/animation/makespinner.sh
index 4fa8dadf86..83142f5034 100755
--- a/src/qt/res/animation/makespinner.sh
+++ b/src/qt/res/animation/makespinner.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2014-2019 The Bitcoin Core developers
+# Copyright (c) 2014-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 236c6e13d5..df98dbbc99 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -457,10 +457,13 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center());
}
+ ui->splitter->restoreState(settings.value("PeersTabSplitterSizes").toByteArray());
+
QChar nonbreaking_hyphen(8209);
ui->dataDir->setToolTip(ui->dataDir->toolTip().arg(QString(nonbreaking_hyphen) + "datadir"));
ui->blocksDir->setToolTip(ui->blocksDir->toolTip().arg(QString(nonbreaking_hyphen) + "blocksdir"));
ui->openDebugLogfileButton->setToolTip(ui->openDebugLogfileButton->toolTip().arg(PACKAGE_NAME));
+ ui->peerConnectionTypeLabel->setToolTip(ui->peerConnectionTypeLabel->toolTip().arg("addnode").arg(QString(nonbreaking_hyphen) + "addnode").arg(QString(nonbreaking_hyphen) + "connect"));
if (platformStyle->getImagesOnButtons()) {
ui->openDebugLogfileButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
@@ -502,6 +505,7 @@ RPCConsole::~RPCConsole()
{
QSettings settings;
settings.setValue("RPCConsoleWindowGeometry", saveGeometry());
+ settings.setValue("PeersTabSplitterSizes", ui->splitter->saveState());
m_node.rpcUnsetTimerInterface(rpcTimerInterface);
delete rpcTimerInterface;
delete ui;
@@ -1018,11 +1022,9 @@ void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
void RPCConsole::peerLayoutAboutToChange()
{
- QModelIndexList selected = ui->peerWidget->selectionModel()->selectedIndexes();
cachedNodeids.clear();
- for(int i = 0; i < selected.size(); i++)
- {
- const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.at(i).row());
+ for (const QModelIndex& peer : GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId)) {
+ const auto stats = peer.data(PeerTableModel::StatsRole).value<CNodeCombinedStats*>();
cachedNodeids.append(stats->nodeStats.nodeid);
}
}
@@ -1081,18 +1083,16 @@ void RPCConsole::peerLayoutChanged()
void RPCConsole::updateDetailWidget()
{
- QModelIndexList selected_rows;
- auto selection_model = ui->peerWidget->selectionModel();
- if (selection_model) selected_rows = selection_model->selectedRows();
- if (!clientModel || !clientModel->getPeerTableModel() || selected_rows.size() != 1) {
+ const QList<QModelIndex> selected_peers = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);
+ if (!clientModel || !clientModel->getPeerTableModel() || selected_peers.size() != 1) {
ui->detailWidget->hide();
ui->peerHeading->setText(tr("Select a peer to view detailed information."));
return;
}
- const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected_rows.first().row());
+ const auto stats = selected_peers.first().data(PeerTableModel::StatsRole).value<CNodeCombinedStats*>();
// update the detail ui with latest node information
QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " ");
- peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid));
+ peerAddrDetails += tr("(peer id: %1)").arg(QString::number(stats->nodeStats.nodeid));
if (!stats->nodeStats.addrLocal.empty())
peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
ui->peerHeading->setText(peerAddrDetails);
@@ -1108,8 +1108,8 @@ void RPCConsole::updateDetailWidget()
ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset));
ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion));
ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
- ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound"));
- ui->peerHeight->setText(QString::number(stats->nodeStats.nStartingHeight));
+ ui->peerConnectionType->setText(GUIUtil::ConnectionTypeToQString(stats->nodeStats.m_conn_type));
+ ui->peerNetwork->setText(GUIUtil::NetworkToQString(stats->nodeStats.m_network));
if (stats->nodeStats.m_permissionFlags == PF_NONE) {
ui->peerPermissions->setText(tr("N/A"));
} else {
@@ -1135,6 +1135,8 @@ void RPCConsole::updateDetailWidget()
ui->peerCommonHeight->setText(QString("%1").arg(stats->nodeStateStats.nCommonHeight));
else
ui->peerCommonHeight->setText(tr("Unknown"));
+
+ ui->peerHeight->setText(QString::number(stats->nodeStateStats.m_starting_height));
}
ui->detailWidget->show();
@@ -1200,19 +1202,9 @@ void RPCConsole::banSelectedNode(int bantime)
if (!clientModel)
return;
- // Get selected peer addresses
- QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);
- for(int i = 0; i < nodes.count(); i++)
- {
- // Get currently selected peer address
- NodeId id = nodes.at(i).data().toLongLong();
-
- // Get currently selected peer address
- int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id);
- if (detailNodeRow < 0) return;
-
+ for (const QModelIndex& peer : GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId)) {
// Find possible nodes, ban it and clear the selected node
- const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
+ const auto stats = peer.data(PeerTableModel::StatsRole).value<CNodeCombinedStats*>();
if (stats) {
m_node.ban(stats->nodeStats.addr, bantime);
m_node.disconnectByAddress(stats->nodeStats.addr);
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 8fea08ab5c..5f308dc36d 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 8a62c64d79..e765e643a3 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -35,7 +35,7 @@
#include <QSettings>
#include <QTextDocument>
-static const std::array<int, 9> confTargets = { {2, 4, 6, 12, 24, 48, 144, 504, 1008} };
+static constexpr std::array confTargets{2, 4, 6, 12, 24, 48, 144, 504, 1008};
int getConfTargetForIndex(int index) {
if (index+1 > static_cast<int>(confTargets.size())) {
return confTargets.back();
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index 8519f1f65b..8e241d3901 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/sendcoinsrecipient.h b/src/qt/sendcoinsrecipient.h
index 6619faf417..01135cdfef 100644
--- a/src/qt/sendcoinsrecipient.h
+++ b/src/qt/sendcoinsrecipient.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 4835dd7954..6c110f0688 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -120,7 +120,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
return;
}
- const PKHash* pkhash = boost::get<PKHash>(&destination);
+ const PKHash* pkhash = std::get_if<PKHash>(&destination);
if (!pkhash) {
ui->addressIn_SM->setValid(false);
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
diff --git a/src/qt/signverifymessagedialog.h b/src/qt/signverifymessagedialog.h
index d33a2d038d..d98cb290a1 100644
--- a/src/qt/signverifymessagedialog.h
+++ b/src/qt/signverifymessagedialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2015 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h
index d49fd87055..386039291c 100644
--- a/src/qt/splashscreen.h
+++ b/src/qt/splashscreen.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/addressbooktests.h b/src/qt/test/addressbooktests.h
index e6d24f202f..ab52206466 100644
--- a/src/qt/test/addressbooktests.h
+++ b/src/qt/test/addressbooktests.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp
index ea7b5f0c9e..24d7735447 100644
--- a/src/qt/test/rpcnestedtests.cpp
+++ b/src/qt/test/rpcnestedtests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -43,41 +43,41 @@ void RPCNestedTests::rpcNestedTests()
tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]);
TestingSetup test;
+ m_node.setContext(&test.m_node);
if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
std::string result;
std::string result2;
std::string filtered;
- interfaces::Node* node = &m_node;
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
QVERIFY(result=="main");
QVERIFY(filtered == "getblockchaininfo()[chain]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())"); //simple 2 level nesting
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getblock(getbestblockhash())[hash], true)");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getbestblockhash())"); //simple 2 level nesting
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getblock(getbestblockhash())[hash], true)");
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo");
QVERIFY(result.substr(0,1) == "{");
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()");
QVERIFY(result.substr(0,1) == "{");
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo "); //whitespace at the end will be tolerated
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo "); //whitespace at the end will be tolerated
QVERIFY(result.substr(0,1) == "{");
- (RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child containing the quotes in the key
+ (RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child containing the quotes in the key
QVERIFY(result == "null");
- (RPCConsole::RPCExecuteCommandLine(*node, result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed
- (RPCConsole::RPCExecuteCommandLine(*node, result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed
+ (RPCConsole::RPCExecuteCommandLine(m_node, result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed
+ (RPCConsole::RPCExecuteCommandLine(m_node, result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed
QVERIFY(result == result2);
- (RPCConsole::RPCExecuteCommandLine(*node, result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parameters is allowed
+ (RPCConsole::RPCExecuteCommandLine(m_node, result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parameters is allowed
QVERIFY(result == result2);
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())[tx][0]", &filtered);
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getbestblockhash())[tx][0]", &filtered);
QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]");
@@ -102,35 +102,35 @@ void RPCNestedTests::rpcNestedTests()
RPCConsole::RPCParseCommandLine(nullptr, result, "help(importprivkey(abc), walletpassphrase(def))", false, &filtered);
QVERIFY(filtered == "help(importprivkey(…), walletpassphrase(…))");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest");
QVERIFY(result == "[]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest ''");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest ''");
QVERIFY(result == "[\"\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest \"\"");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest \"\"");
QVERIFY(result == "[\"\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest '' abc");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest '' abc");
QVERIFY(result == "[\"\",\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc '' abc");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc '' abc");
QVERIFY(result == "[\"abc\",\"\",\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc abc");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc abc");
QVERIFY(result == "[\"abc\",\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc\t\tabc");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc\t\tabc");
QVERIFY(result == "[\"abc\",\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc )");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc )");
QVERIFY(result == "[\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest( abc )");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest( abc )");
QVERIFY(result == "[\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest( abc , cba )");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest( abc , cba )");
QVERIFY(result == "[\"abc\",\"cba\"]");
// do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3)
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
- (RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments
- (RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()()()")); //tolerate non command brackts
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo(True)"), UniValue); //invalid argument
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "a(getblockchaininfo(True))"), UniValue); //method not found
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using ,
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using ,
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
+ (RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments
+ (RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()()()")); //tolerate non command brackets
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo(True)"), UniValue); //invalid argument
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "a(getblockchaininfo(True))"), UniValue); //method not found
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tolerate empty arguments when using ,
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tolerate empty arguments when using ,
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tolerate empty arguments when using ,
}
diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h
index 320275129d..28dc7140e1 100644
--- a/src/qt/test/rpcnestedtests.h
+++ b/src/qt/test/rpcnestedtests.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 86356b43c8..9ef5fe8fc7 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/util.cpp b/src/qt/test/util.cpp
index 759832381b..987d921f03 100644
--- a/src/qt/test/util.cpp
+++ b/src/qt/test/util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/util.h b/src/qt/test/util.h
index 950314da3b..df5931a032 100644
--- a/src/qt/test/util.h
+++ b/src/qt/test/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/wallettests.h b/src/qt/test/wallettests.h
index dfca3370f7..6044bedb1d 100644
--- a/src/qt/test/wallettests.h
+++ b/src/qt/test/wallettests.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp
index 6428fc4daf..dabdf9d887 100644
--- a/src/qt/trafficgraphwidget.cpp
+++ b/src/qt/trafficgraphwidget.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/transactiondescdialog.cpp b/src/qt/transactiondescdialog.cpp
index 715e312b19..b547bf7645 100644
--- a/src/qt/transactiondescdialog.cpp
+++ b/src/qt/transactiondescdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h
index d6bb84f7e6..693b363692 100644
--- a/src/qt/transactionfilterproxy.h
+++ b/src/qt/transactionfilterproxy.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 632a18de5c..77fec93f0f 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -123,7 +123,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface
continue;
}
- if (!boost::get<CNoDestination>(&wtx.txout_address[nOut]))
+ if (!std::get_if<CNoDestination>(&wtx.txout_address[nOut]))
{
// Sent to Bitcoin Address
sub.type = TransactionRecord::SendToAddress;
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index c983c527c0..e10243a28a 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 3148089b52..05b250eea9 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -289,13 +289,17 @@ void TransactionTableModel::updateConfirmations()
int TransactionTableModel::rowCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
+ if (parent.isValid()) {
+ return 0;
+ }
return priv->size();
}
int TransactionTableModel::columnCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
+ if (parent.isValid()) {
+ return 0;
+ }
return columns.length();
}
diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h
index 4b699d4d7d..f8576edd59 100644
--- a/src/qt/transactiontablemodel.h
+++ b/src/qt/transactiontablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index e14e22e9de..0cf6480b82 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 9ce7f4ad97..b268823066 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index 83f3cccbff..7a89325ddf 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -152,7 +152,7 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wal
connect(wallet_model, &WalletModel::unload, this, [this, wallet_model] {
// Defer removeAndDeleteWallet when no modal widget is active.
- // TODO: remove this workaround by removing usage of QDiallog::exec.
+ // TODO: remove this workaround by removing usage of QDialog::exec.
if (QApplication::activeModalWidget()) {
connect(qApp, &QApplication::focusWindowChanged, wallet_model, [this, wallet_model]() {
if (!QApplication::activeModalWidget()) {
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index 271ddfc6c2..f57f8678d6 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/randomenv.cpp b/src/randomenv.cpp
index 5e07c3db40..9248db1539 100644
--- a/src/randomenv.cpp
+++ b/src/randomenv.cpp
@@ -69,7 +69,7 @@ void RandAddSeedPerfmon(CSHA512& hasher)
// This can take up to 2 seconds, so only do it every 10 minutes.
// Initialize last_perfmon to 0 seconds, we don't skip the first call.
- static std::atomic<std::chrono::seconds> last_perfmon{std::chrono::seconds{0}};
+ static std::atomic<std::chrono::seconds> last_perfmon{0s};
auto last_time = last_perfmon.load();
auto current_time = GetTime<std::chrono::seconds>();
if (current_time < last_time + std::chrono::minutes{10}) return;
diff --git a/src/rest.cpp b/src/rest.cpp
index 949cc9d84a..678ffdb760 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 392073d047..689a8165ab 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -17,6 +17,7 @@
#include <node/coinstats.h>
#include <node/context.h>
#include <node/utxo_snapshot.h>
+#include <policy/fees.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@@ -65,7 +66,7 @@ NodeContext& EnsureNodeContext(const util::Ref& context)
CTxMemPool& EnsureMemPool(const util::Ref& context)
{
- NodeContext& node = EnsureNodeContext(context);
+ const NodeContext& node = EnsureNodeContext(context);
if (!node.mempool) {
throw JSONRPCError(RPC_CLIENT_MEMPOOL_DISABLED, "Mempool disabled or instance not found");
}
@@ -74,13 +75,22 @@ CTxMemPool& EnsureMemPool(const util::Ref& context)
ChainstateManager& EnsureChainman(const util::Ref& context)
{
- NodeContext& node = EnsureNodeContext(context);
+ const NodeContext& node = EnsureNodeContext(context);
if (!node.chainman) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node chainman not found");
}
return *node.chainman;
}
+CBlockPolicyEstimator& EnsureFeeEstimator(const util::Ref& context)
+{
+ NodeContext& node = EnsureNodeContext(context);
+ if (!node.fee_estimator) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Fee estimation disabled");
+ }
+ return *node.fee_estimator;
+}
+
/* Calculate the difficulty for a given block index.
*/
double GetDifficulty(const CBlockIndex* blockindex)
@@ -162,16 +172,21 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn
result.pushKV("versionHex", strprintf("%08x", block.nVersion));
result.pushKV("merkleroot", block.hashMerkleRoot.GetHex());
UniValue txs(UniValue::VARR);
- for(const auto& tx : block.vtx)
- {
- if(txDetails)
- {
+ if (txDetails) {
+ CBlockUndo blockUndo;
+ const bool have_undo = !IsBlockPruned(blockindex) && UndoReadFromDisk(blockUndo, blockindex);
+ for (size_t i = 0; i < block.vtx.size(); ++i) {
+ const CTransactionRef& tx = block.vtx.at(i);
+ // coinbase transaction (i == 0) doesn't have undo data
+ const CTxUndo* txundo = (have_undo && i) ? &blockUndo.vtxundo.at(i - 1) : nullptr;
UniValue objTx(UniValue::VOBJ);
- TxToUniv(*tx, uint256(), objTx, true, RPCSerializationFlags());
+ TxToUniv(*tx, uint256(), objTx, true, RPCSerializationFlags(), txundo);
txs.push_back(objTx);
}
- else
+ } else {
+ for (const CTransactionRef& tx : block.vtx) {
txs.push_back(tx->GetHash().GetHex());
+ }
}
result.pushKV("tx", txs);
result.pushKV("time", block.GetBlockTime());
@@ -926,6 +941,7 @@ static RPCHelpMan getblock()
{RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::ELISION, "", "The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result"},
+ {RPCResult::Type::NUM, "fee", "The transaction fee in " + CURRENCY_UNIT + ", omitted if block undo data is not available"},
}},
}},
}},
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index 5b362bf211..e4ce80400e 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,6 +15,7 @@ extern RecursiveMutex cs_main;
class CBlock;
class CBlockIndex;
+class CBlockPolicyEstimator;
class CTxMemPool;
class ChainstateManager;
class UniValue;
@@ -54,5 +55,6 @@ void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES],
NodeContext& EnsureNodeContext(const util::Ref& context);
CTxMemPool& EnsureMemPool(const util::Ref& context);
ChainstateManager& EnsureChainman(const util::Ref& context);
+CBlockPolicyEstimator& EnsureFeeEstimator(const util::Ref& context);
#endif
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 7d45ad9434..52e033d0cc 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -1022,21 +1022,19 @@ static RPCHelpMan submitheader()
static RPCHelpMan estimatesmartfee()
{
return RPCHelpMan{"estimatesmartfee",
- "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
- "confirmation within conf_target blocks if possible and return the number of blocks\n"
- "for which the estimate is valid. Uses virtual transaction size as defined\n"
- "in BIP 141 (witness data is discounted).\n",
- {
- {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
- {"estimate_mode", RPCArg::Type::STR, /* default */ "CONSERVATIVE", "The fee estimate mode.\n"
+ "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
+ "confirmation within conf_target blocks if possible and return the number of blocks\n"
+ "for which the estimate is valid. Uses virtual transaction size as defined\n"
+ "in BIP 141 (witness data is discounted).\n",
+ {
+ {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "conservative", "The fee estimate mode.\n"
" Whether to return a more conservative estimate which also satisfies\n"
" a longer history. A conservative estimate potentially returns a\n"
" higher feerate and is more likely to be sufficient for the desired\n"
" target, but is not as responsive to short term drops in the\n"
- " prevailing fee market. Must be one of:\n"
- " \"UNSET\"\n"
- " \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\""},
+ " prevailing fee market. Must be one of (case insensitive):\n"
+ "\"" + FeeModes("\"\n\"") + "\""},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -1059,7 +1057,10 @@ static RPCHelpMan estimatesmartfee()
{
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
- unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+
+ CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(request.context);
+
+ unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
bool conservative = true;
if (!request.params[1].isNull()) {
@@ -1073,7 +1074,7 @@ static RPCHelpMan estimatesmartfee()
UniValue result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
FeeCalculation feeCalc;
- CFeeRate feeRate = ::feeEstimator.estimateSmartFee(conf_target, &feeCalc, conservative);
+ CFeeRate feeRate = fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative);
if (feeRate != CFeeRate(0)) {
result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
} else {
@@ -1144,7 +1145,10 @@ static RPCHelpMan estimaterawfee()
{
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
- unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+
+ CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(request.context);
+
+ unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
double threshold = 0.95;
if (!request.params[1].isNull()) {
@@ -1156,14 +1160,14 @@ static RPCHelpMan estimaterawfee()
UniValue result(UniValue::VOBJ);
- for (const FeeEstimateHorizon horizon : {FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}) {
+ for (const FeeEstimateHorizon horizon : ALL_FEE_ESTIMATE_HORIZONS) {
CFeeRate feeRate;
EstimationResult buckets;
// Only output results for horizons which track the target
- if (conf_target > ::feeEstimator.HighestTargetTracked(horizon)) continue;
+ if (conf_target > fee_estimator.HighestTargetTracked(horizon)) continue;
- feeRate = ::feeEstimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
+ feeRate = fee_estimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
UniValue horizon_result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
UniValue passbucket(UniValue::VOBJ);
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index e72ef24d12..cfca8b4ad4 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -5,6 +5,7 @@
#include <rpc/server.h>
#include <banman.h>
+#include <chainparams.h>
#include <clientversion.h>
#include <core_io.h>
#include <net.h>
@@ -126,21 +127,19 @@ static RPCHelpMan getpeerinfo()
{RPCResult::Type::NUM, "version", "The peer version, such as 70001"},
{RPCResult::Type::STR, "subver", "The string version"},
{RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
- {RPCResult::Type::BOOL, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n"
- "(DEPRECATED, returned only if the config option -deprecatedrpc=getpeerinfo_addnode is passed)"},
- {RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + ".\n"
- "Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"
- "best capture connection behaviors."},
+ {RPCResult::Type::BOOL, "bip152_hb_to", "Whether we selected peer as (compact blocks) high-bandwidth peer"},
+ {RPCResult::Type::BOOL, "bip152_hb_from", "Whether peer selected us as (compact blocks) high-bandwidth peer"},
{RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
- {RPCResult::Type::NUM, "banscore", "The ban score (DEPRECATED, returned only if config option -deprecatedrpc=banscore is passed)"},
{RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
{RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
{RPCResult::Type::ARR, "inflight", "",
{
{RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
}},
- {RPCResult::Type::BOOL, "whitelisted", /* optional */ true, "Whether the peer is whitelisted with default permissions\n"
- "(DEPRECATED, returned only if config option -deprecatedrpc=whitelisted is passed)"},
+ {RPCResult::Type::ARR, "permissions", "Any special permissions that have been granted to this peer",
+ {
+ {RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
+ }},
{RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
{RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
{
@@ -155,6 +154,9 @@ static RPCHelpMan getpeerinfo()
"Only known message types can appear as keys in the object and all bytes received\n"
"of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'."}
}},
+ {RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + ".\n"
+ "Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"
+ "best capture connection behaviors."},
}},
}},
},
@@ -165,8 +167,9 @@ static RPCHelpMan getpeerinfo()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
- if(!node.connman)
+ if(!node.connman || !node.peerman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ }
std::vector<CNodeStats> vstats;
node.connman->GetNodeStats(vstats);
@@ -176,7 +179,7 @@ static RPCHelpMan getpeerinfo()
for (const CNodeStats& stats : vstats) {
UniValue obj(UniValue::VOBJ);
CNodeStateStats statestats;
- bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
+ bool fStateStats = node.peerman->GetNodeStateStats(stats.nodeid, statestats);
obj.pushKV("id", stats.nodeid);
obj.pushKV("addr", stats.addrName);
if (stats.addrBind.IsValid()) {
@@ -185,7 +188,7 @@ static RPCHelpMan getpeerinfo()
if (!(stats.addrLocal.empty())) {
obj.pushKV("addrlocal", stats.addrLocal);
}
- obj.pushKV("network", stats.m_network);
+ obj.pushKV("network", GetNetworkName(stats.m_network));
if (stats.m_mapped_as != 0) {
obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
}
@@ -215,16 +218,10 @@ static RPCHelpMan getpeerinfo()
// their ver message.
obj.pushKV("subver", stats.cleanSubVer);
obj.pushKV("inbound", stats.fInbound);
- if (IsDeprecatedRPCEnabled("getpeerinfo_addnode")) {
- // addnode is deprecated in v0.21 for removal in v0.22
- obj.pushKV("addnode", stats.m_manual_connection);
- }
- obj.pushKV("startingheight", stats.nStartingHeight);
+ obj.pushKV("bip152_hb_to", stats.m_bip152_highbandwidth_to);
+ obj.pushKV("bip152_hb_from", stats.m_bip152_highbandwidth_from);
if (fStateStats) {
- if (IsDeprecatedRPCEnabled("banscore")) {
- // banscore is deprecated in v0.21 for removal in v0.22
- obj.pushKV("banscore", statestats.m_misbehavior_score);
- }
+ obj.pushKV("startingheight", statestats.m_starting_height);
obj.pushKV("synced_headers", statestats.nSyncHeight);
obj.pushKV("synced_blocks", statestats.nCommonHeight);
UniValue heights(UniValue::VARR);
@@ -233,10 +230,6 @@ static RPCHelpMan getpeerinfo()
}
obj.pushKV("inflight", heights);
}
- if (IsDeprecatedRPCEnabled("whitelisted")) {
- // whitelisted is deprecated in v0.21 for removal in v0.22
- obj.pushKV("whitelisted", stats.m_legacyWhitelisted);
- }
UniValue permissions(UniValue::VARR);
for (const auto& permission : NetPermissions::ToStrings(stats.m_permissionFlags)) {
permissions.push_back(permission);
@@ -257,7 +250,7 @@ static RPCHelpMan getpeerinfo()
recvPerMsgCmd.pushKV(i.first, i.second);
}
obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
- obj.pushKV("connection_type", stats.m_conn_type_string);
+ obj.pushKV("connection_type", ConnectionTypeAsString(stats.m_conn_type));
ret.push_back(obj);
}
@@ -322,6 +315,61 @@ static RPCHelpMan addnode()
};
}
+static RPCHelpMan addconnection()
+{
+ return RPCHelpMan{"addconnection",
+ "\nOpen an outbound connection to a specified node. This RPC is for testing only.\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address and port to attempt connecting to."},
+ {"connection_type", RPCArg::Type::STR, RPCArg::Optional::NO, "Type of connection to open, either \"outbound-full-relay\" or \"block-relay-only\"."},
+ },
+ RPCResult{
+ RPCResult::Type::OBJ, "", "",
+ {
+ { RPCResult::Type::STR, "address", "Address of newly added connection." },
+ { RPCResult::Type::STR, "connection_type", "Type of connection opened." },
+ }},
+ RPCExamples{
+ HelpExampleCli("addconnection", "\"192.168.0.6:8333\" \"outbound-full-relay\"")
+ + HelpExampleRpc("addconnection", "\"192.168.0.6:8333\" \"outbound-full-relay\"")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+{
+ if (Params().NetworkIDString() != CBaseChainParams::REGTEST) {
+ throw std::runtime_error("addconnection is for regression testing (-regtest mode) only.");
+ }
+
+ RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VSTR});
+ const std::string address = request.params[0].get_str();
+ const std::string conn_type_in{TrimString(request.params[1].get_str())};
+ ConnectionType conn_type{};
+ if (conn_type_in == "outbound-full-relay") {
+ conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
+ } else if (conn_type_in == "block-relay-only") {
+ conn_type = ConnectionType::BLOCK_RELAY;
+ } else {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, self.ToString());
+ }
+
+ NodeContext& node = EnsureNodeContext(request.context);
+ if (!node.connman) {
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled.");
+ }
+
+ const bool success = node.connman->AddConnection(address, conn_type);
+ if (!success) {
+ throw JSONRPCError(RPC_CLIENT_NODE_CAPACITY_REACHED, "Error: Already at capacity for specified connection type.");
+ }
+
+ UniValue info(UniValue::VOBJ);
+ info.pushKV("address", address);
+ info.pushKV("connection_type", conn_type_in);
+
+ return info;
+},
+ };
+}
+
static RPCHelpMan disconnectnode()
{
return RPCHelpMan{"disconnectnode",
@@ -482,12 +530,12 @@ static RPCHelpMan getnettotals()
obj.pushKV("timemillis", GetTimeMillis());
UniValue outboundLimit(UniValue::VOBJ);
- outboundLimit.pushKV("timeframe", node.connman->GetMaxOutboundTimeframe());
+ outboundLimit.pushKV("timeframe", count_seconds(node.connman->GetMaxOutboundTimeframe()));
outboundLimit.pushKV("target", node.connman->GetMaxOutboundTarget());
outboundLimit.pushKV("target_reached", node.connman->OutboundTargetReached(false));
outboundLimit.pushKV("serve_historical_blocks", !node.connman->OutboundTargetReached(true));
outboundLimit.pushKV("bytes_left_in_cycle", node.connman->GetOutboundTargetBytesLeft());
- outboundLimit.pushKV("time_left_in_cycle", node.connman->GetMaxOutboundTimeLeftInCycle());
+ outboundLimit.pushKV("time_left_in_cycle", count_seconds(node.connman->GetMaxOutboundTimeLeftInCycle()));
obj.pushKV("uploadtarget", outboundLimit);
return obj;
},
@@ -577,7 +625,9 @@ static RPCHelpMan getnetworkinfo()
obj.pushKV("localservices", strprintf("%016x", services));
obj.pushKV("localservicesnames", GetServicesNames(services));
}
- obj.pushKV("localrelay", g_relay_txes);
+ if (node.peerman) {
+ obj.pushKV("localrelay", !node.peerman->IgnoresIncomingTxs());
+ }
obj.pushKV("timeoffset", GetTimeOffset());
if (node.connman) {
obj.pushKV("networkactive", node.connman->GetNetworkActive());
@@ -906,6 +956,8 @@ static const CRPCCommand commands[] =
{ "network", "clearbanned", &clearbanned, {} },
{ "network", "setnetworkactive", &setnetworkactive, {"state"} },
{ "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
+
+ { "hidden", "addconnection", &addconnection, {"address", "connection_type"} },
{ "hidden", "addpeeraddress", &addpeeraddress, {"address", "port"} },
};
// clang-format on
diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h
index d1475f452d..c8ceb2c186 100644
--- a/src/rpc/protocol.h
+++ b/src/rpc/protocol.h
@@ -62,6 +62,7 @@ enum RPCErrorCode
RPC_CLIENT_NODE_NOT_CONNECTED = -29, //!< Node to disconnect not found in connected nodes
RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //!< Invalid IP/Subnet
RPC_CLIENT_P2P_DISABLED = -31, //!< No valid connection manager instance found
+ RPC_CLIENT_NODE_CAPACITY_REACHED= -34, //!< Max number of outbound or block-relay connections already open
//! Chain errors
RPC_CLIENT_MEMPOOL_DISABLED = -33, //!< No mempool instance found
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index c6d7fea443..e2897549b5 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -109,7 +109,7 @@ static RPCHelpMan getrawtransaction()
{RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::STR_HEX, "txid", "The transaction id"},
- {RPCResult::Type::STR, "vout", ""},
+ {RPCResult::Type::NUM, "vout", "The output number"},
{RPCResult::Type::OBJ, "scriptSig", "The script",
{
{RPCResult::Type::STR, "asm", "asm"},
@@ -244,16 +244,15 @@ static RPCHelpMan gettxoutproof()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::set<uint256> setTxids;
- uint256 oneTxid;
UniValue txids = request.params[0].get_array();
+ if (txids.empty()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Parameter 'txids' cannot be empty");
+ }
for (unsigned int idx = 0; idx < txids.size(); idx++) {
- const UniValue& txid = txids[idx];
- uint256 hash(ParseHashV(txid, "txid"));
- if (setTxids.count(hash)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ") + txid.get_str());
+ auto ret = setTxids.insert(ParseHashV(txids[idx], "txid"));
+ if (!ret.second) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ") + txids[idx].get_str());
}
- setTxids.insert(hash);
- oneTxid = hash;
}
CBlockIndex* pblockindex = nullptr;
@@ -287,7 +286,7 @@ static RPCHelpMan gettxoutproof()
LOCK(cs_main);
if (pblockindex == nullptr) {
- const CTransactionRef tx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, oneTxid, Params().GetConsensus(), hashBlock);
+ const CTransactionRef tx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, *setTxids.begin(), Params().GetConsensus(), hashBlock);
if (!tx || hashBlock.IsNull()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
}
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index f004ecc20c..122a92f084 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -286,7 +286,7 @@ void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
SignTransactionResultToJSON(mtx, complete, coins, input_errors, result);
}
-void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, std::map<int, std::string>& input_errors, UniValue& result)
+void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, const std::map<int, std::string>& input_errors, UniValue& result)
{
// Make errors UniValue
UniValue vErrors(UniValue::VARR);
diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
index 942314eccf..ce7d5834fa 100644
--- a/src/rpc/rawtransaction_util.h
+++ b/src/rpc/rawtransaction_util.h
@@ -25,7 +25,7 @@ class SigningProvider;
* @param result JSON object where signed transaction results accumulate
*/
void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType, UniValue& result);
-void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, std::map<int, std::string>& input_errors, UniValue& result);
+void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, const std::map<int, std::string>& input_errors, UniValue& result);
/**
* Parse a prevtxs UniValue array and get the map of coins from it
diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp
index d9ad70fa37..a7866474e1 100644
--- a/src/rpc/request.cpp
+++ b/src/rpc/request.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpc/request.h b/src/rpc/request.h
index 1241d999a8..de3a4ae840 100644
--- a/src/rpc/request.h
+++ b/src/rpc/request.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpc/server.h b/src/rpc/server.h
index 7d13edb8b0..040192b455 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 1b21587b6d..31072114da 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020 The Bitcoin Core developers
+// Copyright (c) 2017-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -209,7 +209,7 @@ CTxDestination AddAndGetMultisigDestination(const int required, const std::vecto
return dest;
}
-class DescribeAddressVisitor : public boost::static_visitor<UniValue>
+class DescribeAddressVisitor
{
public:
explicit DescribeAddressVisitor() {}
@@ -267,7 +267,7 @@ public:
UniValue DescribeAddress(const CTxDestination& dest)
{
- return boost::apply_visitor(DescribeAddressVisitor(), dest);
+ return std::visit(DescribeAddressVisitor(), dest);
}
unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target)
@@ -562,10 +562,10 @@ std::string RPCArg::GetName() const
bool RPCArg::IsOptional() const
{
- if (m_fallback.which() == 1) {
+ if (m_fallback.index() == 1) {
return true;
} else {
- return RPCArg::Optional::NO != boost::get<RPCArg::Optional>(m_fallback);
+ return RPCArg::Optional::NO != std::get<RPCArg::Optional>(m_fallback);
}
}
@@ -609,10 +609,10 @@ std::string RPCArg::ToDescriptionString() const
}
} // no default case, so the compiler can warn about missing cases
}
- if (m_fallback.which() == 1) {
- ret += ", optional, default=" + boost::get<std::string>(m_fallback);
+ if (m_fallback.index() == 1) {
+ ret += ", optional, default=" + std::get<std::string>(m_fallback);
} else {
- switch (boost::get<RPCArg::Optional>(m_fallback)) {
+ switch (std::get<RPCArg::Optional>(m_fallback)) {
case RPCArg::Optional::OMITTED: {
// nothing to do. Element is treated as if not present and has no default value
break;
diff --git a/src/rpc/util.h b/src/rpc/util.h
index 45b0bb0c7e..942c243718 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020 The Bitcoin Core developers
+// Copyright (c) 2017-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,10 +19,9 @@
#include <util/check.h>
#include <string>
+#include <variant>
#include <vector>
-#include <boost/variant.hpp>
-
/**
* String used to describe UNIX epoch time in documentation, factored out to a
* constant for consistency.
@@ -144,7 +143,7 @@ struct RPCArg {
*/
OMITTED,
};
- using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>;
+ using Fallback = std::variant<Optional, /* default value for optional args */ std::string>;
const std::string m_names; //!< The name of the arg (can be empty for inner args, can contain multiple aliases separated by | for named request arguments)
const Type m_type;
const bool m_hidden;
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index 15e204062f..76609f01a7 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -16,8 +16,7 @@ namespace {
class TxInputStream
{
public:
- TxInputStream(int nTypeIn, int nVersionIn, const unsigned char *txTo, size_t txToLen) :
- m_type(nTypeIn),
+ TxInputStream(int nVersionIn, const unsigned char *txTo, size_t txToLen) :
m_version(nVersionIn),
m_data(txTo),
m_remaining(txToLen)
@@ -47,9 +46,7 @@ public:
}
int GetVersion() const { return m_version; }
- int GetType() const { return m_type; }
private:
- const int m_type;
const int m_version;
const unsigned char* m_data;
size_t m_remaining;
@@ -84,7 +81,7 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
return set_error(err, bitcoinconsensus_ERR_INVALID_FLAGS);
}
try {
- TxInputStream stream(SER_NETWORK, PROTOCOL_VERSION, txTo, txToLen);
+ TxInputStream stream(PROTOCOL_VERSION, txTo, txToLen);
CTransaction tx(deserialize, stream);
if (nIn >= tx.vin.size())
return set_error(err, bitcoinconsensus_ERR_TX_INDEX);
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index e5ba9ba6d2..9e4b8a9dd6 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -565,7 +565,7 @@ public:
Optional<OutputType> GetOutputType() const override
{
- switch (m_destination.which()) {
+ switch (m_destination.index()) {
case 1 /* PKHash */:
case 2 /* ScriptHash */: return OutputType::LEGACY;
case 3 /* WitnessV0ScriptHash */:
@@ -593,7 +593,7 @@ public:
{
CTxDestination dest;
ExtractDestination(m_script, dest);
- switch (dest.which()) {
+ switch (dest.index()) {
case 1 /* PKHash */:
case 2 /* ScriptHash */: return OutputType::LEGACY;
case 3 /* WitnessV0ScriptHash */:
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index bb5a7158a5..ecac3b9e7e 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -305,8 +305,8 @@ private:
uint32_t m_first_false_pos = NO_FALSE;
public:
- bool empty() { return m_stack_size == 0; }
- bool all_true() { return m_first_false_pos == NO_FALSE; }
+ bool empty() const { return m_stack_size == 0; }
+ bool all_true() const { return m_first_false_pos == NO_FALSE; }
void push_back(bool f)
{
if (m_first_false_pos == NO_FALSE && !f) {
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index c0c2b012c6..b4c163c841 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/keyorigin.h b/src/script/keyorigin.h
index a318ff0f9d..210395d177 100644
--- a/src/script/keyorigin.h
+++ b/src/script/keyorigin.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/script.cpp b/src/script/script.cpp
index f31472e42d..9a6419088b 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/script_error.h b/src/script/script_error.h
index b071681613..44e68fe0fa 100644
--- a/src/script/script_error.h
+++ b/src/script/script_error.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index c1786140de..2bfe206597 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -66,7 +66,7 @@ public:
return setValid.contains(entry, erase);
}
- void Set(uint256& entry)
+ void Set(const uint256& entry)
{
boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
setValid.insert(entry);
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index 00534f9758..512f61f2bf 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 0e6864d547..8afbe9ebed 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -388,7 +388,7 @@ bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, C
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
- CTxIn& txin = txTo.vin[nIn];
+ const CTxIn& txin = txTo.vin[nIn];
assert(txin.prevout.n < txFrom.vout.size());
const CTxOut& txout = txFrom.vout[txin.prevout.n];
diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp
index 2d8dc7d471..9781ec32af 100644
--- a/src/script/signingprovider.cpp
+++ b/src/script/signingprovider.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -179,18 +179,18 @@ CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination&
{
// Only supports destinations which map to single public keys, i.e. P2PKH,
// P2WPKH, and P2SH-P2WPKH.
- if (auto id = boost::get<PKHash>(&dest)) {
+ if (auto id = std::get_if<PKHash>(&dest)) {
return ToKeyID(*id);
}
- if (auto witness_id = boost::get<WitnessV0KeyHash>(&dest)) {
+ if (auto witness_id = std::get_if<WitnessV0KeyHash>(&dest)) {
return ToKeyID(*witness_id);
}
- if (auto script_hash = boost::get<ScriptHash>(&dest)) {
+ if (auto script_hash = std::get_if<ScriptHash>(&dest)) {
CScript script;
CScriptID script_id(*script_hash);
CTxDestination inner_dest;
if (store.GetCScript(script_id, script) && ExtractDestination(script, inner_dest)) {
- if (auto inner_witness_id = boost::get<WitnessV0KeyHash>(&inner_dest)) {
+ if (auto inner_witness_id = std::get_if<WitnessV0KeyHash>(&inner_dest)) {
return ToKeyID(*inner_witness_id);
}
}
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index f2f81664f6..7967c01858 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -261,9 +261,8 @@ bool ExtractDestinations(const CScript& scriptPubKey, TxoutType& typeRet, std::v
return true;
}
-namespace
-{
-class CScriptVisitor : public boost::static_visitor<CScript>
+namespace {
+class CScriptVisitor
{
public:
CScript operator()(const CNoDestination& dest) const
@@ -300,7 +299,7 @@ public:
CScript GetScriptForDestination(const CTxDestination& dest)
{
- return boost::apply_visitor(CScriptVisitor(), dest);
+ return std::visit(CScriptVisitor(), dest);
}
CScript GetScriptForRawPubKey(const CPubKey& pubKey)
@@ -320,5 +319,5 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
}
bool IsValidDestination(const CTxDestination& dest) {
- return dest.which() != 0;
+ return dest.index() != 0;
}
diff --git a/src/script/standard.h b/src/script/standard.h
index 4d1ef61964..d5d87392ad 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -9,10 +9,8 @@
#include <script/interpreter.h>
#include <uint256.h>
-#include <boost/variant.hpp>
-
#include <string>
-
+#include <variant>
static const bool DEFAULT_ACCEPT_DATACARRIER = true;
@@ -211,7 +209,7 @@ struct WitnessUnknown
* (taproot outputs do not require their own type as long as no wallet support exists)
* A CTxDestination is the internal data type encoded in a bitcoin address
*/
-typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> CTxDestination;
+using CTxDestination = std::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown>;
/** Check whether a CTxDestination is a CNoDestination. */
bool IsValidDestination(const CTxDestination& dest);
diff --git a/src/shutdown.cpp b/src/shutdown.cpp
index dec497d8ec..df5f996022 100644
--- a/src/shutdown.cpp
+++ b/src/shutdown.cpp
@@ -1,23 +1,112 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 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 <shutdown.h>
+#include <config/bitcoin-config.h>
+
+#include <assert.h>
#include <atomic>
+#ifdef WIN32
+#include <condition_variable>
+#else
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
static std::atomic<bool> fRequestShutdown(false);
+#ifdef WIN32
+/** On windows it is possible to simply use a condition variable. */
+std::mutex g_shutdown_mutex;
+std::condition_variable g_shutdown_cv;
+#else
+/** On UNIX-like operating systems use the self-pipe trick.
+ * Index 0 will be the read end of the pipe, index 1 the write end.
+ */
+static int g_shutdown_pipe[2] = {-1, -1};
+#endif
+
+bool InitShutdownState()
+{
+#ifndef WIN32
+#if HAVE_O_CLOEXEC
+ // If we can, make sure that the file descriptors are closed on exec()
+ // to prevent interference.
+ if (pipe2(g_shutdown_pipe, O_CLOEXEC) != 0) {
+ return false;
+ }
+#else
+ if (pipe(g_shutdown_pipe) != 0) {
+ return false;
+ }
+#endif
+#endif
+ return true;
+}
void StartShutdown()
{
+#ifdef WIN32
+ std::unique_lock<std::mutex> lk(g_shutdown_mutex);
fRequestShutdown = true;
+ g_shutdown_cv.notify_one();
+#else
+ // This must be reentrant and safe for calling in a signal handler, so using a condition variable is not safe.
+ // Make sure that the token is only written once even if multiple threads call this concurrently or in
+ // case of a reentrant signal.
+ if (!fRequestShutdown.exchange(true)) {
+ // Write an arbitrary byte to the write end of the shutdown pipe.
+ const char token = 'x';
+ while (true) {
+ int result = write(g_shutdown_pipe[1], &token, 1);
+ if (result < 0) {
+ // Failure. It's possible that the write was interrupted by another signal.
+ // Other errors are unexpected here.
+ assert(errno == EINTR);
+ } else {
+ assert(result == 1);
+ break;
+ }
+ }
+ }
+#endif
}
+
void AbortShutdown()
{
+ if (fRequestShutdown) {
+ // Cancel existing shutdown by waiting for it, this will reset condition flags and remove
+ // the shutdown token from the pipe.
+ WaitForShutdown();
+ }
fRequestShutdown = false;
}
+
bool ShutdownRequested()
{
return fRequestShutdown;
}
+
+void WaitForShutdown()
+{
+#ifdef WIN32
+ std::unique_lock<std::mutex> lk(g_shutdown_mutex);
+ g_shutdown_cv.wait(lk, [] { return fRequestShutdown.load(); });
+#else
+ char token;
+ while (true) {
+ int result = read(g_shutdown_pipe[0], &token, 1);
+ if (result < 0) {
+ // Failure. Check if the read was interrupted by a signal.
+ // Other errors are unexpected here.
+ assert(errno == EINTR);
+ } else {
+ assert(result == 1);
+ break;
+ }
+ }
+#endif
+}
diff --git a/src/shutdown.h b/src/shutdown.h
index 3ed851c789..b2fbdb8cfb 100644
--- a/src/shutdown.h
+++ b/src/shutdown.h
@@ -1,13 +1,30 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 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_SHUTDOWN_H
#define BITCOIN_SHUTDOWN_H
+/** Initialize shutdown state. This must be called before using either StartShutdown(),
+ * AbortShutdown() or WaitForShutdown(). Calling ShutdownRequested() is always safe.
+ */
+bool InitShutdownState();
+
+/** Request shutdown of the application. */
void StartShutdown();
+
+/** Clear shutdown flag. Only use this during init (before calling WaitForShutdown in any
+ * thread), or in the unit tests. Calling it in other circumstances will cause a race condition.
+ */
void AbortShutdown();
+
+/** Returns true if a shutdown is requested, false otherwise. */
bool ShutdownRequested();
+/** Wait for StartShutdown to be called in any thread. This can only be used
+ * from a single thread.
+ */
+void WaitForShutdown();
+
#endif
diff --git a/src/streams.h b/src/streams.h
index c22f5936fd..fce411d3df 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
index 26de780f29..6965f40253 100644
--- a/src/support/lockedpool.cpp
+++ b/src/support/lockedpool.cpp
@@ -65,7 +65,7 @@ void* Arena::alloc(size_t size)
// Pick a large enough free-chunk. Returns an iterator pointing to the first element that is not less than key.
// This allocation strategy is best-fit. According to "Dynamic Storage Allocation: A Survey and Critical Review",
- // Wilson et. al. 1995, http://www.scs.stanford.edu/14wi-cs140/sched/readings/wilson.pdf, best-fit and first-fit
+ // Wilson et. al. 1995, https://www.scs.stanford.edu/14wi-cs140/sched/readings/wilson.pdf, best-fit and first-fit
// policies seem to work well in practice.
auto size_ptr_it = size_to_free_chunk.lower_bound(size);
if (size_ptr_it == size_to_free_chunk.end())
diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h
index b9e2e99d1a..03e4e371a3 100644
--- a/src/support/lockedpool.h
+++ b/src/support/lockedpool.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/sync.cpp b/src/sync.cpp
index f07916041a..acfbe8fe29 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -228,20 +228,28 @@ template void EnterCritical(const char*, const char*, int, boost::mutex*, bool);
void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line)
{
- {
- LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
-
- const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
- if (!lock_stack.empty()) {
- const auto& lastlock = lock_stack.back();
- if (lastlock.first == cs) {
- lockname = lastlock.second.Name();
- return;
- }
+ LockData& lockdata = GetLockData();
+ std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+
+ const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
+ if (!lock_stack.empty()) {
+ const auto& lastlock = lock_stack.back();
+ if (lastlock.first == cs) {
+ lockname = lastlock.second.Name();
+ return;
}
}
- throw std::system_error(EPERM, std::generic_category(), strprintf("%s:%s %s was not most recent critical section locked", file, line, guardname));
+
+ LogPrintf("INCONSISTENT LOCK ORDER DETECTED\n");
+ LogPrintf("Current lock order (least recent first) is:\n");
+ for (const LockStackItem& i : lock_stack) {
+ LogPrintf(" %s\n", i.second.ToString());
+ }
+ if (g_debug_lockorder_abort) {
+ tfm::format(std::cerr, "%s:%s %s was not most recent critical section locked, details in debug log.\n", file, line, guardname);
+ abort();
+ }
+ throw std::logic_error(strprintf("%s was not most recent critical section locked", guardname));
}
void LeaveCritical()
diff --git a/src/sync.h b/src/sync.h
index faabec2c2d..53213c2089 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -242,10 +242,12 @@ using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove
(cs).lock(); \
}
-#define LEAVE_CRITICAL_SECTION(cs) \
- { \
- (cs).unlock(); \
- LeaveCritical(); \
+#define LEAVE_CRITICAL_SECTION(cs) \
+ { \
+ std::string lockname; \
+ CheckLastCritical((void*)(&cs), lockname, #cs, __FILE__, __LINE__); \
+ (cs).unlock(); \
+ LeaveCritical(); \
}
//! Run code while locking a mutex.
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 25fdd64568..37ff8a9afe 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -71,7 +71,7 @@ public:
}
// Simulates connection failure so that we can test eviction of offline nodes
- void SimConnFail(CService& addr)
+ void SimConnFail(const CService& addr)
{
LOCK(cs);
int64_t nLastSuccess = 1;
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
index c16519a6b1..1a39498899 100644
--- a/src/test/amount_tests.cpp
+++ b/src/test/amount_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index e55d6b3b19..dd760fe999 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 14cf1a4a76..9dfbd7ba7c 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp
index 178c261365..8eb4dbc592 100644
--- a/src/test/blockfilter_tests.cpp
+++ b/src/test/blockfilter_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index 8348810ac1..5dbf07b420 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -26,7 +26,7 @@ static const unsigned int QUEUE_BATCH_SIZE = 128;
static const int SCRIPT_CHECK_THREADS = 3;
struct FakeCheck {
- bool operator()()
+ bool operator()() const
{
return true;
}
@@ -47,7 +47,7 @@ struct FailingCheck {
bool fails;
FailingCheck(bool _fails) : fails(_fails){};
FailingCheck() : fails(true){};
- bool operator()()
+ bool operator()() const
{
return !fails;
}
@@ -76,7 +76,7 @@ struct UniqueCheck {
struct MemoryCheck {
static std::atomic<size_t> fake_allocated_memory;
bool b {false};
- bool operator()()
+ bool operator()() const
{
return true;
}
@@ -107,7 +107,7 @@ struct FrozenCleanupCheck {
// Freezing can't be the default initialized behavior given how the queue
// swaps in default initialized Checks.
bool should_freeze {false};
- bool operator()()
+ bool operator()() const
{
return true;
}
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 6bfcf242d0..06db3b846e 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 0ad5066603..7358b246b6 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -14,7 +14,9 @@
#include <crypto/sha256.h>
#include <crypto/sha3.h>
#include <crypto/sha512.h>
+#include <crypto/muhash.h>
#include <random.h>
+#include <streams.h>
#include <test/util/setup_common.h>
#include <util/strencodings.h>
@@ -857,4 +859,92 @@ BOOST_AUTO_TEST_CASE(sha3_256_tests)
TestSHA3_256("72c57c359e10684d0517e46653a02d18d29eff803eb009e4d5eb9e95add9ad1a4ac1f38a70296f3a369a16985ca3c957de2084cdc9bdd8994eb59b8815e0debad4ec1f001feac089820db8becdaf896aaf95721e8674e5d476b43bd2b873a7d135cd685f545b438210f9319e4dcd55986c85303c1ddf18dc746fe63a409df0a998ed376eb683e16c09e6e9018504152b3e7628ef350659fb716e058a5263a18823d2f2f6ee6a8091945a48ae1c5cb1694cf2c1fe76ef9177953afe8899cfa2b7fe0603bfa3180937dadfb66fbbdd119bbf8063338aa4a699075a3bfdbae8db7e5211d0917e9665a702fc9b0a0a901d08bea97654162d82a9f05622b060b634244779c33427eb7a29353a5f48b07cbefa72f3622ac5900bef77b71d6b314296f304c8426f451f32049b1f6af156a9dab702e8907d3cd72bb2c50493f4d593e731b285b70c803b74825b3524cda3205a8897106615260ac93c01c5ec14f5b11127783989d1824527e99e04f6a340e827b559f24db9292fcdd354838f9339a5fa1d7f6b2087f04835828b13463dd40927866f16ae33ed501ec0e6c4e63948768c5aeea3e4f6754985954bea7d61088c44430204ef491b74a64bde1358cecb2cad28ee6a3de5b752ff6a051104d88478653339457ac45ba44cbb65f54d1969d047cda746931d5e6a8b48e211416aefd5729f3d60b56b54e7f85aa2f42de3cb69419240c24e67139a11790a709edef2ac52cf35dd0a08af45926ebe9761f498ff83bfe263d6897ee97943a4b982fe3404ef0b4a45e06113c60340e0664f14799bf59cb4b3934b465fabefd87155905ee5309ba41e9e402973311831ea600b16437f71df39ee77130490c4d0227e5d1757fdc66af3ae6b9953053ed9aafca0160209858a7d4dd38fe10e0cb153672d08633ed6c54977aa0a6e67f9ff2f8c9d22dd7b21de08192960fd0e0da68d77c8d810db11dcaa61c725cd4092cbff76c8e1debd8d0361bb3f2e607911d45716f53067bdc0d89dd4889177765166a424e9fc0cb711201099dda213355e6639ac7eb86eca2ae0ab38b7f674f37ef8a6fcca1a6f52f55d9e1dcd631d2c3c82bba129172feb991d5af51afecd9d61a88b6832e4107480e392aed61a8644f551665ebff6b20953b635737a4f895e429fddcfe801f606fbda74b3bf6f5767d0fac14907fcfd0aa1d4c11b9e91b01d68052399b51a29f1ae6acd965109977c14a555cbcbd21ad8cb9f8853506d4bc21c01e62d61d7b21be1b923be54914e6b0a7ca84dd11f1159193e1184568a6134a6bbadf5b4df986edcf2019390ae841cfaa44435e28ce877d3dae4177992fa5d4e5c005876dbe3d1e63bec7dcc0942762b48b1ecc6c1a918409a8a72812a1e245c0c67be6e729c2b49bc6ee4d24a8f63e78e75db45655c26a9a78aff36fcd67117f26b8f654dca664b9f0e30681874cb749e1a692720078856286c2560b0292cc837933423147569350955c9571bf8941ba128fd339cb4268f46b94bc6ee203eb7026813706ea51c4f24c91866fc23a724bf2501327e6ae89c29f8db315dc28d2c7c719514036367e018f4835f63fdecd71f9bdced7132b6c4f8b13c69a517026fcd3622d67cb632320d5e7308f78f4b7cea11f6291b137851dc6cd6366f2785c71c3f237f81a7658b2a8d512b61e0ad5a4710b7b124151689fcb2116063fbff7e9115fed7b93de834970b838e49f8f8ba5f1f874c354078b5810a55ae289a56da563f1da6cd80a3757d6073fa55e016e45ac6cec1f69d871c92fd0ae9670c74249045e6b464787f9504128736309fed205f8df4d90e332908581298d9c75a3fa36ab0c3c9272e62de53ab290c803d67b696fd615c260a47bffad16746f18ba1a10a061bacbea9369693b3c042eec36bed289d7d12e52bca8aa1c2dff88ca7816498d25626d0f1e106ebb0b4a12138e00f3df5b1c2f49d98b1756e69b641b7c6353d99dbff050f4d76842c6cf1c2a4b062fc8e6336fa689b7c9d5c6b4ab8c15a5c20e514ff070a602d85ae52fa7810c22f8eeffd34a095b93342144f7a98d024216b3d68ed7bea047517bfcd83ec83febd1ba0e5858e2bdc1d8b1f7b0f89e90ccc432a3f930cb8209462e64556c5054c56ca2a85f16b32eb83a10459d13516faa4d23302b7607b9bd38dab2239ac9e9440c314433fdfb3ceadab4b4f87415ed6f240e017221f3b5f7ac196cdf54957bec42fe6893994b46de3d27dc7fb58ca88feb5b9e79cf20053d12530ac524337b22a3629bea52f40b06d3e2128f32060f9105847daed81d35f20e2002817434659baff64494c5b5c7f9216bfda38412a0f70511159dc73bb6bae1f8eaa0ef08d99bcb31f94f6be12c29c83df45926430b366c99fca3270c15fc4056398fdf3135b7779e3066a006961d1ac0ad1c83179ce39e87a96b722ec23aabc065badf3e188347a360772ca6a447abac7e6a44f0d4632d52926332e44a0a86bff5ce699fd063bdda3ffd4c41b53ded49fecec67f40599b934e16e3fd1bc063ad7026f8d71bfd4cbaf56599586774723194b692036f1b6bb242e2ffb9c600b5215b412764599476ce475c9e5b396fbcebd6be323dcf4d0048077400aac7500db41dc95fc7f7edbe7c9c2ec5ea89943fe13b42217eef530bbd023671509e12dfce4e1c1c82955d965e6a68aa66f6967dba48feda572db1f099d9a6dc4bc8edade852b5e824a06890dc48a6a6510ecaf8cf7620d757290e3166d431abecc624fa9ac2234d2eb783308ead45544910c633a94964b2ef5fbc409cb8835ac4147d384e12e0a5e13951f7de0ee13eafcb0ca0c04946d7804040c0a3cd088352424b097adb7aad1ca4495952f3e6c0158c02d2bcec33bfda69301434a84d9027ce02c0b9725dad118", "d894b86261436362e64241e61f6b3e6589daf64dc641f60570c4c0bf3b1f2ca3");
}
+static MuHash3072 FromInt(unsigned char i) {
+ unsigned char tmp[32] = {i, 0};
+ return MuHash3072(tmp);
+}
+
+BOOST_AUTO_TEST_CASE(muhash_tests)
+{
+ uint256 out;
+
+ for (int iter = 0; iter < 10; ++iter) {
+ uint256 res;
+ int table[4];
+ for (int i = 0; i < 4; ++i) {
+ table[i] = g_insecure_rand_ctx.randbits(3);
+ }
+ for (int order = 0; order < 4; ++order) {
+ MuHash3072 acc;
+ for (int i = 0; i < 4; ++i) {
+ int t = table[i ^ order];
+ if (t & 4) {
+ acc /= FromInt(t & 3);
+ } else {
+ acc *= FromInt(t & 3);
+ }
+ }
+ acc.Finalize(out);
+ if (order == 0) {
+ res = out;
+ } else {
+ BOOST_CHECK(res == out);
+ }
+ }
+
+ MuHash3072 x = FromInt(g_insecure_rand_ctx.randbits(4)); // x=X
+ MuHash3072 y = FromInt(g_insecure_rand_ctx.randbits(4)); // x=X, y=Y
+ MuHash3072 z; // x=X, y=Y, z=1
+ z *= x; // x=X, y=Y, z=X
+ z *= y; // x=X, y=Y, z=X*Y
+ y *= x; // x=X, y=Y*X, z=X*Y
+ z /= y; // x=X, y=Y*X, z=1
+ z.Finalize(out);
+
+ uint256 out2;
+ MuHash3072 a;
+ a.Finalize(out2);
+
+ BOOST_CHECK_EQUAL(out, out2);
+ }
+
+ MuHash3072 acc = FromInt(0);
+ acc *= FromInt(1);
+ acc /= FromInt(2);
+ acc.Finalize(out);
+ BOOST_CHECK_EQUAL(out, uint256S("10d312b100cbd32ada024a6646e40d3482fcff103668d2625f10002a607d5863"));
+
+ MuHash3072 acc2 = FromInt(0);
+ unsigned char tmp[32] = {1, 0};
+ acc2.Insert(tmp);
+ unsigned char tmp2[32] = {2, 0};
+ acc2.Remove(tmp2);
+ acc2.Finalize(out);
+ BOOST_CHECK_EQUAL(out, uint256S("10d312b100cbd32ada024a6646e40d3482fcff103668d2625f10002a607d5863"));
+
+ // Test MuHash3072 serialization
+ MuHash3072 serchk = FromInt(1); serchk *= FromInt(2);
+ std::string ser_exp = "1fa093295ea30a6a3acdc7b3f770fa538eff537528e990e2910e40bbcfd7f6696b1256901929094694b56316de342f593303dd12ac43e06dce1be1ff8301c845beb15468fff0ef002dbf80c29f26e6452bccc91b5cb9437ad410d2a67ea847887fa3c6a6553309946880fe20db2c73fe0641adbd4e86edfee0d9f8cd0ee1230898873dc13ed8ddcaf045c80faa082774279007a2253f8922ee3ef361d378a6af3ddaf180b190ac97e556888c36b3d1fb1c85aab9ccd46e3deaeb7b7cf5db067a7e9ff86b658cf3acd6662bbcce37232daa753c48b794356c020090c831a8304416e2aa7ad633c0ddb2f11be1be316a81be7f7e472071c042cb68faef549c221ebff209273638b741aba5a81675c45a5fa92fea4ca821d7a324cb1e1a2ccd3b76c4228ec8066dad2a5df6e1bd0de45c7dd5de8070bdb46db6c554cf9aefc9b7b2bbf9f75b1864d9f95005314593905c0109b71f703d49944ae94477b51dac10a816bb6d1c700bafabc8bd86fac8df24be519a2f2836b16392e18036cb13e48c5c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ CDataStream ss_chk(SER_DISK, PROTOCOL_VERSION);
+ ss_chk << serchk;
+ BOOST_CHECK_EQUAL(ser_exp, HexStr(ss_chk.str()));
+
+ // Test MuHash3072 deserialization
+ MuHash3072 deserchk;
+ ss_chk >> deserchk;
+ uint256 out3;
+ serchk.Finalize(out);
+ deserchk.Finalize(out3);
+ BOOST_CHECK_EQUAL(HexStr(out), HexStr(out3));
+
+ // Test MuHash3072 overflow, meaning the internal data is larger than the modulus.
+ CDataStream ss_max(ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), SER_DISK, PROTOCOL_VERSION);
+ MuHash3072 overflowchk;
+ ss_max >> overflowchk;
+
+ uint256 out4;
+ overflowchk.Finalize(out4);
+ BOOST_CHECK_EQUAL(HexStr(out4), "3a31e6903aff0de9f62f9a9f7f8b861de76ce2cda09822b90014319ae5dc2271");
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index c399da900f..d926f8d767 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -80,11 +80,12 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
const CChainParams& chainparams = Params();
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);
+ auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler,
+ *m_node.chainman, *m_node.mempool, false);
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
- CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", ConnectionType::OUTBOUND_FULL_RELAY);
+ CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr1, 0, 0, CAddress(), "", ConnectionType::OUTBOUND_FULL_RELAY);
dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
peerLogic->InitializeNode(&dummyNode1);
@@ -135,7 +136,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &peerLogic, CConnmanTest* connman)
{
CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
- vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", ConnectionType::OUTBOUND_FULL_RELAY));
+ vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr, 0, 0, CAddress(), "", ConnectionType::OUTBOUND_FULL_RELAY));
CNode &node = *vNodes.back();
node.SetCommonVersion(PROTOCOL_VERSION);
@@ -149,7 +150,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
const CChainParams& chainparams = Params();
auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);
+ auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler,
+ *m_node.chainman, *m_node.mempool, false);
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
CConnman::Options options;
@@ -222,11 +224,12 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
const CChainParams& chainparams = Params();
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
+ auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler,
+ *m_node.chainman, *m_node.mempool, false);
banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
- CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", ConnectionType::INBOUND);
+ CNode dummyNode1(id++, NODE_NETWORK, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", ConnectionType::INBOUND);
dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
peerLogic->InitializeNode(&dummyNode1);
dummyNode1.fSuccessfullyConnected = true;
@@ -239,7 +242,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
BOOST_CHECK(!banman->IsDiscouraged(ip(0xa0b0c001|0x0000ff00))); // Different IP, not discouraged
CAddress addr2(ip(0xa0b0c002), NODE_NONE);
- CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", ConnectionType::INBOUND);
+ CNode dummyNode2(id++, NODE_NETWORK, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", ConnectionType::INBOUND);
dummyNode2.SetCommonVersion(PROTOCOL_VERSION);
peerLogic->InitializeNode(&dummyNode2);
dummyNode2.fSuccessfullyConnected = true;
@@ -268,14 +271,15 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
const CChainParams& chainparams = Params();
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
+ auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler,
+ *m_node.chainman, *m_node.mempool, false);
banman->ClearBanned();
int64_t nStartTime = GetTime();
SetMockTime(nStartTime); // Overrides future calls to GetTime()
CAddress addr(ip(0xa0b0c001), NODE_NONE);
- CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", ConnectionType::INBOUND);
+ CNode dummyNode(id++, NODE_NETWORK, INVALID_SOCKET, addr, 4, 4, CAddress(), "", ConnectionType::INBOUND);
dummyNode.SetCommonVersion(PROTOCOL_VERSION);
peerLogic->InitializeNode(&dummyNode);
dummyNode.fSuccessfullyConnected = true;
diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp
index be7484cd0b..0c5c19113d 100644
--- a/src/test/flatfile_tests.cpp
+++ b/src/test/flatfile_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/fuzz/FuzzedDataProvider.h b/src/test/fuzz/FuzzedDataProvider.h
index 3e069eba69..744a9d78ce 100644
--- a/src/test/fuzz/FuzzedDataProvider.h
+++ b/src/test/fuzz/FuzzedDataProvider.h
@@ -14,6 +14,7 @@
#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
#include <algorithm>
+#include <array>
#include <climits>
#include <cstddef>
#include <cstdint>
@@ -34,272 +35,362 @@ class FuzzedDataProvider {
: data_ptr_(data), remaining_bytes_(size) {}
~FuzzedDataProvider() = default;
- // Returns a std::vector containing |num_bytes| of input data. If fewer than
- // |num_bytes| of data remain, returns a shorter std::vector containing all
- // of the data that's left. Can be used with any byte sized type, such as
- // char, unsigned char, uint8_t, etc.
- template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes) {
- num_bytes = std::min(num_bytes, remaining_bytes_);
- return ConsumeBytes<T>(num_bytes, num_bytes);
- }
+ // See the implementation below (after the class definition) for more verbose
+ // comments for each of the methods.
- // Similar to |ConsumeBytes|, but also appends the terminator value at the end
- // of the resulting vector. Useful, when a mutable null-terminated C-string is
- // needed, for example. But that is a rare case. Better avoid it, if possible,
- // and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.
+ // Methods returning std::vector of bytes. These are the most popular choice
+ // when splitting fuzzing input into pieces, as every piece is put into a
+ // separate buffer (i.e. ASan would catch any under-/overflow) and the memory
+ // will be released automatically.
+ template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes);
template <typename T>
- std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes,
- T terminator = 0) {
- num_bytes = std::min(num_bytes, remaining_bytes_);
- std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
- result.back() = terminator;
- return result;
- }
+ std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);
+ template <typename T> std::vector<T> ConsumeRemainingBytes();
- // Returns a std::string containing |num_bytes| of input data. Using this and
- // |.c_str()| on the resulting string is the best way to get an immutable
- // null-terminated C string. If fewer than |num_bytes| of data remain, returns
- // a shorter std::string containing all of the data that's left.
- std::string ConsumeBytesAsString(size_t num_bytes) {
- static_assert(sizeof(std::string::value_type) == sizeof(uint8_t),
- "ConsumeBytesAsString cannot convert the data to a string.");
-
- num_bytes = std::min(num_bytes, remaining_bytes_);
- std::string result(
- reinterpret_cast<const std::string::value_type *>(data_ptr_),
- num_bytes);
- Advance(num_bytes);
- return result;
- }
+ // Methods returning strings. Use only when you need a std::string or a null
+ // terminated C-string. Otherwise, prefer the methods returning std::vector.
+ std::string ConsumeBytesAsString(size_t num_bytes);
+ std::string ConsumeRandomLengthString(size_t max_length);
+ std::string ConsumeRandomLengthString();
+ std::string ConsumeRemainingBytesAsString();
- // Returns a number in the range [min, max] by consuming bytes from the
- // input data. The value might not be uniformly distributed in the given
- // range. If there's no input data left, always returns |min|. |min| must
- // be less than or equal to |max|.
- template <typename T> T ConsumeIntegralInRange(T min, T max) {
- static_assert(std::is_integral<T>::value, "An integral type is required.");
- static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
+ // Methods returning integer values.
+ template <typename T> T ConsumeIntegral();
+ template <typename T> T ConsumeIntegralInRange(T min, T max);
- if (min > max)
- abort();
+ // Methods returning floating point values.
+ template <typename T> T ConsumeFloatingPoint();
+ template <typename T> T ConsumeFloatingPointInRange(T min, T max);
- // Use the biggest type possible to hold the range and the result.
- uint64_t range = static_cast<uint64_t>(max) - min;
- uint64_t result = 0;
- size_t offset = 0;
-
- while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 &&
- remaining_bytes_ != 0) {
- // Pull bytes off the end of the seed data. Experimentally, this seems to
- // allow the fuzzer to more easily explore the input space. This makes
- // sense, since it works by modifying inputs that caused new code to run,
- // and this data is often used to encode length of data read by
- // |ConsumeBytes|. Separating out read lengths makes it easier modify the
- // contents of the data that is actually read.
- --remaining_bytes_;
- result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
- offset += CHAR_BIT;
- }
+ // 0 <= return value <= 1.
+ template <typename T> T ConsumeProbability();
- // Avoid division by 0, in case |range + 1| results in overflow.
- if (range != std::numeric_limits<decltype(range)>::max())
- result = result % (range + 1);
+ bool ConsumeBool();
- return static_cast<T>(min + result);
- }
+ // Returns a value chosen from the given enum.
+ template <typename T> T ConsumeEnum();
- // Returns a std::string of length from 0 to |max_length|. When it runs out of
- // input data, returns what remains of the input. Designed to be more stable
- // with respect to a fuzzer inserting characters than just picking a random
- // length and then consuming that many bytes with |ConsumeBytes|.
- std::string ConsumeRandomLengthString(size_t max_length) {
- // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
- // followed by anything else to the end of the string. As a result of this
- // logic, a fuzzer can insert characters into the string, and the string
- // will be lengthened to include those new characters, resulting in a more
- // stable fuzzer than picking the length of a string independently from
- // picking its contents.
- std::string result;
-
- // Reserve the anticipated capaticity to prevent several reallocations.
- result.reserve(std::min(max_length, remaining_bytes_));
- for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
- char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
- Advance(1);
- if (next == '\\' && remaining_bytes_ != 0) {
- next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
- Advance(1);
- if (next != '\\')
- break;
- }
- result += next;
- }
-
- result.shrink_to_fit();
- return result;
- }
+ // Returns a value from the given array.
+ template <typename T, size_t size> T PickValueInArray(const T (&array)[size]);
+ template <typename T, size_t size>
+ T PickValueInArray(const std::array<T, size> &array);
+ template <typename T> T PickValueInArray(std::initializer_list<const T> list);
- // Returns a std::vector containing all remaining bytes of the input data.
- template <typename T> std::vector<T> ConsumeRemainingBytes() {
- return ConsumeBytes<T>(remaining_bytes_);
- }
+ // Writes data to the given destination and returns number of bytes written.
+ size_t ConsumeData(void *destination, size_t num_bytes);
- // Returns a std::string containing all remaining bytes of the input data.
- // Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
- // object.
- std::string ConsumeRemainingBytesAsString() {
- return ConsumeBytesAsString(remaining_bytes_);
- }
+ // Reports the remaining bytes available for fuzzed input.
+ size_t remaining_bytes() { return remaining_bytes_; }
- // Returns a number in the range [Type's min, Type's max]. The value might
- // not be uniformly distributed in the given range. If there's no input data
- // left, always returns |min|.
- template <typename T> T ConsumeIntegral() {
- return ConsumeIntegralInRange(std::numeric_limits<T>::min(),
- std::numeric_limits<T>::max());
- }
+ private:
+ FuzzedDataProvider(const FuzzedDataProvider &) = delete;
+ FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
- // Reads one byte and returns a bool, or false when no data remains.
- bool ConsumeBool() { return 1 & ConsumeIntegral<uint8_t>(); }
+ void CopyAndAdvance(void *destination, size_t num_bytes);
- // Returns a copy of the value selected from the given fixed-size |array|.
- template <typename T, size_t size>
- T PickValueInArray(const T (&array)[size]) {
- static_assert(size > 0, "The array must be non empty.");
- return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
- }
+ void Advance(size_t num_bytes);
template <typename T>
- T PickValueInArray(std::initializer_list<const T> list) {
- // TODO(Dor1s): switch to static_assert once C++14 is allowed.
- if (!list.size())
- abort();
-
- return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
- }
-
- // Returns an enum value. The enum must start at 0 and be contiguous. It must
- // also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
- // enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
- template <typename T> T ConsumeEnum() {
- static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
- return static_cast<T>(ConsumeIntegralInRange<uint32_t>(
- 0, static_cast<uint32_t>(T::kMaxValue)));
- }
+ std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);
- // Returns a floating point number in the range [0.0, 1.0]. If there's no
- // input data left, always returns 0.
- template <typename T> T ConsumeProbability() {
- static_assert(std::is_floating_point<T>::value,
- "A floating point type is required.");
+ template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value);
- // Use different integral types for different floating point types in order
- // to provide better density of the resulting values.
- using IntegralType =
- typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t,
- uint64_t>::type;
+ const uint8_t *data_ptr_;
+ size_t remaining_bytes_;
+};
- T result = static_cast<T>(ConsumeIntegral<IntegralType>());
- result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
- return result;
+// Returns a std::vector containing |num_bytes| of input data. If fewer than
+// |num_bytes| of data remain, returns a shorter std::vector containing all
+// of the data that's left. Can be used with any byte sized type, such as
+// char, unsigned char, uint8_t, etc.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
+ num_bytes = std::min(num_bytes, remaining_bytes_);
+ return ConsumeBytes<T>(num_bytes, num_bytes);
+}
+
+// Similar to |ConsumeBytes|, but also appends the terminator value at the end
+// of the resulting vector. Useful, when a mutable null-terminated C-string is
+// needed, for example. But that is a rare case. Better avoid it, if possible,
+// and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes,
+ T terminator) {
+ num_bytes = std::min(num_bytes, remaining_bytes_);
+ std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);
+ result.back() = terminator;
+ return result;
+}
+
+// Returns a std::vector containing all remaining bytes of the input data.
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes() {
+ return ConsumeBytes<T>(remaining_bytes_);
+}
+
+// Returns a std::string containing |num_bytes| of input data. Using this and
+// |.c_str()| on the resulting string is the best way to get an immutable
+// null-terminated C string. If fewer than |num_bytes| of data remain, returns
+// a shorter std::string containing all of the data that's left.
+inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes) {
+ static_assert(sizeof(std::string::value_type) == sizeof(uint8_t),
+ "ConsumeBytesAsString cannot convert the data to a string.");
+
+ num_bytes = std::min(num_bytes, remaining_bytes_);
+ std::string result(
+ reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);
+ Advance(num_bytes);
+ return result;
+}
+
+// Returns a std::string of length from 0 to |max_length|. When it runs out of
+// input data, returns what remains of the input. Designed to be more stable
+// with respect to a fuzzer inserting characters than just picking a random
+// length and then consuming that many bytes with |ConsumeBytes|.
+inline std::string
+FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
+ // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"
+ // followed by anything else to the end of the string. As a result of this
+ // logic, a fuzzer can insert characters into the string, and the string
+ // will be lengthened to include those new characters, resulting in a more
+ // stable fuzzer than picking the length of a string independently from
+ // picking its contents.
+ std::string result;
+
+ // Reserve the anticipated capaticity to prevent several reallocations.
+ result.reserve(std::min(max_length, remaining_bytes_));
+ for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {
+ char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+ Advance(1);
+ if (next == '\\' && remaining_bytes_ != 0) {
+ next = ConvertUnsignedToSigned<char>(data_ptr_[0]);
+ Advance(1);
+ if (next != '\\')
+ break;
+ }
+ result += next;
}
- // Returns a floating point value in the range [Type's lowest, Type's max] by
- // consuming bytes from the input data. If there's no input data left, always
- // returns approximately 0.
- template <typename T> T ConsumeFloatingPoint() {
- return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),
- std::numeric_limits<T>::max());
+ result.shrink_to_fit();
+ return result;
+}
+
+// Returns a std::string of length from 0 to |remaining_bytes_|.
+inline std::string FuzzedDataProvider::ConsumeRandomLengthString() {
+ return ConsumeRandomLengthString(remaining_bytes_);
+}
+
+// Returns a std::string containing all remaining bytes of the input data.
+// Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
+// object.
+inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString() {
+ return ConsumeBytesAsString(remaining_bytes_);
+}
+
+// Returns a number in the range [Type's min, Type's max]. The value might
+// not be uniformly distributed in the given range. If there's no input data
+// left, always returns |min|.
+template <typename T> T FuzzedDataProvider::ConsumeIntegral() {
+ return ConsumeIntegralInRange(std::numeric_limits<T>::min(),
+ std::numeric_limits<T>::max());
+}
+
+// Returns a number in the range [min, max] by consuming bytes from the
+// input data. The value might not be uniformly distributed in the given
+// range. If there's no input data left, always returns |min|. |min| must
+// be less than or equal to |max|.
+template <typename T>
+T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max) {
+ static_assert(std::is_integral<T>::value, "An integral type is required.");
+ static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");
+
+ if (min > max)
+ abort();
+
+ // Use the biggest type possible to hold the range and the result.
+ uint64_t range = static_cast<uint64_t>(max) - min;
+ uint64_t result = 0;
+ size_t offset = 0;
+
+ while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 &&
+ remaining_bytes_ != 0) {
+ // Pull bytes off the end of the seed data. Experimentally, this seems to
+ // allow the fuzzer to more easily explore the input space. This makes
+ // sense, since it works by modifying inputs that caused new code to run,
+ // and this data is often used to encode length of data read by
+ // |ConsumeBytes|. Separating out read lengths makes it easier modify the
+ // contents of the data that is actually read.
+ --remaining_bytes_;
+ result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];
+ offset += CHAR_BIT;
}
- // Returns a floating point value in the given range by consuming bytes from
- // the input data. If there's no input data left, returns |min|. Note that
- // |min| must be less than or equal to |max|.
- template <typename T> T ConsumeFloatingPointInRange(T min, T max) {
- if (min > max)
- abort();
-
- T range = .0;
- T result = min;
- constexpr T zero(.0);
- if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
- // The diff |max - min| would overflow the given floating point type. Use
- // the half of the diff as the range and consume a bool to decide whether
- // the result is in the first of the second part of the diff.
- range = (max / 2.0) - (min / 2.0);
- if (ConsumeBool()) {
- result += range;
- }
- } else {
- range = max - min;
+ // Avoid division by 0, in case |range + 1| results in overflow.
+ if (range != std::numeric_limits<decltype(range)>::max())
+ result = result % (range + 1);
+
+ return static_cast<T>(min + result);
+}
+
+// Returns a floating point value in the range [Type's lowest, Type's max] by
+// consuming bytes from the input data. If there's no input data left, always
+// returns approximately 0.
+template <typename T> T FuzzedDataProvider::ConsumeFloatingPoint() {
+ return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),
+ std::numeric_limits<T>::max());
+}
+
+// Returns a floating point value in the given range by consuming bytes from
+// the input data. If there's no input data left, returns |min|. Note that
+// |min| must be less than or equal to |max|.
+template <typename T>
+T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max) {
+ if (min > max)
+ abort();
+
+ T range = .0;
+ T result = min;
+ constexpr T zero(.0);
+ if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
+ // The diff |max - min| would overflow the given floating point type. Use
+ // the half of the diff as the range and consume a bool to decide whether
+ // the result is in the first of the second part of the diff.
+ range = (max / 2.0) - (min / 2.0);
+ if (ConsumeBool()) {
+ result += range;
}
-
- return result + range * ConsumeProbability<T>();
+ } else {
+ range = max - min;
}
- // Reports the remaining bytes available for fuzzed input.
- size_t remaining_bytes() { return remaining_bytes_; }
-
- private:
- FuzzedDataProvider(const FuzzedDataProvider &) = delete;
- FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
-
- void Advance(size_t num_bytes) {
- if (num_bytes > remaining_bytes_)
+ return result + range * ConsumeProbability<T>();
+}
+
+// Returns a floating point number in the range [0.0, 1.0]. If there's no
+// input data left, always returns 0.
+template <typename T> T FuzzedDataProvider::ConsumeProbability() {
+ static_assert(std::is_floating_point<T>::value,
+ "A floating point type is required.");
+
+ // Use different integral types for different floating point types in order
+ // to provide better density of the resulting values.
+ using IntegralType =
+ typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t,
+ uint64_t>::type;
+
+ T result = static_cast<T>(ConsumeIntegral<IntegralType>());
+ result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
+ return result;
+}
+
+// Reads one byte and returns a bool, or false when no data remains.
+inline bool FuzzedDataProvider::ConsumeBool() {
+ return 1 & ConsumeIntegral<uint8_t>();
+}
+
+// Returns an enum value. The enum must start at 0 and be contiguous. It must
+// also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
+// enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
+template <typename T> T FuzzedDataProvider::ConsumeEnum() {
+ static_assert(std::is_enum<T>::value, "|T| must be an enum type.");
+ return static_cast<T>(
+ ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));
+}
+
+// Returns a copy of the value selected from the given fixed-size |array|.
+template <typename T, size_t size>
+T FuzzedDataProvider::PickValueInArray(const T (&array)[size]) {
+ static_assert(size > 0, "The array must be non empty.");
+ return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
+}
+
+template <typename T, size_t size>
+T FuzzedDataProvider::PickValueInArray(const std::array<T, size> &array) {
+ static_assert(size > 0, "The array must be non empty.");
+ return array[ConsumeIntegralInRange<size_t>(0, size - 1)];
+}
+
+template <typename T>
+T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) {
+ // TODO(Dor1s): switch to static_assert once C++14 is allowed.
+ if (!list.size())
+ abort();
+
+ return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
+}
+
+// Writes |num_bytes| of input data to the given destination pointer. If there
+// is not enough data left, writes all remaining bytes. Return value is the
+// number of bytes written.
+// In general, it's better to avoid using this function, but it may be useful
+// in cases when it's necessary to fill a certain buffer or object with
+// fuzzing data.
+inline size_t FuzzedDataProvider::ConsumeData(void *destination,
+ size_t num_bytes) {
+ num_bytes = std::min(num_bytes, remaining_bytes_);
+ CopyAndAdvance(destination, num_bytes);
+ return num_bytes;
+}
+
+// Private methods.
+inline void FuzzedDataProvider::CopyAndAdvance(void *destination,
+ size_t num_bytes) {
+ std::memcpy(destination, data_ptr_, num_bytes);
+ Advance(num_bytes);
+}
+
+inline void FuzzedDataProvider::Advance(size_t num_bytes) {
+ if (num_bytes > remaining_bytes_)
+ abort();
+
+ data_ptr_ += num_bytes;
+ remaining_bytes_ -= num_bytes;
+}
+
+template <typename T>
+std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes) {
+ static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
+
+ // The point of using the size-based constructor below is to increase the
+ // odds of having a vector object with capacity being equal to the length.
+ // That part is always implementation specific, but at least both libc++ and
+ // libstdc++ allocate the requested number of bytes in that constructor,
+ // which seems to be a natural choice for other implementations as well.
+ // To increase the odds even more, we also call |shrink_to_fit| below.
+ std::vector<T> result(size);
+ if (size == 0) {
+ if (num_bytes != 0)
abort();
-
- data_ptr_ += num_bytes;
- remaining_bytes_ -= num_bytes;
- }
-
- template <typename T>
- std::vector<T> ConsumeBytes(size_t size, size_t num_bytes_to_consume) {
- static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");
-
- // The point of using the size-based constructor below is to increase the
- // odds of having a vector object with capacity being equal to the length.
- // That part is always implementation specific, but at least both libc++ and
- // libstdc++ allocate the requested number of bytes in that constructor,
- // which seems to be a natural choice for other implementations as well.
- // To increase the odds even more, we also call |shrink_to_fit| below.
- std::vector<T> result(size);
- if (size == 0) {
- if (num_bytes_to_consume != 0)
- abort();
- return result;
- }
-
- std::memcpy(result.data(), data_ptr_, num_bytes_to_consume);
- Advance(num_bytes_to_consume);
-
- // Even though |shrink_to_fit| is also implementation specific, we expect it
- // to provide an additional assurance in case vector's constructor allocated
- // a buffer which is larger than the actual amount of data we put inside it.
- result.shrink_to_fit();
return result;
}
- template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value) {
- static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
- static_assert(!std::numeric_limits<TU>::is_signed,
- "Source type must be unsigned.");
-
- // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
- if (std::numeric_limits<TS>::is_modulo)
- return static_cast<TS>(value);
-
- // Avoid using implementation-defined unsigned to signer conversions.
- // To learn more, see https://stackoverflow.com/questions/13150449.
- if (value <= std::numeric_limits<TS>::max()) {
- return static_cast<TS>(value);
- } else {
- constexpr auto TS_min = std::numeric_limits<TS>::min();
- return TS_min + static_cast<char>(value - TS_min);
- }
+ CopyAndAdvance(result.data(), num_bytes);
+
+ // Even though |shrink_to_fit| is also implementation specific, we expect it
+ // to provide an additional assurance in case vector's constructor allocated
+ // a buffer which is larger than the actual amount of data we put inside it.
+ result.shrink_to_fit();
+ return result;
+}
+
+template <typename TS, typename TU>
+TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value) {
+ static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");
+ static_assert(!std::numeric_limits<TU>::is_signed,
+ "Source type must be unsigned.");
+
+ // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream.
+ if (std::numeric_limits<TS>::is_modulo)
+ return static_cast<TS>(value);
+
+ // Avoid using implementation-defined unsigned to signed conversions.
+ // To learn more, see https://stackoverflow.com/questions/13150449.
+ if (value <= std::numeric_limits<TS>::max()) {
+ return static_cast<TS>(value);
+ } else {
+ constexpr auto TS_min = std::numeric_limits<TS>::min();
+ return TS_min + static_cast<char>(value - TS_min);
}
-
- const uint8_t *data_ptr_;
- size_t remaining_bytes_;
-};
+}
#endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
diff --git a/src/test/fuzz/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp
index 7350ec7838..c6cfbd8d30 100644
--- a/src/test/fuzz/addition_overflow.cpp
+++ b/src/test/fuzz/addition_overflow.cpp
@@ -40,7 +40,7 @@ void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(addition_overflow)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
TestAdditionOverflow<int64_t>(fuzzed_data_provider);
diff --git a/src/test/fuzz/addrdb.cpp b/src/test/fuzz/addrdb.cpp
index 16b1cb755a..d15c785673 100644
--- a/src/test/fuzz/addrdb.cpp
+++ b/src/test/fuzz/addrdb.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(addrdb)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
index ae595be742..af9080b5e9 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -17,7 +17,7 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_addrman()
{
SelectParams(CBaseChainParams::REGTEST);
}
@@ -32,7 +32,7 @@ public:
}
};
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(addrman, initialize_addrman)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
SetMockTime(ConsumeTime(fuzzed_data_provider));
diff --git a/src/test/fuzz/asmap.cpp b/src/test/fuzz/asmap.cpp
index e3aefa18a3..4c5bc0cbf2 100644
--- a/src/test/fuzz/asmap.cpp
+++ b/src/test/fuzz/asmap.cpp
@@ -27,7 +27,7 @@ static const std::vector<bool> IPV4_PREFIX_ASMAP = {
true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true // Match 0xFF
};
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(asmap)
{
// Encoding: [7 bits: asmap size] [1 bit: ipv6?] [3-130 bytes: asmap] [4 or 16 bytes: addr]
if (buffer.size() < 1 + 3 + 4) return;
diff --git a/src/test/fuzz/asmap_direct.cpp b/src/test/fuzz/asmap_direct.cpp
index 2d21eff9d6..8b7822dc16 100644
--- a/src/test/fuzz/asmap_direct.cpp
+++ b/src/test/fuzz/asmap_direct.cpp
@@ -11,7 +11,7 @@
#include <assert.h>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(asmap_direct)
{
// Encoding: [asmap using 1 bit / byte] 0xFF [addr using 1 bit / byte]
std::optional<size_t> sep_pos_opt;
diff --git a/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp
index 7ea0bdd2a7..eb3424ef28 100644
--- a/src/test/fuzz/autofile.cpp
+++ b/src/test/fuzz/autofile.cpp
@@ -15,7 +15,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(autofile)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp
index fc4a1d9261..cf69fa0722 100644
--- a/src/test/fuzz/banman.cpp
+++ b/src/test/fuzz/banman.cpp
@@ -24,14 +24,15 @@ int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept
}
} // namespace
-void initialize()
+void initialize_banman()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(banman, initialize_banman)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
const fs::path banlist_file = GetDataDir() / "fuzzed_banlist.dat";
fs::remove(banlist_file);
{
diff --git a/src/test/fuzz/base_encode_decode.cpp b/src/test/fuzz/base_encode_decode.cpp
index 8d49f93c2f..4470e13a61 100644
--- a/src/test/fuzz/base_encode_decode.cpp
+++ b/src/test/fuzz/base_encode_decode.cpp
@@ -14,7 +14,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(base_encode_decode)
{
const std::string random_encoded_string(buffer.begin(), buffer.end());
diff --git a/src/test/fuzz/bech32.cpp b/src/test/fuzz/bech32.cpp
index 8b91f9bc96..95cd4b413f 100644
--- a/src/test/fuzz/bech32.cpp
+++ b/src/test/fuzz/bech32.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,7 +13,7 @@
#include <utility>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(bech32)
{
const std::string random_string(buffer.begin(), buffer.end());
const std::pair<std::string, std::vector<uint8_t>> r1 = bech32::Decode(random_string);
diff --git a/src/test/fuzz/block.cpp b/src/test/fuzz/block.cpp
index 91bd34a251..65a33de4b4 100644
--- a/src/test/fuzz/block.cpp
+++ b/src/test/fuzz/block.cpp
@@ -17,13 +17,13 @@
#include <cassert>
#include <string>
-void initialize()
+void initialize_block()
{
static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(block, initialize_block)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
CBlock block;
diff --git a/src/test/fuzz/block_header.cpp b/src/test/fuzz/block_header.cpp
index 09c2b4a951..c73270dcb3 100644
--- a/src/test/fuzz/block_header.cpp
+++ b/src/test/fuzz/block_header.cpp
@@ -14,7 +14,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(block_header)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
diff --git a/src/test/fuzz/blockfilter.cpp b/src/test/fuzz/blockfilter.cpp
index 7232325a20..7fa06085f8 100644
--- a/src/test/fuzz/blockfilter.cpp
+++ b/src/test/fuzz/blockfilter.cpp
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(blockfilter)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<BlockFilter> block_filter = ConsumeDeserializable<BlockFilter>(fuzzed_data_provider);
diff --git a/src/test/fuzz/bloom_filter.cpp b/src/test/fuzz/bloom_filter.cpp
index d955c71bc9..c0c66c564b 100644
--- a/src/test/fuzz/bloom_filter.cpp
+++ b/src/test/fuzz/bloom_filter.cpp
@@ -15,7 +15,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(bloom_filter)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/buffered_file.cpp b/src/test/fuzz/buffered_file.cpp
index e575640be5..23e197456a 100644
--- a/src/test/fuzz/buffered_file.cpp
+++ b/src/test/fuzz/buffered_file.cpp
@@ -15,7 +15,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(buffered_file)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp
index 47c71850ce..9f7074b423 100644
--- a/src/test/fuzz/chain.cpp
+++ b/src/test/fuzz/chain.cpp
@@ -11,7 +11,7 @@
#include <optional>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(chain)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
std::optional<CDiskBlockIndex> disk_block_index = ConsumeDeserializable<CDiskBlockIndex>(fuzzed_data_provider);
diff --git a/src/test/fuzz/checkqueue.cpp b/src/test/fuzz/checkqueue.cpp
index c69043bb6b..0b16f0f0d5 100644
--- a/src/test/fuzz/checkqueue.cpp
+++ b/src/test/fuzz/checkqueue.cpp
@@ -32,7 +32,7 @@ struct DumbCheck {
};
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(checkqueue)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index ac034809b0..1ae421493e 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -34,14 +34,14 @@ bool operator==(const Coin& a, const Coin& b)
}
} // namespace
-void initialize()
+void initialize_coins_view()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
CCoinsView backend_coins_view;
diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp
index 6521c3f3b2..fdf51d8558 100644
--- a/src/test/fuzz/connman.cpp
+++ b/src/test/fuzz/connman.cpp
@@ -15,14 +15,15 @@
#include <cstdint>
#include <vector>
-void initialize()
+void initialize_connman()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(connman, initialize_connman)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeBool()};
CAddress random_address;
CNetAddr random_netaddr;
@@ -31,7 +32,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
CSubNet random_subnet;
std::string random_string;
while (fuzzed_data_provider.ConsumeBool()) {
- switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 30)) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 27)) {
case 0:
random_address = ConsumeAddress(fuzzed_data_provider);
break;
@@ -124,28 +125,18 @@ void test_one_input(const std::vector<uint8_t>& buffer)
break;
}
case 25:
- connman.SetBestHeight(fuzzed_data_provider.ConsumeIntegral<int>());
+ connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
break;
case 26:
- connman.SetMaxOutboundTarget(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ connman.SetServices(random_service, ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS));
break;
case 27:
- connman.SetMaxOutboundTimeframe(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
- break;
- case 28:
- connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
- break;
- case 29:
- connman.SetServices(random_service, static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()));
- break;
- case 30:
connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool());
break;
}
}
(void)connman.GetAddedNodeInfo();
- (void)connman.GetBestHeight();
- (void)connman.GetExtraOutboundCount();
+ (void)connman.GetExtraFullOutboundCount();
(void)connman.GetLocalServices();
(void)connman.GetMaxOutboundTarget();
(void)connman.GetMaxOutboundTimeframe();
diff --git a/src/test/fuzz/crypto.cpp b/src/test/fuzz/crypto.cpp
index 664e65accc..9668b84e7b 100644
--- a/src/test/fuzz/crypto.cpp
+++ b/src/test/fuzz/crypto.cpp
@@ -4,6 +4,7 @@
#include <crypto/hmac_sha256.h>
#include <crypto/hmac_sha512.h>
+#include <crypto/muhash.h>
#include <crypto/ripemd160.h>
#include <crypto/sha1.h>
#include <crypto/sha256.h>
@@ -17,7 +18,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
std::vector<uint8_t> data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
@@ -35,6 +36,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
CSHA512 sha512;
SHA3_256 sha3;
CSipHasher sip_hasher{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
+ MuHash3072 muhash;
while (fuzzed_data_provider.ConsumeBool()) {
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 2)) {
@@ -60,6 +62,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)Hash(data);
(void)Hash160(data);
(void)sha512.Size();
+
+ if (fuzzed_data_provider.ConsumeBool()) {
+ muhash *= MuHash3072(data);
+ } else {
+ muhash /= MuHash3072(data);
+ }
break;
}
case 1: {
@@ -70,10 +78,11 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)sha256.Reset();
(void)sha3.Reset();
(void)sha512.Reset();
+ muhash = MuHash3072();
break;
}
case 2: {
- switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 9)) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 10)) {
case 0: {
data.resize(CHash160::OUTPUT_SIZE);
hash160.Finalize(data);
@@ -124,6 +133,11 @@ void test_one_input(const std::vector<uint8_t>& buffer)
sha3.Finalize(data);
break;
}
+ case 10: {
+ uint256 out;
+ muhash.Finalize(out);
+ break;
+ }
}
break;
}
diff --git a/src/test/fuzz/crypto_aes256.cpp b/src/test/fuzz/crypto_aes256.cpp
index ae14073c96..ccabd1f7dc 100644
--- a/src/test/fuzz/crypto_aes256.cpp
+++ b/src/test/fuzz/crypto_aes256.cpp
@@ -11,7 +11,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_aes256)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const std::vector<uint8_t> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, AES256_KEYSIZE);
diff --git a/src/test/fuzz/crypto_aes256cbc.cpp b/src/test/fuzz/crypto_aes256cbc.cpp
index 52983c7e79..6d4138e546 100644
--- a/src/test/fuzz/crypto_aes256cbc.cpp
+++ b/src/test/fuzz/crypto_aes256cbc.cpp
@@ -11,7 +11,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_aes256cbc)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const std::vector<uint8_t> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, AES256_KEYSIZE);
diff --git a/src/test/fuzz/crypto_chacha20.cpp b/src/test/fuzz/crypto_chacha20.cpp
index b7438d312d..d751466f11 100644
--- a/src/test/fuzz/crypto_chacha20.cpp
+++ b/src/test/fuzz/crypto_chacha20.cpp
@@ -10,7 +10,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_chacha20)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp
index 48e4263f27..631af9c70d 100644
--- a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp
+++ b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp
@@ -13,7 +13,7 @@
#include <limits>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_chacha20_poly1305_aead)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/crypto_common.cpp b/src/test/fuzz/crypto_common.cpp
index 7ccb125216..8e07dfedb9 100644
--- a/src/test/fuzz/crypto_common.cpp
+++ b/src/test/fuzz/crypto_common.cpp
@@ -13,7 +13,7 @@
#include <cstring>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_common)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const uint16_t random_u16 = fuzzed_data_provider.ConsumeIntegral<uint16_t>();
diff --git a/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp b/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
index e0a4e90c10..8cb9c55283 100644
--- a/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
+++ b/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_hkdf_hmac_sha256_l32)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/crypto_poly1305.cpp b/src/test/fuzz/crypto_poly1305.cpp
index 5681e6a693..ac555ed68c 100644
--- a/src/test/fuzz/crypto_poly1305.cpp
+++ b/src/test/fuzz/crypto_poly1305.cpp
@@ -10,7 +10,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_poly1305)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp
index 5b45aa79d8..dc20dc3f62 100644
--- a/src/test/fuzz/cuckoocache.cpp
+++ b/src/test/fuzz/cuckoocache.cpp
@@ -26,7 +26,7 @@ struct RandomHasher {
};
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(cuckoocache)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
fuzzed_data_provider_ptr = &fuzzed_data_provider;
diff --git a/src/test/fuzz/danger_link_all.sh b/src/test/fuzz/danger_link_all.sh
new file mode 100755
index 0000000000..2ddd00c658
--- /dev/null
+++ b/src/test/fuzz/danger_link_all.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+# Copyright (c) 2020 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+export LC_ALL=C.UTF-8
+
+set -e
+
+ROOT_DIR="$(git rev-parse --show-toplevel)"
+
+# Run only once (break make recursion)
+if [ -d "${ROOT_DIR}/lock_fuzz_link_all" ]; then
+ exit
+fi
+mkdir "${ROOT_DIR}/lock_fuzz_link_all"
+
+echo "Linking each fuzz target separately."
+for FUZZING_HARNESS in $(PRINT_ALL_FUZZ_TARGETS_AND_ABORT=1 "${ROOT_DIR}/src/test/fuzz/fuzz" | sort -u); do
+ echo "Building src/test/fuzz/${FUZZING_HARNESS} ..."
+ git checkout -- "${ROOT_DIR}/src/test/fuzz/fuzz.cpp"
+ sed -i "s/std::getenv(\"FUZZ\")/\"${FUZZING_HARNESS}\"/g" "${ROOT_DIR}/src/test/fuzz/fuzz.cpp"
+ make
+ mv "${ROOT_DIR}/src/test/fuzz/fuzz" "${ROOT_DIR}/src/test/fuzz/${FUZZING_HARNESS}"
+done
+git checkout -- "${ROOT_DIR}/src/test/fuzz/fuzz.cpp"
+rmdir "${ROOT_DIR}/lock_fuzz_link_all"
+echo "Successfully built all fuzz targets."
diff --git a/src/test/fuzz/data_stream.cpp b/src/test/fuzz/data_stream.cpp
new file mode 100644
index 0000000000..28fc528ceb
--- /dev/null
+++ b/src/test/fuzz/data_stream.cpp
@@ -0,0 +1,25 @@
+// Copyright (c) 2020 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 <addrman.h>
+#include <net.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <vector>
+
+void initialize_data_stream_addr_man()
+{
+ InitializeFuzzingContext();
+}
+
+FUZZ_TARGET_INIT(data_stream_addr_man, initialize_data_stream_addr_man)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ CDataStream data_stream = ConsumeDataStream(fuzzed_data_provider);
+ CAddrMan addr_man;
+ CAddrDB::Read(addr_man, data_stream);
+}
diff --git a/src/test/fuzz/decode_tx.cpp b/src/test/fuzz/decode_tx.cpp
index a2b18c0365..57431e65ba 100644
--- a/src/test/fuzz/decode_tx.cpp
+++ b/src/test/fuzz/decode_tx.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(decode_tx)
{
const std::string tx_hex = HexStr(buffer);
CMutableTransaction mtx;
diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp
index 7b57a2c1e2..0d1921f285 100644
--- a/src/test/fuzz/descriptor_parse.cpp
+++ b/src/test/fuzz/descriptor_parse.cpp
@@ -8,14 +8,14 @@
#include <test/fuzz/fuzz.h>
#include <util/memory.h>
-void initialize()
+void initialize_descriptor_parse()
{
static const ECCVerifyHandle verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::MAIN);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(descriptor_parse, initialize_descriptor_parse)
{
const std::string descriptor(buffer.begin(), buffer.end());
FlatSigningProvider signing_provider;
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index 8ca5366c8a..74dec6475e 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -34,12 +34,21 @@
#include <test/fuzz/fuzz.h>
-void initialize()
+void initialize_deserialize()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
static const ECCVerifyHandle verify_handle;
}
+#define FUZZ_TARGET_DESERIALIZE(name, code) \
+ FUZZ_TARGET_INIT(name, initialize_deserialize) \
+ { \
+ try { \
+ code \
+ } catch (const invalid_fuzzing_input_exception&) { \
+ } \
+ }
+
namespace {
struct invalid_fuzzing_input_exception : public std::exception {
@@ -92,44 +101,51 @@ void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
-{
- try {
-#if BLOCK_FILTER_DESERIALIZE
+FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
BlockFilter block_filter;
DeserializeFromFuzzingInput(buffer, block_filter);
-#elif ADDR_INFO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(addr_info_deserialize, {
CAddrInfo addr_info;
DeserializeFromFuzzingInput(buffer, addr_info);
-#elif BLOCK_FILE_INFO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
CBlockFileInfo block_file_info;
DeserializeFromFuzzingInput(buffer, block_file_info);
-#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
CBlockHeaderAndShortTxIDs block_header_and_short_txids;
DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
-#elif FEE_RATE_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
CFeeRate fee_rate;
DeserializeFromFuzzingInput(buffer, fee_rate);
AssertEqualAfterSerializeDeserialize(fee_rate);
-#elif MERKLE_BLOCK_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
CMerkleBlock merkle_block;
DeserializeFromFuzzingInput(buffer, merkle_block);
-#elif OUT_POINT_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
COutPoint out_point;
DeserializeFromFuzzingInput(buffer, out_point);
AssertEqualAfterSerializeDeserialize(out_point);
-#elif PARTIAL_MERKLE_TREE_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
CPartialMerkleTree partial_merkle_tree;
DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
-#elif PUB_KEY_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
CPubKey pub_key;
DeserializeFromFuzzingInput(buffer, pub_key);
// TODO: The following equivalence should hold for CPubKey? Fix.
// AssertEqualAfterSerializeDeserialize(pub_key);
-#elif SCRIPT_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(script_deserialize, {
CScript script;
DeserializeFromFuzzingInput(buffer, script);
-#elif SUB_NET_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(sub_net_deserialize, {
CSubNet sub_net_1;
DeserializeFromFuzzingInput(buffer, sub_net_1, INIT_PROTO_VERSION);
AssertEqualAfterSerializeDeserialize(sub_net_1, INIT_PROTO_VERSION);
@@ -139,67 +155,85 @@ void test_one_input(const std::vector<uint8_t>& buffer)
CSubNet sub_net_3;
DeserializeFromFuzzingInput(buffer, sub_net_3);
AssertEqualAfterSerializeDeserialize(sub_net_3, INIT_PROTO_VERSION | ADDRV2_FORMAT);
-#elif TX_IN_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
CTxIn tx_in;
DeserializeFromFuzzingInput(buffer, tx_in);
AssertEqualAfterSerializeDeserialize(tx_in);
-#elif FLAT_FILE_POS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
FlatFilePos flat_file_pos;
DeserializeFromFuzzingInput(buffer, flat_file_pos);
AssertEqualAfterSerializeDeserialize(flat_file_pos);
-#elif KEY_ORIGIN_INFO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
KeyOriginInfo key_origin_info;
DeserializeFromFuzzingInput(buffer, key_origin_info);
AssertEqualAfterSerializeDeserialize(key_origin_info);
-#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
PartiallySignedTransaction partially_signed_transaction;
DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
-#elif PREFILLED_TRANSACTION_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
PrefilledTransaction prefilled_transaction;
DeserializeFromFuzzingInput(buffer, prefilled_transaction);
-#elif PSBT_INPUT_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
PSBTInput psbt_input;
DeserializeFromFuzzingInput(buffer, psbt_input);
-#elif PSBT_OUTPUT_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
PSBTOutput psbt_output;
DeserializeFromFuzzingInput(buffer, psbt_output);
-#elif BLOCK_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(block_deserialize, {
CBlock block;
DeserializeFromFuzzingInput(buffer, block);
-#elif BLOCKLOCATOR_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
CBlockLocator bl;
DeserializeFromFuzzingInput(buffer, bl);
-#elif BLOCKMERKLEROOT
+})
+FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
CBlock block;
DeserializeFromFuzzingInput(buffer, block);
bool mutated;
BlockMerkleRoot(block, &mutated);
-#elif ADDRMAN_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(addrman_deserialize, {
CAddrMan am;
DeserializeFromFuzzingInput(buffer, am);
-#elif BLOCKHEADER_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
CBlockHeader bh;
DeserializeFromFuzzingInput(buffer, bh);
-#elif BANENTRY_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(banentry_deserialize, {
CBanEntry be;
DeserializeFromFuzzingInput(buffer, be);
-#elif TXUNDO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
CTxUndo tu;
DeserializeFromFuzzingInput(buffer, tu);
-#elif BLOCKUNDO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
CBlockUndo bu;
DeserializeFromFuzzingInput(buffer, bu);
-#elif COINS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
Coin coin;
DeserializeFromFuzzingInput(buffer, coin);
-#elif NETADDR_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(netaddr_deserialize, {
CNetAddr na;
DeserializeFromFuzzingInput(buffer, na);
if (na.IsAddrV1Compatible()) {
AssertEqualAfterSerializeDeserialize(na);
}
AssertEqualAfterSerializeDeserialize(na, INIT_PROTO_VERSION | ADDRV2_FORMAT);
-#elif SERVICE_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(service_deserialize, {
CService s;
DeserializeFromFuzzingInput(buffer, s);
if (s.IsAddrV1Compatible()) {
@@ -213,50 +247,56 @@ void test_one_input(const std::vector<uint8_t>& buffer)
CService s2;
DeserializeFromFuzzingInput(buffer, s2, INIT_PROTO_VERSION | ADDRV2_FORMAT);
AssertEqualAfterSerializeDeserialize(s2, INIT_PROTO_VERSION | ADDRV2_FORMAT);
-#elif MESSAGEHEADER_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
CMessageHeader mh;
DeserializeFromFuzzingInput(buffer, mh);
(void)mh.IsCommandValid();
-#elif ADDRESS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(address_deserialize, {
CAddress a;
DeserializeFromFuzzingInput(buffer, a);
-#elif INV_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
CInv i;
DeserializeFromFuzzingInput(buffer, i);
-#elif BLOOMFILTER_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
CBloomFilter bf;
DeserializeFromFuzzingInput(buffer, bf);
-#elif DISKBLOCKINDEX_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
CDiskBlockIndex dbi;
DeserializeFromFuzzingInput(buffer, dbi);
-#elif TXOUTCOMPRESSOR_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
CTxOut to;
auto toc = Using<TxOutCompression>(to);
DeserializeFromFuzzingInput(buffer, toc);
-#elif BLOCKTRANSACTIONS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
BlockTransactions bt;
DeserializeFromFuzzingInput(buffer, bt);
-#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
BlockTransactionsRequest btr;
DeserializeFromFuzzingInput(buffer, btr);
-#elif SNAPSHOTMETADATA_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
SnapshotMetadata snapshot_metadata;
DeserializeFromFuzzingInput(buffer, snapshot_metadata);
-#elif UINT160_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
uint160 u160;
DeserializeFromFuzzingInput(buffer, u160);
AssertEqualAfterSerializeDeserialize(u160);
-#elif UINT256_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
uint256 u256;
DeserializeFromFuzzingInput(buffer, u256);
AssertEqualAfterSerializeDeserialize(u256);
-#else
-#error Need at least one fuzz target to compile
-#endif
+})
// Classes intentionally not covered in this file since their deserialization code is
// fuzzed elsewhere:
// * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
// * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
- } catch (const invalid_fuzzing_input_exception&) {
- }
-}
diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp
index c556599db3..635288fc36 100644
--- a/src/test/fuzz/eval_script.cpp
+++ b/src/test/fuzz/eval_script.cpp
@@ -10,12 +10,12 @@
#include <limits>
-void initialize()
+void initialize_eval_script()
{
static const ECCVerifyHandle verify_handle;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(eval_script, initialize_eval_script)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
diff --git a/src/test/fuzz/fee_rate.cpp b/src/test/fuzz/fee_rate.cpp
index f3d44d9f93..2955213635 100644
--- a/src/test/fuzz/fee_rate.cpp
+++ b/src/test/fuzz/fee_rate.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(fee_rate)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CAmount satoshis_per_k = ConsumeMoney(fuzzed_data_provider);
diff --git a/src/test/fuzz/fees.cpp b/src/test/fuzz/fees.cpp
index ce8700befa..61c7681bf9 100644
--- a/src/test/fuzz/fees.cpp
+++ b/src/test/fuzz/fees.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(fees)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)};
diff --git a/src/test/fuzz/flatfile.cpp b/src/test/fuzz/flatfile.cpp
index 95dabb8bab..d142e374b1 100644
--- a/src/test/fuzz/flatfile.cpp
+++ b/src/test/fuzz/flatfile.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(flatfile)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
std::optional<FlatFilePos> flat_file_pos = ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
diff --git a/src/test/fuzz/float.cpp b/src/test/fuzz/float.cpp
index a24bae5b35..d18a87d177 100644
--- a/src/test/fuzz/float.cpp
+++ b/src/test/fuzz/float.cpp
@@ -12,7 +12,7 @@
#include <cassert>
#include <cstdint>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(float)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index 753cfffdcb..fd87667755 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -5,6 +5,7 @@
#include <test/fuzz/fuzz.h>
#include <test/util/setup_common.h>
+#include <util/check.h>
#include <cstdint>
#include <unistd.h>
@@ -12,6 +13,36 @@
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
+std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize>>& FuzzTargets()
+{
+ static std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize>> g_fuzz_targets;
+ return g_fuzz_targets;
+}
+
+void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init)
+{
+ const auto it_ins = FuzzTargets().try_emplace(name, std::move(target), std::move(init));
+ Assert(it_ins.second);
+}
+
+static TypeTestOneInput* g_test_one_input{nullptr};
+
+void initialize()
+{
+ if (std::getenv("PRINT_ALL_FUZZ_TARGETS_AND_ABORT")) {
+ for (const auto& t : FuzzTargets()) {
+ std::cout << t.first << std::endl;
+ }
+ Assert(false);
+ }
+ std::string_view fuzz_target{Assert(std::getenv("FUZZ"))};
+ const auto it = FuzzTargets().find(fuzz_target);
+ Assert(it != FuzzTargets().end());
+ Assert(!g_test_one_input);
+ g_test_one_input = &std::get<0>(it->second);
+ std::get<1>(it->second)();
+}
+
#if defined(PROVIDE_MAIN_FUNCTION)
static bool read_stdin(std::vector<uint8_t>& data)
{
@@ -24,14 +55,10 @@ static bool read_stdin(std::vector<uint8_t>& data)
}
#endif
-// Default initialization: Override using a non-weak initialize().
-__attribute__((weak)) void initialize()
-{
-}
-
// This function is used by libFuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
+ static const auto& test_one_input = *Assert(g_test_one_input);
const std::vector<uint8_t> input(data, data + size);
test_one_input(input);
return 0;
@@ -48,6 +75,7 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
__attribute__((weak)) int main(int argc, char** argv)
{
initialize();
+ static const auto& test_one_input = *Assert(g_test_one_input);
#ifdef __AFL_INIT
// Enable AFL deferred forkserver mode. Requires compilation using
// afl-clang-fast++. See fuzzing.md for details.
diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h
index 3be202b16e..52841e069a 100644
--- a/src/test/fuzz/fuzz.h
+++ b/src/test/fuzz/fuzz.h
@@ -1,14 +1,33 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 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_TEST_FUZZ_FUZZ_H
#define BITCOIN_TEST_FUZZ_FUZZ_H
-#include <stdint.h>
+#include <cstdint>
+#include <functional>
+#include <string_view>
#include <vector>
-void initialize();
-void test_one_input(const std::vector<uint8_t>& buffer);
+using TypeTestOneInput = std::function<void(const std::vector<uint8_t>&)>;
+using TypeInitialize = std::function<void()>;
+
+void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init);
+
+inline void FuzzFrameworkEmptyFun() {}
+
+#define FUZZ_TARGET(name) \
+ FUZZ_TARGET_INIT(name, FuzzFrameworkEmptyFun)
+
+#define FUZZ_TARGET_INIT(name, init_fun) \
+ void name##_fuzz_target(const std::vector<uint8_t>&); \
+ struct name##_Before_Main { \
+ name##_Before_Main() \
+ { \
+ FuzzFrameworkRegisterTarget(#name, name##_fuzz_target, init_fun); \
+ } \
+ } const static g_##name##_before_main; \
+ void name##_fuzz_target(const std::vector<uint8_t>& buffer)
#endif // BITCOIN_TEST_FUZZ_FUZZ_H
diff --git a/src/test/fuzz/golomb_rice.cpp b/src/test/fuzz/golomb_rice.cpp
index a9f450b0c4..c99bf940c7 100644
--- a/src/test/fuzz/golomb_rice.cpp
+++ b/src/test/fuzz/golomb_rice.cpp
@@ -54,7 +54,7 @@ std::vector<uint64_t> BuildHashedSet(const std::unordered_set<std::vector<uint8_
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(golomb_rice)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
std::vector<uint8_t> golomb_rice_data;
diff --git a/src/test/fuzz/hex.cpp b/src/test/fuzz/hex.cpp
index 6a8699fd0f..cc1bc1c8cf 100644
--- a/src/test/fuzz/hex.cpp
+++ b/src/test/fuzz/hex.cpp
@@ -16,12 +16,12 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_hex()
{
static const ECCVerifyHandle verify_handle;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(hex, initialize_hex)
{
const std::string random_hex_string(buffer.begin(), buffer.end());
const std::vector<unsigned char> data = ParseHex(random_hex_string);
diff --git a/src/test/fuzz/http_request.cpp b/src/test/fuzz/http_request.cpp
index 36d44e361f..e3b62032bc 100644
--- a/src/test/fuzz/http_request.cpp
+++ b/src/test/fuzz/http_request.cpp
@@ -39,7 +39,7 @@ extern "C" int evhttp_parse_headers_(struct evhttp_request*, struct evbuffer*);
std::string RequestMethodString(HTTPRequest::RequestMethod m);
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(http_request)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
evhttp_request* evreq = evhttp_request_new(nullptr, nullptr);
diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp
index 35d6804d4f..ac83d91ea0 100644
--- a/src/test/fuzz/integer.cpp
+++ b/src/test/fuzz/integer.cpp
@@ -40,12 +40,12 @@
#include <set>
#include <vector>
-void initialize()
+void initialize_integer()
{
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(integer, initialize_integer)
{
if (buffer.size() < sizeof(uint256) + sizeof(uint160)) {
return;
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index 955b954700..aa8f826e4a 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -26,14 +26,14 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_key()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(key, initialize_key)
{
const CKey key = [&] {
CKey k;
diff --git a/src/test/fuzz/key_io.cpp b/src/test/fuzz/key_io.cpp
index 62aefb650d..665ca01fa1 100644
--- a/src/test/fuzz/key_io.cpp
+++ b/src/test/fuzz/key_io.cpp
@@ -14,14 +14,14 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_key_io()
{
static const ECCVerifyHandle verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::MAIN);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(key_io, initialize_key_io)
{
const std::string random_string(buffer.begin(), buffer.end());
diff --git a/src/test/fuzz/kitchen_sink.cpp b/src/test/fuzz/kitchen_sink.cpp
index 82cbc00a3a..fa4024fc38 100644
--- a/src/test/fuzz/kitchen_sink.cpp
+++ b/src/test/fuzz/kitchen_sink.cpp
@@ -2,6 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <merkleblock.h>
+#include <policy/fees.h>
#include <rpc/util.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -9,18 +11,49 @@
#include <util/error.h>
#include <util/translation.h>
+#include <array>
#include <cstdint>
#include <vector>
+namespace {
+constexpr TransactionError ALL_TRANSACTION_ERROR[] = {
+ TransactionError::OK,
+ TransactionError::MISSING_INPUTS,
+ TransactionError::ALREADY_IN_CHAIN,
+ TransactionError::P2P_DISABLED,
+ TransactionError::MEMPOOL_REJECTED,
+ TransactionError::MEMPOOL_ERROR,
+ TransactionError::INVALID_PSBT,
+ TransactionError::PSBT_MISMATCH,
+ TransactionError::SIGHASH_MISMATCH,
+ TransactionError::MAX_FEE_EXCEEDED,
+};
+}; // namespace
+
// The fuzzing kitchen sink: Fuzzing harness for functions that need to be
// fuzzed but a.) don't belong in any existing fuzzing harness file, and
// b.) are not important enough to warrant their own fuzzing harness file.
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(kitchen_sink)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- const TransactionError transaction_error = fuzzed_data_provider.PickValueInArray<TransactionError>({TransactionError::OK, TransactionError::MISSING_INPUTS, TransactionError::ALREADY_IN_CHAIN, TransactionError::P2P_DISABLED, TransactionError::MEMPOOL_REJECTED, TransactionError::MEMPOOL_ERROR, TransactionError::INVALID_PSBT, TransactionError::PSBT_MISMATCH, TransactionError::SIGHASH_MISMATCH, TransactionError::MAX_FEE_EXCEEDED});
+ const TransactionError transaction_error = fuzzed_data_provider.PickValueInArray(ALL_TRANSACTION_ERROR);
(void)JSONRPCTransactionError(transaction_error);
(void)RPCErrorFromTransactionError(transaction_error);
(void)TransactionErrorString(transaction_error);
+
+ (void)StringForFeeEstimateHorizon(fuzzed_data_provider.PickValueInArray(ALL_FEE_ESTIMATE_HORIZONS));
+
+ const OutputType output_type = fuzzed_data_provider.PickValueInArray(OUTPUT_TYPES);
+ const std::string& output_type_string = FormatOutputType(output_type);
+ OutputType output_type_parsed;
+ const bool parsed = ParseOutputType(output_type_string, output_type_parsed);
+ assert(parsed);
+ assert(output_type == output_type_parsed);
+ (void)ParseOutputType(fuzzed_data_provider.ConsumeRandomLengthString(64), output_type_parsed);
+
+ const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ const std::vector<bool> bits = BytesToBits(bytes);
+ const std::vector<uint8_t> bytes_decoded = BitsToBytes(bits);
+ assert(bytes == bytes_decoded);
}
diff --git a/src/test/fuzz/load_external_block_file.cpp b/src/test/fuzz/load_external_block_file.cpp
index d9de9d9866..c428a86631 100644
--- a/src/test/fuzz/load_external_block_file.cpp
+++ b/src/test/fuzz/load_external_block_file.cpp
@@ -13,12 +13,12 @@
#include <cstdint>
#include <vector>
-void initialize()
+void initialize_load_external_block_file()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
diff --git a/src/test/fuzz/locale.cpp b/src/test/fuzz/locale.cpp
index 2b181c6da1..5b1acae57b 100644
--- a/src/test/fuzz/locale.cpp
+++ b/src/test/fuzz/locale.cpp
@@ -35,7 +35,7 @@ bool IsAvailableLocale(const std::string& locale_identifier)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(locale)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string locale_identifier = ConsumeLocaleIdentifier(fuzzed_data_provider);
diff --git a/src/test/fuzz/merkleblock.cpp b/src/test/fuzz/merkleblock.cpp
index 4710e75757..15bcfab3ad 100644
--- a/src/test/fuzz/merkleblock.cpp
+++ b/src/test/fuzz/merkleblock.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(merkleblock)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
CPartialMerkleTree partial_merkle_tree;
diff --git a/src/test/fuzz/message.cpp b/src/test/fuzz/message.cpp
index fa0322a391..06cd0afe2a 100644
--- a/src/test/fuzz/message.cpp
+++ b/src/test/fuzz/message.cpp
@@ -16,14 +16,14 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_message()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(message, initialize_message)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string random_message = fuzzed_data_provider.ConsumeRandomLengthString(1024);
diff --git a/src/test/fuzz/muhash.cpp b/src/test/fuzz/muhash.cpp
new file mode 100644
index 0000000000..8f843ca773
--- /dev/null
+++ b/src/test/fuzz/muhash.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2020 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 <crypto/muhash.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <vector>
+
+FUZZ_TARGET(muhash)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ std::vector<uint8_t> data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ std::vector<uint8_t> data2 = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ if (data.empty()) {
+ data.resize(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 4096), fuzzed_data_provider.ConsumeIntegral<uint8_t>());
+ }
+ if (data2.empty()) {
+ data2.resize(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 4096), fuzzed_data_provider.ConsumeIntegral<uint8_t>());
+ }
+
+ data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ data2 = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+
+ MuHash3072 muhash;
+
+ // Test that MuHash result is consistent independent of order of operations
+ muhash.Insert(data);
+ muhash.Insert(data2);
+
+ uint256 out;
+ muhash.Finalize(out);
+
+ muhash = MuHash3072();
+ muhash.Insert(data2);
+ muhash.Insert(data);
+
+ uint256 out2;
+ muhash.Finalize(out2);
+
+ assert(out == out2);
+
+ // Test that removing all added elements brings the object back to it's initial state
+ muhash /= muhash;
+ muhash.Finalize(out);
+
+ MuHash3072 muhash2;
+ muhash2.Finalize(out2);
+
+ assert(out == out2);
+}
diff --git a/src/test/fuzz/multiplication_overflow.cpp b/src/test/fuzz/multiplication_overflow.cpp
index 08dc660a19..0f054529a6 100644
--- a/src/test/fuzz/multiplication_overflow.cpp
+++ b/src/test/fuzz/multiplication_overflow.cpp
@@ -40,7 +40,7 @@ void TestMultiplicationOverflow(FuzzedDataProvider& fuzzed_data_provider)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(multiplication_overflow)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
TestMultiplicationOverflow<int64_t>(fuzzed_data_provider);
diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp
index a0c8b7aac5..3ca921b5cf 100644
--- a/src/test/fuzz/net.cpp
+++ b/src/test/fuzz/net.cpp
@@ -13,43 +13,26 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
+#include <test/util/net.h>
#include <test/util/setup_common.h>
#include <cstdint>
#include <string>
#include <vector>
-void initialize()
+void initialize_net()
{
static const BasicTestingSetup basic_testing_setup;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(net, initialize_net)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
-
- const std::optional<CAddress> address = ConsumeDeserializable<CAddress>(fuzzed_data_provider);
- if (!address) {
- return;
- }
- const std::optional<CAddress> address_bind = ConsumeDeserializable<CAddress>(fuzzed_data_provider);
- if (!address_bind) {
- return;
- }
-
- CNode node{fuzzed_data_provider.ConsumeIntegral<NodeId>(),
- static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()),
- fuzzed_data_provider.ConsumeIntegral<int>(),
- INVALID_SOCKET,
- *address,
- fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
- fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
- *address_bind,
- fuzzed_data_provider.ConsumeRandomLengthString(32),
- fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH}),
- fuzzed_data_provider.ConsumeBool()};
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
+ CNode node{ConsumeNode(fuzzed_data_provider)};
+ node.SetCommonVersion(fuzzed_data_provider.ConsumeIntegral<int>());
while (fuzzed_data_provider.ConsumeBool()) {
- switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 11)) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 10)) {
case 0: {
node.CloseSocketDisconnect();
break;
@@ -59,10 +42,6 @@ void test_one_input(const std::vector<uint8_t>& buffer)
break;
}
case 2: {
- node.SetCommonVersion(fuzzed_data_provider.ConsumeIntegral<int>());
- break;
- }
- case 3: {
const std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider);
if (!SanityCheckASMap(asmap)) {
break;
@@ -71,18 +50,18 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.copyStats(stats, asmap);
break;
}
- case 4: {
+ case 3: {
const CNode* add_ref_node = node.AddRef();
assert(add_ref_node == &node);
break;
}
- case 5: {
+ case 4: {
if (node.GetRefCount() > 0) {
node.Release();
}
break;
}
- case 6: {
+ case 5: {
if (node.m_addr_known == nullptr) {
break;
}
@@ -93,7 +72,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.AddAddressKnown(*addr_opt);
break;
}
- case 7: {
+ case 6: {
if (node.m_addr_known == nullptr) {
break;
}
@@ -105,7 +84,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.PushAddress(*addr_opt, fast_random_context);
break;
}
- case 8: {
+ case 7: {
const std::optional<CInv> inv_opt = ConsumeDeserializable<CInv>(fuzzed_data_provider);
if (!inv_opt) {
break;
@@ -113,11 +92,11 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.AddKnownTx(inv_opt->hash);
break;
}
- case 9: {
+ case 8: {
node.PushTxInventory(ConsumeUInt256(fuzzed_data_provider));
break;
}
- case 10: {
+ case 9: {
const std::optional<CService> service_opt = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (!service_opt) {
break;
@@ -125,7 +104,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.SetAddrLocal(*service_opt);
break;
}
- case 11: {
+ case 10: {
const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider);
bool complete;
node.ReceiveMsgBytes(b, complete);
@@ -139,15 +118,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)node.GetId();
(void)node.GetLocalNonce();
(void)node.GetLocalServices();
- (void)node.GetMyStartingHeight();
const int ref_count = node.GetRefCount();
assert(ref_count >= 0);
(void)node.GetCommonVersion();
(void)node.RelayAddrsWithConn();
- const NetPermissionFlags net_permission_flags = fuzzed_data_provider.ConsumeBool() ?
- fuzzed_data_provider.PickValueInArray<NetPermissionFlags>({NetPermissionFlags::PF_NONE, NetPermissionFlags::PF_BLOOMFILTER, NetPermissionFlags::PF_RELAY, NetPermissionFlags::PF_FORCERELAY, NetPermissionFlags::PF_NOBAN, NetPermissionFlags::PF_MEMPOOL, NetPermissionFlags::PF_ISIMPLICIT, NetPermissionFlags::PF_ALL}) :
- static_cast<NetPermissionFlags>(fuzzed_data_provider.ConsumeIntegral<uint32_t>());
+ const NetPermissionFlags net_permission_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
(void)node.HasPermission(net_permission_flags);
(void)node.ConnectedThroughNetwork();
}
diff --git a/src/test/fuzz/net_permissions.cpp b/src/test/fuzz/net_permissions.cpp
index 8a674ac1e9..544a33047b 100644
--- a/src/test/fuzz/net_permissions.cpp
+++ b/src/test/fuzz/net_permissions.cpp
@@ -13,22 +13,11 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(net_permissions)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(32);
- const NetPermissionFlags net_permission_flags = fuzzed_data_provider.ConsumeBool() ? fuzzed_data_provider.PickValueInArray<NetPermissionFlags>({
- NetPermissionFlags::PF_NONE,
- NetPermissionFlags::PF_BLOOMFILTER,
- NetPermissionFlags::PF_RELAY,
- NetPermissionFlags::PF_FORCERELAY,
- NetPermissionFlags::PF_NOBAN,
- NetPermissionFlags::PF_MEMPOOL,
- NetPermissionFlags::PF_ADDR,
- NetPermissionFlags::PF_ISIMPLICIT,
- NetPermissionFlags::PF_ALL,
- }) :
- static_cast<NetPermissionFlags>(fuzzed_data_provider.ConsumeIntegral<uint32_t>());
+ const NetPermissionFlags net_permission_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
NetWhitebindPermissions net_whitebind_permissions;
bilingual_str error_net_whitebind_permissions;
diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp
index 8252f38726..6e9bb47ff6 100644
--- a/src/test/fuzz/netaddress.cpp
+++ b/src/test/fuzz/netaddress.cpp
@@ -12,7 +12,7 @@
#include <netinet/in.h>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(netaddress)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/node_eviction.cpp b/src/test/fuzz/node_eviction.cpp
new file mode 100644
index 0000000000..aaebe83c0a
--- /dev/null
+++ b/src/test/fuzz/node_eviction.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2020 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 <net.h>
+#include <optional.h>
+#include <protocol.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <optional>
+#include <vector>
+
+FUZZ_TARGET(node_eviction)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ std::vector<NodeEvictionCandidate> eviction_candidates;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ eviction_candidates.push_back({
+ fuzzed_data_provider.ConsumeIntegral<NodeId>(),
+ fuzzed_data_provider.ConsumeIntegral<int64_t>(),
+ fuzzed_data_provider.ConsumeIntegral<int64_t>(),
+ fuzzed_data_provider.ConsumeIntegral<int64_t>(),
+ fuzzed_data_provider.ConsumeIntegral<int64_t>(),
+ fuzzed_data_provider.ConsumeBool(),
+ fuzzed_data_provider.ConsumeBool(),
+ fuzzed_data_provider.ConsumeBool(),
+ fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
+ fuzzed_data_provider.ConsumeBool(),
+ fuzzed_data_provider.ConsumeBool(),
+ });
+ }
+ // Make a copy since eviction_candidates may be in some valid but otherwise
+ // indeterminate state after the SelectNodeToEvict(&&) call.
+ const std::vector<NodeEvictionCandidate> eviction_candidates_copy = eviction_candidates;
+ const Optional<NodeId> node_to_evict = SelectNodeToEvict(std::move(eviction_candidates));
+ if (node_to_evict) {
+ assert(std::any_of(eviction_candidates_copy.begin(), eviction_candidates_copy.end(), [&node_to_evict](const NodeEvictionCandidate& eviction_candidate) { return *node_to_evict == eviction_candidate.id; }));
+ }
+}
diff --git a/src/test/fuzz/p2p_transport_deserializer.cpp b/src/test/fuzz/p2p_transport_deserializer.cpp
index 7a6236efac..163f1b839e 100644
--- a/src/test/fuzz/p2p_transport_deserializer.cpp
+++ b/src/test/fuzz/p2p_transport_deserializer.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,12 +12,12 @@
#include <limits>
#include <vector>
-void initialize()
+void initialize_p2p_transport_deserializer()
{
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(p2p_transport_deserializer, initialize_p2p_transport_deserializer)
{
// Construct deserializer, with a dummy NodeId
V1TransportDeserializer deserializer{Params(), (NodeId)0, SER_NETWORK, INIT_PROTO_VERSION};
diff --git a/src/test/fuzz/parse_hd_keypath.cpp b/src/test/fuzz/parse_hd_keypath.cpp
index f668ca8c48..411b70230a 100644
--- a/src/test/fuzz/parse_hd_keypath.cpp
+++ b/src/test/fuzz/parse_hd_keypath.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(parse_hd_keypath)
{
const std::string keypath_str(buffer.begin(), buffer.end());
std::vector<uint32_t> keypath;
diff --git a/src/test/fuzz/parse_iso8601.cpp b/src/test/fuzz/parse_iso8601.cpp
index c86f8a853e..dcb24ac127 100644
--- a/src/test/fuzz/parse_iso8601.cpp
+++ b/src/test/fuzz/parse_iso8601.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(parse_iso8601)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/parse_numbers.cpp b/src/test/fuzz/parse_numbers.cpp
index 59f89dc9fb..ddd2bcfba3 100644
--- a/src/test/fuzz/parse_numbers.cpp
+++ b/src/test/fuzz/parse_numbers.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <string>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(parse_numbers)
{
const std::string random_string(buffer.begin(), buffer.end());
diff --git a/src/test/fuzz/parse_script.cpp b/src/test/fuzz/parse_script.cpp
index 21ac1aecf3..060ad3db12 100644
--- a/src/test/fuzz/parse_script.cpp
+++ b/src/test/fuzz/parse_script.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,7 +6,7 @@
#include <script/script.h>
#include <test/fuzz/fuzz.h>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(parse_script)
{
const std::string script_string(buffer.begin(), buffer.end());
try {
diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp
index a269378607..afe382ba21 100644
--- a/src/test/fuzz/parse_univalue.cpp
+++ b/src/test/fuzz/parse_univalue.cpp
@@ -12,13 +12,13 @@
#include <limits>
#include <string>
-void initialize()
+void initialize_parse_univalue()
{
static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(parse_univalue, initialize_parse_univalue)
{
const std::string random_string(buffer.begin(), buffer.end());
bool valid = true;
diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp
index 6c94a47f3c..35cfc5230b 100644
--- a/src/test/fuzz/policy_estimator.cpp
+++ b/src/test/fuzz/policy_estimator.cpp
@@ -14,12 +14,12 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_policy_estimator()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
CBlockPolicyEstimator block_policy_estimator;
@@ -66,10 +66,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
(void)block_policy_estimator.estimateFee(fuzzed_data_provider.ConsumeIntegral<int>());
EstimationResult result;
- (void)block_policy_estimator.estimateRawFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeFloatingPoint<double>(), fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}), fuzzed_data_provider.ConsumeBool() ? &result : nullptr);
+ (void)block_policy_estimator.estimateRawFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeFloatingPoint<double>(), fuzzed_data_provider.PickValueInArray(ALL_FEE_ESTIMATE_HORIZONS), fuzzed_data_provider.ConsumeBool() ? &result : nullptr);
FeeCalculation fee_calculation;
(void)block_policy_estimator.estimateSmartFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeBool() ? &fee_calculation : nullptr, fuzzed_data_provider.ConsumeBool());
- (void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}));
+ (void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray(ALL_FEE_ESTIMATE_HORIZONS));
}
{
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
diff --git a/src/test/fuzz/policy_estimator_io.cpp b/src/test/fuzz/policy_estimator_io.cpp
index 0edcf201c7..8fa52143d8 100644
--- a/src/test/fuzz/policy_estimator_io.cpp
+++ b/src/test/fuzz/policy_estimator_io.cpp
@@ -10,12 +10,12 @@
#include <cstdint>
#include <vector>
-void initialize()
+void initialize_policy_estimator_io()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(policy_estimator_io, initialize_policy_estimator_io)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp
index b7fc72373d..02beb6eb37 100644
--- a/src/test/fuzz/pow.cpp
+++ b/src/test/fuzz/pow.cpp
@@ -15,12 +15,12 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_pow()
{
SelectParams(CBaseChainParams::MAIN);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(pow, initialize_pow)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const Consensus::Params& consensus_params = Params().GetConsensus();
diff --git a/src/test/fuzz/prevector.cpp b/src/test/fuzz/prevector.cpp
index 626e187cbd..51956bbe9e 100644
--- a/src/test/fuzz/prevector.cpp
+++ b/src/test/fuzz/prevector.cpp
@@ -204,7 +204,7 @@ public:
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(prevector)
{
FuzzedDataProvider prov(buffer.data(), buffer.size());
prevector_tester<8, int> test;
diff --git a/src/test/fuzz/primitives_transaction.cpp b/src/test/fuzz/primitives_transaction.cpp
index 4a0f920f58..48815c8910 100644
--- a/src/test/fuzz/primitives_transaction.cpp
+++ b/src/test/fuzz/primitives_transaction.cpp
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(primitives_transaction)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CScript script = ConsumeScript(fuzzed_data_provider);
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index 9390399878..58637662c5 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -13,6 +13,7 @@
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
#include <test/util/mining.h>
#include <test/util/net.h>
#include <test/util/setup_common.h>
@@ -32,19 +33,10 @@
#include <vector>
namespace {
-
-#ifdef MESSAGE_TYPE
-#define TO_STRING_(s) #s
-#define TO_STRING(s) TO_STRING_(s)
-const std::string LIMIT_TO_MESSAGE_TYPE{TO_STRING(MESSAGE_TYPE)};
-#else
-const std::string LIMIT_TO_MESSAGE_TYPE;
-#endif
-
const TestingSetup* g_setup;
} // namespace
-void initialize()
+void initialize_process_message()
{
static TestingSetup setup{
CBaseChainParams::REGTEST,
@@ -60,7 +52,7 @@ void initialize()
SyncWithValidationInterfaceQueue();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+void fuzz_target(const std::vector<uint8_t>& buffer, const std::string& LIMIT_TO_MESSAGE_TYPE)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
@@ -72,19 +64,50 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
const bool jump_out_of_ibd{fuzzed_data_provider.ConsumeBool()};
if (jump_out_of_ibd) chainstate.JumpOutOfIbd();
- CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes<unsigned char>(), SER_NETWORK, PROTOCOL_VERSION};
- CNode& p2p_node = *MakeUnique<CNode>(0, ServiceFlags(NODE_NETWORK | NODE_WITNESS | NODE_BLOOM), 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, ConnectionType::OUTBOUND_FULL_RELAY).release();
+ CNode& p2p_node = *ConsumeNodeAsUniquePtr(fuzzed_data_provider).release();
+ FillNode(fuzzed_data_provider, p2p_node);
p2p_node.fSuccessfullyConnected = true;
- p2p_node.nVersion = PROTOCOL_VERSION;
- p2p_node.SetCommonVersion(PROTOCOL_VERSION);
connman.AddTestNode(p2p_node);
g_setup->m_node.peerman->InitializeNode(&p2p_node);
+
+ // fuzzed_data_provider is fully consumed after this call, don't use it
+ CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes<unsigned char>(), SER_NETWORK, PROTOCOL_VERSION};
try {
g_setup->m_node.peerman->ProcessMessage(p2p_node, random_message_type, random_bytes_data_stream,
GetTime<std::chrono::microseconds>(), std::atomic<bool>{false});
} catch (const std::ios_base::failure&) {
}
+ {
+ LOCK(p2p_node.cs_sendProcessing);
+ g_setup->m_node.peerman->SendMessages(&p2p_node);
+ }
SyncWithValidationInterfaceQueue();
LOCK2(::cs_main, g_cs_orphans); // See init.cpp for rationale for implicit locking order requirement
g_setup->m_node.connman->StopNodes();
}
+
+FUZZ_TARGET_INIT(process_message, initialize_process_message) { fuzz_target(buffer, ""); }
+FUZZ_TARGET_INIT(process_message_addr, initialize_process_message) { fuzz_target(buffer, "addr"); }
+FUZZ_TARGET_INIT(process_message_block, initialize_process_message) { fuzz_target(buffer, "block"); }
+FUZZ_TARGET_INIT(process_message_blocktxn, initialize_process_message) { fuzz_target(buffer, "blocktxn"); }
+FUZZ_TARGET_INIT(process_message_cmpctblock, initialize_process_message) { fuzz_target(buffer, "cmpctblock"); }
+FUZZ_TARGET_INIT(process_message_feefilter, initialize_process_message) { fuzz_target(buffer, "feefilter"); }
+FUZZ_TARGET_INIT(process_message_filteradd, initialize_process_message) { fuzz_target(buffer, "filteradd"); }
+FUZZ_TARGET_INIT(process_message_filterclear, initialize_process_message) { fuzz_target(buffer, "filterclear"); }
+FUZZ_TARGET_INIT(process_message_filterload, initialize_process_message) { fuzz_target(buffer, "filterload"); }
+FUZZ_TARGET_INIT(process_message_getaddr, initialize_process_message) { fuzz_target(buffer, "getaddr"); }
+FUZZ_TARGET_INIT(process_message_getblocks, initialize_process_message) { fuzz_target(buffer, "getblocks"); }
+FUZZ_TARGET_INIT(process_message_getblocktxn, initialize_process_message) { fuzz_target(buffer, "getblocktxn"); }
+FUZZ_TARGET_INIT(process_message_getdata, initialize_process_message) { fuzz_target(buffer, "getdata"); }
+FUZZ_TARGET_INIT(process_message_getheaders, initialize_process_message) { fuzz_target(buffer, "getheaders"); }
+FUZZ_TARGET_INIT(process_message_headers, initialize_process_message) { fuzz_target(buffer, "headers"); }
+FUZZ_TARGET_INIT(process_message_inv, initialize_process_message) { fuzz_target(buffer, "inv"); }
+FUZZ_TARGET_INIT(process_message_mempool, initialize_process_message) { fuzz_target(buffer, "mempool"); }
+FUZZ_TARGET_INIT(process_message_notfound, initialize_process_message) { fuzz_target(buffer, "notfound"); }
+FUZZ_TARGET_INIT(process_message_ping, initialize_process_message) { fuzz_target(buffer, "ping"); }
+FUZZ_TARGET_INIT(process_message_pong, initialize_process_message) { fuzz_target(buffer, "pong"); }
+FUZZ_TARGET_INIT(process_message_sendcmpct, initialize_process_message) { fuzz_target(buffer, "sendcmpct"); }
+FUZZ_TARGET_INIT(process_message_sendheaders, initialize_process_message) { fuzz_target(buffer, "sendheaders"); }
+FUZZ_TARGET_INIT(process_message_tx, initialize_process_message) { fuzz_target(buffer, "tx"); }
+FUZZ_TARGET_INIT(process_message_verack, initialize_process_message) { fuzz_target(buffer, "verack"); }
+FUZZ_TARGET_INIT(process_message_version, initialize_process_message) { fuzz_target(buffer, "version"); }
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
index 19ea92b750..db52da2f7e 100644
--- a/src/test/fuzz/process_messages.cpp
+++ b/src/test/fuzz/process_messages.cpp
@@ -19,7 +19,7 @@
const TestingSetup* g_setup;
-void initialize()
+void initialize_process_messages()
{
static TestingSetup setup{
CBaseChainParams::REGTEST,
@@ -35,7 +35,7 @@ void initialize()
SyncWithValidationInterfaceQueue();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(process_messages, initialize_process_messages)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
@@ -47,15 +47,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3);
for (int i = 0; i < num_peers_to_add; ++i) {
- const ServiceFlags service_flags = ServiceFlags(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
- const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH});
- peers.push_back(MakeUnique<CNode>(i, service_flags, 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, conn_type).release());
+ peers.push_back(ConsumeNodeAsUniquePtr(fuzzed_data_provider, i).release());
CNode& p2p_node = *peers.back();
+ FillNode(fuzzed_data_provider, p2p_node);
p2p_node.fSuccessfullyConnected = true;
p2p_node.fPauseSend = false;
- p2p_node.nVersion = PROTOCOL_VERSION;
- p2p_node.SetCommonVersion(PROTOCOL_VERSION);
g_setup->m_node.peerman->InitializeNode(&p2p_node);
connman.AddTestNode(p2p_node);
@@ -79,6 +76,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
connman.ProcessMessagesOnce(random_node);
} catch (const std::ios_base::failure&) {
}
+ {
+ LOCK(random_node.cs_sendProcessing);
+ g_setup->m_node.peerman->SendMessages(&random_node);
+ }
}
SyncWithValidationInterfaceQueue();
LOCK2(::cs_main, g_cs_orphans); // See init.cpp for rationale for implicit locking order requirement
diff --git a/src/test/fuzz/protocol.cpp b/src/test/fuzz/protocol.cpp
index 78df0f89e7..572181366b 100644
--- a/src/test/fuzz/protocol.cpp
+++ b/src/test/fuzz/protocol.cpp
@@ -12,7 +12,7 @@
#include <stdexcept>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(protocol)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<CInv> inv = ConsumeDeserializable<CInv>(fuzzed_data_provider);
diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp
index 908e2b16f2..0b4588c4ce 100644
--- a/src/test/fuzz/psbt.cpp
+++ b/src/test/fuzz/psbt.cpp
@@ -17,12 +17,12 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_psbt()
{
static const ECCVerifyHandle verify_handle;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(psbt, initialize_psbt)
{
PartiallySignedTransaction psbt_mut;
const std::string raw_psbt{buffer.begin(), buffer.end()};
diff --git a/src/test/fuzz/random.cpp b/src/test/fuzz/random.cpp
index 7df6594ad6..96668734fd 100644
--- a/src/test/fuzz/random.cpp
+++ b/src/test/fuzz/random.cpp
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(random)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
FastRandomContext fast_random_context{ConsumeUInt256(fuzzed_data_provider)};
diff --git a/src/test/fuzz/rbf.cpp b/src/test/fuzz/rbf.cpp
index 1fd88a5f7b..26c89a70c3 100644
--- a/src/test/fuzz/rbf.cpp
+++ b/src/test/fuzz/rbf.cpp
@@ -15,9 +15,10 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(rbf)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!mtx) {
return;
diff --git a/src/test/fuzz/rolling_bloom_filter.cpp b/src/test/fuzz/rolling_bloom_filter.cpp
index 623b8cff3a..6087ee964a 100644
--- a/src/test/fuzz/rolling_bloom_filter.cpp
+++ b/src/test/fuzz/rolling_bloom_filter.cpp
@@ -14,7 +14,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(rolling_bloom_filter)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index 4274fa4351..d883426c81 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -29,7 +29,7 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_script()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
static const ECCVerifyHandle verify_handle;
@@ -37,7 +37,7 @@ void initialize()
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(script, initialize_script)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<CScript> script_opt = ConsumeDeserializable<CScript>(fuzzed_data_provider);
@@ -71,7 +71,22 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)IsSolvable(signing_provider, script);
TxoutType which_type;
- (void)IsStandard(script, which_type);
+ bool is_standard_ret = IsStandard(script, which_type);
+ if (!is_standard_ret) {
+ assert(which_type == TxoutType::NONSTANDARD ||
+ which_type == TxoutType::NULL_DATA ||
+ which_type == TxoutType::MULTISIG);
+ }
+ if (which_type == TxoutType::NONSTANDARD) {
+ assert(!is_standard_ret);
+ }
+ if (which_type == TxoutType::NULL_DATA) {
+ assert(script.IsUnspendable());
+ }
+ if (script.IsUnspendable()) {
+ assert(which_type == TxoutType::NULL_DATA ||
+ which_type == TxoutType::NONSTANDARD);
+ }
(void)RecursiveDynamicUsage(script);
@@ -82,7 +97,6 @@ void test_one_input(const std::vector<uint8_t>& buffer)
(void)script.IsPayToScriptHash();
(void)script.IsPayToWitnessScriptHash();
(void)script.IsPushOnly();
- (void)script.IsUnspendable();
(void)script.GetSigOpCount(/* fAccurate= */ false);
(void)FormatScript(script);
diff --git a/src/test/fuzz/script_assets_test_minimizer.cpp b/src/test/fuzz/script_assets_test_minimizer.cpp
index d20fa43d68..2091ad5d91 100644
--- a/src/test/fuzz/script_assets_test_minimizer.cpp
+++ b/src/test/fuzz/script_assets_test_minimizer.cpp
@@ -188,9 +188,9 @@ void Test(const std::string& str)
ECCVerifyHandle handle;
-}
+} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_assets_test_minimizer)
{
if (buffer.size() < 2 || buffer.back() != '\n' || buffer[buffer.size() - 2] != ',') return;
const std::string str((const char*)buffer.data(), buffer.size() - 2);
diff --git a/src/test/fuzz/script_bitcoin_consensus.cpp b/src/test/fuzz/script_bitcoin_consensus.cpp
index 22f4b4f44a..fcd66b234e 100644
--- a/src/test/fuzz/script_bitcoin_consensus.cpp
+++ b/src/test/fuzz/script_bitcoin_consensus.cpp
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_bitcoin_consensus)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::vector<uint8_t> random_bytes_1 = ConsumeRandomLengthByteVector(fuzzed_data_provider);
diff --git a/src/test/fuzz/script_descriptor_cache.cpp b/src/test/fuzz/script_descriptor_cache.cpp
index 4bfe61cec7..1c62c018e7 100644
--- a/src/test/fuzz/script_descriptor_cache.cpp
+++ b/src/test/fuzz/script_descriptor_cache.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_descriptor_cache)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
DescriptorCache descriptor_cache;
diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp
index 300c78fca0..ce8915ca2c 100644
--- a/src/test/fuzz/script_flags.cpp
+++ b/src/test/fuzz/script_flags.cpp
@@ -13,12 +13,12 @@
/** Flags that are not forbidden by an assert */
static bool IsValidFlagCombination(unsigned flags);
-void initialize()
+void initialize_script_flags()
{
static const ECCVerifyHandle verify_handle;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(script_flags, initialize_script_flags)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
diff --git a/src/test/fuzz/script_interpreter.cpp b/src/test/fuzz/script_interpreter.cpp
index 26d5732f24..5d59771682 100644
--- a/src/test/fuzz/script_interpreter.cpp
+++ b/src/test/fuzz/script_interpreter.cpp
@@ -15,7 +15,7 @@
bool CastToBool(const std::vector<unsigned char>& vch);
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_interpreter)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
{
diff --git a/src/test/fuzz/script_ops.cpp b/src/test/fuzz/script_ops.cpp
index 7d24af20ac..d232e984bc 100644
--- a/src/test/fuzz/script_ops.cpp
+++ b/src/test/fuzz/script_ops.cpp
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_ops)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
CScript script = ConsumeScript(fuzzed_data_provider);
diff --git a/src/test/fuzz/script_sigcache.cpp b/src/test/fuzz/script_sigcache.cpp
index 87af71897b..f7e45d6889 100644
--- a/src/test/fuzz/script_sigcache.cpp
+++ b/src/test/fuzz/script_sigcache.cpp
@@ -16,7 +16,7 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_script_sigcache()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
@@ -24,12 +24,12 @@ void initialize()
InitSignatureCache();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(script_sigcache, initialize_script_sigcache)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<CMutableTransaction> mutable_transaction = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
- const CTransaction tx = mutable_transaction ? CTransaction{*mutable_transaction} : CTransaction{};
+ const CTransaction tx{mutable_transaction ? *mutable_transaction : CMutableTransaction{}};
const unsigned int n_in = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
const CAmount amount = ConsumeMoney(fuzzed_data_provider);
const bool store = fuzzed_data_provider.ConsumeBool();
diff --git a/src/test/fuzz/script_sign.cpp b/src/test/fuzz/script_sign.cpp
index c626f950e7..fe850a6959 100644
--- a/src/test/fuzz/script_sign.cpp
+++ b/src/test/fuzz/script_sign.cpp
@@ -22,14 +22,14 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_script_sign()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(script_sign, initialize_script_sign)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::vector<uint8_t> key = ConsumeRandomLengthByteVector(fuzzed_data_provider, 128);
diff --git a/src/test/fuzz/scriptnum_ops.cpp b/src/test/fuzz/scriptnum_ops.cpp
index 68c1ae58ca..650318f13c 100644
--- a/src/test/fuzz/scriptnum_ops.cpp
+++ b/src/test/fuzz/scriptnum_ops.cpp
@@ -24,7 +24,7 @@ bool IsValidSubtraction(const CScriptNum& lhs, const CScriptNum& rhs)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(scriptnum_ops)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
CScriptNum script_num = ConsumeScriptNum(fuzzed_data_provider);
diff --git a/src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp b/src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
index d4f302a8d3..0435626356 100644
--- a/src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
+++ b/src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
@@ -14,7 +14,7 @@
int ec_seckey_import_der(const secp256k1_context* ctx, unsigned char* out32, const unsigned char* seckey, size_t seckeylen);
int ec_seckey_export_der(const secp256k1_context* ctx, unsigned char* seckey, size_t* seckeylen, const unsigned char* key32, bool compressed);
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(secp256k1_ec_seckey_import_export_der)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
secp256k1_context* secp256k1_context_sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
diff --git a/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp b/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
index ed8c7aba89..f437d53b57 100644
--- a/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
+++ b/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
@@ -14,7 +14,7 @@
bool SigHasLowR(const secp256k1_ecdsa_signature* sig);
int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char* input, size_t inputlen);
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(secp256k1_ecdsa_signature_parse_der_lax)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const std::vector<uint8_t> signature_bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
diff --git a/src/test/fuzz/signature_checker.cpp b/src/test/fuzz/signature_checker.cpp
index 970452dbcc..3e7b72805e 100644
--- a/src/test/fuzz/signature_checker.cpp
+++ b/src/test/fuzz/signature_checker.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_signature_checker()
{
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
}
@@ -52,7 +52,7 @@ public:
};
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(signature_checker, initialize_signature_checker)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
diff --git a/src/test/fuzz/signet.cpp b/src/test/fuzz/signet.cpp
index 786f1a83fe..541322d484 100644
--- a/src/test/fuzz/signet.cpp
+++ b/src/test/fuzz/signet.cpp
@@ -15,12 +15,12 @@
#include <optional>
#include <vector>
-void initialize()
+void initialize_signet()
{
InitializeFuzzingContext(CBaseChainParams::SIGNET);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(signet, initialize_signet)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const std::optional<CBlock> block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
diff --git a/src/test/fuzz/span.cpp b/src/test/fuzz/span.cpp
index f6b6e8f6f0..8f753948df 100644
--- a/src/test/fuzz/span.cpp
+++ b/src/test/fuzz/span.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(span)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/spanparsing.cpp b/src/test/fuzz/spanparsing.cpp
index e5bf5dd608..b8996632bc 100644
--- a/src/test/fuzz/spanparsing.cpp
+++ b/src/test/fuzz/spanparsing.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,7 +6,7 @@
#include <test/fuzz/fuzz.h>
#include <util/spanparsing.h>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(spanparsing)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const size_t query_size = fuzzed_data_provider.ConsumeIntegral<size_t>();
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index 271062dc95..282a2cd8ca 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -33,7 +33,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(string)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string random_string_1 = fuzzed_data_provider.ConsumeRandomLengthString(32);
diff --git a/src/test/fuzz/strprintf.cpp b/src/test/fuzz/strprintf.cpp
index 29064bc45c..4af0e750ce 100644
--- a/src/test/fuzz/strprintf.cpp
+++ b/src/test/fuzz/strprintf.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(str_printf)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string format_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
diff --git a/src/test/fuzz/system.cpp b/src/test/fuzz/system.cpp
index 01b523cee4..375a8c1ed0 100644
--- a/src/test/fuzz/system.cpp
+++ b/src/test/fuzz/system.cpp
@@ -22,7 +22,7 @@ std::string GetArgumentName(const std::string& name)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(system)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
ArgsManager args_manager{};
diff --git a/src/test/fuzz/timedata.cpp b/src/test/fuzz/timedata.cpp
index a0e579a88f..d7fa66298a 100644
--- a/src/test/fuzz/timedata.cpp
+++ b/src/test/fuzz/timedata.cpp
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(timedata)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int max_size = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 1000);
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index 4f972dea1c..13ae450756 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -21,12 +21,12 @@
#include <cassert>
-void initialize()
+void initialize_transaction()
{
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(transaction, initialize_transaction)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
@@ -42,7 +42,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
return CTransaction(deserialize, ds);
} catch (const std::ios_base::failure&) {
valid_tx = false;
- return CTransaction();
+ return CTransaction{CMutableTransaction{}};
}
}();
bool valid_mutable_tx = true;
diff --git a/src/test/fuzz/tx_in.cpp b/src/test/fuzz/tx_in.cpp
index 8e116537d1..f8247c1fa4 100644
--- a/src/test/fuzz/tx_in.cpp
+++ b/src/test/fuzz/tx_in.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <cassert>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(tx_in)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
CTxIn tx_in;
diff --git a/src/test/fuzz/tx_out.cpp b/src/test/fuzz/tx_out.cpp
index aa1338d5ba..39a50b6c80 100644
--- a/src/test/fuzz/tx_out.cpp
+++ b/src/test/fuzz/tx_out.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
#include <test/fuzz/fuzz.h>
#include <version.h>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(tx_out)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
CTxOut tx_out;
diff --git a/src/test/fuzz/txrequest.cpp b/src/test/fuzz/txrequest.cpp
index 9529ad3274..72438ff2d7 100644
--- a/src/test/fuzz/txrequest.cpp
+++ b/src/test/fuzz/txrequest.cpp
@@ -310,7 +310,7 @@ public:
};
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(txrequest)
{
// Tester object (which encapsulates a TxRequestTracker).
Tester tester;
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index cf666a8b93..4e8e501895 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -22,6 +22,7 @@
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
+#include <test/util/net.h>
#include <test/util/setup_common.h>
#include <txmempool.h>
#include <uint256.h>
@@ -86,6 +87,14 @@ template <typename T>
return obj;
}
+template <typename WeakEnumType, size_t size>
+[[nodiscard]] WeakEnumType ConsumeWeakEnum(FuzzedDataProvider& fuzzed_data_provider, const WeakEnumType (&all_types)[size]) noexcept
+{
+ return fuzzed_data_provider.ConsumeBool() ?
+ fuzzed_data_provider.PickValueInArray<WeakEnumType>(all_types) :
+ WeakEnumType(fuzzed_data_provider.ConsumeIntegral<typename std::underlying_type<WeakEnumType>::type>());
+}
+
[[nodiscard]] inline opcodetype ConsumeOpcodeType(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return static_cast<opcodetype>(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, MAX_OPCODE));
@@ -249,7 +258,7 @@ template <class T>
return result;
}
-CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
+inline CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
const Network network = fuzzed_data_provider.PickValueInArray({Network::NET_IPV4, Network::NET_IPV6, Network::NET_INTERNAL, Network::NET_ONION});
CNetAddr net_addr;
@@ -271,38 +280,60 @@ CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
return net_addr;
}
-CSubNet ConsumeSubNet(FuzzedDataProvider& fuzzed_data_provider) noexcept
+inline CSubNet ConsumeSubNet(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint8_t>()};
}
-CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcept
+inline CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
}
-CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept
+inline CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
- return {ConsumeService(fuzzed_data_provider), static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()), fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+ return {ConsumeService(fuzzed_data_provider), ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS), fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
}
-CNode ConsumeNode(FuzzedDataProvider& fuzzed_data_provider) noexcept
+template <bool ReturnUniquePtr = false>
+auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<NodeId>& node_id_in = std::nullopt) noexcept
{
- const NodeId node_id = fuzzed_data_provider.ConsumeIntegral<NodeId>();
- const ServiceFlags local_services = static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
- const int my_starting_height = fuzzed_data_provider.ConsumeIntegral<int>();
+ const NodeId node_id = node_id_in.value_or(fuzzed_data_provider.ConsumeIntegral<NodeId>());
+ const ServiceFlags local_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS);
const SOCKET socket = INVALID_SOCKET;
const CAddress address = ConsumeAddress(fuzzed_data_provider);
const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider);
const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64);
- const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH});
- const bool inbound_onion = fuzzed_data_provider.ConsumeBool();
- return {node_id, local_services, my_starting_height, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion};
+ const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES);
+ const bool inbound_onion{conn_type == ConnectionType::INBOUND ? fuzzed_data_provider.ConsumeBool() : false};
+ if constexpr (ReturnUniquePtr) {
+ return std::make_unique<CNode>(node_id, local_services, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion);
+ } else {
+ return CNode{node_id, local_services, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion};
+ }
+}
+inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, const std::optional<NodeId>& node_id_in = nullopt) { return ConsumeNode<true>(fdp, node_id_in); }
+
+inline void FillNode(FuzzedDataProvider& fuzzed_data_provider, CNode& node, const std::optional<int32_t>& version_in = std::nullopt) noexcept
+{
+ const ServiceFlags remote_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS);
+ const NetPermissionFlags permission_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
+ const int32_t version = version_in.value_or(fuzzed_data_provider.ConsumeIntegral<int32_t>());
+ const bool filter_txs = fuzzed_data_provider.ConsumeBool();
+
+ node.nServices = remote_services;
+ node.m_permissionFlags = permission_flags;
+ node.nVersion = version;
+ node.SetCommonVersion(version);
+ if (node.m_tx_relay != nullptr) {
+ LOCK(node.m_tx_relay->cs_filter);
+ node.m_tx_relay->fRelayTxes = filter_txs;
+ }
}
-void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST)
+inline void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST)
{
static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}};
}
diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
index b0d4de89f3..73463b071e 100644
--- a/src/test/interfaces_tests.cpp
+++ b/src/test/interfaces_tests.cpp
@@ -17,8 +17,8 @@ BOOST_FIXTURE_TEST_SUITE(interfaces_tests, TestChain100Setup)
BOOST_AUTO_TEST_CASE(findBlock)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
BOOST_CHECK(chain->findBlock(active[10]->GetBlockHash(), FoundBlock().hash(hash)));
@@ -44,13 +44,25 @@ BOOST_AUTO_TEST_CASE(findBlock)
BOOST_CHECK(chain->findBlock(active[60]->GetBlockHash(), FoundBlock().mtpTime(mtp_time)));
BOOST_CHECK_EQUAL(mtp_time, active[60]->GetMedianTimePast());
+ bool cur_active{false}, next_active{false};
+ uint256 next_hash;
+ BOOST_CHECK_EQUAL(active.Height(), 100);
+ BOOST_CHECK(chain->findBlock(active[99]->GetBlockHash(), FoundBlock().inActiveChain(cur_active).nextBlock(FoundBlock().inActiveChain(next_active).hash(next_hash))));
+ BOOST_CHECK(cur_active);
+ BOOST_CHECK(next_active);
+ BOOST_CHECK_EQUAL(next_hash, active[100]->GetBlockHash());
+ cur_active = next_active = false;
+ BOOST_CHECK(chain->findBlock(active[100]->GetBlockHash(), FoundBlock().inActiveChain(cur_active).nextBlock(FoundBlock().inActiveChain(next_active))));
+ BOOST_CHECK(cur_active);
+ BOOST_CHECK(!next_active);
+
BOOST_CHECK(!chain->findBlock({}, FoundBlock()));
}
BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
int height;
BOOST_CHECK(chain->findFirstBlockWithTimeAndHeight(/* min_time= */ 0, /* min_height= */ 5, FoundBlock().hash(hash).height(height)));
@@ -59,25 +71,10 @@ BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
BOOST_CHECK(!chain->findFirstBlockWithTimeAndHeight(/* min_time= */ active.Tip()->GetBlockTimeMax() + 1, /* min_height= */ 0));
}
-BOOST_AUTO_TEST_CASE(findNextBlock)
-{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
- bool reorg;
- uint256 hash;
- BOOST_CHECK(chain->findNextBlock(active[20]->GetBlockHash(), 20, FoundBlock().hash(hash), &reorg));
- BOOST_CHECK_EQUAL(hash, active[21]->GetBlockHash());
- BOOST_CHECK_EQUAL(reorg, false);
- BOOST_CHECK(!chain->findNextBlock(uint256(), 20, {}, &reorg));
- BOOST_CHECK_EQUAL(reorg, true);
- BOOST_CHECK(!chain->findNextBlock(active.Tip()->GetBlockHash(), active.Height(), {}, &reorg));
- BOOST_CHECK_EQUAL(reorg, false);
-}
-
BOOST_AUTO_TEST_CASE(findAncestorByHeight)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
BOOST_CHECK(chain->findAncestorByHeight(active[20]->GetBlockHash(), 10, FoundBlock().hash(hash)));
BOOST_CHECK_EQUAL(hash, active[10]->GetBlockHash());
@@ -86,8 +83,8 @@ BOOST_AUTO_TEST_CASE(findAncestorByHeight)
BOOST_AUTO_TEST_CASE(findAncestorByHash)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
int height = -1;
BOOST_CHECK(chain->findAncestorByHash(active[20]->GetBlockHash(), active[10]->GetBlockHash(), FoundBlock().height(height)));
BOOST_CHECK_EQUAL(height, 10);
@@ -96,8 +93,8 @@ BOOST_AUTO_TEST_CASE(findAncestorByHash)
BOOST_AUTO_TEST_CASE(findCommonAncestor)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
auto* orig_tip = active.Tip();
for (int i = 0; i < 10; ++i) {
BlockValidationState state;
@@ -126,8 +123,8 @@ BOOST_AUTO_TEST_CASE(findCommonAncestor)
BOOST_AUTO_TEST_CASE(hasBlocks)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
// Test ranges
BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, 90));
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 3362b8d17c..cb66d5164e 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -172,20 +172,30 @@ BOOST_AUTO_TEST_CASE(key_signature_tests)
}
BOOST_CHECK(found);
- // When entropy is not specified, we should always see low R signatures that are less than 70 bytes in 256 tries
+ // When entropy is not specified, we should always see low R signatures that are less than or equal to 70 bytes in 256 tries
+ // The low R signatures should always have the value of their "length of R" byte less than or equal to 32
// We should see at least one signature that is less than 70 bytes.
- found = true;
bool found_small = false;
+ bool found_big = false;
+ bool bad_sign = false;
for (int i = 0; i < 256; ++i) {
sig.clear();
std::string msg = "A message to be signed" + ToString(i);
msg_hash = Hash(msg);
- BOOST_CHECK(key.Sign(msg_hash, sig));
- found = sig[3] == 0x20;
- BOOST_CHECK(sig.size() <= 70);
+ if (!key.Sign(msg_hash, sig)) {
+ bad_sign = true;
+ break;
+ }
+ // sig.size() > 70 implies sig[3] > 32, because S is always low.
+ // But check both conditions anyway, just in case this implication is broken for some reason
+ if (sig[3] > 32 || sig.size() > 70) {
+ found_big = true;
+ break;
+ }
found_small |= sig.size() < 70;
}
- BOOST_CHECK(found);
+ BOOST_CHECK(!bad_sign);
+ BOOST_CHECK(!found_big);
BOOST_CHECK(found_small);
}
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 9bc7cc5dab..942d54ede8 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 3de79a9f45..e967273636 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index b23fec9b95..a1b41e17ed 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -9,6 +9,7 @@
#include <cstdint>
#include <net.h>
#include <netbase.h>
+#include <optional.h>
#include <serialize.h>
#include <span.h>
#include <streams.h>
@@ -21,6 +22,7 @@
#include <boost/test/unit_test.hpp>
+#include <algorithm>
#include <ios>
#include <memory>
#include <string>
@@ -75,7 +77,7 @@ public:
}
};
-static CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
+static CDataStream AddrmanToStream(const CAddrManSerializationMock& _addrman)
{
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
ssPeersIn << Params().MessageStart();
@@ -179,7 +181,6 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
{
SOCKET hSocket = INVALID_SOCKET;
NodeId id = 0;
- int height = 0;
in_addr ipv4Addr;
ipv4Addr.s_addr = 0xa0b0c001;
@@ -188,7 +189,7 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
std::string pszDest;
std::unique_ptr<CNode> pnode1 = MakeUnique<CNode>(
- id++, NODE_NETWORK, height, hSocket, addr,
+ id++, NODE_NETWORK, hSocket, addr,
/* nKeyedNetGroupIn = */ 0,
/* nLocalHostNonceIn = */ 0,
CAddress(), pszDest, ConnectionType::OUTBOUND_FULL_RELAY);
@@ -198,10 +199,11 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
BOOST_CHECK(pnode1->IsFeelerConn() == false);
BOOST_CHECK(pnode1->IsAddrFetchConn() == false);
BOOST_CHECK(pnode1->IsInboundConn() == false);
+ BOOST_CHECK(pnode1->IsInboundOnion() == false);
BOOST_CHECK_EQUAL(pnode1->ConnectedThroughNetwork(), Network::NET_IPV4);
std::unique_ptr<CNode> pnode2 = MakeUnique<CNode>(
- id++, NODE_NETWORK, height, hSocket, addr,
+ id++, NODE_NETWORK, hSocket, addr,
/* nKeyedNetGroupIn = */ 1,
/* nLocalHostNonceIn = */ 1,
CAddress(), pszDest, ConnectionType::INBOUND,
@@ -212,24 +214,26 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
BOOST_CHECK(pnode2->IsFeelerConn() == false);
BOOST_CHECK(pnode2->IsAddrFetchConn() == false);
BOOST_CHECK(pnode2->IsInboundConn() == true);
+ BOOST_CHECK(pnode2->IsInboundOnion() == false);
BOOST_CHECK_EQUAL(pnode2->ConnectedThroughNetwork(), Network::NET_IPV4);
std::unique_ptr<CNode> pnode3 = MakeUnique<CNode>(
- id++, NODE_NETWORK, height, hSocket, addr,
+ id++, NODE_NETWORK, hSocket, addr,
/* nKeyedNetGroupIn = */ 0,
/* nLocalHostNonceIn = */ 0,
CAddress(), pszDest, ConnectionType::OUTBOUND_FULL_RELAY,
- /* inbound_onion = */ true);
+ /* inbound_onion = */ false);
BOOST_CHECK(pnode3->IsFullOutboundConn() == true);
BOOST_CHECK(pnode3->IsManualConn() == false);
BOOST_CHECK(pnode3->IsBlockOnlyConn() == false);
BOOST_CHECK(pnode3->IsFeelerConn() == false);
BOOST_CHECK(pnode3->IsAddrFetchConn() == false);
BOOST_CHECK(pnode3->IsInboundConn() == false);
+ BOOST_CHECK(pnode3->IsInboundOnion() == false);
BOOST_CHECK_EQUAL(pnode3->ConnectedThroughNetwork(), Network::NET_IPV4);
std::unique_ptr<CNode> pnode4 = MakeUnique<CNode>(
- id++, NODE_NETWORK, height, hSocket, addr,
+ id++, NODE_NETWORK, hSocket, addr,
/* nKeyedNetGroupIn = */ 1,
/* nLocalHostNonceIn = */ 1,
CAddress(), pszDest, ConnectionType::INBOUND,
@@ -240,6 +244,7 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
BOOST_CHECK(pnode4->IsFeelerConn() == false);
BOOST_CHECK(pnode4->IsAddrFetchConn() == false);
BOOST_CHECK(pnode4->IsInboundConn() == true);
+ BOOST_CHECK(pnode4->IsInboundOnion() == true);
BOOST_CHECK_EQUAL(pnode4->ConnectedThroughNetwork(), Network::NET_ONION);
}
@@ -604,6 +609,16 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_CHECK_EQUAL(addr.ToString(), "fc00:1:2:3:4:5:6:7");
BOOST_REQUIRE(s.empty());
+ // Invalid CJDNS, wrong prefix.
+ s << MakeSpan(ParseHex("06" // network type (CJDNS)
+ "10" // address length
+ "aa000001000200030004000500060007" // address
+ ));
+ s >> addr;
+ BOOST_CHECK(addr.IsCJDNS());
+ BOOST_CHECK(!addr.IsValid());
+ BOOST_REQUIRE(s.empty());
+
// Invalid CJDNS, with bogus length.
s << MakeSpan(ParseHex("06" // network type (CJDNS)
"01" // address length
@@ -664,7 +679,7 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
in_addr ipv4AddrPeer;
ipv4AddrPeer.s_addr = 0xa0b0c001;
CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
- std::unique_ptr<CNode> pnode = MakeUnique<CNode>(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, CAddress{}, std::string{}, ConnectionType::OUTBOUND_FULL_RELAY);
+ std::unique_ptr<CNode> pnode = MakeUnique<CNode>(0, NODE_NETWORK, INVALID_SOCKET, addr, 0, 0, CAddress{}, std::string{}, ConnectionType::OUTBOUND_FULL_RELAY);
pnode->fSuccessfullyConnected.store(true);
// the peer claims to be reaching us via IPv6
@@ -771,4 +786,147 @@ BOOST_AUTO_TEST_CASE(PoissonNextSend)
g_mock_deterministic_tests = false;
}
+std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(const int n_candidates, FastRandomContext& random_context)
+{
+ std::vector<NodeEvictionCandidate> candidates;
+ for (int id = 0; id < n_candidates; ++id) {
+ candidates.push_back({
+ /* id */ id,
+ /* nTimeConnected */ static_cast<int64_t>(random_context.randrange(100)),
+ /* nMinPingUsecTime */ static_cast<int64_t>(random_context.randrange(100)),
+ /* nLastBlockTime */ static_cast<int64_t>(random_context.randrange(100)),
+ /* nLastTXTime */ static_cast<int64_t>(random_context.randrange(100)),
+ /* fRelevantServices */ random_context.randbool(),
+ /* fRelayTxes */ random_context.randbool(),
+ /* fBloomFilter */ random_context.randbool(),
+ /* nKeyedNetGroup */ random_context.randrange(100),
+ /* prefer_evict */ random_context.randbool(),
+ /* m_is_local */ random_context.randbool(),
+ });
+ }
+ return candidates;
+}
+
+// Returns true if any of the node ids in node_ids are selected for eviction.
+bool IsEvicted(std::vector<NodeEvictionCandidate> candidates, const std::vector<NodeId>& node_ids, FastRandomContext& random_context)
+{
+ Shuffle(candidates.begin(), candidates.end(), random_context);
+ const Optional<NodeId> evicted_node_id = SelectNodeToEvict(std::move(candidates));
+ if (!evicted_node_id) {
+ return false;
+ }
+ return std::find(node_ids.begin(), node_ids.end(), *evicted_node_id) != node_ids.end();
+}
+
+// Create number_of_nodes random nodes, apply setup function candidate_setup_fn,
+// apply eviction logic and then return true if any of the node ids in node_ids
+// are selected for eviction.
+bool IsEvicted(const int number_of_nodes, std::function<void(NodeEvictionCandidate&)> candidate_setup_fn, const std::vector<NodeId>& node_ids, FastRandomContext& random_context)
+{
+ std::vector<NodeEvictionCandidate> candidates = GetRandomNodeEvictionCandidates(number_of_nodes, random_context);
+ for (NodeEvictionCandidate& candidate : candidates) {
+ candidate_setup_fn(candidate);
+ }
+ return IsEvicted(candidates, node_ids, random_context);
+}
+
+namespace {
+constexpr int NODE_EVICTION_TEST_ROUNDS{10};
+constexpr int NODE_EVICTION_TEST_UP_TO_N_NODES{200};
+} // namespace
+
+BOOST_AUTO_TEST_CASE(node_eviction_test)
+{
+ FastRandomContext random_context{true};
+
+ for (int i = 0; i < NODE_EVICTION_TEST_ROUNDS; ++i) {
+ for (int number_of_nodes = 0; number_of_nodes < NODE_EVICTION_TEST_UP_TO_N_NODES; ++number_of_nodes) {
+ // Four nodes with the highest keyed netgroup values should be
+ // protected from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nKeyedNetGroup = number_of_nodes - candidate.id;
+ },
+ {0, 1, 2, 3}, random_context));
+
+ // Eight nodes with the lowest minimum ping time should be protected
+ // from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [](NodeEvictionCandidate& candidate) {
+ candidate.nMinPingUsecTime = candidate.id;
+ },
+ {0, 1, 2, 3, 4, 5, 6, 7}, random_context));
+
+ // Four nodes that most recently sent us novel transactions accepted
+ // into our mempool should be protected from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nLastTXTime = number_of_nodes - candidate.id;
+ },
+ {0, 1, 2, 3}, random_context));
+
+ // Up to eight non-tx-relay peers that most recently sent us novel
+ // blocks should be protected from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nLastBlockTime = number_of_nodes - candidate.id;
+ if (candidate.id <= 7) {
+ candidate.fRelayTxes = false;
+ candidate.fRelevantServices = true;
+ }
+ },
+ {0, 1, 2, 3, 4, 5, 6, 7}, random_context));
+
+ // Four peers that most recently sent us novel blocks should be
+ // protected from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nLastBlockTime = number_of_nodes - candidate.id;
+ },
+ {0, 1, 2, 3}, random_context));
+
+ // Combination of the previous two tests.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nLastBlockTime = number_of_nodes - candidate.id;
+ if (candidate.id <= 7) {
+ candidate.fRelayTxes = false;
+ candidate.fRelevantServices = true;
+ }
+ },
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, random_context));
+
+ // Combination of all tests above.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nKeyedNetGroup = number_of_nodes - candidate.id; // 4 protected
+ candidate.nMinPingUsecTime = candidate.id; // 8 protected
+ candidate.nLastTXTime = number_of_nodes - candidate.id; // 4 protected
+ candidate.nLastBlockTime = number_of_nodes - candidate.id; // 4 protected
+ },
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, random_context));
+
+ // An eviction is expected given >= 29 random eviction candidates. The eviction logic protects at most
+ // four peers by net group, eight by lowest ping time, four by last time of novel tx, up to eight non-tx-relay
+ // peers by last novel block time, and four more peers by last novel block time.
+ if (number_of_nodes >= 29) {
+ BOOST_CHECK(SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context)));
+ }
+
+ // No eviction is expected given <= 20 random eviction candidates. The eviction logic protects at least
+ // four peers by net group, eight by lowest ping time, four by last time of novel tx and four peers by last
+ // novel block time.
+ if (number_of_nodes <= 20) {
+ BOOST_CHECK(!SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context)));
+ }
+
+ // Cases left to test:
+ // * "Protect the half of the remaining nodes which have been connected the longest. [...]"
+ // * "Pick out up to 1/4 peers that are localhost, sorted by longest uptime. [...]"
+ // * "If any remaining peers are preferred for eviction consider only them. [...]"
+ // * "Identify the network group with the most connections and youngest member. [...]"
+ }
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index ac4db3a5b6..66ad7bb5ea 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -226,8 +226,22 @@ BOOST_AUTO_TEST_CASE(subnet_test)
// IPv4 address with IPv6 netmask or the other way around.
BOOST_CHECK(!CSubNet(ResolveIP("1.1.1.1"), ResolveIP("ffff::")).IsValid());
BOOST_CHECK(!CSubNet(ResolveIP("::1"), ResolveIP("255.0.0.0")).IsValid());
- // Can't subnet TOR (or any other non-IPv4 and non-IPv6 network).
- BOOST_CHECK(!CSubNet(ResolveIP("5wyqrzbvrdsumnok.onion"), ResolveIP("255.0.0.0")).IsValid());
+
+ // Create Non-IP subnets.
+
+ const CNetAddr tor_addr{
+ ResolveIP("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion")};
+
+ subnet = CSubNet(tor_addr);
+ BOOST_CHECK(subnet.IsValid());
+ BOOST_CHECK_EQUAL(subnet.ToString(), tor_addr.ToString());
+ BOOST_CHECK(subnet.Match(tor_addr));
+ BOOST_CHECK(
+ !subnet.Match(ResolveIP("kpgvmscirrdqpekbqjsvw5teanhatztpp2gl6eee4zkowvwfxwenqaid.onion")));
+ BOOST_CHECK(!subnet.Match(ResolveIP("1.2.3.4")));
+
+ BOOST_CHECK(!CSubNet(tor_addr, 200).IsValid());
+ BOOST_CHECK(!CSubNet(tor_addr, ResolveIP("255.0.0.0")).IsValid());
subnet = ResolveSubNet("1.2.3.4/255.255.255.255");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
@@ -442,8 +456,7 @@ BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters)
BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0"s, ret));
BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com"s, ret));
BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com\0"s, ret));
- // We only do subnetting for IPv4 and IPv6
- BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion"s, ret));
+ BOOST_CHECK(LookupSubNet("5wyqrzbvrdsumnok.onion"s, ret));
BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0"s, ret));
BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com"s, ret));
BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com\0"s, ret));
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 1d7f4861fb..d5a4d3fd80 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp
index 8c2712f764..c489ac04e9 100644
--- a/src/test/raii_event_tests.cpp
+++ b/src/test/raii_event_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp
index a42608a66d..7da364d316 100644
--- a/src/test/reverselock_tests.cpp
+++ b/src/test/reverselock_tests.cpp
@@ -48,12 +48,14 @@ BOOST_AUTO_TEST_CASE(reverselock_errors)
WAIT_LOCK(mutex, lock);
#ifdef DEBUG_LOCKORDER
+ bool prev = g_debug_lockorder_abort;
+ g_debug_lockorder_abort = false;
+
// Make sure trying to reverse lock a previous lock fails
- try {
- REVERSE_LOCK(lock2);
- BOOST_CHECK(false); // REVERSE_LOCK(lock2) succeeded
- } catch(...) { }
+ BOOST_CHECK_EXCEPTION(REVERSE_LOCK(lock2), std::logic_error, HasReason("lock2 was not most recent critical section locked"));
BOOST_CHECK(lock2.owns_lock());
+
+ g_debug_lockorder_abort = prev;
#endif
// Make sure trying to reverse lock an unlocked lock fails
diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp
index 9a490aaf6b..740b2c72db 100644
--- a/src/test/sanity_tests.cpp
+++ b/src/test/sanity_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
index 1d6bcadf69..366385b619 100644
--- a/src/test/script_standard_tests.cpp
+++ b/src/test/script_standard_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -183,23 +183,23 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
s.clear();
s << ToByteVector(pubkey) << OP_CHECKSIG;
BOOST_CHECK(ExtractDestination(s, address));
- BOOST_CHECK(boost::get<PKHash>(&address) &&
- *boost::get<PKHash>(&address) == PKHash(pubkey));
+ BOOST_CHECK(std::get_if<PKHash>(&address) &&
+ *std::get_if<PKHash>(&address) == PKHash(pubkey));
// TxoutType::PUBKEYHASH
s.clear();
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
BOOST_CHECK(ExtractDestination(s, address));
- BOOST_CHECK(boost::get<PKHash>(&address) &&
- *boost::get<PKHash>(&address) == PKHash(pubkey));
+ BOOST_CHECK(std::get_if<PKHash>(&address) &&
+ *std::get_if<PKHash>(&address) == PKHash(pubkey));
// TxoutType::SCRIPTHASH
CScript redeemScript(s); // initialize with leftover P2PKH script
s.clear();
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
BOOST_CHECK(ExtractDestination(s, address));
- BOOST_CHECK(boost::get<ScriptHash>(&address) &&
- *boost::get<ScriptHash>(&address) == ScriptHash(redeemScript));
+ BOOST_CHECK(std::get_if<ScriptHash>(&address) &&
+ *std::get_if<ScriptHash>(&address) == ScriptHash(redeemScript));
// TxoutType::MULTISIG
s.clear();
@@ -217,7 +217,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
BOOST_CHECK(ExtractDestination(s, address));
WitnessV0KeyHash keyhash;
CHash160().Write(pubkey).Finalize(keyhash);
- BOOST_CHECK(boost::get<WitnessV0KeyHash>(&address) && *boost::get<WitnessV0KeyHash>(&address) == keyhash);
+ BOOST_CHECK(std::get_if<WitnessV0KeyHash>(&address) && *std::get_if<WitnessV0KeyHash>(&address) == keyhash);
// TxoutType::WITNESS_V0_SCRIPTHASH
s.clear();
@@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());
s << OP_0 << ToByteVector(scripthash);
BOOST_CHECK(ExtractDestination(s, address));
- BOOST_CHECK(boost::get<WitnessV0ScriptHash>(&address) && *boost::get<WitnessV0ScriptHash>(&address) == scripthash);
+ BOOST_CHECK(std::get_if<WitnessV0ScriptHash>(&address) && *std::get_if<WitnessV0ScriptHash>(&address) == scripthash);
// TxoutType::WITNESS_UNKNOWN with unknown version
s.clear();
@@ -235,7 +235,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
unk.length = 33;
unk.version = 1;
std::copy(pubkey.begin(), pubkey.end(), unk.program);
- BOOST_CHECK(boost::get<WitnessUnknown>(&address) && *boost::get<WitnessUnknown>(&address) == unk);
+ BOOST_CHECK(std::get_if<WitnessUnknown>(&address) && *std::get_if<WitnessUnknown>(&address) == unk);
}
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
@@ -259,8 +259,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
BOOST_CHECK_EQUAL(whichType, TxoutType::PUBKEY);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
- BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
- *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
+ BOOST_CHECK(std::get_if<PKHash>(&addresses[0]) &&
+ *std::get_if<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
// TxoutType::PUBKEYHASH
s.clear();
@@ -269,8 +269,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
BOOST_CHECK_EQUAL(whichType, TxoutType::PUBKEYHASH);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
- BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
- *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
+ BOOST_CHECK(std::get_if<PKHash>(&addresses[0]) &&
+ *std::get_if<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
// TxoutType::SCRIPTHASH
CScript redeemScript(s); // initialize with leftover P2PKH script
@@ -280,8 +280,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
BOOST_CHECK_EQUAL(whichType, TxoutType::SCRIPTHASH);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
- BOOST_CHECK(boost::get<ScriptHash>(&addresses[0]) &&
- *boost::get<ScriptHash>(&addresses[0]) == ScriptHash(redeemScript));
+ BOOST_CHECK(std::get_if<ScriptHash>(&addresses[0]) &&
+ *std::get_if<ScriptHash>(&addresses[0]) == ScriptHash(redeemScript));
// TxoutType::MULTISIG
s.clear();
@@ -293,10 +293,10 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
BOOST_CHECK_EQUAL(whichType, TxoutType::MULTISIG);
BOOST_CHECK_EQUAL(addresses.size(), 2U);
BOOST_CHECK_EQUAL(nRequired, 2);
- BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
- *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
- BOOST_CHECK(boost::get<PKHash>(&addresses[1]) &&
- *boost::get<PKHash>(&addresses[1]) == PKHash(pubkeys[1]));
+ BOOST_CHECK(std::get_if<PKHash>(&addresses[0]) &&
+ *std::get_if<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
+ BOOST_CHECK(std::get_if<PKHash>(&addresses[1]) &&
+ *std::get_if<PKHash>(&addresses[1]) == PKHash(pubkeys[1]));
// TxoutType::NULL_DATA
s.clear();
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index c509a252e0..8f5ee1e8e2 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp
index 14145ced7e..71275f69d9 100644
--- a/src/test/sync_tests.cpp
+++ b/src/test/sync_tests.cpp
@@ -62,6 +62,19 @@ void TestDoubleLock(bool should_throw)
g_debug_lockorder_abort = prev;
}
#endif /* DEBUG_LOCKORDER */
+
+template <typename MutexType>
+void TestInconsistentLockOrderDetected(MutexType& mutex1, MutexType& mutex2) NO_THREAD_SAFETY_ANALYSIS
+{
+ ENTER_CRITICAL_SECTION(mutex1);
+ ENTER_CRITICAL_SECTION(mutex2);
+#ifdef DEBUG_LOCKORDER
+ BOOST_CHECK_EXCEPTION(LEAVE_CRITICAL_SECTION(mutex1), std::logic_error, HasReason("mutex1 was not most recent critical section locked"));
+#endif // DEBUG_LOCKORDER
+ LEAVE_CRITICAL_SECTION(mutex2);
+ LEAVE_CRITICAL_SECTION(mutex1);
+ BOOST_CHECK(LockStackEmpty());
+}
} // namespace
BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup)
@@ -108,4 +121,28 @@ BOOST_AUTO_TEST_CASE(double_lock_recursive_mutex)
}
#endif /* DEBUG_LOCKORDER */
+BOOST_AUTO_TEST_CASE(inconsistent_lock_order_detected)
+{
+#ifdef DEBUG_LOCKORDER
+ bool prev = g_debug_lockorder_abort;
+ g_debug_lockorder_abort = false;
+#endif // DEBUG_LOCKORDER
+
+ RecursiveMutex rmutex1, rmutex2;
+ TestInconsistentLockOrderDetected(rmutex1, rmutex2);
+ // By checking lock order consistency (CheckLastCritical) before any unlocking (LeaveCritical)
+ // the lock tracking data must not have been broken by exception.
+ TestInconsistentLockOrderDetected(rmutex1, rmutex2);
+
+ Mutex mutex1, mutex2;
+ TestInconsistentLockOrderDetected(mutex1, mutex2);
+ // By checking lock order consistency (CheckLastCritical) before any unlocking (LeaveCritical)
+ // the lock tracking data must not have been broken by exception.
+ TestInconsistentLockOrderDetected(mutex1, mutex2);
+
+#ifdef DEBUG_LOCKORDER
+ g_debug_lockorder_abort = prev;
+#endif // DEBUG_LOCKORDER
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/system_tests.cpp b/src/test/system_tests.cpp
index a55145c738..ce555f7299 100644
--- a/src/test/system_tests.cpp
+++ b/src/test/system_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 1f520074b1..5b35ed6976 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -762,7 +762,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
// Only one TxoutType::NULL_DATA permitted in all cases
t.vout.resize(2);
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ t.vout[0].nValue = 0;
t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ t.vout[1].nValue = 0;
reason.clear();
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
BOOST_CHECK_EQUAL(reason, "multi-op-return");
diff --git a/src/test/util/logging.cpp b/src/test/util/logging.cpp
index 65a64f2384..c1dd47f06c 100644
--- a/src/test/util/logging.cpp
+++ b/src/test/util/logging.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/util/logging.h b/src/test/util/logging.h
index a49f9a7292..ebe0ecf623 100644
--- a/src/test/util/logging.h
+++ b/src/test/util/logging.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp
index 74536ae74c..0c6487fbfa 100644
--- a/src/test/util/mining.cpp
+++ b/src/test/util/mining.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/util/net.h b/src/test/util/net.h
index 1208e92762..e25036be26 100644
--- a/src/test/util/net.h
+++ b/src/test/util/net.h
@@ -30,4 +30,35 @@ struct ConnmanTestMsg : public CConnman {
bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const;
};
+constexpr ServiceFlags ALL_SERVICE_FLAGS[]{
+ NODE_NONE,
+ NODE_NETWORK,
+ NODE_BLOOM,
+ NODE_WITNESS,
+ NODE_COMPACT_FILTERS,
+ NODE_NETWORK_LIMITED,
+};
+
+constexpr NetPermissionFlags ALL_NET_PERMISSION_FLAGS[]{
+ NetPermissionFlags::PF_NONE,
+ NetPermissionFlags::PF_BLOOMFILTER,
+ NetPermissionFlags::PF_RELAY,
+ NetPermissionFlags::PF_FORCERELAY,
+ NetPermissionFlags::PF_NOBAN,
+ NetPermissionFlags::PF_MEMPOOL,
+ NetPermissionFlags::PF_ADDR,
+ NetPermissionFlags::PF_DOWNLOAD,
+ NetPermissionFlags::PF_ISIMPLICIT,
+ NetPermissionFlags::PF_ALL,
+};
+
+constexpr ConnectionType ALL_CONNECTION_TYPES[]{
+ ConnectionType::INBOUND,
+ ConnectionType::OUTBOUND_FULL_RELAY,
+ ConnectionType::MANUAL,
+ ConnectionType::FEELER,
+ ConnectionType::BLOCK_RELAY,
+ ConnectionType::ADDR_FETCH,
+};
+
#endif // BITCOIN_TEST_UTIL_NET_H
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index adf5970206..e167fc98fd 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -16,6 +16,7 @@
#include <net.h>
#include <net_processing.h>
#include <noui.h>
+#include <policy/fees.h>
#include <pow.h>
#include <rpc/blockchain.h>
#include <rpc/register.h>
@@ -124,40 +125,21 @@ BasicTestingSetup::~BasicTestingSetup()
ECC_Stop();
}
-TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
+ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
: BasicTestingSetup(chainName, extra_args)
{
- const CChainParams& chainparams = Params();
- // Ideally we'd move all the RPC tests to the functional testing framework
- // instead of unit tests, but for now we need these here.
- RegisterAllCoreRPCCommands(tableRPC);
-
- m_node.scheduler = MakeUnique<CScheduler>();
-
// We have to run a scheduler thread to prevent ActivateBestChain
// from blocking due to queue overrun.
+ m_node.scheduler = MakeUnique<CScheduler>();
threadGroup.create_thread([&] { TraceThread("scheduler", [&] { m_node.scheduler->serviceQueue(); }); });
GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler);
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
- m_node.mempool = MakeUnique<CTxMemPool>(&::feeEstimator, 1);
+ m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
+ m_node.mempool = std::make_unique<CTxMemPool>(m_node.fee_estimator.get(), 1);
m_node.chainman = &::g_chainman;
- m_node.chainman->InitializeChainstate(*m_node.mempool);
- ::ChainstateActive().InitCoinsDB(
- /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
- assert(!::ChainstateActive().CanFlushToDisk());
- ::ChainstateActive().InitCoinsCache(1 << 23);
- assert(::ChainstateActive().CanFlushToDisk());
- if (!LoadGenesisBlock(chainparams)) {
- throw std::runtime_error("LoadGenesisBlock failed.");
- }
-
- BlockValidationState state;
- if (!ActivateBestChain(state, chainparams)) {
- throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
- }
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
constexpr int script_check_threads = 2;
@@ -165,18 +147,9 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
}
g_parallel_script_checks = true;
-
- m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
- m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
- m_node.peerman = MakeUnique<PeerManager>(chainparams, *m_node.connman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
- {
- CConnman::Options options;
- options.m_msgproc = m_node.peerman.get();
- m_node.connman->Init(options);
- }
}
-TestingSetup::~TestingSetup()
+ChainTestingSetup::~ChainTestingSetup()
{
if (m_node.scheduler) m_node.scheduler->stop();
threadGroup.interrupt_all();
@@ -194,6 +167,41 @@ TestingSetup::~TestingSetup()
pblocktree.reset();
}
+TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
+ : ChainTestingSetup(chainName, extra_args)
+{
+ const CChainParams& chainparams = Params();
+ // Ideally we'd move all the RPC tests to the functional testing framework
+ // instead of unit tests, but for now we need these here.
+ RegisterAllCoreRPCCommands(tableRPC);
+
+ m_node.chainman->InitializeChainstate(*m_node.mempool);
+ ::ChainstateActive().InitCoinsDB(
+ /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
+ assert(!::ChainstateActive().CanFlushToDisk());
+ ::ChainstateActive().InitCoinsCache(1 << 23);
+ assert(::ChainstateActive().CanFlushToDisk());
+ if (!LoadGenesisBlock(chainparams)) {
+ throw std::runtime_error("LoadGenesisBlock failed.");
+ }
+
+ BlockValidationState state;
+ if (!ActivateBestChain(state, chainparams)) {
+ throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
+ }
+
+ m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
+ m_node.peerman = std::make_unique<PeerManager>(chainparams, *m_node.connman, m_node.banman.get(),
+ *m_node.scheduler, *m_node.chainman, *m_node.mempool,
+ false);
+ {
+ CConnman::Options options;
+ options.m_msgproc = m_node.peerman.get();
+ m_node.connman->Init(options);
+ }
+}
+
TestChain100Setup::TestChain100Setup()
{
// Generate a 100-block chain:
@@ -231,12 +239,12 @@ TestChain100Setup::~TestChain100Setup()
gArgs.ForceSetArg("-segwitheight", "0");
}
-CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction& tx)
+CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction& tx) const
{
return FromTx(MakeTransactionRef(tx));
}
-CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransactionRef& tx)
+CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransactionRef& tx) const
{
return CTxMemPoolEntry(tx, nFee, nTime, nHeight,
spendsCoinbase, sigOpCost, lp);
diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h
index 1812ce1666..dff8cf825e 100644
--- a/src/test/util/setup_common.h
+++ b/src/test/util/setup_common.h
@@ -83,14 +83,21 @@ private:
const fs::path m_path_root;
};
-/** Testing setup that configures a complete environment.
- * Included are coins database, script check threads setup.
+/** Testing setup that performs all steps up until right before
+ * ChainstateManager gets initialized. Meant for testing ChainstateManager
+ * initialization behaviour.
*/
-struct TestingSetup : public BasicTestingSetup {
+struct ChainTestingSetup : public BasicTestingSetup {
boost::thread_group threadGroup;
+ explicit ChainTestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
+ ~ChainTestingSetup();
+};
+
+/** Testing setup that configures a complete environment.
+ */
+struct TestingSetup : public ChainTestingSetup {
explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
- ~TestingSetup();
};
/** Identical to TestingSetup, but chain set to regtest */
@@ -138,8 +145,8 @@ struct TestMemPoolEntryHelper
nFee(0), nTime(0), nHeight(1),
spendsCoinbase(false), sigOpCost(4) { }
- CTxMemPoolEntry FromTx(const CMutableTransaction& tx);
- CTxMemPoolEntry FromTx(const CTransactionRef& tx);
+ CTxMemPoolEntry FromTx(const CMutableTransaction& tx) const;
+ CTxMemPoolEntry FromTx(const CTransactionRef& tx) const;
// Change the default value
TestMemPoolEntryHelper &Fee(CAmount _fee) { nFee = _fee; return *this; }
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 131508f5f8..4133f2623b 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1860,7 +1860,7 @@ BOOST_AUTO_TEST_CASE(test_Capitalize)
BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
}
-static std::string SpanToStr(Span<const char>& span)
+static std::string SpanToStr(const Span<const char>& span)
{
return std::string(span.begin(), span.end());
}
@@ -2014,12 +2014,6 @@ struct Tracker
copies = t.copies + 1;
return *this;
}
- Tracker& operator=(Tracker&& t) noexcept
- {
- origin = t.origin;
- copies = t.copies;
- return *this;
- }
};
}
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
index a6ec4ce17f..3d8570e27c 100644
--- a/src/test/validation_chainstatemanager_tests.cpp
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -15,15 +15,16 @@
#include <boost/test/unit_test.hpp>
-BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup)
//! Basic tests for ChainstateManager.
//!
//! First create a legacy (IBD) chainstate, then create a snapshot chainstate.
BOOST_AUTO_TEST_CASE(chainstatemanager)
{
- ChainstateManager manager;
- CTxMemPool mempool;
+ ChainstateManager& manager = *m_node.chainman;
+ CTxMemPool& mempool = *m_node.mempool;
+
std::vector<CChainState*> chainstates;
const CChainParams& chainparams = Params();
@@ -104,8 +105,9 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
//! Test rebalancing the caches associated with each chainstate.
BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
- ChainstateManager manager;
- CTxMemPool mempool;
+ ChainstateManager& manager = *m_node.chainman;
+ CTxMemPool& mempool = *m_node.mempool;
+
size_t max_cache = 10000;
manager.m_total_coinsdb_cache = max_cache;
manager.m_total_coinstip_cache = max_cache;
@@ -122,6 +124,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
LOCK(::cs_main);
c1.InitCoinsCache(1 << 23);
+ BOOST_REQUIRE(c1.LoadGenesisBlock(Params()));
c1.CoinsTip().SetBestBlock(InsecureRand256());
manager.MaybeRebalanceCaches();
}
@@ -139,6 +142,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
LOCK(::cs_main);
c2.InitCoinsCache(1 << 23);
+ BOOST_REQUIRE(c2.LoadGenesisBlock(Params()));
c2.CoinsTip().SetBestBlock(InsecureRand256());
manager.MaybeRebalanceCaches();
}
diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp
index c3816af0cd..9e37f14921 100644
--- a/src/test/validation_tests.cpp
+++ b/src/test/validation_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(signet_parse_tests)
CMutableTransaction cb;
cb.vout.emplace_back(0, CScript{});
block.vtx.push_back(MakeTransactionRef(cb));
- block.vtx.push_back(MakeTransactionRef(cb)); // Add dummy tx to excercise merkle root code
+ block.vtx.push_back(MakeTransactionRef(cb)); // Add dummy tx to exercise merkle root code
BOOST_CHECK(!SignetTxs::Create(block, challenge));
BOOST_CHECK(!CheckSignetBlockSolution(block, signet_params->GetConsensus()));
diff --git a/src/threadsafety.h b/src/threadsafety.h
index 52bf83b676..28b6177927 100644
--- a/src/threadsafety.h
+++ b/src/threadsafety.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 9d91f42b1b..90ee9422ba 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Copyright (c) 2017 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/torcontrol.h b/src/torcontrol.h
index 71a6960e54..00f19db6ae 100644
--- a/src/torcontrol.h
+++ b/src/torcontrol.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/uint256.cpp b/src/uint256.cpp
index f358b62903..cd9cbb566a 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/uint256.h b/src/uint256.h
index ceae70707e..fadf2320af 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/util/asmap.h b/src/util/asmap.h
index b31e639bb5..d0588bc8c3 100644
--- a/src/util/asmap.h
+++ b/src/util/asmap.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/util/check.h b/src/util/check.h
index 9edf394492..bc62da3440 100644
--- a/src/util/check.h
+++ b/src/util/check.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -46,7 +46,7 @@ class NonFatalCheckError : public std::runtime_error
#error "Cannot compile without assertions!"
#endif
-/** Helper for Assert(). TODO remove in C++14 and replace `decltype(get_pure_r_value(val))` with `T` (templated lambda) */
+/** Helper for Assert() */
template <typename T>
T get_pure_r_value(T&& val)
{
@@ -54,6 +54,22 @@ T get_pure_r_value(T&& val)
}
/** Identity function. Abort if the value compares equal to zero */
-#define Assert(val) [&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); assert(#val && check); return std::forward<decltype(get_pure_r_value(val))>(check); }()
+#define Assert(val) ([&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); assert(#val && check); return std::forward<decltype(get_pure_r_value(val))>(check); }())
+
+/**
+ * Assume is the identity function.
+ *
+ * - Should be used to run non-fatal checks. In debug builds it behaves like
+ * Assert()/assert() to notify developers and testers about non-fatal errors.
+ * In production it doesn't warn or log anything.
+ * - For fatal errors, use Assert().
+ * - For non-fatal errors in interactive sessions (e.g. RPC or command line
+ * interfaces), CHECK_NONFATAL() might be more appropriate.
+ */
+#ifdef ABORT_ON_FAILED_ASSUME
+#define Assume(val) Assert(val)
+#else
+#define Assume(val) ((void)(val))
+#endif
#endif // BITCOIN_UTIL_CHECK_H
diff --git a/src/util/error.cpp b/src/util/error.cpp
index 6c94b80683..76fac4d391 100644
--- a/src/util/error.cpp
+++ b/src/util/error.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2010-2019 The Bitcoin Core developers
+// Copyright (c) 2010-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/util/error.h b/src/util/error.h
index b9830c9eea..6633498d2b 100644
--- a/src/util/error.h
+++ b/src/util/error.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010-2019 The Bitcoin Core developers
+// Copyright (c) 2010-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/util/fees.cpp b/src/util/fees.cpp
index 1855c0bc90..cbefe18dbb 100644
--- a/src/util/fees.cpp
+++ b/src/util/fees.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/util/fees.h b/src/util/fees.h
index 3f1c33ad9c..9ef2389d3e 100644
--- a/src/util/fees.h
+++ b/src/util/fees.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 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_UTIL_FEES_H
diff --git a/src/util/golombrice.h b/src/util/golombrice.h
index 425e7f6681..67d262406f 100644
--- a/src/util/golombrice.h
+++ b/src/util/golombrice.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/util/memory.h b/src/util/memory.h
index 4d73b32869..f21b81bade 100644
--- a/src/util/memory.h
+++ b/src/util/memory.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/util/message.cpp b/src/util/message.cpp
index e1d5cff48c..73948e4ff1 100644
--- a/src/util/message.cpp
+++ b/src/util/message.cpp
@@ -31,7 +31,7 @@ MessageVerificationResult MessageVerify(
return MessageVerificationResult::ERR_INVALID_ADDRESS;
}
- if (boost::get<PKHash>(&destination) == nullptr) {
+ if (std::get_if<PKHash>(&destination) == nullptr) {
return MessageVerificationResult::ERR_ADDRESS_NO_KEY;
}
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 8ee43c620b..b4a61202ef 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -166,7 +166,7 @@ bool TimingResistantEqual(const T& a, const T& b)
}
/** Parse number as fixed point according to JSON number syntax.
- * See http://json.org/number.gif
+ * See https://json.org/number.gif
* @returns true on success, false on error.
* @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger.
*/
diff --git a/src/util/system.cpp b/src/util/system.cpp
index 5f30136fa2..917d37ccc7 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -1047,27 +1047,36 @@ bool FileCommit(FILE *file)
LogPrintf("%s: FlushFileBuffers failed: %d\n", __func__, GetLastError());
return false;
}
-#else
- #if HAVE_FDATASYNC
- if (fdatasync(fileno(file)) != 0 && errno != EINVAL) { // Ignore EINVAL for filesystems that don't support sync
- LogPrintf("%s: fdatasync failed: %d\n", __func__, errno);
- return false;
- }
- #elif defined(MAC_OSX) && defined(F_FULLFSYNC)
+#elif defined(MAC_OSX) && defined(F_FULLFSYNC)
if (fcntl(fileno(file), F_FULLFSYNC, 0) == -1) { // Manpage says "value other than -1" is returned on success
LogPrintf("%s: fcntl F_FULLFSYNC failed: %d\n", __func__, errno);
return false;
}
- #else
+#elif HAVE_FDATASYNC
+ if (fdatasync(fileno(file)) != 0 && errno != EINVAL) { // Ignore EINVAL for filesystems that don't support sync
+ LogPrintf("%s: fdatasync failed: %d\n", __func__, errno);
+ return false;
+ }
+#else
if (fsync(fileno(file)) != 0 && errno != EINVAL) {
LogPrintf("%s: fsync failed: %d\n", __func__, errno);
return false;
}
- #endif
#endif
return true;
}
+void DirectoryCommit(const fs::path &dirname)
+{
+#ifndef WIN32
+ FILE* file = fsbridge::fopen(dirname, "r");
+ if (file) {
+ fsync(fileno(file));
+ fclose(file);
+ }
+#endif
+}
+
bool TruncateFile(FILE *file, unsigned int length) {
#if defined(WIN32)
return _chsize(_fileno(file), length) == 0;
diff --git a/src/util/system.h b/src/util/system.h
index 2be8bb754b..010fc5b49f 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -56,7 +56,19 @@ bool error(const char* fmt, const Args&... args)
}
void PrintExceptionContinue(const std::exception *pex, const char* pszThread);
+
+/**
+ * Ensure file contents are fully committed to disk, using a platform-specific
+ * feature analogous to fsync().
+ */
bool FileCommit(FILE *file);
+
+/**
+ * Sync directory contents. This is required on some environments to ensure that
+ * newly created files are committed to disk.
+ */
+void DirectoryCommit(const fs::path &dirname);
+
bool TruncateFile(FILE *file, unsigned int length);
int RaiseFileDescriptorLimit(int nMinFD);
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
diff --git a/src/util/time.h b/src/util/time.h
index af934e423b..c69f604dc6 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -6,9 +6,11 @@
#ifndef BITCOIN_UTIL_TIME_H
#define BITCOIN_UTIL_TIME_H
+#include <chrono>
#include <stdint.h>
#include <string>
-#include <chrono>
+
+using namespace std::chrono_literals;
void UninterruptibleSleep(const std::chrono::microseconds& n);
diff --git a/src/util/translation.h b/src/util/translation.h
index 695d6dac96..99899ef3c2 100644
--- a/src/util/translation.h
+++ b/src/util/translation.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/validation.cpp b/src/validation.cpp
index a774e76fa9..4f7c95b2ad 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -22,7 +22,6 @@
#include <logging/timer.h>
#include <node/ui_interface.h>
#include <optional.h>
-#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <pow.h>
@@ -148,8 +147,6 @@ arith_uint256 nMinimumChainWork;
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
-CBlockPolicyEstimator feeEstimator;
-
// Internal stuff
namespace {
CBlockIndex* pindexBestInvalid = nullptr;
@@ -505,13 +502,13 @@ private:
// Run the script checks using our policy flags. As this can be slow, we should
// only invoke this on transactions that have otherwise passed policy checks.
- bool PolicyScriptChecks(ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool PolicyScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Re-run the script checks, using consensus flags, and try to cache the
// result in the scriptcache. This should be done after
// PolicyScriptChecks(). This requires that all inputs either be in our
// utxo set or in the mempool.
- bool ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, PrecomputedTransactionData &txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool ConsensusScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData &txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Try to add the transaction to the mempool, removing any conflicts first.
// Returns true if the transaction is in the mempool after any size
@@ -640,7 +637,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
LockPoints lp;
m_view.SetBackend(m_viewmempool);
- CCoinsViewCache& coins_cache = ::ChainstateActive().CoinsTip();
+ const CCoinsViewCache& coins_cache = ::ChainstateActive().CoinsTip();
// do all inputs exist?
for (const CTxIn& txin : tx.vin) {
if (!coins_cache.HaveCoinInCache(txin.prevout)) {
@@ -921,7 +918,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return true;
}
-bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata)
+bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata)
{
const CTransaction& tx = *ws.m_ptx;
@@ -948,7 +945,7 @@ bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, Workspace& ws, Precompute
return true;
}
-bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata)
+bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata)
{
const CTransaction& tx = *ws.m_ptx;
const uint256& hash = ws.m_hash;
@@ -5038,15 +5035,9 @@ bool LoadMempool(CTxMemPool& pool)
pool.PrioritiseTransaction(i.first, i.second);
}
- // TODO: remove this try except in v0.22
std::set<uint256> unbroadcast_txids;
- try {
- file >> unbroadcast_txids;
- unbroadcast = unbroadcast_txids.size();
- } catch (const std::exception&) {
- // mempool.dat files created prior to v0.21 will not have an
- // unbroadcast set. No need to log a failure if parsing fails here.
- }
+ file >> unbroadcast_txids;
+ unbroadcast = unbroadcast_txids.size();
for (const auto& txid : unbroadcast_txids) {
// Ensure transactions were accepted to mempool then add to
// unbroadcast set.
diff --git a/src/validation.h b/src/validation.h
index ffb038ad75..d10b260d8a 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -42,7 +42,6 @@ class CChainParams;
class CInv;
class CConnman;
class CScriptCheck;
-class CBlockPolicyEstimator;
class CTxMemPool;
class ChainstateManager;
class TxValidationState;
@@ -110,7 +109,6 @@ enum class SynchronizationState {
};
extern RecursiveMutex cs_main;
-extern CBlockPolicyEstimator feeEstimator;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
@@ -564,7 +562,7 @@ public:
//! @returns whether or not the CoinsViews object has been fully initialized and we can
//! safely flush this object to disk.
- bool CanFlushToDisk() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
+ bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
return m_coins_views && m_coins_views->m_cacheview;
}
diff --git a/src/version.h b/src/version.h
index 019c3a3ae7..ee646eefc3 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/versionbitsinfo.cpp b/src/versionbitsinfo.cpp
index 20dfc044ca..fa41bad46d 100644
--- a/src/versionbitsinfo.cpp
+++ b/src/versionbitsinfo.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp
index 85aae0170d..6ed48593fb 100644
--- a/src/wallet/bdb.cpp
+++ b/src/wallet/bdb.cpp
@@ -53,16 +53,13 @@ bool WalletDatabaseFileId::operator==(const WalletDatabaseFileId& rhs) const
}
/**
- * @param[in] wallet_path Path to wallet directory. Or (for backwards compatibility only) a path to a berkeley btree data file inside a wallet directory.
- * @param[out] database_filename Filename of berkeley btree data file inside the wallet directory.
+ * @param[in] env_directory Path to environment directory
* @return A shared pointer to the BerkeleyEnvironment object for the wallet directory, never empty because ~BerkeleyEnvironment
* erases the weak pointer from the g_dbenvs map.
* @post A new BerkeleyEnvironment weak pointer is inserted into g_dbenvs if the directory path key was not already in the map.
*/
-std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& wallet_path, std::string& database_filename)
+std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory)
{
- fs::path env_directory;
- SplitWalletPath(wallet_path, env_directory, database_filename);
LOCK(cs_db);
auto inserted = g_dbenvs.emplace(env_directory.string(), std::weak_ptr<BerkeleyEnvironment>());
if (inserted.second) {
@@ -808,21 +805,14 @@ std::unique_ptr<DatabaseBatch> BerkeleyDatabase::MakeBatch(bool flush_on_close)
return MakeUnique<BerkeleyBatch>(*this, false, flush_on_close);
}
-bool ExistsBerkeleyDatabase(const fs::path& path)
-{
- fs::path env_directory;
- std::string data_filename;
- SplitWalletPath(path, env_directory, data_filename);
- return IsBDBFile(env_directory / data_filename);
-}
-
std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)
{
+ fs::path data_file = BDBDataFile(path);
std::unique_ptr<BerkeleyDatabase> db;
{
LOCK(cs_db); // Lock env.m_databases until insert in BerkeleyDatabase constructor
- std::string data_filename;
- std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(path, data_filename);
+ std::string data_filename = data_file.filename().string();
+ std::shared_ptr<BerkeleyEnvironment> env = GetBerkeleyEnv(data_file.parent_path());
if (env->m_databases.count(data_filename)) {
error = Untranslated(strprintf("Refusing to load database. Data file '%s' is already loaded.", (env->Directory() / data_filename).string()));
status = DatabaseStatus::FAILED_ALREADY_LOADED;
@@ -839,28 +829,3 @@ std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, con
status = DatabaseStatus::SUCCESS;
return db;
}
-
-bool IsBDBFile(const fs::path& path)
-{
- if (!fs::exists(path)) return false;
-
- // A Berkeley DB Btree file has at least 4K.
- // This check also prevents opening lock files.
- boost::system::error_code ec;
- auto size = fs::file_size(path, ec);
- if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
- if (size < 4096) return false;
-
- fsbridge::ifstream file(path, std::ios::binary);
- if (!file.is_open()) return false;
-
- file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
- uint32_t data = 0;
- file.read((char*) &data, sizeof(data)); // Read 4 bytes of file to compare against magic
-
- // Berkeley DB Btree magic bytes, from:
- // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
- // - big endian systems - 00 05 31 62
- // - little endian systems - 62 31 05 00
- return data == 0x00053162 || data == 0x62310500;
-}
diff --git a/src/wallet/bdb.h b/src/wallet/bdb.h
index 4f97665f08..bf1617d67f 100644
--- a/src/wallet/bdb.h
+++ b/src/wallet/bdb.h
@@ -83,11 +83,8 @@ public:
}
};
-/** Get BerkeleyEnvironment and database filename given a wallet path. */
-std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& wallet_path, std::string& database_filename);
-
-/** Check format of database file */
-bool IsBDBFile(const fs::path& path);
+/** Get BerkeleyEnvironment given a directory path. */
+std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory);
class BerkeleyBatch;
@@ -226,9 +223,6 @@ public:
std::string BerkeleyDatabaseVersion();
-//! Check if Berkeley database exists at specified path.
-bool ExistsBerkeleyDatabase(const fs::path& path);
-
//! Return object giving access to Berkeley database at specified path.
std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index 1a45a2b313..a2dea84d17 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index 49c1134ec6..cf9768b927 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index f2df786e2e..f7325541a9 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index bd1d114730..cd49baeb78 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -3,23 +3,130 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <chainparams.h>
#include <fs.h>
+#include <logging.h>
#include <wallet/db.h>
#include <string>
-void SplitWalletPath(const fs::path& wallet_path, fs::path& env_directory, std::string& database_filename)
+std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
+{
+ const size_t offset = wallet_dir.string().size() + 1;
+ std::vector<fs::path> paths;
+ boost::system::error_code ec;
+
+ for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
+ if (ec) {
+ LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string());
+ continue;
+ }
+
+ try {
+ // Get wallet path relative to walletdir by removing walletdir from the wallet path.
+ // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
+ const fs::path path = it->path().string().substr(offset);
+
+ if (it->status().type() == fs::directory_file &&
+ (IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
+ // Found a directory which contains wallet.dat btree file, add it as a wallet.
+ paths.emplace_back(path);
+ } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBDBFile(it->path())) {
+ if (it->path().filename() == "wallet.dat") {
+ // Found top-level wallet.dat btree file, add top level directory ""
+ // as a wallet.
+ paths.emplace_back();
+ } else {
+ // Found top-level btree file not called wallet.dat. Current bitcoin
+ // software will never create these files but will allow them to be
+ // opened in a shared database environment for backwards compatibility.
+ // Add it to the list of available wallets.
+ paths.emplace_back(path);
+ }
+ }
+ } catch (const std::exception& e) {
+ LogPrintf("%s: Error scanning %s: %s\n", __func__, it->path().string(), e.what());
+ it.no_push();
+ }
+ }
+
+ return paths;
+}
+
+fs::path BDBDataFile(const fs::path& wallet_path)
{
if (fs::is_regular_file(wallet_path)) {
// Special case for backwards compatibility: if wallet path points to an
// existing file, treat it as the path to a BDB data file in a parent
// directory that also contains BDB log files.
- env_directory = wallet_path.parent_path();
- database_filename = wallet_path.filename().string();
+ return wallet_path;
} else {
// Normal case: Interpret wallet path as a directory path containing
// data and log files.
- env_directory = wallet_path;
- database_filename = "wallet.dat";
+ return wallet_path / "wallet.dat";
}
}
+
+fs::path SQLiteDataFile(const fs::path& path)
+{
+ return path / "wallet.dat";
+}
+
+bool IsBDBFile(const fs::path& path)
+{
+ if (!fs::exists(path)) return false;
+
+ // A Berkeley DB Btree file has at least 4K.
+ // This check also prevents opening lock files.
+ boost::system::error_code ec;
+ auto size = fs::file_size(path, ec);
+ if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
+ if (size < 4096) return false;
+
+ fsbridge::ifstream file(path, std::ios::binary);
+ if (!file.is_open()) return false;
+
+ file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
+ uint32_t data = 0;
+ file.read((char*) &data, sizeof(data)); // Read 4 bytes of file to compare against magic
+
+ // Berkeley DB Btree magic bytes, from:
+ // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
+ // - big endian systems - 00 05 31 62
+ // - little endian systems - 62 31 05 00
+ return data == 0x00053162 || data == 0x62310500;
+}
+
+bool IsSQLiteFile(const fs::path& path)
+{
+ if (!fs::exists(path)) return false;
+
+ // A SQLite Database file is at least 512 bytes.
+ boost::system::error_code ec;
+ auto size = fs::file_size(path, ec);
+ if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
+ if (size < 512) return false;
+
+ fsbridge::ifstream file(path, std::ios::binary);
+ if (!file.is_open()) return false;
+
+ // Magic is at beginning and is 16 bytes long
+ char magic[16];
+ file.read(magic, 16);
+
+ // Application id is at offset 68 and 4 bytes long
+ file.seekg(68, std::ios::beg);
+ char app_id[4];
+ file.read(app_id, 4);
+
+ file.close();
+
+ // Check the magic, see https://sqlite.org/fileformat2.html
+ std::string magic_str(magic, 16);
+ if (magic_str != std::string("SQLite format 3", 16)) {
+ return false;
+ }
+
+ // Check the application id matches our network magic
+ return memcmp(Params().MessageStart(), app_id, 4) == 0;
+}
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 940d1cd242..2c75486a44 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -223,6 +223,14 @@ enum class DatabaseStatus {
FAILED_ENCRYPT,
};
+/** Recursively list database paths in directory. */
+std::vector<fs::path> ListDatabases(const fs::path& path);
+
std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
+fs::path BDBDataFile(const fs::path& path);
+fs::path SQLiteDataFile(const fs::path& path);
+bool IsBDBFile(const fs::path& path);
+bool IsSQLiteFile(const fs::path& path);
+
#endif // BITCOIN_WALLET_DB_H
diff --git a/src/wallet/dump.cpp b/src/wallet/dump.cpp
new file mode 100644
index 0000000000..e314107988
--- /dev/null
+++ b/src/wallet/dump.cpp
@@ -0,0 +1,282 @@
+// Copyright (c) 2020 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 <wallet/dump.h>
+
+#include <util/translation.h>
+#include <wallet/wallet.h>
+
+static const std::string DUMP_MAGIC = "BITCOIN_CORE_WALLET_DUMP";
+uint32_t DUMP_VERSION = 1;
+
+bool DumpWallet(CWallet& wallet, bilingual_str& error)
+{
+ // Get the dumpfile
+ std::string dump_filename = gArgs.GetArg("-dumpfile", "");
+ if (dump_filename.empty()) {
+ error = _("No dump file provided. To use dump, -dumpfile=<filename> must be provided.");
+ return false;
+ }
+
+ fs::path path = dump_filename;
+ path = fs::absolute(path);
+ if (fs::exists(path)) {
+ error = strprintf(_("File %s already exists. If you are sure this is what you want, move it out of the way first."), path.string());
+ return false;
+ }
+ fsbridge::ofstream dump_file;
+ dump_file.open(path);
+ if (dump_file.fail()) {
+ error = strprintf(_("Unable to open %s for writing"), path.string());
+ return false;
+ }
+
+ CHashWriter hasher(0, 0);
+
+ WalletDatabase& db = wallet.GetDatabase();
+ std::unique_ptr<DatabaseBatch> batch = db.MakeBatch();
+
+ bool ret = true;
+ if (!batch->StartCursor()) {
+ error = _("Error: Couldn't create cursor into database");
+ ret = false;
+ }
+
+ // Write out a magic string with version
+ std::string line = strprintf("%s,%u\n", DUMP_MAGIC, DUMP_VERSION);
+ dump_file.write(line.data(), line.size());
+ hasher.write(line.data(), line.size());
+
+ // Write out the file format
+ line = strprintf("%s,%s\n", "format", db.Format());
+ dump_file.write(line.data(), line.size());
+ hasher.write(line.data(), line.size());
+
+ if (ret) {
+
+ // Read the records
+ while (true) {
+ CDataStream ss_key(SER_DISK, CLIENT_VERSION);
+ CDataStream ss_value(SER_DISK, CLIENT_VERSION);
+ bool complete;
+ ret = batch->ReadAtCursor(ss_key, ss_value, complete);
+ if (complete) {
+ ret = true;
+ break;
+ } else if (!ret) {
+ error = _("Error reading next record from wallet database");
+ break;
+ }
+ std::string key_str = HexStr(ss_key);
+ std::string value_str = HexStr(ss_value);
+ line = strprintf("%s,%s\n", key_str, value_str);
+ dump_file.write(line.data(), line.size());
+ hasher.write(line.data(), line.size());
+ }
+ }
+
+ batch->CloseCursor();
+ batch.reset();
+
+ // Close the wallet after we're done with it. The caller won't be doing this
+ wallet.Close();
+
+ if (ret) {
+ // Write the hash
+ tfm::format(dump_file, "checksum,%s\n", HexStr(hasher.GetHash()));
+ dump_file.close();
+ } else {
+ // Remove the dumpfile on failure
+ dump_file.close();
+ fs::remove(path);
+ }
+
+ return ret;
+}
+
+// The standard wallet deleter function blocks on the validation interface
+// queue, which doesn't exist for the bitcoin-wallet. Define our own
+// deleter here.
+static void WalletToolReleaseWallet(CWallet* wallet)
+{
+ wallet->WalletLogPrintf("Releasing wallet\n");
+ wallet->Close();
+ delete wallet;
+}
+
+bool CreateFromDump(const std::string& name, const fs::path& wallet_path, bilingual_str& error, std::vector<bilingual_str>& warnings)
+{
+ // Get the dumpfile
+ std::string dump_filename = gArgs.GetArg("-dumpfile", "");
+ if (dump_filename.empty()) {
+ error = _("No dump file provided. To use createfromdump, -dumpfile=<filename> must be provided.");
+ return false;
+ }
+
+ fs::path dump_path = dump_filename;
+ dump_path = fs::absolute(dump_path);
+ if (!fs::exists(dump_path)) {
+ error = strprintf(_("Dump file %s does not exist."), dump_path.string());
+ return false;
+ }
+ fsbridge::ifstream dump_file(dump_path);
+
+ // Compute the checksum
+ CHashWriter hasher(0, 0);
+ uint256 checksum;
+
+ // Check the magic and version
+ std::string magic_key;
+ std::getline(dump_file, magic_key, ',');
+ std::string version_value;
+ std::getline(dump_file, version_value, '\n');
+ if (magic_key != DUMP_MAGIC) {
+ error = strprintf(_("Error: Dumpfile identifier record is incorrect. Got \"%s\", expected \"%s\"."), magic_key, DUMP_MAGIC);
+ dump_file.close();
+ return false;
+ }
+ // Check the version number (value of first record)
+ uint32_t ver;
+ if (!ParseUInt32(version_value, &ver)) {
+ error =strprintf(_("Error: Unable to parse version %u as a uint32_t"), version_value);
+ dump_file.close();
+ return false;
+ }
+ if (ver != DUMP_VERSION) {
+ error = strprintf(_("Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s"), version_value);
+ dump_file.close();
+ return false;
+ }
+ std::string magic_hasher_line = strprintf("%s,%s\n", magic_key, version_value);
+ hasher.write(magic_hasher_line.data(), magic_hasher_line.size());
+
+ // Get the stored file format
+ std::string format_key;
+ std::getline(dump_file, format_key, ',');
+ std::string format_value;
+ std::getline(dump_file, format_value, '\n');
+ if (format_key != "format") {
+ error = strprintf(_("Error: Dumpfile format record is incorrect. Got \"%s\", expected \"format\"."), format_key);
+ dump_file.close();
+ return false;
+ }
+ // Get the data file format with format_value as the default
+ std::string file_format = gArgs.GetArg("-format", format_value);
+ if (file_format.empty()) {
+ error = _("No wallet file format provided. To use createfromdump, -format=<format> must be provided.");
+ return false;
+ }
+ DatabaseFormat data_format;
+ if (file_format == "bdb") {
+ data_format = DatabaseFormat::BERKELEY;
+ } else if (file_format == "sqlite") {
+ data_format = DatabaseFormat::SQLITE;
+ } else {
+ error = strprintf(_("Unknown wallet file format \"%s\" provided. Please provide one of \"bdb\" or \"sqlite\"."), file_format);
+ return false;
+ }
+ if (file_format != format_value) {
+ warnings.push_back(strprintf(_("Warning: Dumpfile wallet format \"%s\" does not match command line specified format \"%s\"."), format_value, file_format));
+ }
+ std::string format_hasher_line = strprintf("%s,%s\n", format_key, format_value);
+ hasher.write(format_hasher_line.data(), format_hasher_line.size());
+
+ DatabaseOptions options;
+ DatabaseStatus status;
+ options.require_create = true;
+ options.require_format = data_format;
+ std::unique_ptr<WalletDatabase> database = MakeDatabase(wallet_path, options, status, error);
+ if (!database) return false;
+
+ // dummy chain interface
+ bool ret = true;
+ std::shared_ptr<CWallet> wallet(new CWallet(nullptr /* chain */, name, std::move(database)), WalletToolReleaseWallet);
+ {
+ LOCK(wallet->cs_wallet);
+ bool first_run = true;
+ DBErrors load_wallet_ret = wallet->LoadWallet(first_run);
+ if (load_wallet_ret != DBErrors::LOAD_OK) {
+ error = strprintf(_("Error creating %s"), name);
+ return false;
+ }
+
+ // Get the database handle
+ WalletDatabase& db = wallet->GetDatabase();
+ std::unique_ptr<DatabaseBatch> batch = db.MakeBatch();
+ batch->TxnBegin();
+
+ // Read the records from the dump file and write them to the database
+ while (dump_file.good()) {
+ std::string key;
+ std::getline(dump_file, key, ',');
+ std::string value;
+ std::getline(dump_file, value, '\n');
+
+ if (key == "checksum") {
+ std::vector<unsigned char> parsed_checksum = ParseHex(value);
+ std::copy(parsed_checksum.begin(), parsed_checksum.end(), checksum.begin());
+ break;
+ }
+
+ std::string line = strprintf("%s,%s\n", key, value);
+ hasher.write(line.data(), line.size());
+
+ if (key.empty() || value.empty()) {
+ continue;
+ }
+
+ if (!IsHex(key)) {
+ error = strprintf(_("Error: Got key that was not hex: %s"), key);
+ ret = false;
+ break;
+ }
+ if (!IsHex(value)) {
+ error = strprintf(_("Error: Got value that was not hex: %s"), value);
+ ret = false;
+ break;
+ }
+
+ std::vector<unsigned char> k = ParseHex(key);
+ std::vector<unsigned char> v = ParseHex(value);
+
+ CDataStream ss_key(k, SER_DISK, CLIENT_VERSION);
+ CDataStream ss_value(v, SER_DISK, CLIENT_VERSION);
+
+ if (!batch->Write(ss_key, ss_value)) {
+ error = strprintf(_("Error: Unable to write record to new wallet"));
+ ret = false;
+ break;
+ }
+ }
+
+ if (ret) {
+ uint256 comp_checksum = hasher.GetHash();
+ if (checksum.IsNull()) {
+ error = _("Error: Missing checksum");
+ ret = false;
+ } else if (checksum != comp_checksum) {
+ error = strprintf(_("Error: Dumpfile checksum does not match. Computed %s, expected %s"), HexStr(comp_checksum), HexStr(checksum));
+ ret = false;
+ }
+ }
+
+ if (ret) {
+ batch->TxnCommit();
+ } else {
+ batch->TxnAbort();
+ }
+
+ batch.reset();
+
+ dump_file.close();
+ }
+ wallet.reset(); // The pointer deleter will close the wallet for us.
+
+ // Remove the wallet dir if we have a failure
+ if (!ret) {
+ fs::remove_all(wallet_path);
+ }
+
+ return ret;
+}
diff --git a/src/wallet/dump.h b/src/wallet/dump.h
new file mode 100644
index 0000000000..d0a4f5ef1d
--- /dev/null
+++ b/src/wallet/dump.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2020 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_WALLET_DUMP_H
+#define BITCOIN_WALLET_DUMP_H
+
+#include <fs.h>
+
+class CWallet;
+
+struct bilingual_str;
+
+bool DumpWallet(CWallet& wallet, bilingual_str& error);
+bool CreateFromDump(const std::string& name, const fs::path& wallet_path, bilingual_str& error, std::vector<bilingual_str>& warnings);
+
+#endif // BITCOIN_WALLET_DUMP_H
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 6cbad14de8..5e319d4f95 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -111,7 +111,7 @@ static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wt
return feebumper::Result::OK;
}
-static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CAmount old_fee, CCoinControl& coin_control)
+static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CAmount old_fee, const CCoinControl& coin_control)
{
// Get the fee rate of the original transaction. This is calculated from
// the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the
@@ -215,7 +215,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
// We cannot source new unconfirmed inputs(bip125 rule 2)
new_coin_control.m_min_depth = 1;
- CTransactionRef tx_new = MakeTransactionRef();
+ CTransactionRef tx_new;
CAmount fee_ret;
int change_pos_in_out = -1; // No requested location for change
bilingual_str fail_reason;
@@ -231,7 +231,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
// Write back transaction
mtx = CMutableTransaction(*tx_new);
// Mark new tx not replaceable, if requested.
- if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet.m_signal_rbf)) {
+ if (!coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf)) {
for (auto& input : mtx.vin) {
if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe;
}
@@ -256,7 +256,7 @@ Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransacti
errors.push_back(Untranslated("Invalid or non-wallet transaction id"));
return Result::MISC_ERROR;
}
- CWalletTx& oldWtx = it->second;
+ const CWalletTx& oldWtx = it->second;
// make sure the transaction still has no descendants and hasn't been mined in the meantime
Result result = PreconditionChecks(wallet, oldWtx, errors);
diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp
index 249bc833c6..429101e774 100644
--- a/src/wallet/fees.cpp
+++ b/src/wallet/fees.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -49,7 +49,7 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr
// We will use smart fee estimation
unsigned int target = coin_control.m_confirm_target ? *coin_control.m_confirm_target : wallet.m_confirm_target;
// By default estimates are economical iff we are signaling opt-in-RBF
- bool conservative_estimate = !coin_control.m_signal_bip125_rbf.get_value_or(wallet.m_signal_rbf);
+ bool conservative_estimate = !coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf);
// Allow to override the default fee estimate mode over the CoinControl instance
if (coin_control.m_fee_mode == FeeEstimateMode::CONSERVATIVE) conservative_estimate = true;
else if (coin_control.m_fee_mode == FeeEstimateMode::ECONOMICAL) conservative_estimate = false;
diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp
index 3fbba9ab92..e4e8c50f4f 100644
--- a/src/wallet/interfaces.cpp
+++ b/src/wallet/interfaces.cpp
@@ -77,7 +77,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
}
//! Construct wallet tx status struct.
-WalletTxStatus MakeWalletTxStatus(CWallet& wallet, const CWalletTx& wtx)
+WalletTxStatus MakeWalletTxStatus(const CWallet& wallet, const CWalletTx& wtx)
{
WalletTxStatus result;
result.block_height = wtx.m_confirm.block_height > 0 ? wtx.m_confirm.block_height : std::numeric_limits<int>::max();
@@ -94,7 +94,7 @@ WalletTxStatus MakeWalletTxStatus(CWallet& wallet, const CWalletTx& wtx)
}
//! Construct wallet TxOut struct.
-WalletTxOut MakeWalletTxOut(CWallet& wallet,
+WalletTxOut MakeWalletTxOut(const CWallet& wallet,
const CWalletTx& wtx,
int n,
int depth) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
@@ -551,7 +551,7 @@ public:
std::vector<std::string> listWalletDir() override
{
std::vector<std::string> paths;
- for (auto& path : ListWalletDir()) {
+ for (auto& path : ListDatabases(GetWalletDir())) {
paths.push_back(path.string());
}
return paths;
diff --git a/src/wallet/load.h b/src/wallet/load.h
index e12343de27..7910f0d6e1 100644
--- a/src/wallet/load.h
+++ b/src/wallet/load.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 7ea6a214b2..7705794c63 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -309,7 +309,7 @@ static RPCHelpMan getrawchangeaddress()
throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
}
- OutputType output_type = pwallet->m_default_change_type.get_value_or(pwallet->m_default_address_type);
+ OutputType output_type = pwallet->m_default_change_type.value_or(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()));
@@ -627,7 +627,7 @@ static RPCHelpMan signmessage()
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
}
- const PKHash *pkhash = boost::get<PKHash>(&dest);
+ const PKHash* pkhash = std::get_if<PKHash>(&dest);
if (!pkhash) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
}
@@ -1573,8 +1573,7 @@ static RPCHelpMan listsinceblock()
LOCK(wallet.cs_wallet);
- // The way the 'height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
- Optional<int> height = MakeOptional(false, int()); // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
+ Optional<int> height; // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
Optional<int> altheight; // Height of the specified block, even if it's in a deactivated chain.
int target_confirms = 1;
isminefilter filter = ISMINE_SPENDABLE;
@@ -2537,7 +2536,7 @@ static RPCHelpMan listwalletdir()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
UniValue wallets(UniValue::VARR);
- for (const auto& path : ListWalletDir()) {
+ for (const auto& path : ListDatabases(GetWalletDir())) {
UniValue wallet(UniValue::VOBJ);
wallet.pushKV("name", path.string());
wallets.push_back(wallet);
@@ -3003,7 +3002,7 @@ static RPCHelpMan listunspent()
std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
if (provider) {
if (scriptPubKey.IsPayToScriptHash()) {
- const CScriptID& hash = CScriptID(boost::get<ScriptHash>(address));
+ const CScriptID& hash = CScriptID(std::get<ScriptHash>(address));
CScript redeemScript;
if (provider->GetCScript(hash, redeemScript)) {
entry.pushKV("redeemScript", HexStr(redeemScript));
@@ -3013,7 +3012,7 @@ static RPCHelpMan listunspent()
bool extracted = ExtractDestination(redeemScript, witness_destination);
CHECK_NONFATAL(extracted);
// Also return the witness script
- const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(witness_destination);
+ const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(witness_destination);
CScriptID id;
CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
CScript witnessScript;
@@ -3023,7 +3022,7 @@ static RPCHelpMan listunspent()
}
}
} else if (scriptPubKey.IsPayToWitnessScriptHash()) {
- const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(address);
+ const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(address);
CScriptID id;
CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
CScript witnessScript;
@@ -3597,7 +3596,7 @@ static RPCHelpMan rescanblockchain()
}
int start_height = 0;
- Optional<int> stop_height = MakeOptional(false, int());
+ Optional<int> stop_height;
uint256 start_block;
{
LOCK(pwallet->cs_wallet);
@@ -3646,7 +3645,7 @@ static RPCHelpMan rescanblockchain()
};
}
-class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue>
+class DescribeWalletAddressVisitor
{
public:
const SigningProvider * const provider;
@@ -3665,7 +3664,7 @@ public:
UniValue subobj(UniValue::VOBJ);
UniValue detail = DescribeAddress(embedded);
subobj.pushKVs(detail);
- UniValue wallet_detail = boost::apply_visitor(*this, embedded);
+ UniValue wallet_detail = std::visit(*this, embedded);
subobj.pushKVs(wallet_detail);
subobj.pushKV("address", EncodeDestination(embedded));
subobj.pushKV("scriptPubKey", HexStr(subscript));
@@ -3748,7 +3747,7 @@ static UniValue DescribeWalletAddress(const CWallet* const pwallet, const CTxDes
provider = pwallet->GetSolvingProvider(script);
}
ret.pushKVs(detail);
- ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(provider.get()), dest));
+ ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
return ret;
}
@@ -4089,7 +4088,7 @@ static RPCHelpMan send()
UniValueType(), // outputs (ARR or OBJ, checked later)
UniValue::VNUM, // conf_target
UniValue::VSTR, // estimate_mode
- UniValue::VNUM, // fee_rate
+ UniValueType(), // fee_rate, will be checked by AmountFromValue() in SetFeeEstimateMode()
UniValue::VOBJ, // options
}, true
);
diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp
index da5ca7858f..09a9ec68cd 100644
--- a/src/wallet/salvage.cpp
+++ b/src/wallet/salvage.cpp
@@ -32,8 +32,9 @@ bool RecoverDatabaseFile(const fs::path& file_path, bilingual_str& error, std::v
std::unique_ptr<WalletDatabase> database = MakeDatabase(file_path, options, status, error);
if (!database) return false;
- std::string filename;
- std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, filename);
+ BerkeleyDatabase& berkeley_database = static_cast<BerkeleyDatabase&>(*database);
+ std::string filename = berkeley_database.Filename();
+ std::shared_ptr<BerkeleyEnvironment> env = berkeley_database.env;
if (!env->Open(error)) {
return false;
diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp
index d278d96476..0fb3b1d3c4 100644
--- a/src/wallet/sqlite.cpp
+++ b/src/wallet/sqlite.cpp
@@ -17,7 +17,6 @@
#include <sqlite3.h>
#include <stdint.h>
-static const char* const DATABASE_FILENAME = "wallet.dat";
static constexpr int32_t WALLET_SCHEMA_VERSION = 0;
static Mutex g_sqlite_mutex;
@@ -568,17 +567,11 @@ bool SQLiteBatch::TxnAbort()
return res == SQLITE_OK;
}
-bool ExistsSQLiteDatabase(const fs::path& path)
-{
- const fs::path file = path / DATABASE_FILENAME;
- return fs::symlink_status(file).type() == fs::regular_file && IsSQLiteFile(file);
-}
-
std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)
{
- const fs::path file = path / DATABASE_FILENAME;
try {
- auto db = MakeUnique<SQLiteDatabase>(path, file);
+ fs::path data_file = SQLiteDataFile(path);
+ auto db = MakeUnique<SQLiteDatabase>(data_file.parent_path(), data_file);
if (options.verify && !db->Verify(error)) {
status = DatabaseStatus::FAILED_VERIFY;
return nullptr;
@@ -596,37 +589,3 @@ std::string SQLiteDatabaseVersion()
{
return std::string(sqlite3_libversion());
}
-
-bool IsSQLiteFile(const fs::path& path)
-{
- if (!fs::exists(path)) return false;
-
- // A SQLite Database file is at least 512 bytes.
- boost::system::error_code ec;
- auto size = fs::file_size(path, ec);
- if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
- if (size < 512) return false;
-
- fsbridge::ifstream file(path, std::ios::binary);
- if (!file.is_open()) return false;
-
- // Magic is at beginning and is 16 bytes long
- char magic[16];
- file.read(magic, 16);
-
- // Application id is at offset 68 and 4 bytes long
- file.seekg(68, std::ios::beg);
- char app_id[4];
- file.read(app_id, 4);
-
- file.close();
-
- // Check the magic, see https://sqlite.org/fileformat2.html
- std::string magic_str(magic, 16);
- if (magic_str != std::string("SQLite format 3", 16)) {
- return false;
- }
-
- // Check the application id matches our network magic
- return memcmp(Params().MessageStart(), app_id, 4) == 0;
-}
diff --git a/src/wallet/sqlite.h b/src/wallet/sqlite.h
index 693a2ef55a..70ab4f797a 100644
--- a/src/wallet/sqlite.h
+++ b/src/wallet/sqlite.h
@@ -37,7 +37,7 @@ public:
explicit SQLiteBatch(SQLiteDatabase& database);
~SQLiteBatch() override { Close(); }
- /* No-op. See commeng on SQLiteDatabase::Flush */
+ /* No-op. See comment on SQLiteDatabase::Flush */
void Flush() override {}
void Close() override;
@@ -113,10 +113,8 @@ public:
sqlite3* m_db{nullptr};
};
-bool ExistsSQLiteDatabase(const fs::path& path);
std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
std::string SQLiteDatabaseVersion();
-bool IsSQLiteFile(const fs::path& path);
#endif // BITCOIN_WALLET_SQLITE_H
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index f38ccba384..202804c9ff 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -64,7 +64,8 @@ static void add_coin(CWallet& wallet, const CAmount& nValue, int nAge = 6*24, bo
if (spendable) {
CTxDestination dest;
std::string error;
- assert(wallet.GetNewDestination(OutputType::BECH32, "", dest, error));
+ const bool destination_ok = wallet.GetNewDestination(OutputType::BECH32, "", dest, error);
+ assert(destination_ok);
tx.vout[nInput].scriptPubKey = GetScriptForDestination(dest);
}
if (fIsFromMe) {
@@ -283,7 +284,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
// Make sure that can use BnB when there are preset inputs
empty_wallet();
{
- std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
+ std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->SetupLegacyScriptPubKeyMan();
@@ -452,7 +453,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
BOOST_CHECK( testWallet.SelectCoinsMinConf(1 * MIN_CHANGE, filter_confirmed, GroupCoins(vCoins), setCoinsRet, nValueRet, coin_selection_params, bnb_used));
BOOST_CHECK_EQUAL(nValueRet, 1 * MIN_CHANGE); // we should get the exact amount
- // run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf)
+ // run the 'mtgox' test (see https://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf)
// they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change
empty_wallet();
for (int j = 0; j < 20; j++)
diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp
index 8f0083cd2e..27179839b7 100644
--- a/src/wallet/test/db_tests.cpp
+++ b/src/wallet/test/db_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,6 +13,13 @@
BOOST_FIXTURE_TEST_SUITE(db_tests, BasicTestingSetup)
+static std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& path, std::string& database_filename)
+{
+ fs::path data_file = BDBDataFile(path);
+ database_filename = data_file.filename().string();
+ return GetBerkeleyEnv(data_file.parent_path());
+}
+
BOOST_AUTO_TEST_CASE(getwalletenv_file)
{
std::string test_name = "test_name.dat";
diff --git a/src/wallet/test/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp
index c80310045a..aa7f1c83d8 100644
--- a/src/wallet/test/init_test_fixture.cpp
+++ b/src/wallet/test/init_test_fixture.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{
- m_wallet_client = MakeWalletClient(*m_chain, *Assert(m_node.args));
+ m_wallet_client = MakeWalletClient(*m_node.chain, *Assert(m_node.args));
std::string sep;
sep += fs::path::preferred_separator;
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
index f5bade77df..37ae907de5 100644
--- a/src/wallet/test/init_test_fixture.h
+++ b/src/wallet/test/init_test_fixture.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,7 +19,6 @@ struct InitWalletDirTestingSetup: public BasicTestingSetup {
fs::path m_datadir;
fs::path m_cwd;
std::map<std::string, fs::path> m_walletdir_path_cases;
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<interfaces::WalletClient> m_wallet_client;
};
diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp
index 9b905569fc..e70b56c529 100644
--- a/src/wallet/test/init_tests.cpp
+++ b/src/wallet/test/init_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp
index d5aed99d99..5d25885bd4 100644
--- a/src/wallet/test/ismine_tests.cpp
+++ b/src/wallet/test/ismine_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -27,8 +27,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
CKey uncompressedKey;
uncompressedKey.MakeNewKey(false);
CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
+ std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
CScript scriptPubKey;
isminetype result;
diff --git a/src/wallet/test/scriptpubkeyman_tests.cpp b/src/wallet/test/scriptpubkeyman_tests.cpp
index f7c1337b0d..347a436429 100644
--- a/src/wallet/test/scriptpubkeyman_tests.cpp
+++ b/src/wallet/test/scriptpubkeyman_tests.cpp
@@ -17,9 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(scriptpubkeyman_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(CanProvide)
{
// Set up wallet and keyman variables.
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
LegacyScriptPubKeyMan& keyman = *wallet.GetOrCreateLegacyScriptPubKeyMan();
// Make a 1 of 2 multisig script
diff --git a/src/wallet/test/wallet_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp
index 10ddfa22ef..5b421840e0 100644
--- a/src/wallet/test/wallet_crypto_tests.cpp
+++ b/src/wallet/test/wallet_crypto_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index 4d6f427618..badf2eb459 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -6,10 +6,10 @@
WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
: TestingSetup(chainName),
- m_wallet(m_chain.get(), "", CreateMockWalletDatabase())
+ m_wallet(m_node.chain.get(), "", CreateMockWalletDatabase())
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
- m_chain_notifications_handler = m_chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
+ m_chain_notifications_handler = m_node.chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
m_wallet_client->registerRpcs();
}
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index ba8a5ff1f3..ab7fb8c42b 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -20,8 +20,7 @@
struct WalletTestingSetup : public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
- std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_chain, *Assert(m_node.args));
+ std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_node.chain, *Assert(m_node.args));
CWallet m_wallet;
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
};
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 4911af08c6..5480f3ab22 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -28,6 +28,8 @@ RPCHelpMan importmulti();
RPCHelpMan dumpwallet();
RPCHelpMan importwallet();
+extern RecursiveMutex cs_wallets;
+
// Ensure that fee levels defined in the wallet are at least as high
// as the default levels for node policy.
static_assert(DEFAULT_TRANSACTION_MINFEE >= DEFAULT_MIN_RELAY_TX_FEE, "wallet minimum fee is smaller than default relay fee");
@@ -83,12 +85,9 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
// Verify ScanForWalletTransactions fails to read an unknown start block.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -107,7 +106,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions picks up transactions in both the old
// and new block files.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -133,7 +132,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions only picks transactions in the new block
// file.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -158,7 +157,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions scans no blocks.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -183,9 +182,6 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
// Prune the older block file.
{
LOCK(cs_main);
@@ -197,7 +193,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
// before the missing block, and success for a key whose creation time is
// after.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
WITH_LOCK(wallet->cs_wallet, wallet->SetLastBlockProcessed(newTip->nHeight, newTip->GetBlockHash()));
AddWallet(wallet);
@@ -255,14 +251,11 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(KEY_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
std::string backup_file = (GetDataDir() / "wallet.backup").string();
// Import key into wallet and call dumpwallet to create backup file.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
@@ -284,7 +277,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
// were scanned, and no prior blocks were scanned.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
LOCK(wallet->cs_wallet);
wallet->SetupLegacyScriptPubKeyMan();
@@ -317,10 +310,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// debit functions.
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
auto spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
CWalletTx wtx(&wallet, m_coinbase_txns.back());
@@ -495,7 +485,7 @@ public:
ListCoinsTestingSetup()
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- wallet = MakeUnique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
+ wallet = MakeUnique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
{
LOCK2(wallet->cs_wallet, ::cs_main);
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -545,7 +535,6 @@ public:
return it->second;
}
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<CWallet> wallet;
};
@@ -561,7 +550,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
- BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
+ BOOST_CHECK_EQUAL(std::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
BOOST_CHECK_EQUAL(list.begin()->second.size(), 1U);
// Check initial balance from one mature coinbase transaction.
@@ -577,7 +566,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
- BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
+ BOOST_CHECK_EQUAL(std::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
BOOST_CHECK_EQUAL(list.begin()->second.size(), 2U);
// Lock both coins. Confirm number of available coins drops to 0.
@@ -606,15 +595,13 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
list = wallet->ListCoins();
}
BOOST_CHECK_EQUAL(list.size(), 1U);
- BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
+ BOOST_CHECK_EQUAL(std::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
BOOST_CHECK_EQUAL(list.begin()->second.size(), 2U);
}
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
{
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
@@ -709,8 +696,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
{
// Create new wallet with known key and unload it.
- auto chain = interfaces::MakeChain(m_node);
- auto wallet = TestLoadWallet(*chain);
+ auto wallet = TestLoadWallet(*m_node.chain);
CKey key;
key.MakeNewKey(true);
AddKey(*wallet, key);
@@ -745,12 +731,12 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
- BOOST_CHECK(chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
+ BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
// Reload wallet and make sure new transactions are detected despite events
// being blocked
- wallet = TestLoadWallet(*chain);
+ wallet = TestLoadWallet(*m_node.chain);
BOOST_CHECK(rescan_completed);
BOOST_CHECK_EQUAL(addtx_count, 2);
{
@@ -777,18 +763,20 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
// deadlock during the sync and simulates a new block notification happening
// as soon as possible.
addtx_count = 0;
- auto handler = HandleLoadWallet([&](std::unique_ptr<interfaces::Wallet> wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet->wallet()->cs_wallet) {
+ auto handler = HandleLoadWallet([&](std::unique_ptr<interfaces::Wallet> wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet->wallet()->cs_wallet, cs_wallets) {
BOOST_CHECK(rescan_completed);
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
block_tx = TestSimpleSpend(*m_coinbase_txns[2], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
- BOOST_CHECK(chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
+ BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
+ LEAVE_CRITICAL_SECTION(cs_wallets);
LEAVE_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
SyncWithValidationInterfaceQueue();
ENTER_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
+ ENTER_CRITICAL_SECTION(cs_wallets);
});
- wallet = TestLoadWallet(*chain);
+ wallet = TestLoadWallet(*m_node.chain);
BOOST_CHECK_EQUAL(addtx_count, 4);
{
LOCK(wallet->cs_wallet);
@@ -802,8 +790,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
{
- auto chain = interfaces::MakeChain(m_node);
- auto wallet = TestLoadWallet(*chain);
+ auto wallet = TestLoadWallet(*m_node.chain);
CKey key;
key.MakeNewKey(true);
AddKey(*wallet, key);
diff --git a/src/wallet/test/walletdb_tests.cpp b/src/wallet/test/walletdb_tests.cpp
index a3859e2e4b..558121ae42 100644
--- a/src/wallet/test/walletdb_tests.cpp
+++ b/src/wallet/test/walletdb_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Copyright (c) 2012-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 65b54f39b4..918946f9e7 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -52,7 +52,7 @@ const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{
static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10;
-static RecursiveMutex cs_wallets;
+RecursiveMutex cs_wallets;
static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
static std::list<LoadWalletFn> g_load_wallet_fns GUARDED_BY(cs_wallets);
@@ -85,9 +85,9 @@ static void UpdateWalletSetting(interfaces::Chain& chain,
std::vector<bilingual_str>& warnings)
{
if (load_on_startup == nullopt) return;
- if (load_on_startup.get() && !AddWalletSetting(chain, wallet_name)) {
+ if (load_on_startup.value() && !AddWalletSetting(chain, wallet_name)) {
warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
- } else if (!load_on_startup.get() && !RemoveWalletSetting(chain, wallet_name)) {
+ } else if (!load_on_startup.value() && !RemoveWalletSetting(chain, wallet_name)) {
warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
}
}
@@ -570,7 +570,7 @@ void CWallet::AddToSpends(const uint256& wtxid)
{
auto it = mapWallet.find(wtxid);
assert(it != mapWallet.end());
- CWalletTx& thisTx = it->second;
+ const CWalletTx& thisTx = it->second;
if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
return;
@@ -946,11 +946,12 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx
}
// If wallet doesn't have a chain (e.g wallet-tool), don't bother to update txn.
if (HaveChain()) {
- Optional<int> block_height = chain().getBlockHeight(wtx.m_confirm.hashBlock);
- if (block_height) {
+ bool active;
+ int height;
+ if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
// Update cached block height variable since it not stored in the
// serialized transaction.
- wtx.m_confirm.block_height = *block_height;
+ wtx.m_confirm.block_height = height;
} else if (wtx.isConflicted() || wtx.isConfirmed()) {
// If tx block (or conflicting block) was reorged out of chain
// while the wallet was shutdown, change tx status to UNCONFIRMED
@@ -1053,7 +1054,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
// Can't mark abandoned if confirmed or in mempool
auto it = mapWallet.find(hashTx);
assert(it != mapWallet.end());
- CWalletTx& origtx = it->second;
+ const CWalletTx& origtx = it->second;
if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
return false;
}
@@ -1177,9 +1178,8 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe
// Handle transactions that were removed from the mempool because they
// conflict with transactions in a newly connected block.
if (reason == MemPoolRemovalReason::CONFLICT) {
- // Call SyncNotifications, so external -walletnotify notifications will
- // be triggered for these transactions. Set Status::UNCONFIRMED instead
- // of Status::CONFLICTED for a few reasons:
+ // Trigger external -walletnotify notifications for these transactions.
+ // Set Status::UNCONFIRMED instead of Status::CONFLICTED for a few reasons:
//
// 1. The transactionRemovedFromMempool callback does not currently
// provide the conflicting block's hash and height, and for backwards
@@ -1771,18 +1771,22 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
}
+ // Read block data
CBlock block;
- bool next_block;
+ chain().findBlock(block_hash, FoundBlock().data(block));
+
+ // Find next block separately from reading data above, because reading
+ // is slow and there might be a reorg while it is read.
+ bool block_still_active = false;
+ bool next_block = false;
uint256 next_block_hash;
- bool reorg = false;
- if (chain().findBlock(block_hash, FoundBlock().data(block)) && !block.IsNull()) {
+ chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
+
+ if (!block.IsNull()) {
LOCK(cs_wallet);
- next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg);
- if (reorg) {
+ if (!block_still_active) {
// Abort scan if current block is no longer active, to prevent
// marking transactions as coming from the wrong block.
- // TODO: This should return success instead of failure, see
- // https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518
result.last_failed_block = block_hash;
result.status = ScanResult::FAILURE;
break;
@@ -1797,13 +1801,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
// could not scan block, keep scanning but record this block as the most recent failure
result.last_failed_block = block_hash;
result.status = ScanResult::FAILURE;
- next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg);
}
if (max_height && block_height >= *max_height) {
break;
}
{
- if (!next_block || reorg) {
+ if (!next_block) {
// break successfully when rescan has reached the tip, or
// previous block is no longer on the chain due to a reorg
break;
@@ -2706,7 +2709,7 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, const uin
return locktime;
}
-OutputType CWallet::TransactionChangeType(const Optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend)
+OutputType CWallet::TransactionChangeType(const Optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const
{
// If -changetype is specified, always use that change type.
if (change_type) {
@@ -2786,7 +2789,7 @@ bool CWallet::CreateTransactionInternal(
CScript scriptChange;
// coin control: send change to custom address
- if (!boost::get<CNoDestination>(&coin_control.destChange)) {
+ if (!std::get_if<CNoDestination>(&coin_control.destChange)) {
scriptChange = GetScriptForDestination(coin_control.destChange);
} else { // no coin control: send change to newly generated address
// Note: We use a new key here to keep it from being obvious which side is the change.
@@ -3048,7 +3051,7 @@ bool CWallet::CreateTransactionInternal(
// to avoid conflicting with other possible uses of nSequence,
// and in the spirit of "smallest possible change from prior
// behavior."
- const uint32_t nSequence = coin_control.m_signal_bip125_rbf.get_value_or(m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
+ const uint32_t nSequence = coin_control.m_signal_bip125_rbf.value_or(m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1);
for (const auto& coin : selected_coins) {
txNew.vin.push_back(CTxIn(coin.outpoint, CScript(), nSequence));
}
@@ -3109,13 +3112,14 @@ bool CWallet::CreateTransaction(
bool sign)
{
int nChangePosIn = nChangePosInOut;
- CTransactionRef tx2 = tx;
+ Assert(!tx); // tx is an out-param. TODO change the return type from bool to tx (or nullptr)
bool res = CreateTransactionInternal(vecSend, tx, nFeeRet, nChangePosInOut, error, coin_control, fee_calc_out, sign);
// try with avoidpartialspends unless it's enabled already
if (res && nFeeRet > 0 /* 0 means non-functional fee rate estimation */ && m_max_aps_fee > -1 && !coin_control.m_avoid_partial_spends) {
CCoinControl tmp_cc = coin_control;
tmp_cc.m_avoid_partial_spends = true;
CAmount nFeeRet2;
+ CTransactionRef tx2;
int nChangePosInOut2 = nChangePosIn;
bilingual_str error2; // fired and forgotten; if an error occurs, we discard the results
if (CreateTransactionInternal(vecSend, tx2, nFeeRet2, nChangePosInOut2, error2, tmp_cc, fee_calc_out, sign)) {
@@ -3720,7 +3724,7 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
bool CWallet::AddDestData(WalletBatch& batch, const CTxDestination &dest, const std::string &key, const std::string &value)
{
- if (boost::get<CNoDestination>(&dest))
+ if (std::get_if<CNoDestination>(&dest))
return false;
m_address_book[dest].destdata.insert(std::make_pair(key, value));
@@ -4051,16 +4055,13 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
// No need to read and scan block if block was created before
// our wallet birthday (as adjusted for block time variability)
- // The way the 'time_first_key' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
- Optional<int64_t> time_first_key = MakeOptional(false, int64_t());;
+ Optional<int64_t> time_first_key;
for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
int64_t time = spk_man->GetTimeFirstKey();
if (!time_first_key || time < *time_first_key) time_first_key = time;
}
if (time_first_key) {
- if (Optional<int> first_block = chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
- rescan_height = *first_block;
- }
+ chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, FoundBlock().height(rescan_height));
}
{
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index e6beb111fb..e3eae1dd95 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -930,7 +930,7 @@ public:
Balance GetBalance(int min_depth = 0, bool avoid_reuse = true) const;
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
- OutputType TransactionChangeType(const Optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend);
+ OutputType TransactionChangeType(const Optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const;
/**
* Insert additional inputs into the transaction by
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index c0521d3386..4e6270220e 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -426,7 +426,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
uint256 checksum;
ssValue >> checksum;
if ((checksum_valid = Hash(vchPrivKey) != checksum)) {
- strErr = "Error reading wallet database: Crypted key corrupt";
+ strErr = "Error reading wallet database: Encrypted key corrupt";
return false;
}
}
@@ -1013,13 +1013,10 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
Optional<DatabaseFormat> format;
if (exists) {
-#ifdef USE_BDB
- if (ExistsBerkeleyDatabase(path)) {
+ if (IsBDBFile(BDBDataFile(path))) {
format = DatabaseFormat::BERKELEY;
}
-#endif
-#ifdef USE_SQLITE
- if (ExistsSQLiteDatabase(path)) {
+ if (IsSQLiteFile(SQLiteDataFile(path))) {
if (format) {
error = Untranslated(strprintf("Failed to load database path '%s'. Data is in ambiguous format.", path.string()));
status = DatabaseStatus::FAILED_BAD_FORMAT;
@@ -1027,7 +1024,6 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
}
format = DatabaseFormat::SQLITE;
}
-#endif
} else if (options.require_existing) {
error = Untranslated(strprintf("Failed to load database path '%s'. Path does not exist.", path.string()));
status = DatabaseStatus::FAILED_NOT_FOUND;
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
index dad1232e10..a1bb7343f4 100644
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -5,6 +5,7 @@
#include <fs.h>
#include <util/system.h>
#include <util/translation.h>
+#include <wallet/dump.h>
#include <wallet/salvage.h>
#include <wallet/wallet.h>
#include <wallet/walletutil.h>
@@ -21,30 +22,27 @@ static void WalletToolReleaseWallet(CWallet* wallet)
delete wallet;
}
-static void WalletCreate(CWallet* wallet_instance)
+static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flags)
{
LOCK(wallet_instance->cs_wallet);
wallet_instance->SetMinVersion(FEATURE_HD_SPLIT);
+ wallet_instance->AddWalletFlags(wallet_creation_flags);
- // generate a new HD seed
- auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
- CPubKey seed = spk_man->GenerateNewSeed();
- spk_man->SetHDSeed(seed);
+ if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
+ auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
+ spk_man->SetupGeneration(false);
+ } else {
+ wallet_instance->SetupDescriptorScriptPubKeyMans();
+ }
tfm::format(std::cout, "Topping up keypool...\n");
wallet_instance->TopUpKeyPool();
}
-static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, bool create)
+static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options)
{
- DatabaseOptions options;
DatabaseStatus status;
- if (create) {
- options.require_create = true;
- } else {
- options.require_existing = true;
- }
bilingual_str error;
std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
if (!database) {
@@ -85,7 +83,7 @@ static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::pa
}
}
- if (create) WalletCreate(wallet_instance.get());
+ if (options.require_create) WalletCreate(wallet_instance.get(), options.create_flags);
return wallet_instance;
}
@@ -105,41 +103,85 @@ static void WalletShowInfo(CWallet* wallet_instance)
tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
}
-bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
+bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command, const std::string& name)
{
fs::path path = fs::absolute(name, GetWalletDir());
+ if (args.IsArgSet("-format") && command != "createfromdump") {
+ tfm::format(std::cerr, "The -format option can only be used with the \"createfromdump\" command.\n");
+ return false;
+ }
+ if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
+ tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
+ return false;
+ }
+ if (args.IsArgSet("-descriptors") && command != "create") {
+ tfm::format(std::cerr, "The -descriptors option can only be used with the 'create' command.\n");
+ return false;
+ }
+
if (command == "create") {
- std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, /* create= */ true);
+ DatabaseOptions options;
+ options.require_create = true;
+ if (args.GetBoolArg("-descriptors", false)) {
+ options.create_flags |= WALLET_FLAG_DESCRIPTORS;
+ options.require_format = DatabaseFormat::SQLITE;
+ }
+
+ std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
if (wallet_instance) {
WalletShowInfo(wallet_instance.get());
wallet_instance->Close();
}
- } else if (command == "info" || command == "salvage") {
- if (command == "info") {
- std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, /* create= */ false);
- if (!wallet_instance) return false;
- WalletShowInfo(wallet_instance.get());
- wallet_instance->Close();
- } else if (command == "salvage") {
+ } else if (command == "info") {
+ DatabaseOptions options;
+ options.require_existing = true;
+ std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
+ if (!wallet_instance) return false;
+ WalletShowInfo(wallet_instance.get());
+ wallet_instance->Close();
+ } else if (command == "salvage") {
#ifdef USE_BDB
- bilingual_str error;
- std::vector<bilingual_str> warnings;
- bool ret = RecoverDatabaseFile(path, error, warnings);
- if (!ret) {
- for (const auto& warning : warnings) {
- tfm::format(std::cerr, "%s\n", warning.original);
- }
- if (!error.empty()) {
- tfm::format(std::cerr, "%s\n", error.original);
- }
+ bilingual_str error;
+ std::vector<bilingual_str> warnings;
+ bool ret = RecoverDatabaseFile(path, error, warnings);
+ if (!ret) {
+ for (const auto& warning : warnings) {
+ tfm::format(std::cerr, "%s\n", warning.original);
}
- return ret;
+ if (!error.empty()) {
+ tfm::format(std::cerr, "%s\n", error.original);
+ }
+ }
+ return ret;
#else
- tfm::format(std::cerr, "Salvage command is not available as BDB support is not compiled");
- return false;
+ tfm::format(std::cerr, "Salvage command is not available as BDB support is not compiled");
+ return false;
#endif
+ } else if (command == "dump") {
+ DatabaseOptions options;
+ options.require_existing = true;
+ std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
+ if (!wallet_instance) return false;
+ bilingual_str error;
+ bool ret = DumpWallet(*wallet_instance, error);
+ if (!ret && !error.empty()) {
+ tfm::format(std::cerr, "%s\n", error.original);
+ return ret;
+ }
+ tfm::format(std::cout, "The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n");
+ return ret;
+ } else if (command == "createfromdump") {
+ bilingual_str error;
+ std::vector<bilingual_str> warnings;
+ bool ret = CreateFromDump(name, path, error, warnings);
+ for (const auto& warning : warnings) {
+ tfm::format(std::cout, "%s\n", warning.original);
+ }
+ if (!ret && !error.empty()) {
+ tfm::format(std::cerr, "%s\n", error.original);
}
+ return ret;
} else {
tfm::format(std::cerr, "Invalid command: %s\n", command);
return false;
diff --git a/src/wallet/wallettool.h b/src/wallet/wallettool.h
index d0b8d6812a..f544a6f727 100644
--- a/src/wallet/wallettool.h
+++ b/src/wallet/wallettool.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Copyright (c) 2016-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
namespace WalletTool {
void WalletShowInfo(CWallet* wallet_instance);
-bool ExecuteWalletToolFunc(const std::string& command, const std::string& file);
+bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command, const std::string& file);
} // namespace WalletTool
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index 9be610e8bd..dd2f071b6c 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,17 +7,6 @@
#include <logging.h>
#include <util/system.h>
-#ifdef USE_BDB
-bool ExistsBerkeleyDatabase(const fs::path& path);
-#else
-# define ExistsBerkeleyDatabase(path) (false)
-#endif
-#ifdef USE_SQLITE
-bool ExistsSQLiteDatabase(const fs::path& path);
-#else
-# define ExistsSQLiteDatabase(path) (false)
-#endif
-
fs::path GetWalletDir()
{
fs::path path;
@@ -40,50 +29,6 @@ fs::path GetWalletDir()
return path;
}
-std::vector<fs::path> ListWalletDir()
-{
- const fs::path wallet_dir = GetWalletDir();
- const size_t offset = wallet_dir.string().size() + 1;
- std::vector<fs::path> paths;
- boost::system::error_code ec;
-
- for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
- if (ec) {
- LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string());
- continue;
- }
-
- try {
- // Get wallet path relative to walletdir by removing walletdir from the wallet path.
- // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
- const fs::path path = it->path().string().substr(offset);
-
- if (it->status().type() == fs::directory_file &&
- (ExistsBerkeleyDatabase(it->path()) || ExistsSQLiteDatabase(it->path()))) {
- // Found a directory which contains wallet.dat btree file, add it as a wallet.
- paths.emplace_back(path);
- } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && ExistsBerkeleyDatabase(it->path())) {
- if (it->path().filename() == "wallet.dat") {
- // Found top-level wallet.dat btree file, add top level directory ""
- // as a wallet.
- paths.emplace_back();
- } else {
- // Found top-level btree file not called wallet.dat. Current bitcoin
- // software will never create these files but will allow them to be
- // opened in a shared database environment for backwards compatibility.
- // Add it to the list of available wallets.
- paths.emplace_back(path);
- }
- }
- } catch (const std::exception& e) {
- LogPrintf("%s: Error scanning %s: %s\n", __func__, it->path().string(), e.what());
- it.no_push();
- }
- }
-
- return paths;
-}
-
bool IsFeatureSupported(int wallet_version, int feature_version)
{
return wallet_version >= feature_version;
@@ -91,7 +36,7 @@ bool IsFeatureSupported(int wallet_version, int feature_version)
WalletFeature GetClosestWalletFeature(int version)
{
- const std::array<WalletFeature, 8> wallet_features{{FEATURE_LATEST, FEATURE_PRE_SPLIT_KEYPOOL, FEATURE_NO_DEFAULT_KEY, FEATURE_HD_SPLIT, FEATURE_HD, FEATURE_COMPRPUBKEY, FEATURE_WALLETCRYPT, FEATURE_BASE}};
+ static constexpr std::array wallet_features{FEATURE_LATEST, FEATURE_PRE_SPLIT_KEYPOOL, FEATURE_NO_DEFAULT_KEY, FEATURE_HD_SPLIT, FEATURE_HD, FEATURE_COMPRPUBKEY, FEATURE_WALLETCRYPT, FEATURE_BASE};
for (const WalletFeature& wf : wallet_features) {
if (version >= wf) return wf;
}
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index 27521abd81..67b2ee2b98 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -65,9 +65,6 @@ enum WalletFlags : uint64_t {
//! Get the path of the wallet directory.
fs::path GetWalletDir();
-//! Get wallets in wallet directory.
-std::vector<fs::path> ListWalletDir();
-
/** Descriptor with some wallet metadata */
class WalletDescriptor
{
diff --git a/src/walletinitinterface.h b/src/walletinitinterface.h
index a55e02f2dc..660b0eed5d 100644
--- a/src/walletinitinterface.h
+++ b/src/walletinitinterface.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/warnings.cpp b/src/warnings.cpp
index 1dec663a73..60388cc713 100644
--- a/src/warnings.cpp
+++ b/src/warnings.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/warnings.h b/src/warnings.h
index e87b64a86d..c38edb4570 100644
--- a/src/warnings.h
+++ b/src/warnings.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp
index 3938f6fd2c..90aefb0018 100644
--- a/src/zmq/zmqabstractnotifier.cpp
+++ b/src/zmq/zmqabstractnotifier.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h
index dddba8d6b6..6f0b202a18 100644
--- a/src/zmq/zmqabstractnotifier.h
+++ b/src/zmq/zmqabstractnotifier.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index a2f994d7df..86f47d71f3 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index 788a383517..8f81bfd63f 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h
index f13ed6f537..c1d66bddb1 100644
--- a/src/zmq/zmqpublishnotifier.h
+++ b/src/zmq/zmqpublishnotifier.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.