aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.clang-tidy16
-rw-r--r--src/Makefile.am8
-rw-r--r--src/Makefile.minisketch.include2
-rw-r--r--src/Makefile.test.include4
-rw-r--r--src/Makefile.test_util.include2
-rw-r--r--src/addrdb.cpp11
-rw-r--r--src/addrman.cpp70
-rw-r--r--src/addrman.h12
-rw-r--r--src/addrman_impl.h14
-rw-r--r--src/arith_uint256.cpp2
-rw-r--r--src/arith_uint256.h30
-rw-r--r--src/banman.cpp2
-rw-r--r--src/banman.h2
-rw-r--r--src/base58.cpp2
-rw-r--r--src/base58.h2
-rw-r--r--src/bech32.cpp2
-rw-r--r--src/bench/addrman.cpp2
-rw-r--r--src/bench/base58.cpp2
-rw-r--r--src/bench/bech32.cpp2
-rw-r--r--src/bench/bench.cpp5
-rw-r--r--src/bench/bench.h2
-rw-r--r--src/bench/bench_bitcoin.cpp4
-rw-r--r--src/bench/block_assemble.cpp16
-rw-r--r--src/bench/ccoins_caching.cpp3
-rw-r--r--src/bench/chacha20.cpp2
-rw-r--r--src/bench/chacha_poly_aead.cpp2
-rw-r--r--src/bench/checkblock.cpp2
-rw-r--r--src/bench/checkqueue.cpp3
-rw-r--r--src/bench/coin_selection.cpp8
-rw-r--r--src/bench/crypto_hash.cpp6
-rw-r--r--src/bench/descriptors.cpp3
-rw-r--r--src/bench/duplicate_inputs.cpp2
-rw-r--r--src/bench/examples.cpp2
-rw-r--r--src/bench/gcs_filter.cpp4
-rw-r--r--src/bench/hashpadding.cpp2
-rw-r--r--src/bench/load_external.cpp2
-rw-r--r--src/bench/lockedpool.cpp2
-rw-r--r--src/bench/logging.cpp2
-rw-r--r--src/bench/mempool_eviction.cpp2
-rw-r--r--src/bench/mempool_stress.cpp2
-rw-r--r--src/bench/merkle_root.cpp2
-rw-r--r--src/bench/nanobench.h461
-rw-r--r--src/bench/peer_eviction.cpp2
-rw-r--r--src/bench/poly1305.cpp2
-rw-r--r--src/bench/prevector.cpp4
-rw-r--r--src/bench/rollingbloom.cpp2
-rw-r--r--src/bench/rpc_blockchain.cpp2
-rw-r--r--src/bench/rpc_mempool.cpp3
-rw-r--r--src/bench/util_time.cpp2
-rw-r--r--src/bench/verify_script.cpp3
-rw-r--r--src/bench/wallet_balance.cpp2
-rw-r--r--src/bench/wallet_create_tx.cpp40
-rw-r--r--src/bench/wallet_loading.cpp2
-rw-r--r--src/bitcoin-cli.cpp6
-rw-r--r--src/bitcoin-tx.cpp4
-rw-r--r--src/bitcoin-util.cpp16
-rw-r--r--src/bitcoin-wallet.cpp3
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/blockencodings.cpp22
-rw-r--r--src/blockencodings.h12
-rw-r--r--src/blockfilter.cpp17
-rw-r--r--src/blockfilter.h2
-rw-r--r--src/chain.cpp2
-rw-r--r--src/chain.h27
-rw-r--r--src/chainparams.cpp2
-rw-r--r--src/checkqueue.h2
-rw-r--r--src/clientversion.cpp2
-rw-r--r--src/clientversion.h2
-rw-r--r--src/coins.cpp56
-rw-r--r--src/coins.h24
-rw-r--r--src/common/bloom.cpp6
-rw-r--r--src/common/interfaces.cpp2
-rw-r--r--src/common/url.cpp2
-rw-r--r--src/common/url.h2
-rw-r--r--src/compat/byteswap.h2
-rw-r--r--src/compat/compat.h2
-rw-r--r--src/compat/cpuid.h2
-rw-r--r--src/compat/endian.h2
-rw-r--r--src/compat/stdin.cpp4
-rw-r--r--src/consensus/consensus.h2
-rw-r--r--src/consensus/params.h2
-rw-r--r--src/consensus/tx_verify.h4
-rw-r--r--src/consensus/validation.h2
-rw-r--r--src/core_io.h5
-rw-r--r--src/core_read.cpp4
-rw-r--r--src/core_write.cpp8
-rw-r--r--src/crypto/chacha20.cpp2
-rw-r--r--src/crypto/chacha20.h2
-rw-r--r--src/crypto/chacha_poly_aead.cpp2
-rw-r--r--src/crypto/hkdf_sha256_32.h2
-rw-r--r--src/crypto/hmac_sha256.h2
-rw-r--r--src/crypto/hmac_sha512.h2
-rw-r--r--src/crypto/muhash.cpp2
-rw-r--r--src/crypto/poly1305.h2
-rw-r--r--src/crypto/ripemd160.cpp2
-rw-r--r--src/crypto/ripemd160.h4
-rw-r--r--src/crypto/sha1.cpp2
-rw-r--r--src/crypto/sha1.h4
-rw-r--r--src/crypto/sha256.cpp4
-rw-r--r--src/crypto/sha256.h4
-rw-r--r--src/crypto/sha256_sse4.cpp2
-rw-r--r--src/crypto/sha256_x86_shani.cpp2
-rw-r--r--src/crypto/sha3.h2
-rw-r--r--src/crypto/sha512.cpp4
-rw-r--r--src/crypto/sha512.h4
-rw-r--r--src/crypto/siphash.cpp6
-rw-r--r--src/cuckoocache.h13
-rw-r--r--src/dbwrapper.cpp2
-rw-r--r--src/dbwrapper.h18
-rw-r--r--src/deploymentstatus.cpp2
-rw-r--r--src/deploymentstatus.h2
-rw-r--r--src/external_signer.cpp4
-rw-r--r--src/external_signer.h2
-rw-r--r--src/flatfile.cpp2
-rw-r--r--src/fs.cpp2
-rw-r--r--src/fs.h4
-rw-r--r--src/hash.cpp2
-rw-r--r--src/hash.h69
-rw-r--r--src/httprpc.cpp2
-rw-r--r--src/httpserver.cpp5
-rw-r--r--src/httpserver.h2
-rw-r--r--src/i2p.cpp2
-rw-r--r--src/i2p.h2
-rw-r--r--src/index/base.cpp7
-rw-r--r--src/index/base.h2
-rw-r--r--src/index/blockfilterindex.cpp6
-rw-r--r--src/index/blockfilterindex.h2
-rw-r--r--src/index/coinstatsindex.cpp2
-rw-r--r--src/index/coinstatsindex.h2
-rw-r--r--src/index/txindex.cpp2
-rw-r--r--src/index/txindex.h2
-rw-r--r--src/init.cpp45
-rw-r--r--src/init.h2
-rw-r--r--src/init/bitcoin-gui.cpp2
-rw-r--r--src/init/bitcoin-node.cpp2
-rw-r--r--src/init/bitcoin-qt.cpp2
-rw-r--r--src/init/bitcoin-wallet.cpp2
-rw-r--r--src/init/bitcoind.cpp2
-rw-r--r--src/init/common.cpp2
-rw-r--r--src/init/common.h2
-rw-r--r--src/interfaces/chain.h6
-rw-r--r--src/interfaces/handler.h2
-rw-r--r--src/interfaces/init.h2
-rw-r--r--src/interfaces/node.h2
-rw-r--r--src/interfaces/wallet.h2
-rw-r--r--src/ipc/interfaces.cpp2
-rw-r--r--src/ipc/process.cpp2
-rw-r--r--src/kernel/coinstats.cpp5
-rw-r--r--src/kernel/coinstats.h2
-rw-r--r--src/kernel/context.cpp2
-rw-r--r--src/kernel/context.h4
-rw-r--r--src/kernel/cs_main.cpp7
-rw-r--r--src/kernel/cs_main.h22
-rw-r--r--src/kernel/mempool_options.h2
-rw-r--r--src/key.cpp19
-rw-r--r--src/key.h8
-rw-r--r--src/logging.cpp2
-rw-r--r--src/logging.h2
-rw-r--r--src/logging/timer.h28
-rw-r--r--src/mapport.cpp2
-rw-r--r--src/mapport.h8
-rw-r--r--src/memusage.h2
-rw-r--r--src/net.cpp47
-rw-r--r--src/net.h9
-rw-r--r--src/net_permissions.h2
-rw-r--r--src/net_processing.cpp159
-rw-r--r--src/net_processing.h2
-rw-r--r--src/net_types.cpp2
-rw-r--r--src/netaddress.cpp4
-rw-r--r--src/netaddress.h2
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/netbase.h2
-rw-r--r--src/netgroup.cpp2
-rw-r--r--src/node/blockstorage.cpp14
-rw-r--r--src/node/blockstorage.h19
-rw-r--r--src/node/caches.cpp2
-rw-r--r--src/node/chainstate.cpp8
-rw-r--r--src/node/chainstate.h2
-rw-r--r--src/node/coin.h2
-rw-r--r--src/node/context.cpp2
-rw-r--r--src/node/context.h2
-rw-r--r--src/node/interface_ui.cpp2
-rw-r--r--src/node/interface_ui.h2
-rw-r--r--src/node/interfaces.cpp18
-rw-r--r--src/node/miner.cpp23
-rw-r--r--src/node/miner.h10
-rw-r--r--src/node/psbt.cpp2
-rw-r--r--src/node/transaction.h2
-rw-r--r--src/node/utxo_snapshot.cpp5
-rw-r--r--src/node/utxo_snapshot.h11
-rw-r--r--src/noui.cpp2
-rw-r--r--src/outputtype.cpp2
-rw-r--r--src/outputtype.h2
-rw-r--r--src/policy/feerate.cpp2
-rw-r--r--src/policy/feerate.h2
-rw-r--r--src/policy/fees.cpp4
-rw-r--r--src/policy/fees.h20
-rw-r--r--src/policy/fees_args.cpp4
-rw-r--r--src/policy/packages.cpp2
-rw-r--r--src/policy/packages.h2
-rw-r--r--src/policy/policy.cpp2
-rw-r--r--src/policy/policy.h6
-rw-r--r--src/policy/rbf.cpp10
-rw-r--r--src/policy/rbf.h2
-rw-r--r--src/policy/settings.cpp2
-rw-r--r--src/policy/settings.h2
-rw-r--r--src/pow.cpp2
-rw-r--r--src/pow.h2
-rw-r--r--src/prevector.h2
-rw-r--r--src/primitives/block.h2
-rw-r--r--src/primitives/transaction.cpp2
-rw-r--r--src/primitives/transaction.h9
-rw-r--r--src/protocol.cpp2
-rw-r--r--src/protocol.h2
-rw-r--r--src/psbt.cpp2
-rw-r--r--src/psbt.h12
-rw-r--r--src/pubkey.cpp102
-rw-r--r--src/pubkey.h19
-rw-r--r--src/qt/addressbookpage.cpp3
-rw-r--r--src/qt/addressbookpage.h2
-rw-r--r--src/qt/addresstablemodel.cpp2
-rw-r--r--src/qt/askpassphrasedialog.cpp2
-rw-r--r--src/qt/askpassphrasedialog.h4
-rw-r--r--src/qt/bantablemodel.cpp2
-rw-r--r--src/qt/bitcoin.cpp59
-rw-r--r--src/qt/bitcoin.h15
-rw-r--r--src/qt/bitcoinamountfield.cpp7
-rw-r--r--src/qt/bitcoinamountfield.h2
-rw-r--r--src/qt/bitcoingui.cpp8
-rw-r--r--src/qt/bitcoingui.h6
-rw-r--r--src/qt/clientmodel.cpp4
-rw-r--r--src/qt/clientmodel.h6
-rw-r--r--src/qt/coincontroldialog.cpp2
-rw-r--r--src/qt/csvmodelwriter.cpp6
-rw-r--r--src/qt/csvmodelwriter.h2
-rw-r--r--src/qt/editaddressdialog.cpp10
-rw-r--r--src/qt/editaddressdialog.h4
-rw-r--r--src/qt/guiconstants.h2
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/guiutil.h2
-rw-r--r--src/qt/initexecutor.cpp2
-rw-r--r--src/qt/intro.cpp4
-rw-r--r--src/qt/intro.h4
-rw-r--r--src/qt/main.cpp2
-rw-r--r--src/qt/modaloverlay.cpp13
-rw-r--r--src/qt/modaloverlay.h8
-rw-r--r--src/qt/networkstyle.cpp2
-rw-r--r--src/qt/notificator.cpp6
-rw-r--r--src/qt/notificator.h6
-rw-r--r--src/qt/optionsdialog.cpp10
-rw-r--r--src/qt/optionsdialog.h6
-rw-r--r--src/qt/optionsmodel.cpp6
-rw-r--r--src/qt/optionsmodel.h2
-rw-r--r--src/qt/overviewpage.cpp19
-rw-r--r--src/qt/overviewpage.h7
-rw-r--r--src/qt/paymentserver.cpp9
-rw-r--r--src/qt/paymentserver.h6
-rw-r--r--src/qt/peertablemodel.cpp9
-rw-r--r--src/qt/peertablemodel.h4
-rw-r--r--src/qt/peertablesortproxy.cpp2
-rw-r--r--src/qt/platformstyle.cpp4
-rw-r--r--src/qt/psbtoperationsdialog.cpp2
-rw-r--r--src/qt/qrimagewidget.cpp4
-rw-r--r--src/qt/qrimagewidget.h2
-rw-r--r--src/qt/qvalidatedlineedit.cpp8
-rw-r--r--src/qt/qvalidatedlineedit.h6
-rw-r--r--src/qt/qvaluecombobox.cpp4
-rw-r--r--src/qt/qvaluecombobox.h2
-rw-r--r--src/qt/receivecoinsdialog.cpp3
-rw-r--r--src/qt/receivecoinsdialog.h2
-rw-r--r--src/qt/receiverequestdialog.cpp7
-rw-r--r--src/qt/receiverequestdialog.h2
-rw-r--r--src/qt/recentrequeststablemodel.cpp6
-rw-r--r--src/qt/recentrequeststablemodel.h4
-rw-r--r--src/qt/rpcconsole.cpp6
-rw-r--r--src/qt/rpcconsole.h2
-rw-r--r--src/qt/sendcoinsdialog.cpp8
-rw-r--r--src/qt/sendcoinsdialog.h10
-rw-r--r--src/qt/sendcoinsentry.cpp3
-rw-r--r--src/qt/sendcoinsentry.h4
-rw-r--r--src/qt/signverifymessagedialog.cpp3
-rw-r--r--src/qt/signverifymessagedialog.h2
-rw-r--r--src/qt/splashscreen.cpp14
-rw-r--r--src/qt/splashscreen.h7
-rw-r--r--src/qt/test/addressbooktests.cpp2
-rw-r--r--src/qt/test/apptests.cpp2
-rw-r--r--src/qt/test/optiontests.cpp2
-rw-r--r--src/qt/test/optiontests.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.cpp4
-rw-r--r--src/qt/trafficgraphwidget.cpp15
-rw-r--r--src/qt/trafficgraphwidget.h12
-rw-r--r--src/qt/transactiondesc.cpp2
-rw-r--r--src/qt/transactiondesc.h2
-rw-r--r--src/qt/transactionfilterproxy.cpp29
-rw-r--r--src/qt/transactionfilterproxy.h12
-rw-r--r--src/qt/transactionoverviewwidget.cpp2
-rw-r--r--src/qt/transactionoverviewwidget.h2
-rw-r--r--src/qt/transactionrecord.cpp2
-rw-r--r--src/qt/transactionrecord.h6
-rw-r--r--src/qt/transactiontablemodel.cpp8
-rw-r--r--src/qt/transactiontablemodel.h2
-rw-r--r--src/qt/transactionview.cpp5
-rw-r--r--src/qt/utilitydialog.cpp2
-rw-r--r--src/qt/walletcontroller.cpp2
-rw-r--r--src/qt/walletframe.cpp4
-rw-r--r--src/qt/walletmodel.cpp20
-rw-r--r--src/qt/walletmodel.h10
-rw-r--r--src/qt/walletmodeltransaction.cpp7
-rw-r--r--src/qt/walletmodeltransaction.h2
-rw-r--r--src/qt/walletview.cpp3
-rw-r--r--src/qt/walletview.h2
-rw-r--r--src/random.cpp6
-rw-r--r--src/random.h6
-rw-r--r--src/randomenv.cpp18
-rw-r--r--src/rest.cpp22
-rw-r--r--src/reverse_iterator.h2
-rw-r--r--src/rpc/blockchain.cpp84
-rw-r--r--src/rpc/blockchain.h4
-rw-r--r--src/rpc/client.cpp44
-rw-r--r--src/rpc/external_signer.cpp2
-rw-r--r--src/rpc/fees.cpp6
-rw-r--r--src/rpc/mempool.cpp52
-rw-r--r--src/rpc/mining.cpp8
-rw-r--r--src/rpc/net.cpp67
-rw-r--r--src/rpc/node.cpp36
-rw-r--r--src/rpc/output_script.cpp5
-rw-r--r--src/rpc/rawtransaction.cpp178
-rw-r--r--src/rpc/rawtransaction_util.cpp2
-rw-r--r--src/rpc/rawtransaction_util.h2
-rw-r--r--src/rpc/register.h2
-rw-r--r--src/rpc/request.cpp2
-rw-r--r--src/rpc/server.cpp9
-rw-r--r--src/rpc/server_util.cpp2
-rw-r--r--src/rpc/server_util.h2
-rw-r--r--src/rpc/txoutproof.cpp6
-rw-r--r--src/rpc/util.cpp210
-rw-r--r--src/rpc/util.h108
-rw-r--r--src/scheduler.cpp2
-rw-r--r--src/scheduler.h2
-rw-r--r--src/script/bitcoinconsensus.cpp8
-rw-r--r--src/script/bitcoinconsensus.h2
-rw-r--r--src/script/descriptor.cpp13
-rw-r--r--src/script/descriptor.h6
-rw-r--r--src/script/interpreter.cpp33
-rw-r--r--src/script/interpreter.h7
-rw-r--r--src/script/miniscript.cpp2
-rw-r--r--src/script/miniscript.h6
-rw-r--r--src/script/script.cpp2
-rw-r--r--src/script/script.h2
-rw-r--r--src/script/sigcache.cpp2
-rw-r--r--src/script/sigcache.h2
-rw-r--r--src/script/sign.cpp17
-rw-r--r--src/script/sign.h3
-rw-r--r--src/script/signingprovider.cpp2
-rw-r--r--src/script/signingprovider.h2
-rw-r--r--src/script/standard.cpp27
-rw-r--r--src/script/standard.h12
-rw-r--r--src/secp256k1/.cirrus.yml159
-rw-r--r--src/secp256k1/.gitignore4
-rw-r--r--src/secp256k1/CHANGELOG.md28
-rw-r--r--src/secp256k1/Makefile.am21
-rw-r--r--src/secp256k1/README.md8
-rw-r--r--src/secp256k1/build-aux/m4/bitcoin_secp.m42
-rwxr-xr-xsrc/secp256k1/ci/cirrus.sh44
-rw-r--r--src/secp256k1/ci/linux-debian.Dockerfile31
-rw-r--r--src/secp256k1/configure.ac89
-rw-r--r--src/secp256k1/contrib/lax_der_privatekey_parsing.h3
-rw-r--r--src/secp256k1/doc/CHANGELOG.md12
-rw-r--r--src/secp256k1/doc/release-process.md62
-rw-r--r--src/secp256k1/examples/ecdh.c8
-rw-r--r--src/secp256k1/examples/ecdsa.c8
-rw-r--r--src/secp256k1/examples/schnorr.c8
-rw-r--r--src/secp256k1/include/secp256k1.h175
-rw-r--r--src/secp256k1/include/secp256k1_extrakeys.h8
-rw-r--r--src/secp256k1/include/secp256k1_preallocated.h2
-rw-r--r--src/secp256k1/include/secp256k1_recovery.h4
-rw-r--r--src/secp256k1/include/secp256k1_schnorrsig.h4
-rw-r--r--src/secp256k1/src/assumptions.h7
-rw-r--r--src/secp256k1/src/basic-config.h17
-rw-r--r--src/secp256k1/src/bench.c15
-rw-r--r--src/secp256k1/src/bench.h18
-rw-r--r--src/secp256k1/src/bench_ecmult.c6
-rw-r--r--src/secp256k1/src/bench_internal.c15
-rw-r--r--src/secp256k1/src/ecmult.h11
-rw-r--r--src/secp256k1/src/ecmult_gen.h12
-rw-r--r--src/secp256k1/src/ecmult_gen_impl.h17
-rw-r--r--src/secp256k1/src/ecmult_impl.h12
-rw-r--r--src/secp256k1/src/field_5x52_int128_impl.h252
-rw-r--r--src/secp256k1/src/group.h5
-rw-r--r--src/secp256k1/src/group_impl.h7
-rw-r--r--src/secp256k1/src/int128.h85
-rw-r--r--src/secp256k1/src/int128_impl.h18
-rw-r--r--src/secp256k1/src/int128_native.h19
-rw-r--r--src/secp256k1/src/int128_native_impl.h87
-rw-r--r--src/secp256k1/src/int128_struct.h14
-rw-r--r--src/secp256k1/src/int128_struct_impl.h192
-rw-r--r--src/secp256k1/src/modinv64_impl.h212
-rw-r--r--src/secp256k1/src/modules/ecdh/bench_impl.h2
-rw-r--r--src/secp256k1/src/modules/ecdh/tests_impl.h2
-rw-r--r--src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h2
-rw-r--r--src/secp256k1/src/modules/extrakeys/tests_impl.h236
-rw-r--r--src/secp256k1/src/modules/recovery/bench_impl.h4
-rw-r--r--src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h2
-rw-r--r--src/secp256k1/src/modules/recovery/tests_impl.h84
-rw-r--r--src/secp256k1/src/modules/schnorrsig/bench_impl.h12
-rw-r--r--src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h2
-rw-r--r--src/secp256k1/src/modules/schnorrsig/tests_impl.h72
-rw-r--r--src/secp256k1/src/precompute_ecmult.c3
-rw-r--r--src/secp256k1/src/precompute_ecmult_gen.c3
-rw-r--r--src/secp256k1/src/scalar_4x64_impl.h150
-rw-r--r--src/secp256k1/src/scratch_impl.h2
-rw-r--r--src/secp256k1/src/secp256k1.c36
-rw-r--r--src/secp256k1/src/selftest.h2
-rw-r--r--src/secp256k1/src/tests.c699
-rw-r--r--src/secp256k1/src/tests_exhaustive.c8
-rw-r--r--src/secp256k1/src/util.h41
-rw-r--r--src/secp256k1/src/valgrind_ctime_test.c4
-rw-r--r--src/serialize.h6
-rw-r--r--src/shutdown.cpp2
-rw-r--r--src/span.h6
-rw-r--r--src/streams.h82
-rw-r--r--src/support/allocators/zeroafterfree.h2
-rw-r--r--src/support/cleanse.h2
-rw-r--r--src/support/lockedpool.cpp9
-rw-r--r--src/support/lockedpool.h6
-rw-r--r--src/sync.h4
-rw-r--r--src/test/addrman_tests.cpp114
-rw-r--r--src/test/arith_uint256_tests.cpp2
-rw-r--r--src/test/banman_tests.cpp2
-rw-r--r--src/test/base32_tests.cpp2
-rw-r--r--src/test/base58_tests.cpp5
-rw-r--r--src/test/base64_tests.cpp2
-rw-r--r--src/test/bip32_tests.cpp2
-rw-r--r--src/test/blockchain_tests.cpp2
-rw-r--r--src/test/blockencodings_tests.cpp8
-rw-r--r--src/test/blockfilter_index_tests.cpp2
-rw-r--r--src/test/blockfilter_tests.cpp4
-rw-r--r--src/test/bloom_tests.cpp10
-rw-r--r--src/test/checkqueue_tests.cpp6
-rw-r--r--src/test/coins_tests.cpp282
-rw-r--r--src/test/coinstatsindex_tests.cpp2
-rw-r--r--src/test/crypto_tests.cpp8
-rw-r--r--src/test/dbwrapper_tests.cpp45
-rw-r--r--src/test/denialofservice_tests.cpp2
-rw-r--r--src/test/descriptor_tests.cpp2
-rw-r--r--src/test/flatfile_tests.cpp2
-rw-r--r--src/test/fs_tests.cpp2
-rw-r--r--src/test/fuzz/addition_overflow.cpp2
-rw-r--r--src/test/fuzz/addrman.cpp6
-rw-r--r--src/test/fuzz/autofile.cpp2
-rw-r--r--src/test/fuzz/banman.cpp2
-rw-r--r--src/test/fuzz/base_encode_decode.cpp9
-rw-r--r--src/test/fuzz/block.cpp1
-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.cpp5
-rw-r--r--src/test/fuzz/connman.cpp2
-rw-r--r--src/test/fuzz/descriptor_parse.cpp1
-rw-r--r--src/test/fuzz/deserialize.cpp3
-rw-r--r--src/test/fuzz/eval_script.cpp7
-rw-r--r--src/test/fuzz/fuzz.cpp2
-rw-r--r--src/test/fuzz/golomb_rice.cpp2
-rw-r--r--src/test/fuzz/hex.cpp9
-rw-r--r--src/test/fuzz/http_request.cpp2
-rw-r--r--src/test/fuzz/i2p.cpp2
-rw-r--r--src/test/fuzz/integer.cpp8
-rw-r--r--src/test/fuzz/key.cpp5
-rw-r--r--src/test/fuzz/key_io.cpp1
-rw-r--r--src/test/fuzz/message.cpp1
-rw-r--r--src/test/fuzz/miniscript.cpp4
-rw-r--r--src/test/fuzz/net.cpp2
-rw-r--r--src/test/fuzz/net_permissions.cpp2
-rw-r--r--src/test/fuzz/netaddress.cpp2
-rw-r--r--src/test/fuzz/netbase_dns_lookup.cpp2
-rw-r--r--src/test/fuzz/node_eviction.cpp2
-rw-r--r--src/test/fuzz/p2p_transport_serialization.cpp4
-rw-r--r--src/test/fuzz/parse_univalue.cpp3
-rw-r--r--src/test/fuzz/partially_downloaded_block.cpp142
-rw-r--r--src/test/fuzz/policy_estimator.cpp2
-rw-r--r--src/test/fuzz/policy_estimator_io.cpp2
-rw-r--r--src/test/fuzz/pow.cpp16
-rw-r--r--src/test/fuzz/prevector.cpp6
-rw-r--r--src/test/fuzz/process_message.cpp6
-rw-r--r--src/test/fuzz/process_messages.cpp6
-rw-r--r--src/test/fuzz/psbt.cpp9
-rw-r--r--src/test/fuzz/rbf.cpp2
-rw-r--r--src/test/fuzz/rpc.cpp4
-rw-r--r--src/test/fuzz/script.cpp5
-rw-r--r--src/test/fuzz/script_assets_test_minimizer.cpp7
-rw-r--r--src/test/fuzz/script_flags.cpp7
-rw-r--r--src/test/fuzz/script_sigcache.cpp2
-rw-r--r--src/test/fuzz/script_sign.cpp1
-rw-r--r--src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp6
-rw-r--r--src/test/fuzz/signature_checker.cpp9
-rw-r--r--src/test/fuzz/socks5.cpp2
-rw-r--r--src/test/fuzz/string.cpp6
-rw-r--r--src/test/fuzz/transaction.cpp2
-rw-r--r--src/test/fuzz/tx_in.cpp5
-rw-r--r--src/test/fuzz/tx_out.cpp7
-rw-r--r--src/test/fuzz/tx_pool.cpp8
-rw-r--r--src/test/fuzz/txorphan.cpp12
-rw-r--r--src/test/fuzz/util.cpp2
-rw-r--r--src/test/fuzz/util.h4
-rw-r--r--src/test/fuzz/util/net.cpp2
-rw-r--r--src/test/fuzz/util/net.h2
-rw-r--r--src/test/fuzz/utxo_snapshot.cpp2
-rw-r--r--src/test/fuzz/validation_load_mempool.cpp2
-rw-r--r--src/test/fuzz/versionbits.cpp2
-rw-r--r--src/test/getarg_tests.cpp2
-rw-r--r--src/test/i2p_tests.cpp2
-rw-r--r--src/test/interfaces_tests.cpp2
-rw-r--r--src/test/key_io_tests.cpp5
-rw-r--r--src/test/key_tests.cpp9
-rw-r--r--src/test/logging_tests.cpp17
-rw-r--r--src/test/main.cpp2
-rw-r--r--src/test/mempool_tests.cpp17
-rw-r--r--src/test/merkle_tests.cpp16
-rw-r--r--src/test/miner_tests.cpp14
-rw-r--r--src/test/miniscript_tests.cpp2
-rw-r--r--src/test/minisketch_tests.cpp2
-rw-r--r--src/test/multisig_tests.cpp2
-rw-r--r--src/test/net_peer_eviction_tests.cpp2
-rw-r--r--src/test/net_tests.cpp2
-rw-r--r--src/test/netbase_tests.cpp2
-rw-r--r--src/test/pmt_tests.cpp4
-rw-r--r--src/test/policyestimator_tests.cpp2
-rw-r--r--src/test/pow_tests.cpp2
-rw-r--r--src/test/prevector_tests.cpp6
-rw-r--r--src/test/raii_event_tests.cpp2
-rw-r--r--src/test/random_tests.cpp6
-rw-r--r--src/test/rbf_tests.cpp2
-rw-r--r--src/test/rpc_tests.cpp10
-rw-r--r--src/test/sanity_tests.cpp2
-rw-r--r--src/test/scheduler_tests.cpp2
-rw-r--r--src/test/script_p2sh_tests.cpp2
-rw-r--r--src/test/script_standard_tests.cpp7
-rw-r--r--src/test/script_tests.cpp32
-rw-r--r--src/test/serfloat_tests.cpp2
-rw-r--r--src/test/serialize_tests.cpp27
-rw-r--r--src/test/sighash_tests.cpp5
-rw-r--r--src/test/sigopcount_tests.cpp2
-rw-r--r--src/test/skiplist_tests.cpp2
-rw-r--r--src/test/sock_tests.cpp2
-rw-r--r--src/test/streams_tests.cpp34
-rw-r--r--src/test/sync_tests.cpp2
-rw-r--r--src/test/system_tests.cpp2
-rw-r--r--src/test/timedata_tests.cpp2
-rw-r--r--src/test/transaction_tests.cpp51
-rw-r--r--src/test/txindex_tests.cpp2
-rw-r--r--src/test/txpackage_tests.cpp120
-rw-r--r--src/test/txreconciliation_tests.cpp2
-rw-r--r--src/test/txvalidationcache_tests.cpp12
-rw-r--r--src/test/uint256_tests.cpp2
-rw-r--r--src/test/util/chainstate.h2
-rw-r--r--src/test/util/json.cpp17
-rw-r--r--src/test/util/json.h14
-rw-r--r--src/test/util/logging.h2
-rw-r--r--src/test/util/mining.cpp14
-rw-r--r--src/test/util/mining.h4
-rw-r--r--src/test/util/net.cpp9
-rw-r--r--src/test/util/net.h6
-rw-r--r--src/test/util/setup_common.cpp25
-rw-r--r--src/test/util/setup_common.h2
-rw-r--r--src/test/util/validation.cpp2
-rw-r--r--src/test/util/validation.h2
-rw-r--r--src/test/util_tests.cpp10
-rw-r--r--src/test/validation_block_tests.cpp2
-rw-r--r--src/test/validation_chainstate_tests.cpp4
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp4
-rw-r--r--src/test/validation_flush_tests.cpp4
-rw-r--r--src/test/versionbits_tests.cpp4
-rw-r--r--src/timedata.cpp2
-rw-r--r--src/timedata.h2
-rw-r--r--src/tinyformat.h12
-rw-r--r--src/torcontrol.cpp6
-rw-r--r--src/torcontrol.h2
-rw-r--r--src/txdb.cpp7
-rw-r--r--src/txdb.h8
-rw-r--r--src/txmempool.cpp128
-rw-r--r--src/txmempool.h71
-rw-r--r--src/txorphanage.cpp27
-rw-r--r--src/txorphanage.h21
-rw-r--r--src/uint256.h2
-rw-r--r--src/univalue/include/univalue_utffilter.h12
-rw-r--r--src/univalue/test/object.cpp2
-rw-r--r--src/util/asmap.cpp2
-rw-r--r--src/util/bip32.cpp2
-rw-r--r--src/util/bip32.h2
-rw-r--r--src/util/bytevectorhash.cpp2
-rw-r--r--src/util/bytevectorhash.h2
-rw-r--r--src/util/check.cpp7
-rw-r--r--src/util/check.h10
-rw-r--r--src/util/epochguard.h2
-rw-r--r--src/util/error.cpp2
-rw-r--r--src/util/error.h2
-rw-r--r--src/util/fastrange.h2
-rw-r--r--src/util/fees.cpp2
-rw-r--r--src/util/fees.h2
-rw-r--r--src/util/getuniquepath.cpp2
-rw-r--r--src/util/golombrice.h2
-rw-r--r--src/util/hasher.cpp2
-rw-r--r--src/util/hasher.h2
-rw-r--r--src/util/macros.h2
-rw-r--r--src/util/message.cpp2
-rw-r--r--src/util/message.h2
-rw-r--r--src/util/moneystr.cpp4
-rw-r--r--src/util/moneystr.h2
-rw-r--r--src/util/overflow.h2
-rw-r--r--src/util/readwritefile.cpp2
-rw-r--r--src/util/serfloat.h2
-rw-r--r--src/util/settings.cpp2
-rw-r--r--src/util/settings.h2
-rw-r--r--src/util/sock.cpp2
-rw-r--r--src/util/sock.h6
-rw-r--r--src/util/spanparsing.cpp2
-rw-r--r--src/util/spanparsing.h2
-rw-r--r--src/util/strencodings.cpp2
-rw-r--r--src/util/strencodings.h2
-rw-r--r--src/util/string.cpp2
-rw-r--r--src/util/string.h2
-rw-r--r--src/util/syscall_sandbox.cpp2
-rw-r--r--src/util/syscall_sandbox.h2
-rw-r--r--src/util/system.cpp6
-rw-r--r--src/util/system.h6
-rw-r--r--src/util/thread.cpp2
-rw-r--r--src/util/thread.h2
-rw-r--r--src/util/threadinterrupt.cpp2
-rw-r--r--src/util/threadinterrupt.h2
-rw-r--r--src/util/threadnames.cpp2
-rw-r--r--src/util/time.cpp2
-rw-r--r--src/util/time.h2
-rw-r--r--src/util/tokenpipe.cpp2
-rw-r--r--src/util/translation.h2
-rw-r--r--src/util/vector.h2
-rw-r--r--src/validation.cpp229
-rw-r--r--src/validation.h44
-rw-r--r--src/validationinterface.cpp4
-rw-r--r--src/validationinterface.h4
-rw-r--r--src/versionbits.cpp4
-rw-r--r--src/versionbits.h2
-rw-r--r--src/wallet/bdb.cpp84
-rw-r--r--src/wallet/bdb.h67
-rw-r--r--src/wallet/coincontrol.h2
-rw-r--r--src/wallet/coinselection.cpp18
-rw-r--r--src/wallet/coinselection.h16
-rw-r--r--src/wallet/context.cpp2
-rw-r--r--src/wallet/crypter.h2
-rw-r--r--src/wallet/db.h64
-rw-r--r--src/wallet/dump.cpp23
-rw-r--r--src/wallet/dump.h2
-rw-r--r--src/wallet/external_signer_scriptpubkeyman.cpp2
-rw-r--r--src/wallet/feebumper.cpp19
-rw-r--r--src/wallet/feebumper.h2
-rw-r--r--src/wallet/fees.cpp2
-rw-r--r--src/wallet/init.cpp2
-rw-r--r--src/wallet/interfaces.cpp2
-rw-r--r--src/wallet/load.cpp2
-rw-r--r--src/wallet/load.h2
-rw-r--r--src/wallet/receive.cpp2
-rw-r--r--src/wallet/receive.h2
-rw-r--r--src/wallet/rpc/addresses.cpp18
-rw-r--r--src/wallet/rpc/backup.cpp65
-rw-r--r--src/wallet/rpc/coins.cpp13
-rw-r--r--src/wallet/rpc/encrypt.cpp2
-rw-r--r--src/wallet/rpc/signmessage.cpp2
-rw-r--r--src/wallet/rpc/spend.cpp158
-rw-r--r--src/wallet/rpc/transactions.cpp22
-rw-r--r--src/wallet/rpc/util.cpp9
-rw-r--r--src/wallet/rpc/util.h2
-rw-r--r--src/wallet/rpc/wallet.cpp45
-rw-r--r--src/wallet/salvage.cpp2
-rw-r--r--src/wallet/salvage.h2
-rw-r--r--src/wallet/scriptpubkeyman.cpp17
-rw-r--r--src/wallet/scriptpubkeyman.h14
-rw-r--r--src/wallet/spend.cpp231
-rw-r--r--src/wallet/spend.h31
-rw-r--r--src/wallet/sqlite.cpp58
-rw-r--r--src/wallet/sqlite.h28
-rw-r--r--src/wallet/test/availablecoins_tests.cpp107
-rw-r--r--src/wallet/test/coinselector_tests.cpp26
-rw-r--r--src/wallet/test/db_tests.cpp2
-rw-r--r--src/wallet/test/fuzz/notifications.cpp2
-rw-r--r--src/wallet/test/fuzz/parse_iso8601.cpp2
-rw-r--r--src/wallet/test/init_test_fixture.cpp2
-rw-r--r--src/wallet/test/init_tests.cpp2
-rw-r--r--src/wallet/test/ismine_tests.cpp2
-rw-r--r--src/wallet/test/psbt_wallet_tests.cpp2
-rw-r--r--src/wallet/test/spend_tests.cpp2
-rw-r--r--src/wallet/test/util.cpp14
-rw-r--r--src/wallet/test/util.h2
-rw-r--r--src/wallet/test/wallet_crypto_tests.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.h2
-rw-r--r--src/wallet/test/wallet_tests.cpp74
-rw-r--r--src/wallet/test/walletdb_tests.cpp2
-rw-r--r--src/wallet/test/walletload_tests.cpp14
-rw-r--r--src/wallet/transaction.h3
-rw-r--r--src/wallet/wallet.cpp132
-rw-r--r--src/wallet/wallet.h13
-rw-r--r--src/wallet/walletdb.cpp68
-rw-r--r--src/wallet/walletdb.h6
-rw-r--r--src/wallet/wallettool.cpp4
-rw-r--r--src/wallet/walletutil.cpp2
-rw-r--r--src/walletinitinterface.h2
-rw-r--r--src/warnings.cpp2
-rw-r--r--src/zmq/zmqabstractnotifier.h6
-rw-r--r--src/zmq/zmqnotificationinterface.cpp4
-rw-r--r--src/zmq/zmqnotificationinterface.h4
-rw-r--r--src/zmq/zmqpublishnotifier.cpp3
-rw-r--r--src/zmq/zmqpublishnotifier.h2
-rw-r--r--src/zmq/zmqrpc.cpp2
-rw-r--r--src/zmq/zmqutil.cpp2
716 files changed, 6315 insertions, 4240 deletions
diff --git a/src/.clang-tidy b/src/.clang-tidy
index 9d78ccc959..b2c1b49588 100644
--- a/src/.clang-tidy
+++ b/src/.clang-tidy
@@ -7,22 +7,14 @@ modernize-use-default-member-init,
modernize-use-nullptr,
performance-for-range-copy,
performance-move-const-arg,
+performance-no-automatic-move,
performance-unnecessary-copy-initialization,
+readability-const-return-type,
readability-redundant-declaration,
readability-redundant-string-init,
'
-WarningsAsErrors: '
-bugprone-argument-comment,
-bugprone-use-after-move,
-misc-unused-using-decls,
-modernize-use-default-member-init,
-modernize-use-nullptr,
-performance-for-range-copy,
-performance-move-const-arg,
-performance-unnecessary-copy-initialization,
-readability-redundant-declaration,
-readability-redundant-string-init,
-'
+WarningsAsErrors: '*'
CheckOptions:
- key: performance-move-const-arg.CheckTriviallyCopyableMove
value: false
+HeaderFilterRegex: '.'
diff --git a/src/Makefile.am b/src/Makefile.am
index e73245daeb..5830090ada 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,6 +20,7 @@ noinst_LTLIBRARIES =
bin_PROGRAMS =
noinst_PROGRAMS =
+check_PROGRAMS =
TESTS =
BENCHMARKS =
@@ -177,6 +178,7 @@ BITCOIN_CORE_H = \
kernel/checks.h \
kernel/coinstats.h \
kernel/context.h \
+ kernel/cs_main.h \
kernel/mempool_entry.h \
kernel/mempool_limits.h \
kernel/mempool_options.h \
@@ -375,6 +377,7 @@ libbitcoin_node_a_SOURCES = \
kernel/checks.cpp \
kernel/coinstats.cpp \
kernel/context.cpp \
+ kernel/cs_main.cpp \
kernel/mempool_persist.cpp \
mapport.cpp \
net.cpp \
@@ -653,8 +656,9 @@ libbitcoin_common_a_SOURCES = \
policy/policy.cpp \
protocol.cpp \
psbt.cpp \
- rpc/rawtransaction_util.cpp \
rpc/external_signer.cpp \
+ rpc/rawtransaction_util.cpp \
+ rpc/request.cpp \
rpc/util.cpp \
scheduler.cpp \
script/descriptor.cpp \
@@ -682,7 +686,6 @@ libbitcoin_util_a_SOURCES = \
logging.cpp \
random.cpp \
randomenv.cpp \
- rpc/request.cpp \
support/cleanse.cpp \
sync.cpp \
util/asmap.cpp \
@@ -906,6 +909,7 @@ libbitcoinkernel_la_SOURCES = \
kernel/checks.cpp \
kernel/coinstats.cpp \
kernel/context.cpp \
+ kernel/cs_main.cpp \
kernel/mempool_persist.cpp \
key.cpp \
logging.cpp \
diff --git a/src/Makefile.minisketch.include b/src/Makefile.minisketch.include
index b337f48349..1363bec34e 100644
--- a/src/Makefile.minisketch.include
+++ b/src/Makefile.minisketch.include
@@ -31,7 +31,7 @@ if ENABLE_TESTS
if !ENABLE_FUZZ
MINISKETCH_TEST = minisketch/test
TESTS += $(MINISKETCH_TEST)
-noinst_PROGRAMS += $(MINISKETCH_TEST)
+check_PROGRAMS += $(MINISKETCH_TEST)
minisketch_test_SOURCES = $(MINISKETCH_TEST_SOURCES_INT)
minisketch_test_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMINISKETCH_CPPFLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 74c30f1caf..4d867fdc2f 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -174,7 +174,6 @@ BITCOIN_TESTS += \
wallet/test/wallet_crypto_tests.cpp \
wallet/test/wallet_transaction_tests.cpp \
wallet/test/coinselector_tests.cpp \
- wallet/test/availablecoins_tests.cpp \
wallet/test/init_tests.cpp \
wallet/test/ismine_tests.cpp \
wallet/test/rpc_util_tests.cpp \
@@ -294,6 +293,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/parse_numbers.cpp \
test/fuzz/parse_script.cpp \
test/fuzz/parse_univalue.cpp \
+ test/fuzz/partially_downloaded_block.cpp \
test/fuzz/policy_estimator.cpp \
test/fuzz/policy_estimator_io.cpp \
test/fuzz/pow.cpp \
@@ -376,7 +376,7 @@ if TARGET_WINDOWS
else
if ENABLE_BENCH
@echo "Running bench/bench_bitcoin (one iteration sanity check, only high priority)..."
- $(BENCH_BINARY) -sanity-check -priority-level=high > /dev/null
+ $(BENCH_BINARY) -sanity-check -priority-level=high
endif
endif
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include
index a4e8b3f842..8496b3698a 100644
--- a/src/Makefile.test_util.include
+++ b/src/Makefile.test_util.include
@@ -10,6 +10,7 @@ EXTRA_LIBRARIES += \
TEST_UTIL_H = \
test/util/blockfilter.h \
test/util/chainstate.h \
+ test/util/json.h \
test/util/logging.h \
test/util/mining.h \
test/util/net.h \
@@ -28,6 +29,7 @@ libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
libtest_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libtest_util_a_SOURCES = \
test/util/blockfilter.cpp \
+ test/util/json.cpp \
test/util/logging.cpp \
test/util/mining.cpp \
test/util/net.cpp \
diff --git a/src/addrdb.cpp b/src/addrdb.cpp
index 7106d819b0..7be13c8f1e 100644
--- a/src/addrdb.cpp
+++ b/src/addrdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -34,10 +34,9 @@ bool SerializeDB(Stream& stream, const Data& data)
{
// Write and commit header, data
try {
- CHashWriter hasher(stream.GetType(), stream.GetVersion());
- stream << Params().MessageStart() << data;
- hasher << Params().MessageStart() << data;
- stream << hasher.GetHash();
+ HashedSourceWriter hashwriter{stream};
+ hashwriter << Params().MessageStart() << data;
+ stream << hashwriter.GetHash();
} catch (const std::exception& e) {
return error("%s: Serialize or I/O error - %s", __func__, e.what());
}
@@ -191,7 +190,7 @@ std::optional<bilingual_str> LoadAddrman(const NetGroupManager& netgroupman, con
const auto path_addr{args.GetDataDirNet() / "peers.dat"};
try {
DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
- LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
+ LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
} catch (const DbNotFoundError&) {
// Addrman can be in an inconsistent state after failure, reset it
addrman = std::make_unique<AddrMan>(netgroupman, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
diff --git a/src/addrman.cpp b/src/addrman.cpp
index f16ff2230b..a740760faf 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2012 Pieter Wuille
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -291,6 +291,7 @@ void AddrManImpl::Unserialize(Stream& s_)
mapAddr[info] = n;
info.nRandomPos = vRandom.size();
vRandom.push_back(n);
+ m_network_counts[info.GetNetwork()].n_new++;
}
nIdCount = nNew;
@@ -310,6 +311,7 @@ void AddrManImpl::Unserialize(Stream& s_)
mapAddr[info] = nIdCount;
vvTried[nKBucket][nKBucketPos] = nIdCount;
nIdCount++;
+ m_network_counts[info.GetNetwork()].n_tried++;
} else {
nLost++;
}
@@ -425,6 +427,8 @@ AddrInfo* AddrManImpl::Create(const CAddress& addr, const CNetAddr& addrSource,
mapAddr[addr] = nId;
mapInfo[nId].nRandomPos = vRandom.size();
vRandom.push_back(nId);
+ nNew++;
+ m_network_counts[addr.GetNetwork()].n_new++;
if (pnId)
*pnId = nId;
return &mapInfo[nId];
@@ -464,6 +468,7 @@ void AddrManImpl::Delete(int nId)
assert(info.nRefCount == 0);
SwapRandom(info.nRandomPos, vRandom.size() - 1);
+ m_network_counts[info.GetNetwork()].n_new--;
vRandom.pop_back();
mapAddr.erase(info);
mapInfo.erase(nId);
@@ -504,6 +509,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
}
}
nNew--;
+ m_network_counts[info.GetNetwork()].n_new--;
assert(info.nRefCount == 0);
@@ -522,6 +528,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
infoOld.fInTried = false;
vvTried[nKBucket][nKBucketPos] = -1;
nTried--;
+ m_network_counts[infoOld.GetNetwork()].n_tried--;
// find which new bucket it belongs to
int nUBucket = infoOld.GetNewBucket(nKey, m_netgroupman);
@@ -533,6 +540,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
infoOld.nRefCount = 1;
vvNew[nUBucket][nUBucketPos] = nIdEvict;
nNew++;
+ m_network_counts[infoOld.GetNetwork()].n_new++;
LogPrint(BCLog::ADDRMAN, "Moved %s from tried[%i][%i] to new[%i][%i] to make space\n",
infoOld.ToString(), nKBucket, nKBucketPos, nUBucket, nUBucketPos);
}
@@ -541,6 +549,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
vvTried[nKBucket][nKBucketPos] = nId;
nTried++;
info.fInTried = true;
+ m_network_counts[info.GetNetwork()].n_tried++;
}
bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, std::chrono::seconds time_penalty)
@@ -591,7 +600,6 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, std::c
} else {
pinfo = Create(addr, source, &nId);
pinfo->nTime = std::max(NodeSeconds{0s}, pinfo->nTime - time_penalty);
- nNew++;
}
int nUBucket = pinfo->GetNewBucket(nKey, source, m_netgroupman);
@@ -962,6 +970,28 @@ std::optional<AddressPosition> AddrManImpl::FindAddressEntry_(const CAddress& ad
}
}
+size_t AddrManImpl::Size_(std::optional<Network> net, std::optional<bool> in_new) const
+{
+ AssertLockHeld(cs);
+
+ if (!net.has_value()) {
+ if (in_new.has_value()) {
+ return *in_new ? nNew : nTried;
+ } else {
+ return vRandom.size();
+ }
+ }
+ if (auto it = m_network_counts.find(*net); it != m_network_counts.end()) {
+ auto net_count = it->second;
+ if (in_new.has_value()) {
+ return *in_new ? net_count.n_new : net_count.n_tried;
+ } else {
+ return net_count.n_new + net_count.n_tried;
+ }
+ }
+ return 0;
+}
+
void AddrManImpl::Check() const
{
AssertLockHeld(cs);
@@ -986,6 +1016,7 @@ int AddrManImpl::CheckAddrman() const
std::unordered_set<int> setTried;
std::unordered_map<int, int> mapNew;
+ std::unordered_map<Network, NewTriedCount> local_counts;
if (vRandom.size() != (size_t)(nTried + nNew))
return -7;
@@ -1000,12 +1031,14 @@ int AddrManImpl::CheckAddrman() const
if (info.nRefCount)
return -2;
setTried.insert(n);
+ local_counts[info.GetNetwork()].n_tried++;
} else {
if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
return -3;
if (!info.nRefCount)
return -4;
mapNew[n] = info.nRefCount;
+ local_counts[info.GetNetwork()].n_new++;
}
const auto it{mapAddr.find(info)};
if (it == mapAddr.end() || it->second != n) {
@@ -1065,13 +1098,27 @@ int AddrManImpl::CheckAddrman() const
if (nKey.IsNull())
return -16;
+ // It's possible that m_network_counts may have all-zero entries that local_counts
+ // doesn't have if addrs from a network were being added and then removed again in the past.
+ if (m_network_counts.size() < local_counts.size()) {
+ return -20;
+ }
+ for (const auto& [net, count] : m_network_counts) {
+ if (local_counts[net].n_new != count.n_new || local_counts[net].n_tried != count.n_tried) {
+ return -21;
+ }
+ }
+
return 0;
}
-size_t AddrManImpl::size() const
+size_t AddrManImpl::Size(std::optional<Network> net, std::optional<bool> in_new) const
{
- LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead
- return vRandom.size();
+ LOCK(cs);
+ Check();
+ auto ret = Size_(net, in_new);
+ Check();
+ return ret;
}
bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
@@ -1112,7 +1159,7 @@ std::pair<CAddress, NodeSeconds> AddrManImpl::SelectTriedCollision()
{
LOCK(cs);
Check();
- const auto ret = SelectTriedCollision_();
+ auto ret = SelectTriedCollision_();
Check();
return ret;
}
@@ -1121,7 +1168,7 @@ std::pair<CAddress, NodeSeconds> AddrManImpl::Select(bool newOnly) const
{
LOCK(cs);
Check();
- const auto addrRet = Select_(newOnly);
+ auto addrRet = Select_(newOnly);
Check();
return addrRet;
}
@@ -1130,7 +1177,7 @@ std::vector<CAddress> AddrManImpl::GetAddr(size_t max_addresses, size_t max_pct,
{
LOCK(cs);
Check();
- const auto addresses = GetAddr_(max_addresses, max_pct, network);
+ auto addresses = GetAddr_(max_addresses, max_pct, network);
Check();
return addresses;
}
@@ -1178,17 +1225,16 @@ void AddrMan::Unserialize(Stream& s_)
}
// explicit instantiation
-template void AddrMan::Serialize(CHashWriter& s) const;
-template void AddrMan::Serialize(CAutoFile& s) const;
+template void AddrMan::Serialize(HashedSourceWriter<CAutoFile>& s) const;
template void AddrMan::Serialize(CDataStream& s) const;
template void AddrMan::Unserialize(CAutoFile& s);
template void AddrMan::Unserialize(CHashVerifier<CAutoFile>& s);
template void AddrMan::Unserialize(CDataStream& s);
template void AddrMan::Unserialize(CHashVerifier<CDataStream>& s);
-size_t AddrMan::size() const
+size_t AddrMan::Size(std::optional<Network> net, std::optional<bool> in_new) const
{
- return m_impl->size();
+ return m_impl->Size(net, in_new);
}
bool AddrMan::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
diff --git a/src/addrman.h b/src/addrman.h
index 5099c8c7a3..4985fc764c 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -1,5 +1,5 @@
// Copyright (c) 2012 Pieter Wuille
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -99,8 +99,14 @@ public:
template <typename Stream>
void Unserialize(Stream& s_);
- //! Return the number of (unique) addresses in all tables.
- size_t size() const;
+ /**
+ * Return size information about addrman.
+ *
+ * @param[in] net Select addresses only from specified network (nullopt = all)
+ * @param[in] in_new Select addresses only from one table (true = new, false = tried, nullopt = both)
+ * @return Number of unique addresses that match specified options.
+ */
+ size_t Size(std::optional<Network> net = std::nullopt, std::optional<bool> in_new = std::nullopt) const;
/**
* Attempt to add one or more addresses to addrman's new table.
diff --git a/src/addrman_impl.h b/src/addrman_impl.h
index 376e79f49f..94fe81aca9 100644
--- a/src/addrman_impl.h
+++ b/src/addrman_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -112,7 +112,7 @@ public:
template <typename Stream>
void Unserialize(Stream& s_) EXCLUSIVE_LOCKS_REQUIRED(!cs);
- size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
+ size_t Size(std::optional<Network> net, std::optional<bool> in_new) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
@@ -215,6 +215,14 @@ private:
/** Reference to the netgroup manager. netgroupman must be constructed before addrman and destructed after. */
const NetGroupManager& m_netgroupman;
+ struct NewTriedCount {
+ size_t n_new;
+ size_t n_tried;
+ };
+
+ /** Number of entries in addrman per network and new/tried table. */
+ std::unordered_map<Network, NewTriedCount> m_network_counts GUARDED_BY(cs);
+
//! Find an entry.
AddrInfo* Find(const CService& addr, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
@@ -257,6 +265,8 @@ private:
std::optional<AddressPosition> FindAddressEntry_(const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ size_t Size_(std::optional<Network> net, std::optional<bool> in_new) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+
//! Consistency check, taking into account m_consistency_check_ratio.
//! Will std::abort if an inconsistency is detected.
void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs);
diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp
index e614102de3..3776cfb6de 100644
--- a/src/arith_uint256.cpp
+++ b/src/arith_uint256.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/arith_uint256.h b/src/arith_uint256.h
index b7b3b3a285..c710fe9471 100644
--- a/src/arith_uint256.h
+++ b/src/arith_uint256.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -58,7 +58,7 @@ public:
explicit base_uint(const std::string& str);
- const base_uint operator~() const
+ base_uint operator~() const
{
base_uint ret;
for (int i = 0; i < WIDTH; i++)
@@ -66,7 +66,7 @@ public:
return ret;
}
- const base_uint operator-() const
+ base_uint operator-() const
{
base_uint ret;
for (int i = 0; i < WIDTH; i++)
@@ -171,7 +171,7 @@ public:
return *this;
}
- const base_uint operator++(int)
+ base_uint operator++(int)
{
// postfix operator
const base_uint ret = *this;
@@ -188,7 +188,7 @@ public:
return *this;
}
- const base_uint operator--(int)
+ base_uint operator--(int)
{
// postfix operator
const base_uint ret = *this;
@@ -199,16 +199,16 @@ public:
int CompareTo(const base_uint& b) const;
bool EqualTo(uint64_t b) const;
- friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; }
- friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; }
- friend inline const base_uint operator*(const base_uint& a, const base_uint& b) { return base_uint(a) *= b; }
- friend inline const base_uint operator/(const base_uint& a, const base_uint& b) { return base_uint(a) /= b; }
- friend inline const base_uint operator|(const base_uint& a, const base_uint& b) { return base_uint(a) |= b; }
- friend inline const base_uint operator&(const base_uint& a, const base_uint& b) { return base_uint(a) &= b; }
- friend inline const base_uint operator^(const base_uint& a, const base_uint& b) { return base_uint(a) ^= b; }
- friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; }
- friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; }
- friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; }
+ friend inline base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; }
+ friend inline base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; }
+ friend inline base_uint operator*(const base_uint& a, const base_uint& b) { return base_uint(a) *= b; }
+ friend inline base_uint operator/(const base_uint& a, const base_uint& b) { return base_uint(a) /= b; }
+ friend inline base_uint operator|(const base_uint& a, const base_uint& b) { return base_uint(a) |= b; }
+ friend inline base_uint operator&(const base_uint& a, const base_uint& b) { return base_uint(a) &= b; }
+ friend inline base_uint operator^(const base_uint& a, const base_uint& b) { return base_uint(a) ^= b; }
+ friend inline base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; }
+ friend inline base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; }
+ friend inline base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; }
friend inline bool operator==(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) == 0; }
friend inline bool operator!=(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) != 0; }
friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; }
diff --git a/src/banman.cpp b/src/banman.cpp
index 3cd646c148..ece949d997 100644
--- a/src/banman.cpp
+++ b/src/banman.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.h b/src/banman.h
index 77b043f081..241f01dd2e 100644
--- a/src/banman.h
+++ b/src/banman.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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_BANMAN_H
diff --git a/src/base58.cpp b/src/base58.cpp
index 11c1ce7397..cf5d62f164 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2021 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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 d2a8d5e3bc..2f4d0b74b1 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/bech32.cpp b/src/bech32.cpp
index 8e0025b8f4..ba3c419d8b 100644
--- a/src/bech32.cpp
+++ b/src/bech32.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2017, 2021 Pieter Wuille
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/addrman.cpp b/src/bench/addrman.cpp
index 019b133345..d6b52eb587 100644
--- a/src/bench/addrman.cpp
+++ b/src/bench/addrman.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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 3d08b7201b..78748bc5bd 100644
--- a/src/bench/base58.cpp
+++ b/src/bench/base58.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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/bech32.cpp b/src/bench/bech32.cpp
index 1a166e7081..9922653766 100644
--- a/src/bench/bech32.cpp
+++ b/src/bench/bech32.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/bench.cpp b/src/bench/bench.cpp
index 1a3a006286..4374a63250 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -83,7 +83,7 @@ void BenchRunner::RunAll(const Args& args)
std::smatch baseMatch;
if (args.sanity_check) {
- std::cout << "Running with --sanity-check option, benchmark results will be useless." << std::endl;
+ std::cout << "Running with -sanity-check option, output is being suppressed as benchmark results will be useless." << std::endl;
}
std::vector<ankerl::nanobench::Result> benchmarkResults;
@@ -106,6 +106,7 @@ void BenchRunner::RunAll(const Args& args)
Bench bench;
if (args.sanity_check) {
bench.epochs(1).epochIterations(1);
+ bench.output(nullptr);
}
bench.name(name);
if (args.min_time > 0ms) {
diff --git a/src/bench/bench.h b/src/bench/bench.h
index 63e1bf67e2..22c63a797b 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index 1ac8db19fd..06e32f684f 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -31,7 +31,7 @@ static void SetupBenchArgs(ArgsManager& argsman)
argsman.AddArg("-min-time=<milliseconds>", strprintf("Minimum runtime per benchmark, in milliseconds (default: %d)", DEFAULT_MIN_TIME_MS), ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
argsman.AddArg("-output-csv=<output.csv>", "Generate CSV file with the most important benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-output-json=<output.json>", "Generate JSON file with all benchmark results", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-sanity-check", "Run benchmarks for only one iteration", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-sanity-check", "Run benchmarks for only one iteration with no output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-priority-level=<l1,l2,l3>", strprintf("Run benchmarks of one or multiple priority level(s) (%s), default: '%s'",
benchmark::ListPriorities(), DEFAULT_PRIORITY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
}
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index 69258377d5..8dd4117a3e 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 <bench/bench.h>
#include <consensus/validation.h>
#include <crypto/sha256.h>
+#include <node/miner.h>
#include <test/util/mining.h>
#include <test/util/script.h>
#include <test/util/setup_common.h>
@@ -45,5 +46,18 @@ static void AssembleBlock(benchmark::Bench& bench)
PrepareBlock(test_setup->m_node, P2WSH_OP_TRUE);
});
}
+static void BlockAssemblerAddPackageTxns(benchmark::Bench& bench)
+{
+ FastRandomContext det_rand{true};
+ auto testing_setup{MakeNoLogFileContext<TestChain100Setup>()};
+ testing_setup->PopulateMempool(det_rand, /*num_transactions=*/1000, /*submit=*/true);
+ node::BlockAssembler::Options assembler_options;
+ assembler_options.test_block_validity = false;
+
+ bench.run([&] {
+ PrepareBlock(testing_setup->m_node, P2WSH_OP_TRUE, assembler_options);
+ });
+}
BENCHMARK(AssembleBlock, benchmark::PriorityLevel::HIGH);
+BENCHMARK(BlockAssemblerAddPackageTxns, benchmark::PriorityLevel::LOW);
diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp
index 5d55ed9332..4a3ec67c2b 100644
--- a/src/bench/ccoins_caching.cpp
+++ b/src/bench/ccoins_caching.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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,7 +18,6 @@
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
static void CCoinsCaching(benchmark::Bench& bench)
{
- const ECCVerifyHandle verify_handle;
ECC_Start();
FillableSigningProvider keystore;
diff --git a/src/bench/chacha20.cpp b/src/bench/chacha20.cpp
index 9584dd58bb..656fb833e7 100644
--- a/src/bench/chacha20.cpp
+++ b/src/bench/chacha20.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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 15b3a4f310..db88841c32 100644
--- a/src/bench/chacha_poly_aead.cpp
+++ b/src/bench/chacha_poly_aead.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/checkblock.cpp b/src/bench/checkblock.cpp
index 747279c161..ee76f7b767 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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/checkqueue.cpp b/src/bench/checkqueue.cpp
index 8517c9fee2..dfd7275f46 100644
--- a/src/bench/checkqueue.cpp
+++ b/src/bench/checkqueue.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -25,7 +25,6 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::Bench& bench)
// We shouldn't ever be running with the checkqueue on a single core machine.
if (GetNumCores() <= 1) return;
- const ECCVerifyHandle verify_handle;
ECC_Start();
struct PrevectorJob {
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index 53d89039a7..087e1442fe 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -99,9 +99,9 @@ static CAmount make_hard_case(int utxos, std::vector<OutputGroup>& utxo_pool)
utxo_pool.clear();
CAmount target = 0;
for (int i = 0; i < utxos; ++i) {
- target += (CAmount)1 << (utxos+i);
- add_coin((CAmount)1 << (utxos+i), 2*i, utxo_pool);
- add_coin(((CAmount)1 << (utxos+i)) + ((CAmount)1 << (utxos-1-i)), 2*i + 1, utxo_pool);
+ target += CAmount{1} << (utxos+i);
+ add_coin(CAmount{1} << (utxos+i), 2*i, utxo_pool);
+ add_coin((CAmount{1} << (utxos+i)) + (CAmount{1} << (utxos-1-i)), 2*i + 1, utxo_pool);
}
return target;
}
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index 162b02f344..cf8d807d7b 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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,7 +18,7 @@
/* Number of bytes to hash per iteration */
static const uint64_t BUFFER_SIZE = 1000*1000;
-static void RIPEMD160(benchmark::Bench& bench)
+static void BenchRIPEMD160(benchmark::Bench& bench)
{
uint8_t hash[CRIPEMD160::OUTPUT_SIZE];
std::vector<uint8_t> in(BUFFER_SIZE,0);
@@ -150,7 +150,7 @@ static void MuHashPrecompute(benchmark::Bench& bench)
});
}
-BENCHMARK(RIPEMD160, benchmark::PriorityLevel::HIGH);
+BENCHMARK(BenchRIPEMD160, benchmark::PriorityLevel::HIGH);
BENCHMARK(SHA1, benchmark::PriorityLevel::HIGH);
BENCHMARK(SHA256, benchmark::PriorityLevel::HIGH);
BENCHMARK(SHA512, benchmark::PriorityLevel::HIGH);
diff --git a/src/bench/descriptors.cpp b/src/bench/descriptors.cpp
index 972a6ff953..5d28d26909 100644
--- a/src/bench/descriptors.cpp
+++ b/src/bench/descriptors.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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,6 @@
static void ExpandDescriptor(benchmark::Bench& bench)
{
- const ECCVerifyHandle verify_handle;
ECC_Start();
const auto desc_str = "sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))";
diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp
index 559854ff48..b3799ad1b7 100644
--- a/src/bench/duplicate_inputs.cpp
+++ b/src/bench/duplicate_inputs.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/examples.cpp b/src/bench/examples.cpp
index abef69cc42..671902ef2f 100644
--- a/src/bench/examples.cpp
+++ b/src/bench/examples.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/gcs_filter.cpp b/src/bench/gcs_filter.cpp
index b795ebff39..0af4ee98fe 100644
--- a/src/bench/gcs_filter.cpp
+++ b/src/bench/gcs_filter.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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 <bench/bench.h>
#include <blockfilter.h>
-static const GCSFilter::ElementSet GenerateGCSTestElements()
+static GCSFilter::ElementSet GenerateGCSTestElements()
{
GCSFilter::ElementSet elements;
diff --git a/src/bench/hashpadding.cpp b/src/bench/hashpadding.cpp
index ac5aeebe51..e9d2c25fe3 100644
--- a/src/bench/hashpadding.cpp
+++ b/src/bench/hashpadding.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/load_external.cpp b/src/bench/load_external.cpp
index be01b2a483..0fd842c7c3 100644
--- a/src/bench/load_external.cpp
+++ b/src/bench/load_external.cpp
@@ -27,7 +27,7 @@ static void LoadExternalBlockFile(benchmark::Bench& bench)
// Create a single block as in the blocks files (magic bytes, block size,
// block data) as a stream object.
const fs::path blkfile{testing_setup.get()->m_path_root / "blk.dat"};
- CDataStream ss(SER_DISK, 0);
+ DataStream ss{};
auto params{testing_setup->m_node.chainman->GetParams()};
ss << params.MessageStart();
ss << static_cast<uint32_t>(benchmark::data::block413567.size());
diff --git a/src/bench/lockedpool.cpp b/src/bench/lockedpool.cpp
index ac8262654c..161f9af621 100644
--- a/src/bench/lockedpool.cpp
+++ b/src/bench/lockedpool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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/logging.cpp b/src/bench/logging.cpp
index 49a9e59893..c38552f0b8 100644
--- a/src/bench/logging.cpp
+++ b/src/bench/logging.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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 2b133f58f4..735dc92dfb 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 67564508d9..80c959cdfb 100644
--- a/src/bench/mempool_stress.cpp
+++ b/src/bench/mempool_stress.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/merkle_root.cpp b/src/bench/merkle_root.cpp
index 4140d67bc7..55409335bd 100644
--- a/src/bench/merkle_root.cpp
+++ b/src/bench/merkle_root.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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/nanobench.h b/src/bench/nanobench.h
index 916a7d61ef..8b3dc6c71c 100644
--- a/src/bench/nanobench.h
+++ b/src/bench/nanobench.h
@@ -7,7 +7,7 @@
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
-// Copyright (c) 2019-2021 Martin Ankerl <martin.ankerl@gmail.com>
+// Copyright (c) 2019-2023 Martin Leitner-Ankerl <martin.ankerl@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -31,19 +31,20 @@
#define ANKERL_NANOBENCH_H_INCLUDED
// see https://semver.org/
-#define ANKERL_NANOBENCH_VERSION_MAJOR 4 // incompatible API changes
-#define ANKERL_NANOBENCH_VERSION_MINOR 3 // backwards-compatible changes
-#define ANKERL_NANOBENCH_VERSION_PATCH 6 // backwards-compatible bug fixes
+#define ANKERL_NANOBENCH_VERSION_MAJOR 4 // incompatible API changes
+#define ANKERL_NANOBENCH_VERSION_MINOR 3 // backwards-compatible changes
+#define ANKERL_NANOBENCH_VERSION_PATCH 10 // backwards-compatible bug fixes
///////////////////////////////////////////////////////////////////////////////////////////////////
// public facing api - as minimal as possible
///////////////////////////////////////////////////////////////////////////////////////////////////
-#include <chrono> // high_resolution_clock
-#include <cstring> // memcpy
-#include <iosfwd> // for std::ostream* custom output target in Config
-#include <string> // all names
-#include <vector> // holds all results
+#include <chrono> // high_resolution_clock
+#include <cstring> // memcpy
+#include <iosfwd> // for std::ostream* custom output target in Config
+#include <string> // all names
+#include <unordered_map> // holds context information of results
+#include <vector> // holds all results
#define ANKERL_NANOBENCH(x) ANKERL_NANOBENCH_PRIVATE_##x()
@@ -91,7 +92,7 @@
#define ANKERL_NANOBENCH_PRIVATE_PERF_COUNTERS() 0
#if defined(__linux__) && !defined(ANKERL_NANOBENCH_DISABLE_PERF_COUNTERS)
# include <linux/version.h>
-# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
// PERF_COUNT_HW_REF_CPU_CYCLES only available since kernel 3.3
// PERF_FLAG_FD_CLOEXEC since kernel 3.14
# undef ANKERL_NANOBENCH_PRIVATE_PERF_COUNTERS
@@ -144,43 +145,45 @@ class BigO;
* * `{{#result}}` Marks the begin of the result layer. Whatever comes after this will be instantiated as often as
* a benchmark result is available. Within it, you can use these tags:
*
- * * `{{title}}` See Bench::title().
+ * * `{{title}}` See Bench::title.
*
- * * `{{name}}` Benchmark name, usually directly provided with Bench::run(), but can also be set with Bench::name().
+ * * `{{name}}` Benchmark name, usually directly provided with Bench::run, but can also be set with Bench::name.
*
- * * `{{unit}}` Unit, e.g. `byte`. Defaults to `op`, see Bench::title().
+ * * `{{unit}}` Unit, e.g. `byte`. Defaults to `op`, see Bench::unit.
*
- * * `{{batch}}` Batch size, see Bench::batch().
+ * * `{{batch}}` Batch size, see Bench::batch.
*
- * * `{{complexityN}}` Value used for asymptotic complexity calculation. See Bench::complexityN().
+ * * `{{complexityN}}` Value used for asymptotic complexity calculation. See Bench::complexityN.
*
- * * `{{epochs}}` Number of epochs, see Bench::epochs().
+ * * `{{epochs}}` Number of epochs, see Bench::epochs.
*
* * `{{clockResolution}}` Accuracy of the clock, i.e. what's the smallest time possible to measure with the clock.
* For modern systems, this can be around 20 ns. This value is automatically determined by nanobench at the first
* benchmark that is run, and used as a static variable throughout the application's runtime.
*
- * * `{{clockResolutionMultiple}}` Configuration multiplier for `clockResolution`. See Bench::clockResolutionMultiple().
+ * * `{{clockResolutionMultiple}}` Configuration multiplier for `clockResolution`. See Bench::clockResolutionMultiple.
* This is the target runtime for each measurement (epoch). That means the more accurate your clock is, the faster
* will be the benchmark. Basing the measurement's runtime on the clock resolution is the main reason why nanobench is so fast.
*
* * `{{maxEpochTime}}` Configuration for a maximum time each measurement (epoch) is allowed to take. Note that at least
- * a single iteration will be performed, even when that takes longer than maxEpochTime. See Bench::maxEpochTime().
+ * a single iteration will be performed, even when that takes longer than maxEpochTime. See Bench::maxEpochTime.
*
- * * `{{minEpochTime}}` Minimum epoch time, usually not set. See Bench::minEpochTime().
+ * * `{{minEpochTime}}` Minimum epoch time, defaults to 1ms. See Bench::minEpochTime.
*
- * * `{{minEpochIterations}}` See Bench::minEpochIterations().
+ * * `{{minEpochIterations}}` See Bench::minEpochIterations.
*
- * * `{{epochIterations}}` See Bench::epochIterations().
+ * * `{{epochIterations}}` See Bench::epochIterations.
*
- * * `{{warmup}}` Number of iterations used before measuring starts. See Bench::warmup().
+ * * `{{warmup}}` Number of iterations used before measuring starts. See Bench::warmup.
*
- * * `{{relative}}` True or false, depending on the setting you have used. See Bench::relative().
+ * * `{{relative}}` True or false, depending on the setting you have used. See Bench::relative.
+ *
+ * * `{{context(variableName)}}` See Bench::context.
*
* Apart from these tags, it is also possible to use some mathematical operations on the measurement data. The operations
* are of the form `{{command(name)}}`. Currently `name` can be one of `elapsed`, `iterations`. If performance counters
* are available (currently only on current Linux systems), you also have `pagefaults`, `cpucycles`,
- * `contextswitches`, `instructions`, `branchinstructions`, and `branchmisses`. All the measuers (except `iterations`) are
+ * `contextswitches`, `instructions`, `branchinstructions`, and `branchmisses`. All the measures (except `iterations`) are
* provided for a single iteration (so `elapsed` is the time a single iteration took). The following tags are available:
*
* * `{{median(<name>)}}` Calculate median of a measurement data set, e.g. `{{median(elapsed)}}`.
@@ -201,7 +204,7 @@ class BigO;
* This measurement is a bit hard to interpret, but it is very robust against outliers. E.g. a value of 5% means that half of the
* measurements deviate less than 5% from the median, and the other deviate more than 5% from the median.
*
- * * `{{sum(<name>)}}` Sums of all the measurements. E.g. `{{sum(iterations)}}` will give you the total number of iterations
+ * * `{{sum(<name>)}}` Sum of all the measurements. E.g. `{{sum(iterations)}}` will give you the total number of iterations
* measured in this benchmark.
*
* * `{{minimum(<name>)}}` Minimum of all measurements.
@@ -244,21 +247,21 @@ class BigO;
* For the layer tags *result* and *measurement* you additionally can use these special markers:
*
* * ``{{#-first}}`` - Begin marker of a template that will be instantiated *only for the first* entry in the layer. Use is only
- * allowed between the begin and end marker of the layer allowed. So between ``{{#result}}`` and ``{{/result}}``, or between
+ * allowed between the begin and end marker of the layer. So between ``{{#result}}`` and ``{{/result}}``, or between
* ``{{#measurement}}`` and ``{{/measurement}}``. Finish the template with ``{{/-first}}``.
*
* * ``{{^-first}}`` - Begin marker of a template that will be instantiated *for each except the first* entry in the layer. This,
- * this is basically the inversion of ``{{#-first}}``. Use is only allowed between the begin and end marker of the layer allowed.
+ * this is basically the inversion of ``{{#-first}}``. Use is only allowed between the begin and end marker of the layer.
* So between ``{{#result}}`` and ``{{/result}}``, or between ``{{#measurement}}`` and ``{{/measurement}}``.
*
* * ``{{/-first}}`` - End marker for either ``{{#-first}}`` or ``{{^-first}}``.
*
* * ``{{#-last}}`` - Begin marker of a template that will be instantiated *only for the last* entry in the layer. Use is only
- * allowed between the begin and end marker of the layer allowed. So between ``{{#result}}`` and ``{{/result}}``, or between
+ * allowed between the begin and end marker of the layer. So between ``{{#result}}`` and ``{{/result}}``, or between
* ``{{#measurement}}`` and ``{{/measurement}}``. Finish the template with ``{{/-last}}``.
*
* * ``{{^-last}}`` - Begin marker of a template that will be instantiated *for each except the last* entry in the layer. This,
- * this is basically the inversion of ``{{#-last}}``. Use is only allowed between the begin and end marker of the layer allowed.
+ * this is basically the inversion of ``{{#-last}}``. Use is only allowed between the begin and end marker of the layer.
* So between ``{{#result}}`` and ``{{/result}}``, or between ``{{#measurement}}`` and ``{{/measurement}}``.
*
* * ``{{/-last}}`` - End marker for either ``{{#-last}}`` or ``{{^-last}}``.
@@ -316,12 +319,12 @@ char const* csv() noexcept;
See the tutorial at :ref:`tutorial-template-html` for an example.
@endverbatim
- @see ankerl::nanobench::render()
+ @see also ankerl::nanobench::render()
*/
char const* htmlBoxplot() noexcept;
/*!
- @brief Output in pyperf compatible JSON format, which can be used for more analyzations.
+ @brief Output in pyperf compatible JSON format, which can be used for more analyzation.
@verbatim embed:rst
See the tutorial at :ref:`tutorial-template-pyperf` for an example how to further analyze the output.
@endverbatim
@@ -378,30 +381,32 @@ struct PerfCountSet {
ANKERL_NANOBENCH(IGNORE_PADDED_PUSH)
struct Config {
// actual benchmark config
- std::string mBenchmarkTitle = "benchmark";
- std::string mBenchmarkName = "noname";
- std::string mUnit = "op";
- double mBatch = 1.0;
- double mComplexityN = -1.0;
- size_t mNumEpochs = 11;
- size_t mClockResolutionMultiple = static_cast<size_t>(1000);
- std::chrono::nanoseconds mMaxEpochTime = std::chrono::milliseconds(100);
- std::chrono::nanoseconds mMinEpochTime{};
- uint64_t mMinEpochIterations{1};
- uint64_t mEpochIterations{0}; // If not 0, run *exactly* these number of iterations per epoch.
- uint64_t mWarmup = 0;
- std::ostream* mOut = nullptr;
- std::chrono::duration<double> mTimeUnit = std::chrono::nanoseconds{1};
- std::string mTimeUnitName = "ns";
- bool mShowPerformanceCounters = true;
- bool mIsRelative = false;
+ std::string mBenchmarkTitle = "benchmark"; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::string mBenchmarkName = "noname"; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::string mUnit = "op"; // NOLINT(misc-non-private-member-variables-in-classes)
+ double mBatch = 1.0; // NOLINT(misc-non-private-member-variables-in-classes)
+ double mComplexityN = -1.0; // NOLINT(misc-non-private-member-variables-in-classes)
+ size_t mNumEpochs = 11; // NOLINT(misc-non-private-member-variables-in-classes)
+ size_t mClockResolutionMultiple = static_cast<size_t>(1000); // NOLINT(misc-non-private-member-variables-in-classes)
+ std::chrono::nanoseconds mMaxEpochTime = std::chrono::milliseconds(100); // NOLINT(misc-non-private-member-variables-in-classes)
+ std::chrono::nanoseconds mMinEpochTime = std::chrono::milliseconds(1); // NOLINT(misc-non-private-member-variables-in-classes)
+ uint64_t mMinEpochIterations{1}; // NOLINT(misc-non-private-member-variables-in-classes)
+ // If not 0, run *exactly* these number of iterations per epoch.
+ uint64_t mEpochIterations{0}; // NOLINT(misc-non-private-member-variables-in-classes)
+ uint64_t mWarmup = 0; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::ostream* mOut = nullptr; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::chrono::duration<double> mTimeUnit = std::chrono::nanoseconds{1}; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::string mTimeUnitName = "ns"; // NOLINT(misc-non-private-member-variables-in-classes)
+ bool mShowPerformanceCounters = true; // NOLINT(misc-non-private-member-variables-in-classes)
+ bool mIsRelative = false; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::unordered_map<std::string, std::string> mContext{}; // NOLINT(misc-non-private-member-variables-in-classes)
Config();
~Config();
- Config& operator=(Config const&);
- Config& operator=(Config&&);
- Config(Config const&);
- Config(Config&&) noexcept;
+ Config& operator=(Config const& other);
+ Config& operator=(Config&& other) noexcept;
+ Config(Config const& other);
+ Config(Config&& other) noexcept;
};
ANKERL_NANOBENCH(IGNORE_PADDED_POP)
@@ -421,13 +426,13 @@ public:
_size
};
- explicit Result(Config const& benchmarkConfig);
+ explicit Result(Config benchmarkConfig);
~Result();
- Result& operator=(Result const&);
- Result& operator=(Result&&);
- Result(Result const&);
- Result(Result&&) noexcept;
+ Result& operator=(Result const& other);
+ Result& operator=(Result&& other) noexcept;
+ Result(Result const& other);
+ Result(Result&& other) noexcept;
// adds new measurement results
// all values are scaled by iters (except iters...)
@@ -442,6 +447,8 @@ public:
ANKERL_NANOBENCH(NODISCARD) double sumProduct(Measure m1, Measure m2) const noexcept;
ANKERL_NANOBENCH(NODISCARD) double minimum(Measure m) const noexcept;
ANKERL_NANOBENCH(NODISCARD) double maximum(Measure m) const noexcept;
+ ANKERL_NANOBENCH(NODISCARD) std::string const& context(char const* variableName) const;
+ ANKERL_NANOBENCH(NODISCARD) std::string const& context(std::string const& variableName) const;
ANKERL_NANOBENCH(NODISCARD) bool has(Measure m) const noexcept;
ANKERL_NANOBENCH(NODISCARD) double get(size_t idx, Measure m) const;
@@ -485,9 +492,9 @@ public:
static constexpr uint64_t(max)();
/**
- * As a safety precausion, we don't allow copying. Copying a PRNG would mean you would have two random generators that produce the
+ * As a safety precaution, we don't allow copying. Copying a PRNG would mean you would have two random generators that produce the
* same sequence, which is generally not what one wants. Instead create a new rng with the default constructor Rng(), which is
- * automatically seeded from `std::random_device`. If you really need a copy, use copy().
+ * automatically seeded from `std::random_device`. If you really need a copy, use `copy()`.
*/
Rng(Rng const&) = delete;
@@ -528,7 +535,7 @@ public:
*/
explicit Rng(uint64_t seed) noexcept;
Rng(uint64_t x, uint64_t y) noexcept;
- Rng(std::vector<uint64_t> const& data);
+ explicit Rng(std::vector<uint64_t> const& data);
/**
* Creates a copy of the Rng, thus the copy provides exactly the same random sequence as the original.
@@ -620,8 +627,8 @@ public:
*/
Bench();
- Bench(Bench&& other);
- Bench& operator=(Bench&& other);
+ Bench(Bench&& other) noexcept;
+ Bench& operator=(Bench&& other) noexcept;
Bench(Bench const& other);
Bench& operator=(Bench const& other);
~Bench() noexcept;
@@ -667,6 +674,10 @@ public:
*/
Bench& title(char const* benchmarkTitle);
Bench& title(std::string const& benchmarkTitle);
+
+ /**
+ * @brief Gets the title of the benchmark
+ */
ANKERL_NANOBENCH(NODISCARD) std::string const& title() const noexcept;
/// Name of the benchmark, will be shown in the table row.
@@ -675,6 +686,31 @@ public:
ANKERL_NANOBENCH(NODISCARD) std::string const& name() const noexcept;
/**
+ * @brief Set context information.
+ *
+ * The information can be accessed using custom render templates via `{{context(variableName)}}`.
+ * Trying to render a variable that hasn't been set before raises an exception.
+ * Not included in (default) markdown table.
+ *
+ * @see clearContext, render
+ *
+ * @param variableName The name of the context variable.
+ * @param variableValue The value of the context variable.
+ */
+ Bench& context(char const* variableName, char const* variableValue);
+ Bench& context(std::string const& variableName, std::string const& variableValue);
+
+ /**
+ * @brief Reset context information.
+ *
+ * This may improve efficiency when using many context entries,
+ * or improve robustness by removing spurious context entries.
+ *
+ * @see context
+ */
+ Bench& clearContext();
+
+ /**
* @brief Sets the batch size.
*
* E.g. number of processed byte, or some other metric for the size of the processed data in each iteration. If you benchmark
@@ -754,9 +790,9 @@ public:
* representation of the benchmarked code's runtime stability.
*
* Choose the value wisely. In practice, 11 has been shown to be a reasonable choice between runtime performance and accuracy.
- * This setting goes hand in hand with minEpocIterations() (or minEpochTime()). If you are more interested in *median* runtime, you
- * might want to increase epochs(). If you are more interested in *mean* runtime, you might want to increase minEpochIterations()
- * instead.
+ * This setting goes hand in hand with minEpochIterations() (or minEpochTime()). If you are more interested in *median* runtime,
+ * you might want to increase epochs(). If you are more interested in *mean* runtime, you might want to increase
+ * minEpochIterations() instead.
*
* @param numEpochs Number of epochs.
*/
@@ -766,10 +802,10 @@ public:
/**
* @brief Upper limit for the runtime of each epoch.
*
- * As a safety precausion if the clock is not very accurate, we can set an upper limit for the maximum evaluation time per
+ * As a safety precaution if the clock is not very accurate, we can set an upper limit for the maximum evaluation time per
* epoch. Default is 100ms. At least a single evaluation of the benchmark is performed.
*
- * @see minEpochTime(), minEpochIterations()
+ * @see minEpochTime, minEpochIterations
*
* @param t Maximum target runtime for a single epoch.
*/
@@ -782,7 +818,7 @@ public:
* Default is zero, so we are fully relying on clockResolutionMultiple(). In most cases this is exactly what you want. If you see
* that the evaluation is unreliable with a high `err%`, you can increase either minEpochTime() or minEpochIterations().
*
- * @see maxEpochTime(), minEpochIterations()
+ * @see maxEpochTim), minEpochIterations
*
* @param t Minimum time each epoch should take.
*/
@@ -793,9 +829,9 @@ public:
* @brief Sets the minimum number of iterations each epoch should take.
*
* Default is 1, and we rely on clockResolutionMultiple(). If the `err%` is high and you want a more smooth result, you might want
- * to increase the minimum number or iterations, or increase the minEpochTime().
+ * to increase the minimum number of iterations, or increase the minEpochTime().
*
- * @see minEpochTime(), maxEpochTime(), minEpochIterations()
+ * @see minEpochTime, maxEpochTime, minEpochIterations
*
* @param numIters Minimum number of iterations per epoch.
*/
@@ -886,10 +922,10 @@ public:
@endverbatim
@tparam T Any type is cast to `double`.
- @param b Length of N for the next benchmark run, so it is possible to calculate `bigO`.
+ @param n Length of N for the next benchmark run, so it is possible to calculate `bigO`.
*/
template <typename T>
- Bench& complexityN(T b) noexcept;
+ Bench& complexityN(T n) noexcept;
ANKERL_NANOBENCH(NODISCARD) double complexityN() const noexcept;
/*!
@@ -993,7 +1029,7 @@ void doNotOptimizeAway(T const& val);
#else
// These assembly magic is directly from what Google Benchmark is doing. I have previously used what facebook's folly was doing, but
-// this seemd to have compilation problems in some cases. Google Benchmark seemed to be the most well tested anyways.
+// this seemed to have compilation problems in some cases. Google Benchmark seemed to be the most well tested anyways.
// see https://github.com/google/benchmark/blob/master/include/benchmark/benchmark.h#L307
template <typename T>
void doNotOptimizeAway(T const& val) {
@@ -1019,7 +1055,11 @@ void doNotOptimizeAway(T& val) {
ANKERL_NANOBENCH(IGNORE_EFFCPP_PUSH)
class IterationLogic {
public:
- explicit IterationLogic(Bench const& config) noexcept;
+ explicit IterationLogic(Bench const& bench);
+ IterationLogic(IterationLogic&&) = delete;
+ IterationLogic& operator=(IterationLogic&&) = delete;
+ IterationLogic(IterationLogic const&) = delete;
+ IterationLogic& operator=(IterationLogic const&) = delete;
~IterationLogic();
ANKERL_NANOBENCH(NODISCARD) uint64_t numIters() const noexcept;
@@ -1036,7 +1076,9 @@ ANKERL_NANOBENCH(IGNORE_PADDED_PUSH)
class PerformanceCounters {
public:
PerformanceCounters(PerformanceCounters const&) = delete;
+ PerformanceCounters(PerformanceCounters&&) = delete;
PerformanceCounters& operator=(PerformanceCounters const&) = delete;
+ PerformanceCounters& operator=(PerformanceCounters&&) = delete;
PerformanceCounters();
~PerformanceCounters();
@@ -1081,11 +1123,11 @@ public:
: BigO(bigOName, mapRangeMeasure(rangeMeasure, rangeToN)) {}
template <typename Op>
- BigO(std::string const& bigOName, RangeMeasure const& rangeMeasure, Op rangeToN)
- : BigO(bigOName, mapRangeMeasure(rangeMeasure, rangeToN)) {}
+ BigO(std::string bigOName, RangeMeasure const& rangeMeasure, Op rangeToN)
+ : BigO(std::move(bigOName), mapRangeMeasure(rangeMeasure, rangeToN)) {}
BigO(char const* bigOName, RangeMeasure const& scaledRangeMeasure);
- BigO(std::string const& bigOName, RangeMeasure const& scaledRangeMeasure);
+ BigO(std::string bigOName, RangeMeasure const& scaledRangeMeasure);
ANKERL_NANOBENCH(NODISCARD) std::string const& name() const noexcept;
ANKERL_NANOBENCH(NODISCARD) double constant() const noexcept;
ANKERL_NANOBENCH(NODISCARD) double normalizedRootMeanSquare() const noexcept;
@@ -1127,7 +1169,7 @@ uint64_t Rng::operator()() noexcept {
ANKERL_NANOBENCH_NO_SANITIZE("integer", "undefined")
uint32_t Rng::bounded(uint32_t range) noexcept {
- uint64_t r32 = static_cast<uint32_t>(operator()());
+ uint64_t const r32 = static_cast<uint32_t>(operator()());
auto multiresult = r32 * range;
return static_cast<uint32_t>(multiresult >> 32U);
}
@@ -1136,18 +1178,23 @@ double Rng::uniform01() noexcept {
auto i = (UINT64_C(0x3ff) << 52U) | (operator()() >> 12U);
// can't use union in c++ here for type puning, it's undefined behavior.
// std::memcpy is optimized anyways.
- double d;
+ double d{};
std::memcpy(&d, &i, sizeof(double));
return d - 1.0;
}
template <typename Container>
void Rng::shuffle(Container& container) noexcept {
- auto size = static_cast<uint32_t>(container.size());
- for (auto i = size; i > 1U; --i) {
+ auto i = container.size();
+ while (i > 1U) {
using std::swap;
- auto p = bounded(i); // number in [0, i)
- swap(container[i - 1], container[p]);
+ auto n = operator()();
+ // using decltype(i) instead of size_t to be compatible to containers with 32bit index (see #80)
+ auto b1 = static_cast<decltype(i)>((static_cast<uint32_t>(n) * static_cast<uint64_t>(i)) >> 32U);
+ swap(container[--i], container[b1]);
+
+ auto b2 = static_cast<decltype(i)>(((n >> 32U) * static_cast<uint64_t>(i)) >> 32U);
+ swap(container[--i], container[b2]);
}
}
@@ -1165,11 +1212,11 @@ Bench& Bench::run(Op&& op) {
while (auto n = iterationLogic.numIters()) {
pc.beginMeasure();
- Clock::time_point before = Clock::now();
+ Clock::time_point const before = Clock::now();
while (n-- > 0) {
op();
}
- Clock::time_point after = Clock::now();
+ Clock::time_point const after = Clock::now();
pc.endMeasure();
pc.updateResults(iterationLogic.numIters());
iterationLogic.add(after - before, pc);
@@ -1270,7 +1317,6 @@ void doNotOptimizeAway(T const& val) {
# include <linux/perf_event.h>
# include <sys/ioctl.h>
# include <sys/syscall.h>
-# include <unistd.h>
# endif
// declarations ///////////////////////////////////////////////////////////////////////////////////
@@ -1436,31 +1482,37 @@ struct Node {
template <size_t N>
// NOLINTNEXTLINE(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
bool operator==(char const (&str)[N]) const noexcept {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
return static_cast<size_t>(std::distance(begin, end) + 1) == N && 0 == strncmp(str, begin, N - 1);
}
};
ANKERL_NANOBENCH(IGNORE_PADDED_POP)
+// NOLINTNEXTLINE(misc-no-recursion)
static std::vector<Node> parseMustacheTemplate(char const** tpl) {
std::vector<Node> nodes;
while (true) {
- auto begin = std::strstr(*tpl, "{{");
- auto end = begin;
+ auto const* begin = std::strstr(*tpl, "{{");
+ auto const* end = begin;
if (begin != nullptr) {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
begin += 2;
end = std::strstr(begin, "}}");
}
if (begin == nullptr || end == nullptr) {
// nothing found, finish node
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
nodes.emplace_back(Node{*tpl, *tpl + std::strlen(*tpl), std::vector<Node>{}, Node::Type::content});
return nodes;
}
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
nodes.emplace_back(Node{*tpl, begin - 2, std::vector<Node>{}, Node::Type::content});
// we found a tag
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
*tpl = end + 2;
switch (*begin) {
case '/':
@@ -1468,10 +1520,12 @@ static std::vector<Node> parseMustacheTemplate(char const** tpl) {
return nodes;
case '#':
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
nodes.emplace_back(Node{begin + 1, end, parseMustacheTemplate(tpl), Node::Type::section});
break;
case '^':
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
nodes.emplace_back(Node{begin + 1, end, parseMustacheTemplate(tpl), Node::Type::inverted_section});
break;
@@ -1484,8 +1538,8 @@ static std::vector<Node> parseMustacheTemplate(char const** tpl) {
static bool generateFirstLast(Node const& n, size_t idx, size_t size, std::ostream& out) {
ANKERL_NANOBENCH_LOG("n.type=" << static_cast<int>(n.type));
- bool matchFirst = n == "-first";
- bool matchLast = n == "-last";
+ bool const matchFirst = n == "-first";
+ bool const matchLast = n == "-last";
if (!matchFirst && !matchLast) {
return false;
}
@@ -1518,7 +1572,7 @@ static bool matchCmdArgs(std::string const& str, std::vector<std::string>& match
matchResult.emplace_back(str.substr(0, idxOpen));
// split by comma
- matchResult.emplace_back(std::string{});
+ matchResult.emplace_back();
for (size_t i = idxOpen + 1; i != idxClose; ++i) {
if (str[i] == ' ' || str[i] == '\t') {
// skip whitespace
@@ -1526,7 +1580,7 @@ static bool matchCmdArgs(std::string const& str, std::vector<std::string>& match
}
if (str[i] == ',') {
// got a comma => new string
- matchResult.emplace_back(std::string{});
+ matchResult.emplace_back();
continue;
}
// no whitespace no comma, append
@@ -1541,49 +1595,63 @@ static bool generateConfigTag(Node const& n, Config const& config, std::ostream&
if (n == "title") {
out << config.mBenchmarkTitle;
return true;
- } else if (n == "name") {
+ }
+ if (n == "name") {
out << config.mBenchmarkName;
return true;
- } else if (n == "unit") {
+ }
+ if (n == "unit") {
out << config.mUnit;
return true;
- } else if (n == "batch") {
+ }
+ if (n == "batch") {
out << config.mBatch;
return true;
- } else if (n == "complexityN") {
+ }
+ if (n == "complexityN") {
out << config.mComplexityN;
return true;
- } else if (n == "epochs") {
+ }
+ if (n == "epochs") {
out << config.mNumEpochs;
return true;
- } else if (n == "clockResolution") {
+ }
+ if (n == "clockResolution") {
out << d(detail::clockResolution());
return true;
- } else if (n == "clockResolutionMultiple") {
+ }
+ if (n == "clockResolutionMultiple") {
out << config.mClockResolutionMultiple;
return true;
- } else if (n == "maxEpochTime") {
+ }
+ if (n == "maxEpochTime") {
out << d(config.mMaxEpochTime);
return true;
- } else if (n == "minEpochTime") {
+ }
+ if (n == "minEpochTime") {
out << d(config.mMinEpochTime);
return true;
- } else if (n == "minEpochIterations") {
+ }
+ if (n == "minEpochIterations") {
out << config.mMinEpochIterations;
return true;
- } else if (n == "epochIterations") {
+ }
+ if (n == "epochIterations") {
out << config.mEpochIterations;
return true;
- } else if (n == "warmup") {
+ }
+ if (n == "warmup") {
out << config.mWarmup;
return true;
- } else if (n == "relative") {
+ }
+ if (n == "relative") {
out << config.mIsRelative;
return true;
}
return false;
}
+// NOLINTNEXTLINE(readability-function-cognitive-complexity)
static std::ostream& generateResultTag(Node const& n, Result const& r, std::ostream& out) {
if (generateConfigTag(n, r.config(), out)) {
return out;
@@ -1596,6 +1664,10 @@ static std::ostream& generateResultTag(Node const& n, Result const& r, std::ostr
std::vector<std::string> matchResult;
if (matchCmdArgs(std::string(n.begin, n.end), matchResult)) {
if (matchResult.size() == 2) {
+ if (matchResult[0] == "context") {
+ return out << r.context(matchResult[1]);
+ }
+
auto m = Result::fromString(matchResult[1]);
if (m == Result::Measure::_size) {
return out << 0.0;
@@ -1712,7 +1784,7 @@ template <typename T>
T parseFile(std::string const& filename);
void gatherStabilityInformation(std::vector<std::string>& warnings, std::vector<std::string>& recommendations);
-void printStabilityInformationOnce(std::ostream* os);
+void printStabilityInformationOnce(std::ostream* outStream);
// remembers the last table settings used. When it changes, a new table header is automatically written for the new entry.
uint64_t& singletonHeaderHash() noexcept;
@@ -1779,13 +1851,13 @@ private:
};
// helper replacement for std::to_string of signed/unsigned numbers so we are locale independent
-std::string to_s(uint64_t s);
+std::string to_s(uint64_t n);
std::ostream& operator<<(std::ostream& os, Number const& n);
class MarkDownColumn {
public:
- MarkDownColumn(int w, int prec, std::string const& tit, std::string const& suff, double val);
+ MarkDownColumn(int w, int prec, std::string tit, std::string suff, double val);
std::string title() const;
std::string separator() const;
std::string invalid() const;
@@ -1823,8 +1895,9 @@ std::ostream& operator<<(std::ostream& os, MarkDownCode const& mdCode);
namespace ankerl {
namespace nanobench {
+// NOLINTNEXTLINE(readability-function-cognitive-complexity)
void render(char const* mustacheTemplate, std::vector<Result> const& results, std::ostream& out) {
- detail::fmt::StreamStateRestorer restorer(out);
+ detail::fmt::StreamStateRestorer const restorer(out);
out.precision(std::numeric_limits<double>::digits10);
auto nodes = templates::parseMustacheTemplate(&mustacheTemplate);
@@ -1914,7 +1987,7 @@ void doNotOptimizeAwaySink(void const*) {}
template <typename T>
T parseFile(std::string const& filename) {
- std::ifstream fin(filename);
+ std::ifstream fin(filename); // NOLINT(misc-const-correctness)
T num{};
fin >> num;
return num;
@@ -1925,20 +1998,20 @@ char const* getEnv(char const* name) {
# pragma warning(push)
# pragma warning(disable : 4996) // getenv': This function or variable may be unsafe.
# endif
- return std::getenv(name);
+ return std::getenv(name); // NOLINT(concurrency-mt-unsafe)
# if defined(_MSC_VER)
# pragma warning(pop)
# endif
}
bool isEndlessRunning(std::string const& name) {
- auto endless = getEnv("NANOBENCH_ENDLESS");
+ auto const* const endless = getEnv("NANOBENCH_ENDLESS");
return nullptr != endless && endless == name;
}
// True when environment variable NANOBENCH_SUPPRESS_WARNINGS is either not set at all, or set to "0"
bool isWarningsEnabled() {
- auto suppression = getEnv("NANOBENCH_SUPPRESS_WARNINGS");
+ auto const* const suppression = getEnv("NANOBENCH_SUPPRESS_WARNINGS");
return nullptr == suppression || suppression == std::string("0");
}
@@ -1946,11 +2019,11 @@ void gatherStabilityInformation(std::vector<std::string>& warnings, std::vector<
warnings.clear();
recommendations.clear();
- bool recommendCheckFlags = false;
-
# if defined(DEBUG)
warnings.emplace_back("DEBUG defined");
- recommendCheckFlags = true;
+ bool const recommendCheckFlags = true;
+# else
+ bool const recommendCheckFlags = false;
# endif
bool recommendPyPerf = false;
@@ -2000,7 +2073,7 @@ void gatherStabilityInformation(std::vector<std::string>& warnings, std::vector<
void printStabilityInformationOnce(std::ostream* outStream) {
static bool shouldPrint = true;
- if (shouldPrint && outStream && isWarningsEnabled()) {
+ if (shouldPrint && (nullptr != outStream) && isWarningsEnabled()) {
auto& os = *outStream;
shouldPrint = false;
std::vector<std::string> warnings;
@@ -2050,7 +2123,7 @@ Clock::duration calcClockResolution(size_t numEvaluations) noexcept {
// Calculates clock resolution once, and remembers the result
Clock::duration clockResolution() noexcept {
- static Clock::duration sResolution = calcClockResolution(20);
+ static Clock::duration const sResolution = calcClockResolution(20);
return sResolution;
}
@@ -2183,6 +2256,7 @@ struct IterationLogic::Impl {
<< ", mState=" << static_cast<int>(mState));
}
+ // NOLINTNEXTLINE(readability-function-cognitive-complexity)
void showResult(std::string const& errorMessage) const {
ANKERL_NANOBENCH_LOG(errorMessage);
@@ -2208,7 +2282,7 @@ struct IterationLogic::Impl {
rMedian / (mBench.timeUnit().count() * mBench.batch()));
columns.emplace_back(22, 2, mBench.unit() + "/s", "", rMedian <= 0.0 ? 0.0 : mBench.batch() / rMedian);
- double rErrorMedian = mResult.medianAbsolutePercentError(Result::Measure::elapsed);
+ double const rErrorMedian = mResult.medianAbsolutePercentError(Result::Measure::elapsed);
columns.emplace_back(10, 1, "err%", "%", rErrorMedian * 100.0);
double rInsMedian = -1.0;
@@ -2226,7 +2300,7 @@ struct IterationLogic::Impl {
columns.emplace_back(9, 3, "IPC", "", rCycMedian <= 0.0 ? 0.0 : rInsMedian / rCycMedian);
}
if (mBench.performanceCounters() && mResult.has(Result::Measure::branchinstructions)) {
- double rBraMedian = mResult.median(Result::Measure::branchinstructions);
+ double const rBraMedian = mResult.median(Result::Measure::branchinstructions);
columns.emplace_back(17, 2, "bra/" + mBench.unit(), "", rBraMedian / mBench.batch());
if (mResult.has(Result::Measure::branchmisses)) {
double p = 0.0;
@@ -2299,25 +2373,22 @@ struct IterationLogic::Impl {
return elapsed * 3 >= mTargetRuntimePerEpoch * 2;
}
- uint64_t mNumIters = 1;
- Bench const& mBench;
- std::chrono::nanoseconds mTargetRuntimePerEpoch{};
- Result mResult;
- Rng mRng{123};
- std::chrono::nanoseconds mTotalElapsed{};
- uint64_t mTotalNumIters = 0;
-
- State mState = State::upscaling_runtime;
+ uint64_t mNumIters = 1; // NOLINT(misc-non-private-member-variables-in-classes)
+ Bench const& mBench; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::chrono::nanoseconds mTargetRuntimePerEpoch{}; // NOLINT(misc-non-private-member-variables-in-classes)
+ Result mResult; // NOLINT(misc-non-private-member-variables-in-classes)
+ Rng mRng{123}; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::chrono::nanoseconds mTotalElapsed{}; // NOLINT(misc-non-private-member-variables-in-classes)
+ uint64_t mTotalNumIters = 0; // NOLINT(misc-non-private-member-variables-in-classes)
+ State mState = State::upscaling_runtime; // NOLINT(misc-non-private-member-variables-in-classes)
};
ANKERL_NANOBENCH(IGNORE_PADDED_POP)
-IterationLogic::IterationLogic(Bench const& bench) noexcept
+IterationLogic::IterationLogic(Bench const& bench)
: mPimpl(new Impl(bench)) {}
IterationLogic::~IterationLogic() {
- if (mPimpl) {
- delete mPimpl;
- }
+ delete mPimpl;
}
uint64_t IterationLogic::numIters() const noexcept {
@@ -2344,11 +2415,16 @@ public:
, correctMeasuringOverhead(correctMeasuringOverhead_)
, correctLoopOverhead(correctLoopOverhead_) {}
- uint64_t* targetValue{};
- bool correctMeasuringOverhead{};
- bool correctLoopOverhead{};
+ uint64_t* targetValue{}; // NOLINT(misc-non-private-member-variables-in-classes)
+ bool correctMeasuringOverhead{}; // NOLINT(misc-non-private-member-variables-in-classes)
+ bool correctLoopOverhead{}; // NOLINT(misc-non-private-member-variables-in-classes)
};
+ LinuxPerformanceCounters() = default;
+ LinuxPerformanceCounters(LinuxPerformanceCounters const&) = delete;
+ LinuxPerformanceCounters(LinuxPerformanceCounters&&) = delete;
+ LinuxPerformanceCounters& operator=(LinuxPerformanceCounters const&) = delete;
+ LinuxPerformanceCounters& operator=(LinuxPerformanceCounters&&) = delete;
~LinuxPerformanceCounters();
// quick operation
@@ -2370,13 +2446,13 @@ public:
return;
}
- // NOLINTNEXTLINE(hicpp-signed-bitwise)
+ // NOLINTNEXTLINE(hicpp-signed-bitwise,cppcoreguidelines-pro-type-vararg)
mHasError = -1 == ioctl(mFd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);
if (mHasError) {
return;
}
- // NOLINTNEXTLINE(hicpp-signed-bitwise)
+ // NOLINTNEXTLINE(hicpp-signed-bitwise,cppcoreguidelines-pro-type-vararg)
mHasError = -1 == ioctl(mFd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);
}
@@ -2385,7 +2461,7 @@ public:
return;
}
- // NOLINTNEXTLINE(hicpp-signed-bitwise)
+ // NOLINTNEXTLINE(hicpp-signed-bitwise,cppcoreguidelines-pro-type-vararg)
mHasError = (-1 == ioctl(mFd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP));
if (mHasError) {
return;
@@ -2406,9 +2482,9 @@ public:
ANKERL_NANOBENCH_NO_SANITIZE("integer", "undefined")
static inline uint32_t mix(uint32_t x) noexcept {
- x ^= x << 13;
- x ^= x >> 17;
- x ^= x << 5;
+ x ^= x << 13U;
+ x ^= x >> 17U;
+ x ^= x << 5U;
return x;
}
@@ -2448,7 +2524,7 @@ public:
// marsaglia's xorshift: mov, sal/shr, xor. Times 3.
// This has the nice property that the compiler doesn't seem to be able to optimize multiple calls any further.
// see https://godbolt.org/z/49RVQ5
- uint64_t const numIters = 100000U + (std::random_device{}() & 3);
+ uint64_t const numIters = 100000U + (std::random_device{}() & 3U);
uint64_t n = numIters;
uint32_t x = 1234567;
@@ -2582,6 +2658,7 @@ bool LinuxPerformanceCounters::monitor(uint32_t type, uint64_t eventid, Target t
const unsigned long flags = 0;
# endif
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
auto fd = static_cast<int>(syscall(__NR_perf_event_open, &pea, pid, cpu, mFd, flags));
if (-1 == fd) {
return false;
@@ -2591,7 +2668,7 @@ bool LinuxPerformanceCounters::monitor(uint32_t type, uint64_t eventid, Target t
mFd = fd;
}
uint64_t id = 0;
- // NOLINTNEXTLINE(hicpp-signed-bitwise)
+ // NOLINTNEXTLINE(hicpp-signed-bitwise,cppcoreguidelines-pro-type-vararg)
if (-1 == ioctl(fd, PERF_EVENT_IOC_ID, &id)) {
// couldn't get id
return false;
@@ -2639,9 +2716,8 @@ PerformanceCounters::PerformanceCounters()
}
PerformanceCounters::~PerformanceCounters() {
- if (nullptr != mPc) {
- delete mPc;
- }
+ // no need to check for nullptr, delete nullptr has no effect
+ delete mPc;
}
void PerformanceCounters::beginMeasure() {
@@ -2721,7 +2797,7 @@ Number::Number(int width, int precision, double value)
, mValue(value) {}
std::ostream& Number::write(std::ostream& os) const {
- StreamStateRestorer restorer(os);
+ StreamStateRestorer const restorer(os);
os.imbue(std::locale(os.getloc(), new NumSep(',')));
os << std::setw(mWidth) << std::setprecision(mPrecision) << std::fixed << mValue;
return os;
@@ -2747,11 +2823,11 @@ std::ostream& operator<<(std::ostream& os, Number const& n) {
return n.write(os);
}
-MarkDownColumn::MarkDownColumn(int w, int prec, std::string const& tit, std::string const& suff, double val)
+MarkDownColumn::MarkDownColumn(int w, int prec, std::string tit, std::string suff, double val)
: mWidth(w)
, mPrecision(prec)
- , mTitle(tit)
- , mSuffix(suff)
+ , mTitle(std::move(tit))
+ , mSuffix(std::move(suff))
, mValue(val) {}
std::string MarkDownColumn::title() const {
@@ -2785,7 +2861,7 @@ std::string MarkDownColumn::value() const {
MarkDownCode::MarkDownCode(std::string const& what) {
mWhat.reserve(what.size() + 2);
mWhat.push_back('`');
- for (char c : what) {
+ for (char const c : what) {
mWhat.push_back(c);
if ('`' == c) {
mWhat.push_back('`');
@@ -2808,14 +2884,14 @@ std::ostream& operator<<(std::ostream& os, MarkDownCode const& mdCode) {
Config::Config() = default;
Config::~Config() = default;
Config& Config::operator=(Config const&) = default;
-Config& Config::operator=(Config&&) = default;
+Config& Config::operator=(Config&&) noexcept = default;
Config::Config(Config const&) = default;
Config::Config(Config&&) noexcept = default;
// provide implementation here so it's only generated once
Result::~Result() = default;
Result& Result::operator=(Result const&) = default;
-Result& Result::operator=(Result&&) = default;
+Result& Result::operator=(Result&&) noexcept = default;
Result::Result(Result const&) = default;
Result::Result(Result&&) noexcept = default;
@@ -2827,15 +2903,15 @@ inline constexpr typename std::underlying_type<T>::type u(T val) noexcept {
} // namespace detail
// Result returned after a benchmark has finished. Can be used as a baseline for relative().
-Result::Result(Config const& benchmarkConfig)
- : mConfig(benchmarkConfig)
+Result::Result(Config benchmarkConfig)
+ : mConfig(std::move(benchmarkConfig))
, mNameToMeasurements{detail::u(Result::Measure::_size)} {}
void Result::add(Clock::duration totalElapsed, uint64_t iters, detail::PerformanceCounters const& pc) {
using detail::d;
using detail::u;
- double dIters = d(iters);
+ double const dIters = d(iters);
mNameToMeasurements[u(Result::Measure::iterations)].push_back(dIters);
mNameToMeasurements[u(Result::Measure::elapsed)].push_back(d(totalElapsed) / dIters);
@@ -2987,27 +3063,41 @@ double Result::maximum(Measure m) const noexcept {
return *std::max_element(data.begin(), data.end());
}
+std::string const& Result::context(char const* variableName) const {
+ return mConfig.mContext.at(variableName);
+}
+
+std::string const& Result::context(std::string const& variableName) const {
+ return mConfig.mContext.at(variableName);
+}
+
Result::Measure Result::fromString(std::string const& str) {
if (str == "elapsed") {
return Measure::elapsed;
- } else if (str == "iterations") {
+ }
+ if (str == "iterations") {
return Measure::iterations;
- } else if (str == "pagefaults") {
+ }
+ if (str == "pagefaults") {
return Measure::pagefaults;
- } else if (str == "cpucycles") {
+ }
+ if (str == "cpucycles") {
return Measure::cpucycles;
- } else if (str == "contextswitches") {
+ }
+ if (str == "contextswitches") {
return Measure::contextswitches;
- } else if (str == "instructions") {
+ }
+ if (str == "instructions") {
return Measure::instructions;
- } else if (str == "branchinstructions") {
+ }
+ if (str == "branchinstructions") {
return Measure::branchinstructions;
- } else if (str == "branchmisses") {
+ }
+ if (str == "branchmisses") {
return Measure::branchmisses;
- } else {
- // not found, return _size
- return Measure::_size;
}
+ // not found, return _size
+ return Measure::_size;
}
// Configuration of a microbenchmark.
@@ -3015,8 +3105,8 @@ Bench::Bench() {
mConfig.mOut = &std::cout;
}
-Bench::Bench(Bench&&) = default;
-Bench& Bench::operator=(Bench&&) = default;
+Bench::Bench(Bench&&) noexcept = default;
+Bench& Bench::operator=(Bench&&) noexcept = default;
Bench::Bench(Bench const&) = default;
Bench& Bench::operator=(Bench const&) = default;
Bench::~Bench() noexcept = default;
@@ -3114,6 +3204,21 @@ std::string const& Bench::name() const noexcept {
return mConfig.mBenchmarkName;
}
+Bench& Bench::context(char const* variableName, char const* variableValue) {
+ mConfig.mContext[variableName] = variableValue;
+ return *this;
+}
+
+Bench& Bench::context(std::string const& variableName, std::string const& variableValue) {
+ mConfig.mContext[variableName] = variableValue;
+ return *this;
+}
+
+Bench& Bench::clearContext() {
+ mConfig.mContext.clear();
+ return *this;
+}
+
// Number of epochs to evaluate. The reported result will be the median of evaluation of each epoch.
Bench& Bench::epochs(size_t numEpochs) noexcept {
mConfig.mNumEpochs = numEpochs;
@@ -3295,27 +3400,27 @@ BigO::RangeMeasure BigO::collectRangeMeasure(std::vector<Result> const& results)
return rangeMeasure;
}
-BigO::BigO(std::string const& bigOName, RangeMeasure const& rangeMeasure)
- : mName(bigOName) {
+BigO::BigO(std::string bigOName, RangeMeasure const& rangeMeasure)
+ : mName(std::move(bigOName)) {
// estimate the constant factor
double sumRangeMeasure = 0.0;
double sumRangeRange = 0.0;
- for (size_t i = 0; i < rangeMeasure.size(); ++i) {
- sumRangeMeasure += rangeMeasure[i].first * rangeMeasure[i].second;
- sumRangeRange += rangeMeasure[i].first * rangeMeasure[i].first;
+ for (const auto& rm : rangeMeasure) {
+ sumRangeMeasure += rm.first * rm.second;
+ sumRangeRange += rm.first * rm.first;
}
mConstant = sumRangeMeasure / sumRangeRange;
// calculate root mean square
double err = 0.0;
double sumMeasure = 0.0;
- for (size_t i = 0; i < rangeMeasure.size(); ++i) {
- auto diff = mConstant * rangeMeasure[i].first - rangeMeasure[i].second;
+ for (const auto& rm : rangeMeasure) {
+ auto diff = mConstant * rm.first - rm.second;
err += diff * diff;
- sumMeasure += rangeMeasure[i].second;
+ sumMeasure += rm.second;
}
auto n = static_cast<double>(rangeMeasure.size());
@@ -3347,7 +3452,7 @@ std::ostream& operator<<(std::ostream& os, BigO const& bigO) {
}
std::ostream& operator<<(std::ostream& os, std::vector<ankerl::nanobench::BigO> const& bigOs) {
- detail::fmt::StreamStateRestorer restorer(os);
+ detail::fmt::StreamStateRestorer const restorer(os);
os << std::endl << "| coefficient | err% | complexity" << std::endl << "|--------------:|-------:|------------" << std::endl;
for (auto const& bigO : bigOs) {
os << "|" << std::setw(14) << std::setprecision(7) << std::scientific << bigO.constant() << " ";
diff --git a/src/bench/peer_eviction.cpp b/src/bench/peer_eviction.cpp
index d83342be93..e04f3c403c 100644
--- a/src/bench/peer_eviction.cpp
+++ b/src/bench/peer_eviction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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 ad5a72ffde..f7d17dfa96 100644
--- a/src/bench/poly1305.cpp
+++ b/src/bench/poly1305.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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 9e2e7d11c4..59c4af086e 100644
--- a/src/bench/prevector.cpp
+++ b/src/bench/prevector.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -61,7 +61,7 @@ static void PrevectorResize(benchmark::Bench& bench)
template <typename T>
static void PrevectorDeserialize(benchmark::Bench& bench)
{
- CDataStream s0(SER_NETWORK, 0);
+ DataStream s0{};
prevector<28, T> t0;
t0.resize(28);
for (auto x = 0; x < 900; ++x) {
diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp
index 865d99f9e8..de76a87278 100644
--- a/src/bench/rollingbloom.cpp
+++ b/src/bench/rollingbloom.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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_blockchain.cpp b/src/bench/rpc_blockchain.cpp
index 5a178f308a..f68b6acb5b 100644
--- a/src/bench/rpc_blockchain.cpp
+++ b/src/bench/rpc_blockchain.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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 6bac6419e5..e3e1a07c83 100644
--- a/src/bench/rpc_mempool.cpp
+++ b/src/bench/rpc_mempool.cpp
@@ -1,9 +1,10 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 <bench/bench.h>
#include <chainparamsbase.h>
+#include <kernel/cs_main.h>
#include <kernel/mempool_entry.h>
#include <rpc/mempool.h>
#include <test/util/setup_common.h>
diff --git a/src/bench/util_time.cpp b/src/bench/util_time.cpp
index 8256b5f7ba..8dbbdec28c 100644
--- a/src/bench/util_time.cpp
+++ b/src/bench/util_time.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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 f0e9db8ba1..757094167a 100644
--- a/src/bench/verify_script.cpp
+++ b/src/bench/verify_script.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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,7 +18,6 @@
// modified to measure performance of other types of scripts.
static void VerifyScriptBench(benchmark::Bench& bench)
{
- const ECCVerifyHandle verify_handle;
ECC_Start();
const uint32_t flags{SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH};
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
index 5a52774a8e..ea272b2120 100644
--- a/src/bench/wallet_balance.cpp
+++ b/src/bench/wallet_balance.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/wallet_create_tx.cpp b/src/bench/wallet_create_tx.cpp
index 3cbf2c9008..820c9d5d50 100644
--- a/src/bench/wallet_create_tx.cpp
+++ b/src/bench/wallet_create_tx.cpp
@@ -133,11 +133,51 @@ static void WalletCreateTx(benchmark::Bench& bench, const OutputType output_type
});
}
+static void AvailableCoins(benchmark::Bench& bench, const std::vector<OutputType>& output_type)
+{
+ const auto test_setup = MakeNoLogFileContext<const TestingSetup>();
+ CWallet wallet{test_setup->m_node.chain.get(), "", gArgs, CreateMockWalletDatabase()};
+ {
+ LOCK(wallet.cs_wallet);
+ wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ wallet.SetupDescriptorScriptPubKeyMans();
+ if (wallet.LoadWallet() != DBErrors::LOAD_OK) assert(false);
+ }
+
+ // Generate destinations
+ std::vector<CScript> dest_wallet;
+ for (auto type : output_type) {
+ dest_wallet.emplace_back(GetScriptForDestination(getNewDestination(wallet, type)));
+ }
+
+ // Generate chain; each coinbase will have two outputs to fill-up the wallet
+ const auto& params = Params();
+ unsigned int chain_size = 1000;
+ for (unsigned int i = 0; i < chain_size / dest_wallet.size(); ++i) {
+ for (const auto& dest : dest_wallet) {
+ generateFakeBlock(params, test_setup->m_node, wallet, dest);
+ }
+ }
+
+ // Check available balance
+ auto bal = wallet::GetAvailableBalance(wallet); // Cache
+ assert(bal == 50 * COIN * (chain_size - COINBASE_MATURITY));
+
+ bench.epochIterations(2).run([&] {
+ LOCK(wallet.cs_wallet);
+ const auto& res = wallet::AvailableCoins(wallet);
+ assert(res.All().size() == (chain_size - COINBASE_MATURITY) * 2);
+ });
+}
+
static void WalletCreateTxUseOnlyPresetInputs(benchmark::Bench& bench) { WalletCreateTx(bench, OutputType::BECH32, /*allow_other_inputs=*/false,
{{/*num_of_internal_inputs=*/4}}); }
static void WalletCreateTxUsePresetInputsAndCoinSelection(benchmark::Bench& bench) { WalletCreateTx(bench, OutputType::BECH32, /*allow_other_inputs=*/true,
{{/*num_of_internal_inputs=*/4}}); }
+static void WalletAvailableCoins(benchmark::Bench& bench) { AvailableCoins(bench, {OutputType::BECH32M}); }
+
BENCHMARK(WalletCreateTxUseOnlyPresetInputs, benchmark::PriorityLevel::LOW)
BENCHMARK(WalletCreateTxUsePresetInputsAndCoinSelection, benchmark::PriorityLevel::LOW)
+BENCHMARK(WalletAvailableCoins, benchmark::PriorityLevel::LOW); \ No newline at end of file
diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp
index 2f7dc53b0c..6b09adcc9d 100644
--- a/src/bench/wallet_loading.cpp
+++ b/src/bench/wallet_loading.cpp
@@ -24,7 +24,7 @@ using wallet::WALLET_FLAG_DESCRIPTORS;
using wallet::WalletContext;
using wallet::WalletDatabase;
-static const std::shared_ptr<CWallet> BenchLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, DatabaseOptions& options)
+static std::shared_ptr<CWallet> BenchLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, DatabaseOptions& options)
{
bilingual_str error;
std::vector<bilingual_str> warnings;
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 55fa3116ac..e6e33007d5 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -642,7 +642,7 @@ public:
" 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"
- " \"*\" - whether we relay transactions to this peer (relaytxes is false)\n"
+ " \"*\" - we do not relay transactions to this peer (relaytxes is false)\n"
" blk Time since last novel block passing initial validity checks received from the peer, in minutes\n"
" hb High-bandwidth BIP152 compact block relay\n"
" \".\" (to) - we selected the peer as a high-bandwidth peer\n"
@@ -822,7 +822,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
UniValue valReply(UniValue::VSTR);
if (!valReply.read(response.body))
throw std::runtime_error("couldn't parse reply from server");
- const UniValue reply = rh->ProcessReply(valReply);
+ UniValue reply = rh->ProcessReply(valReply);
if (reply.empty())
throw std::runtime_error("expected reply to have result, error and id properties");
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 010cac5920..57ca2bbe8a 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -681,8 +681,6 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
class Secp256k1Init
{
- ECCVerifyHandle globalVerifyHandle;
-
public:
Secp256k1Init() {
ECC_Start();
diff --git a/src/bitcoin-util.cpp b/src/bitcoin-util.cpp
index fb184c0486..61d4b9c6f1 100644
--- a/src/bitcoin-util.cpp
+++ b/src/bitcoin-util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,13 +82,12 @@ static int AppInitUtil(ArgsManager& args, int argc, char* argv[])
return CONTINUE_EXECUTION;
}
-static void grind_task(uint32_t nBits, CBlockHeader& header_orig, uint32_t offset, uint32_t step, std::atomic<bool>& found)
+static void grind_task(uint32_t nBits, CBlockHeader header, uint32_t offset, uint32_t step, std::atomic<bool>& found, uint32_t& proposed_nonce)
{
arith_uint256 target;
bool neg, over;
target.SetCompact(nBits, &neg, &over);
if (target == 0 || neg || over) return;
- CBlockHeader header = header_orig; // working copy
header.nNonce = offset;
uint32_t finish = std::numeric_limits<uint32_t>::max() - step;
@@ -99,7 +98,7 @@ static void grind_task(uint32_t nBits, CBlockHeader& header_orig, uint32_t offse
do {
if (UintToArith256(header.GetHash()) <= target) {
if (!found.exchange(true)) {
- header_orig.nNonce = header.nNonce;
+ proposed_nonce = header.nNonce;
}
return;
}
@@ -123,21 +122,24 @@ static int Grind(const std::vector<std::string>& args, std::string& strPrint)
uint32_t nBits = header.nBits;
std::atomic<bool> found{false};
+ uint32_t proposed_nonce{};
std::vector<std::thread> threads;
int n_tasks = std::max(1u, std::thread::hardware_concurrency());
for (int i = 0; i < n_tasks; ++i) {
- threads.emplace_back( grind_task, nBits, std::ref(header), i, n_tasks, std::ref(found) );
+ threads.emplace_back(grind_task, nBits, header, i, n_tasks, std::ref(found), std::ref(proposed_nonce));
}
for (auto& t : threads) {
t.join();
}
- if (!found) {
+ if (found) {
+ header.nNonce = proposed_nonce;
+ } else {
strPrint = "Could not satisfy difficulty target";
return EXIT_FAILURE;
}
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ss{};
ss << header;
strPrint = HexStr(ss);
return EXIT_SUCCESS;
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index 78c1a2060c..12cb60e6de 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -130,7 +130,6 @@ MAIN_FUNCTION
return EXIT_FAILURE;
}
- ECCVerifyHandle globalVerifyHandle;
ECC_Start();
if (!wallet::WalletTool::ExecuteWalletToolFunc(args, command->command)) {
return EXIT_FAILURE;
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index d8d4e34e47..07002cc8a3 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/blockencodings.cpp b/src/blockencodings.cpp
index f96353510f..a29e4f794e 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -29,7 +29,7 @@ CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block) :
}
void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const {
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << header << nonce;
CSHA256 hasher;
hasher.Write((unsigned char*)&(*stream.begin()), stream.end() - stream.begin());
@@ -52,7 +52,8 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_WEIGHT / MIN_SERIALIZABLE_TRANSACTION_WEIGHT)
return READ_STATUS_INVALID;
- assert(header.IsNull() && txn_available.empty());
+ if (!header.IsNull() || !txn_available.empty()) return READ_STATUS_INVALID;
+
header = cmpctblock.header;
txn_available.resize(cmpctblock.BlockTxCount());
@@ -167,14 +168,18 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
return READ_STATUS_OK;
}
-bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const {
- assert(!header.IsNull());
+bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const
+{
+ if (header.IsNull()) return false;
+
assert(index < txn_available.size());
return txn_available[index] != nullptr;
}
-ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing) {
- assert(!header.IsNull());
+ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing)
+{
+ if (header.IsNull()) return READ_STATUS_INVALID;
+
uint256 hash = header.GetHash();
block = header;
block.vtx.resize(txn_available.size());
@@ -197,7 +202,8 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
return READ_STATUS_INVALID;
BlockValidationState state;
- if (!CheckBlock(block, state, Params().GetConsensus())) {
+ CheckBlockFn check_block = m_check_block_mock ? m_check_block_mock : CheckBlock;
+ if (!check_block(block, state, Params().GetConsensus(), /*fCheckPoW=*/true, /*fCheckMerkleRoot=*/true)) {
// TODO: We really want to just check merkle tree manually here,
// but that is expensive, and CheckBlock caches a block's
// "checked-status" (in the CBlock?). CBlock should be able to
diff --git a/src/blockencodings.h b/src/blockencodings.h
index 67c4e57156..7207ff1ae2 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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,8 +7,13 @@
#include <primitives/block.h>
+#include <functional>
class CTxMemPool;
+class BlockValidationState;
+namespace Consensus {
+struct Params;
+};
// Transaction compression schemes for compact block relay can be introduced by writing
// an actual formatter here.
@@ -129,6 +134,11 @@ protected:
const CTxMemPool* pool;
public:
CBlockHeader header;
+
+ // Can be overriden for testing
+ using CheckBlockFn = std::function<bool(const CBlock&, BlockValidationState&, const Consensus::Params&, bool, bool)>;
+ CheckBlockFn m_check_block_mock{nullptr};
+
explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {}
// extra_txn is a list of extra transactions to look at, in <witness hash, reference> form
diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp
index 85929747be..88c7526b9e 100644
--- a/src/blockfilter.cpp
+++ b/src/blockfilter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -247,21 +247,10 @@ bool BlockFilter::BuildParams(GCSFilter::Params& params) const
uint256 BlockFilter::GetHash() const
{
- const std::vector<unsigned char>& data = GetEncodedFilter();
-
- uint256 result;
- CHash256().Write(data).Finalize(result);
- return result;
+ return Hash(GetEncodedFilter());
}
uint256 BlockFilter::ComputeHeader(const uint256& prev_header) const
{
- const uint256& filter_hash = GetHash();
-
- uint256 result;
- CHash256()
- .Write(filter_hash)
- .Write(prev_header)
- .Finalize(result);
- return result;
+ return Hash(GetHash(), prev_header);
}
diff --git a/src/blockfilter.h b/src/blockfilter.h
index 0cb627d9df..fb5114edb3 100644
--- a/src/blockfilter.h
+++ b/src/blockfilter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/chain.cpp b/src/chain.cpp
index 66a0830394..82007a8a1e 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/chain.h b/src/chain.h
index 2d3b084b9b..f5dd0fd315 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,6 +9,7 @@
#include <arith_uint256.h>
#include <consensus/params.h>
#include <flatfile.h>
+#include <kernel/cs_main.h>
#include <primitives/block.h>
#include <sync.h>
#include <uint256.h>
@@ -38,8 +39,6 @@ static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
*/
static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60;
-extern RecursiveMutex cs_main;
-
class CBlockFileInfo
{
public:
@@ -213,10 +212,6 @@ public:
//! (memory only) Maximum nTime in the chain up to and including this block.
unsigned int nTimeMax{0};
- CBlockIndex()
- {
- }
-
explicit CBlockIndex(const CBlockHeader& block)
: nVersion{block.nVersion},
hashMerkleRoot{block.hashMerkleRoot},
@@ -355,6 +350,24 @@ public:
//! Efficiently find an ancestor of this block.
CBlockIndex* GetAncestor(int height);
const CBlockIndex* GetAncestor(int height) const;
+
+ CBlockIndex() = default;
+ ~CBlockIndex() = default;
+
+protected:
+ //! CBlockIndex should not allow public copy construction because equality
+ //! comparison via pointer is very common throughout the codebase, making
+ //! use of copy a footgun. Also, use of copies do not have the benefit
+ //! of simplifying lifetime considerations due to attributes like pprev and
+ //! pskip, which are at risk of becoming dangling pointers in a copied
+ //! instance.
+ //!
+ //! We declare these protected instead of simply deleting them so that
+ //! CDiskBlockIndex can reuse copy construction.
+ CBlockIndex(const CBlockIndex&) = default;
+ CBlockIndex& operator=(const CBlockIndex&) = delete;
+ CBlockIndex(CBlockIndex&&) = delete;
+ CBlockIndex& operator=(CBlockIndex&&) = delete;
};
arith_uint256 GetBlockProof(const CBlockIndex& block);
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index c6d4eee7b9..19b5c332f4 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/checkqueue.h b/src/checkqueue.h
index c4a64444e9..d83f717fb7 100644
--- a/src/checkqueue.h
+++ b/src/checkqueue.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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 192e9c52bc..e7d63e34c6 100644
--- a/src/clientversion.cpp
+++ b/src/clientversion.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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 d2efd7dcab..9da0cd0b39 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 5983a8a39f..e98bf816ab 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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 @@
bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
-bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
+bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase) { return false; }
std::unique_ptr<CCoinsViewCursor> CCoinsView::Cursor() const { return nullptr; }
bool CCoinsView::HaveCoin(const COutPoint &outpoint) const
@@ -28,11 +28,11 @@ bool CCoinsViewBacked::HaveCoin(const COutPoint &outpoint) const { return base->
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
-bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
+bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase) { return base->BatchWrite(mapCoins, hashBlock, erase); }
std::unique_ptr<CCoinsViewCursor> CCoinsViewBacked::Cursor() const { return base->Cursor(); }
size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
-CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), cachedCoinsUsage(0) {}
+CCoinsViewCache::CCoinsViewCache(CCoinsView* baseIn) : CCoinsViewBacked(baseIn) {}
size_t CCoinsViewCache::DynamicMemoryUsage() const {
return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage;
@@ -176,8 +176,10 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
hashBlock = hashBlockIn;
}
-bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
- for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = mapCoins.erase(it)) {
+bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn, bool erase) {
+ for (CCoinsMap::iterator it = mapCoins.begin();
+ it != mapCoins.end();
+ it = erase ? mapCoins.erase(it) : std::next(it)) {
// Ignore non-dirty entries (optimization).
if (!(it->second.flags & CCoinsCacheEntry::DIRTY)) {
continue;
@@ -190,7 +192,14 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
// Create the coin in the parent cache, move the data up
// and mark it as dirty.
CCoinsCacheEntry& entry = cacheCoins[it->first];
- entry.coin = std::move(it->second.coin);
+ if (erase) {
+ // The `move` call here is purely an optimization; we rely on the
+ // `mapCoins.erase` call in the `for` expression to actually remove
+ // the entry from the child map.
+ entry.coin = std::move(it->second.coin);
+ } else {
+ entry.coin = it->second.coin;
+ }
cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
entry.flags = CCoinsCacheEntry::DIRTY;
// We can mark it FRESH in the parent if it was FRESH in the child
@@ -218,7 +227,14 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
} else {
// A normal modification.
cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
- itUs->second.coin = std::move(it->second.coin);
+ if (erase) {
+ // The `move` call here is purely an optimization; we rely on the
+ // `mapCoins.erase` call in the `for` expression to actually remove
+ // the entry from the child map.
+ itUs->second.coin = std::move(it->second.coin);
+ } else {
+ itUs->second.coin = it->second.coin;
+ }
cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
// NOTE: It isn't safe to mark the coin as FRESH in the parent
@@ -233,12 +249,32 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
}
bool CCoinsViewCache::Flush() {
- bool fOk = base->BatchWrite(cacheCoins, hashBlock);
- cacheCoins.clear();
+ bool fOk = base->BatchWrite(cacheCoins, hashBlock, /*erase=*/true);
+ if (fOk && !cacheCoins.empty()) {
+ /* BatchWrite must erase all cacheCoins elements when erase=true. */
+ throw std::logic_error("Not all cached coins were erased");
+ }
cachedCoinsUsage = 0;
return fOk;
}
+bool CCoinsViewCache::Sync()
+{
+ bool fOk = base->BatchWrite(cacheCoins, hashBlock, /*erase=*/false);
+ // Instead of clearing `cacheCoins` as we would in Flush(), just clear the
+ // FRESH/DIRTY flags of any coin that isn't spent.
+ for (auto it = cacheCoins.begin(); it != cacheCoins.end(); ) {
+ if (it->second.coin.IsSpent()) {
+ cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
+ it = cacheCoins.erase(it);
+ } else {
+ it->second.flags = 0;
+ ++it;
+ }
+ }
+ return fOk;
+}
+
void CCoinsViewCache::Uncache(const COutPoint& hash)
{
CCoinsMap::iterator it = cacheCoins.find(hash);
diff --git a/src/coins.h b/src/coins.h
index 67fecc9785..710b8c7c83 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -176,7 +176,7 @@ public:
//! Do a bulk modification (multiple Coin changes + BestBlock change).
//! The passed mapCoins can be modified.
- virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
+ virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase = true);
//! Get a cursor to iterate over the whole state
virtual std::unique_ptr<CCoinsViewCursor> Cursor() const;
@@ -202,7 +202,7 @@ public:
uint256 GetBestBlock() const override;
std::vector<uint256> GetHeadBlocks() const override;
void SetBackend(CCoinsView &viewIn);
- bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
+ bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase = true) override;
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
size_t EstimateSize() const override;
};
@@ -220,7 +220,7 @@ protected:
mutable CCoinsMap cacheCoins;
/* Cached dynamic memory usage for the inner Coin objects. */
- mutable size_t cachedCoinsUsage;
+ mutable size_t cachedCoinsUsage{0};
public:
CCoinsViewCache(CCoinsView *baseIn);
@@ -235,7 +235,7 @@ public:
bool HaveCoin(const COutPoint &outpoint) const override;
uint256 GetBestBlock() const override;
void SetBestBlock(const uint256 &hashBlock);
- bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
+ bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase = true) override;
std::unique_ptr<CCoinsViewCursor> Cursor() const override {
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
}
@@ -282,13 +282,23 @@ public:
bool SpendCoin(const COutPoint &outpoint, Coin* moveto = nullptr);
/**
- * Push the modifications applied to this cache to its base.
- * Failure to call this method before destruction will cause the changes to be forgotten.
+ * Push the modifications applied to this cache to its base and wipe local state.
+ * Failure to call this method or Sync() before destruction will cause the changes
+ * to be forgotten.
* If false is returned, the state of this cache (and its backing view) will be undefined.
*/
bool Flush();
/**
+ * Push the modifications applied to this cache to its base while retaining
+ * the contents of this cache (except for spent coins, which we erase).
+ * Failure to call this method or Flush() before destruction will cause the changes
+ * to be forgotten.
+ * If false is returned, the state of this cache (and its backing view) will be undefined.
+ */
+ bool Sync();
+
+ /**
* Removes the UTXO with the given outpoint from the cache, if it is
* not modified.
*/
diff --git a/src/common/bloom.cpp b/src/common/bloom.cpp
index aa3fcf1ce2..fd3276b5a7 100644
--- a/src/common/bloom.cpp
+++ b/src/common/bloom.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -60,7 +60,7 @@ void CBloomFilter::insert(Span<const unsigned char> vKey)
void CBloomFilter::insert(const COutPoint& outpoint)
{
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << outpoint;
insert(MakeUCharSpan(stream));
}
@@ -81,7 +81,7 @@ bool CBloomFilter::contains(Span<const unsigned char> vKey) const
bool CBloomFilter::contains(const COutPoint& outpoint) const
{
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << outpoint;
return contains(MakeUCharSpan(stream));
}
diff --git a/src/common/interfaces.cpp b/src/common/interfaces.cpp
index b9b4f5dded..c8bbe2b3c0 100644
--- a/src/common/interfaces.cpp
+++ b/src/common/interfaces.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/common/url.cpp b/src/common/url.cpp
index 5200d55096..053e1a825c 100644
--- a/src/common/url.cpp
+++ b/src/common/url.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/common/url.h b/src/common/url.h
index 7bbd8b60de..b16b8241af 100644
--- a/src/common/url.h
+++ b/src/common/url.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/byteswap.h b/src/compat/byteswap.h
index 2f4232fa5c..9ee71ef267 100644
--- a/src/compat/byteswap.h
+++ b/src/compat/byteswap.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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/compat.h b/src/compat/compat.h
index cc37797577..88f58120b8 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/cpuid.h b/src/compat/cpuid.h
index e78c1ce6d1..4237c8ebc9 100644
--- a/src/compat/cpuid.h
+++ b/src/compat/cpuid.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/endian.h b/src/compat/endian.h
index bdd8b84c1b..882de2dbf0 100644
--- a/src/compat/endian.h
+++ b/src/compat/endian.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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/stdin.cpp b/src/compat/stdin.cpp
index 61d66e39f2..c11763f68f 100644
--- a/src/compat/stdin.cpp
+++ b/src/compat/stdin.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -58,7 +58,7 @@ bool StdinReady()
return false;
#else
struct pollfd fds;
- fds.fd = 0; /* this is STDIN */
+ fds.fd = STDIN_FILENO;
fds.events = POLLIN;
return poll(&fds, 1, 0) == 1;
#endif
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index 10bdbf31a8..384f70bc10 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 3b5eb1034d..25f53eb620 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 1209c0faa5..d2cf792cf3 100644
--- a/src/consensus/tx_verify.h
+++ b/src/consensus/tx_verify.h
@@ -63,8 +63,8 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
/**
* Calculates the block height and previous block's median time past at
* which the transaction will be considered final in the context of BIP 68.
- * Also removes from the vector of input heights any entries which did not
- * correspond to sequence locked inputs as they do not affect the calculation.
+ * For each input that is not sequence locked, the corresponding entries in
+ * prevHeights are set to 0 as they do not affect the calculation.
*/
std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block);
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index 9c0aa09356..ad8ee676b2 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 c91c8199d8..997f3bfd5b 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 @@ class CBlockHeader;
class CScript;
class CTransaction;
struct CMutableTransaction;
+class SigningProvider;
class uint256;
class UniValue;
class CTxUndo;
@@ -52,7 +53,7 @@ UniValue ValueFromAmount(const CAmount amount);
std::string FormatScript(const CScript& script);
std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
std::string SighashToStr(unsigned char sighash_type);
-void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex = true, bool include_address = false);
+void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex = true, bool include_address = false, const SigningProvider* provider = nullptr);
void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex = true, int serialize_flags = 0, const CTxUndo* txundo = nullptr, TxVerbosity verbosity = TxVerbosity::SHOW_DETAILS);
#endif // BITCOIN_CORE_IO_H
diff --git a/src/core_read.cpp b/src/core_read.cpp
index ec21a2f7f4..84cd559b7f 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -207,7 +207,7 @@ bool DecodeHexBlockHeader(CBlockHeader& header, const std::string& hex_header)
if (!IsHex(hex_header)) return false;
const std::vector<unsigned char> header_data{ParseHex(hex_header)};
- CDataStream ser_header(header_data, SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ser_header{header_data};
try {
ser_header >> header;
} catch (const std::exception&) {
diff --git a/src/core_write.cpp b/src/core_write.cpp
index cfd4cb1b49..b0e3b0b3c4 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -147,13 +147,13 @@ std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags)
return HexStr(ssTx);
}
-void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool include_address)
+void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool include_address, const SigningProvider* provider)
{
CTxDestination address;
out.pushKV("asm", ScriptToAsmStr(script));
if (include_address) {
- out.pushKV("desc", InferDescriptor(script, DUMMY_SIGNING_PROVIDER)->ToString());
+ out.pushKV("desc", InferDescriptor(script, provider ? *provider : DUMMY_SIGNING_PROVIDER)->ToString());
}
if (include_hex) {
out.pushKV("hex", HexStr(script));
@@ -170,6 +170,8 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool i
void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry, bool include_hex, int serialize_flags, const CTxUndo* txundo, TxVerbosity verbosity)
{
+ CHECK_NONFATAL(verbosity >= TxVerbosity::SHOW_DETAILS);
+
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
// Transaction version is actually unsigned in consensus checks, just signed in memory,
diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp
index c7e12b0612..25d7baa8cc 100644
--- a/src/crypto/chacha20.cpp
+++ b/src/crypto/chacha20.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/chacha20.h b/src/crypto/chacha20.h
index de16a77878..624c083191 100644
--- a/src/crypto/chacha20.h
+++ b/src/crypto/chacha20.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/chacha_poly_aead.cpp b/src/crypto/chacha_poly_aead.cpp
index f736b2d867..6511f46adc 100644
--- a/src/crypto/chacha_poly_aead.cpp
+++ b/src/crypto/chacha_poly_aead.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/hkdf_sha256_32.h b/src/crypto/hkdf_sha256_32.h
index 878b03a37f..d373520300 100644
--- a/src/crypto/hkdf_sha256_32.h
+++ b/src/crypto/hkdf_sha256_32.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/hmac_sha256.h b/src/crypto/hmac_sha256.h
index 9c25edd7c1..abd731d1fe 100644
--- a/src/crypto/hmac_sha256.h
+++ b/src/crypto/hmac_sha256.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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/hmac_sha512.h b/src/crypto/hmac_sha512.h
index 6acce8992e..8fa55d2844 100644
--- a/src/crypto/hmac_sha512.h
+++ b/src/crypto/hmac_sha512.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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
index 7d14b7938e..26f0248663 100644
--- a/src/crypto/muhash.cpp
+++ b/src/crypto/muhash.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/poly1305.h b/src/crypto/poly1305.h
index c80faada7e..650e35bbca 100644
--- a/src/crypto/poly1305.h
+++ b/src/crypto/poly1305.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/ripemd160.cpp b/src/crypto/ripemd160.cpp
index 29a4ad906f..a2f7c6e156 100644
--- a/src/crypto/ripemd160.cpp
+++ b/src/crypto/ripemd160.cpp
@@ -239,7 +239,7 @@ void Transform(uint32_t* s, const unsigned char* chunk)
////// RIPEMD160
-CRIPEMD160::CRIPEMD160() : bytes(0)
+CRIPEMD160::CRIPEMD160()
{
ripemd160::Initialize(s);
}
diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h
index f1d89b8407..fb631a66d2 100644
--- a/src/crypto/ripemd160.h
+++ b/src/crypto/ripemd160.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2016 The Bitcoin Core developers
+// Copyright (c) 2014-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,7 +14,7 @@ class CRIPEMD160
private:
uint32_t s[5];
unsigned char buf[64];
- uint64_t bytes;
+ uint64_t bytes{0};
public:
static const size_t OUTPUT_SIZE = 20;
diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp
index 1fb9bb2b72..2610108f60 100644
--- a/src/crypto/sha1.cpp
+++ b/src/crypto/sha1.cpp
@@ -146,7 +146,7 @@ void Transform(uint32_t* s, const unsigned char* chunk)
////// SHA1
-CSHA1::CSHA1() : bytes(0)
+CSHA1::CSHA1()
{
sha1::Initialize(s);
}
diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h
index 6ef0187efd..741cdaad58 100644
--- a/src/crypto/sha1.h
+++ b/src/crypto/sha1.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2016 The Bitcoin Core developers
+// Copyright (c) 2014-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,7 +14,7 @@ class CSHA1
private:
uint32_t s[5];
unsigned char buf[64];
- uint64_t bytes;
+ uint64_t bytes{0};
public:
static const size_t OUTPUT_SIZE = 20;
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index 196f81ea16..a4eef36480 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -673,7 +673,7 @@ std::string SHA256AutoDetect()
////// SHA-256
-CSHA256::CSHA256() : bytes(0)
+CSHA256::CSHA256()
{
sha256::Initialize(s);
}
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index 24bd1f2e7e..7625508665 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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 @@ class CSHA256
private:
uint32_t s[8];
unsigned char buf[64];
- uint64_t bytes;
+ uint64_t bytes{0};
public:
static const size_t OUTPUT_SIZE = 32;
diff --git a/src/crypto/sha256_sse4.cpp b/src/crypto/sha256_sse4.cpp
index bc69703607..f4557291ce 100644
--- a/src/crypto/sha256_sse4.cpp
+++ b/src/crypto/sha256_sse4.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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_x86_shani.cpp b/src/crypto/sha256_x86_shani.cpp
index a82802199f..e3143a55c2 100644
--- a/src/crypto/sha256_x86_shani.cpp
+++ b/src/crypto/sha256_x86_shani.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/sha3.h b/src/crypto/sha3.h
index 78608eae76..e8e91f1ee4 100644
--- a/src/crypto/sha3.h
+++ b/src/crypto/sha3.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/sha512.cpp b/src/crypto/sha512.cpp
index 59b79609dd..2713f06210 100644
--- a/src/crypto/sha512.cpp
+++ b/src/crypto/sha512.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -151,7 +151,7 @@ void Transform(uint64_t* s, const unsigned char* chunk)
////// SHA-512
-CSHA512::CSHA512() : bytes(0)
+CSHA512::CSHA512()
{
sha512::Initialize(s);
}
diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h
index 7356dff6d9..d2f7d6a05e 100644
--- a/src/crypto/sha512.h
+++ b/src/crypto/sha512.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,7 +14,7 @@ class CSHA512
private:
uint64_t s[8];
unsigned char buf[128];
- uint64_t bytes;
+ uint64_t bytes{0};
public:
static constexpr size_t OUTPUT_SIZE = 64;
diff --git a/src/crypto/siphash.cpp b/src/crypto/siphash.cpp
index 2e90c393e1..2f7555d02e 100644
--- a/src/crypto/siphash.cpp
+++ b/src/crypto/siphash.cpp
@@ -119,10 +119,10 @@ uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
SIPROUND;
SIPROUND;
v0 ^= d;
- v3 ^= ((uint64_t)4) << 59;
+ v3 ^= (uint64_t{4}) << 59;
SIPROUND;
SIPROUND;
- v0 ^= ((uint64_t)4) << 59;
+ v0 ^= (uint64_t{4}) << 59;
v2 ^= 0xFF;
SIPROUND;
SIPROUND;
@@ -159,7 +159,7 @@ uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint3
SIPROUND;
SIPROUND;
v0 ^= d;
- d = (((uint64_t)36) << 56) | extra;
+ d = ((uint64_t{36}) << 56) | extra;
v3 ^= d;
SIPROUND;
SIPROUND;
diff --git a/src/cuckoocache.h b/src/cuckoocache.h
index 61f553806e..cb0b362143 100644
--- a/src/cuckoocache.h
+++ b/src/cuckoocache.h
@@ -166,7 +166,7 @@ private:
std::vector<Element> table;
/** size stores the total available slots in the hash table */
- uint32_t size;
+ uint32_t size{0};
/** The bit_packed_atomic_flags array is marked mutable because we want
* garbage collection to be allowed to occur from const methods */
@@ -183,7 +183,7 @@ private:
* decremented on insert and reset to the new number of inserts which would
* cause the epoch to reach epoch_size when it reaches zero.
*/
- uint32_t epoch_heuristic_counter;
+ uint32_t epoch_heuristic_counter{0};
/** epoch_size is set to be the number of elements supposed to be in a
* epoch. When the number of non-erased elements in an epoch
@@ -193,12 +193,12 @@ private:
* one "dead" which has been erased, one "dying" which has been marked to be
* erased next, and one "living" which new inserts add to.
*/
- uint32_t epoch_size;
+ uint32_t epoch_size{0};
/** depth_limit determines how many elements insert should try to replace.
* Should be set to log2(n).
*/
- uint8_t depth_limit;
+ uint8_t depth_limit{0};
/** hash_function is a const instance of the hash function. It cannot be
* static or initialized at call time as it may have internal state (such as
@@ -322,8 +322,7 @@ public:
/** You must always construct a cache with some elements via a subsequent
* call to setup or setup_bytes, otherwise operations may segfault.
*/
- cache() : table(), size(), collection_flags(0), epoch_flags(),
- epoch_heuristic_counter(), epoch_size(), depth_limit(0), hash_function()
+ cache() : table(), collection_flags(0), epoch_flags(), hash_function()
{
}
@@ -344,7 +343,7 @@ public:
collection_flags.setup(size);
epoch_flags.resize(size);
// Set to 45% as described above
- epoch_size = std::max((uint32_t)1, (45 * size) / 100);
+ epoch_size = std::max(uint32_t{1}, (45 * size) / 100);
// Initially set to wait for a whole epoch
epoch_heuristic_counter = epoch_size;
return size;
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
index 7f45e35aef..6efaf2ec19 100644
--- a/src/dbwrapper.cpp
+++ b/src/dbwrapper.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/dbwrapper.h b/src/dbwrapper.h
index 1052da01d5..b389d039fb 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -68,16 +68,16 @@ private:
const CDBWrapper &parent;
leveldb::WriteBatch batch;
- CDataStream ssKey;
+ DataStream ssKey{};
CDataStream ssValue;
- size_t size_estimate;
+ size_t size_estimate{0};
public:
/**
* @param[in] _parent CDBWrapper that this batch is to be submitted to
*/
- explicit CDBBatch(const CDBWrapper &_parent) : parent(_parent), ssKey(SER_DISK, CLIENT_VERSION), ssValue(SER_DISK, CLIENT_VERSION), size_estimate(0) { };
+ explicit CDBBatch(const CDBWrapper& _parent) : parent(_parent), ssValue(SER_DISK, CLIENT_VERSION){};
void Clear()
{
@@ -151,7 +151,7 @@ public:
void SeekToFirst();
template<typename K> void Seek(const K& key) {
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{};
ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size());
@@ -163,7 +163,7 @@ public:
template<typename K> bool GetKey(K& key) {
leveldb::Slice slKey = piter->key();
try {
- CDataStream ssKey{MakeByteSpan(slKey), SER_DISK, CLIENT_VERSION};
+ DataStream ssKey{MakeByteSpan(slKey)};
ssKey >> key;
} catch (const std::exception&) {
return false;
@@ -247,7 +247,7 @@ public:
template <typename K, typename V>
bool Read(const K& key, V& value) const
{
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{};
ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size());
@@ -289,7 +289,7 @@ public:
template <typename K>
bool Exists(const K& key) const
{
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{};
ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size());
@@ -331,7 +331,7 @@ public:
template<typename K>
size_t EstimateSize(const K& key_begin, const K& key_end) const
{
- CDataStream ssKey1(SER_DISK, CLIENT_VERSION), ssKey2(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey1{}, ssKey2{};
ssKey1.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey1 << key_begin;
diff --git a/src/deploymentstatus.cpp b/src/deploymentstatus.cpp
index 3a524af29e..71f2702430 100644
--- a/src/deploymentstatus.cpp
+++ b/src/deploymentstatus.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/deploymentstatus.h b/src/deploymentstatus.h
index 9f5919f71b..03d3c531cc 100644
--- a/src/deploymentstatus.h
+++ b/src/deploymentstatus.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/external_signer.cpp b/src/external_signer.cpp
index f255834830..5524b943f4 100644
--- a/src/external_signer.cpp
+++ b/src/external_signer.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,7 +16,7 @@
ExternalSigner::ExternalSigner(const std::string& command, const std::string chain, const std::string& fingerprint, const std::string name): m_command(command), m_chain(chain), m_fingerprint(fingerprint), m_name(name) {}
-const std::string ExternalSigner::NetworkArg() const
+std::string ExternalSigner::NetworkArg() const
{
return " --chain " + m_chain;
}
diff --git a/src/external_signer.h b/src/external_signer.h
index e40fd7f010..90f07478e3 100644
--- a/src/external_signer.h
+++ b/src/external_signer.h
@@ -24,7 +24,7 @@ private:
//! Bitcoin mainnet, testnet, etc
std::string m_chain;
- const std::string NetworkArg() const;
+ std::string NetworkArg() const;
public:
//! @param[in] command the command which handles interaction with the external signer
diff --git a/src/flatfile.cpp b/src/flatfile.cpp
index 0fecf4f504..d6e84d02c1 100644
--- a/src/flatfile.cpp
+++ b/src/flatfile.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/fs.cpp b/src/fs.cpp
index 07cce269ed..0429b8cd0f 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/fs.h b/src/fs.h
index ac58c4a2ba..0ece256acb 100644
--- a/src/fs.h
+++ b/src/fs.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -35,7 +35,7 @@ public:
// Allow path objects arguments for compatibility.
path(std::filesystem::path path) : std::filesystem::path::path(std::move(path)) {}
path& operator=(std::filesystem::path path) { std::filesystem::path::operator=(std::move(path)); return *this; }
- path& operator/=(std::filesystem::path path) { std::filesystem::path::operator/=(std::move(path)); return *this; }
+ path& operator/=(std::filesystem::path path) { std::filesystem::path::operator/=(path); return *this; }
// Allow literal string arguments, which are safe as long as the literals are ASCII.
path(const char* c) : std::filesystem::path(c) {}
diff --git a/src/hash.cpp b/src/hash.cpp
index 06caaac6ee..1ece8c5a79 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2021 The Bitcoin Core developers
+// Copyright (c) 2013-2022 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.h b/src/hash.h
index b1ff3acc7d..2e3ed11b43 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -1,16 +1,18 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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_HASH_H
#define BITCOIN_HASH_H
+#include <attributes.h>
#include <crypto/common.h>
#include <crypto/ripemd160.h>
#include <crypto/sha256.h>
#include <prevector.h>
#include <serialize.h>
+#include <span.h>
#include <uint256.h>
#include <version.h>
@@ -165,6 +167,39 @@ public:
};
/** Reads data from an underlying stream, while hashing the read data. */
+template <typename Source>
+class HashVerifier : public HashWriter
+{
+private:
+ Source& m_source;
+
+public:
+ explicit HashVerifier(Source& source LIFETIMEBOUND) : m_source{source} {}
+
+ void read(Span<std::byte> dst)
+ {
+ m_source.read(dst);
+ this->write(dst);
+ }
+
+ void ignore(size_t num_bytes)
+ {
+ std::byte data[1024];
+ while (num_bytes > 0) {
+ size_t now = std::min<size_t>(num_bytes, 1024);
+ read({data, now});
+ num_bytes -= now;
+ }
+ }
+
+ template <typename T>
+ HashVerifier<Source>& operator>>(T&& obj)
+ {
+ ::Unserialize(*this, obj);
+ return *this;
+ }
+};
+
template<typename Source>
class CHashVerifier : public CHashWriter
{
@@ -199,6 +234,30 @@ public:
}
};
+/** Writes data to an underlying source stream, while hashing the written data. */
+template <typename Source>
+class HashedSourceWriter : public CHashWriter
+{
+private:
+ Source& m_source;
+
+public:
+ explicit HashedSourceWriter(Source& source LIFETIMEBOUND) : CHashWriter{source.GetType(), source.GetVersion()}, m_source{source} {}
+
+ void write(Span<const std::byte> src)
+ {
+ m_source.write(src);
+ CHashWriter::write(src);
+ }
+
+ template <typename T>
+ HashedSourceWriter& operator<<(const T& obj)
+ {
+ ::Serialize(*this, obj);
+ return *this;
+ }
+};
+
/** Compute the 256-bit hash of an object's serialization. */
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
@@ -223,4 +282,12 @@ void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char he
*/
HashWriter TaggedHash(const std::string& tag);
+/** Compute the 160-bit RIPEMD-160 hash of an array. */
+inline uint160 RIPEMD160(Span<const unsigned char> data)
+{
+ uint160 result;
+ CRIPEMD160().Write(data.data(), data.size()).Finalize(result.begin());
+ return result;
+}
+
#endif // BITCOIN_HASH_H
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 4e7e72b037..33a75df68e 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/httpserver.cpp b/src/httpserver.cpp
index 6f84d5c83b..720f5c9353 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -279,7 +279,7 @@ static void http_reject_request_cb(struct evhttp_request* req, void*)
}
/** Event dispatcher thread */
-static bool ThreadHTTP(struct event_base* base)
+static void ThreadHTTP(struct event_base* base)
{
util::ThreadRename("http");
SetSyscallSandboxPolicy(SyscallSandboxPolicy::NET_HTTP_SERVER);
@@ -287,7 +287,6 @@ static bool ThreadHTTP(struct event_base* base)
event_base_dispatch(base);
// Event loop will be interrupted by InterruptHTTPServer()
LogPrint(BCLog::HTTP, "Exited http event loop\n");
- return event_base_got_break(base) == 0;
}
/** Bind HTTP server to specified addresses */
diff --git a/src/httpserver.h b/src/httpserver.h
index 5ab3f18927..036a39a023 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/i2p.cpp b/src/i2p.cpp
index d54486ecff..586ee649a7 100644
--- a/src/i2p.cpp
+++ b/src/i2p.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/i2p.h b/src/i2p.h
index e025f2cb22..6e7bafc945 100644
--- a/src/i2p.h
+++ b/src/i2p.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/base.cpp b/src/index/base.cpp
index 3eea09b17d..1d5c0dbe24 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -415,8 +415,9 @@ IndexSummary BaseIndex::GetSummary() const
return summary;
}
-void BaseIndex::SetBestBlockIndex(const CBlockIndex* block) {
- assert(!node::fPruneMode || AllowPrune());
+void BaseIndex::SetBestBlockIndex(const CBlockIndex* block)
+{
+ assert(!m_chainstate->m_blockman.IsPruneMode() || AllowPrune());
if (AllowPrune() && block) {
node::PruneLockInfo prune_lock;
diff --git a/src/index/base.h b/src/index/base.h
index 54c59f7557..231f36b605 100644
--- a/src/index/base.h
+++ b/src/index/base.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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 292e11c874..59bf6d34cf 100644
--- a/src/index/blockfilterindex.cpp
+++ b/src/index/blockfilterindex.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -157,9 +157,7 @@ bool BlockFilterIndex::ReadFilterFromDisk(const FlatFilePos& pos, const uint256&
std::vector<uint8_t> encoded_filter;
try {
filein >> block_hash >> encoded_filter;
- uint256 result;
- CHash256().Write(encoded_filter).Finalize(result);
- if (result != hash) return error("Checksum mismatch in filter decode.");
+ if (Hash(encoded_filter) != hash) return error("Checksum mismatch in filter decode.");
filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter), /*skip_decode_check=*/true);
}
catch (const std::exception& e) {
diff --git a/src/index/blockfilterindex.h b/src/index/blockfilterindex.h
index 9e69388dc8..ce1961c776 100644
--- a/src/index/blockfilterindex.h
+++ b/src/index/blockfilterindex.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/coinstatsindex.cpp b/src/index/coinstatsindex.cpp
index 271e5bb1f6..8cece7d78d 100644
--- a/src/index/coinstatsindex.cpp
+++ b/src/index/coinstatsindex.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/coinstatsindex.h b/src/index/coinstatsindex.h
index aa0d7f9fd5..21ce4c4767 100644
--- a/src/index/coinstatsindex.h
+++ b/src/index/coinstatsindex.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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 a4fe1b611e..25ccc3e636 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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.h b/src/index/txindex.h
index 4cea35045d..ef835fe5d7 100644
--- a/src/index/txindex.h
+++ b/src/index/txindex.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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 f31a45aa9f..5b486854e0 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -126,8 +126,9 @@ using node::fPruneMode;
using node::fReindex;
using node::nPruneTarget;
-static const bool DEFAULT_PROXYRANDOMIZE = true;
-static const bool DEFAULT_REST_ENABLE = false;
+static constexpr bool DEFAULT_PROXYRANDOMIZE{true};
+static constexpr bool DEFAULT_REST_ENABLE{false};
+static constexpr bool DEFAULT_I2P_ACCEPT_INCOMING{true};
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
@@ -190,8 +191,24 @@ static fs::path GetPidFile(const ArgsManager& args)
// shutdown thing.
//
+#if HAVE_SYSTEM
+static void ShutdownNotify(const ArgsManager& args)
+{
+ std::vector<std::thread> threads;
+ for (const auto& cmd : args.GetArgs("-shutdownnotify")) {
+ threads.emplace_back(runCommand, cmd);
+ }
+ for (auto& t : threads) {
+ t.join();
+ }
+}
+#endif
+
void Interrupt(NodeContext& node)
{
+#if HAVE_SYSTEM
+ ShutdownNotify(*node.args);
+#endif
InterruptHTTPServer();
InterruptHTTPRPC();
InterruptRPC();
@@ -440,6 +457,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-settings=<file>", strprintf("Specify path to dynamic settings data file. Can be disabled with -nosettings. File is written at runtime and not meant to be edited by users (use %s instead for custom settings). Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME, BITCOIN_SETTINGS_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#if HAVE_SYSTEM
argsman.AddArg("-startupnotify=<cmd>", "Execute command on startup.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-shutdownnotify=<cmd>", "Execute command immediately before beginning shutdown. The need for shutdown may be urgent, so be careful not to delay it long (if the command doesn't require interaction with the server, consider having it fork into the background).", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#endif
#ifndef WIN32
argsman.AddArg("-sysperms", "Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -473,7 +491,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target per 24h. Limit does not apply to peers with 'download' permission or blocks created within past week. 0 = no limit (default: %s). Optional suffix units [k|K|m|M|g|G|t|T] (default: M). Lowercase is 1000 base while uppercase is 1024 base", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-i2psam=<ip:port>", "I2P SAM proxy to reach I2P peers and accept I2P connections (default: none)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
- argsman.AddArg("-i2pacceptincoming", "If set and -i2psam is also set then incoming I2P connections are accepted via the SAM proxy. If this is not set but -i2psam is set then only outgoing connections will be made to the I2P network. Ignored if -i2psam is not set. Listening for incoming I2P connections is done through the SAM proxy, not by binding to a local address and port (default: 1)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
+ argsman.AddArg("-i2pacceptincoming", strprintf("Whether to accept inbound I2P connections (default: %i). Ignored if -i2psam is not set. Listening for inbound I2P connections is done through the SAM proxy, not by binding to a local address and port.", DEFAULT_I2P_ACCEPT_INCOMING), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-onlynet=<net>", "Make automatic outbound connections only to network <net> (" + Join(GetNetworkNames(), ", ") + "). Inbound and manual connections are not affected by this option. It can be specified multiple times to allow multiple networks.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
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);
@@ -585,7 +603,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rpcauth=<userpw>", "Username and HMAC-SHA-256 hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcauth. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
- argsman.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
+ argsman.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC);
argsman.AddArg("-rpcdoccheck", strprintf("Throw a non-fatal error at runtime if the documentation for an RPC is incorrect (default: %u)", DEFAULT_RPC_DOC_CHECK), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
argsman.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
@@ -718,10 +736,13 @@ void InitParameterInteraction(ArgsManager& args)
LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__);
}
- // disable whitelistrelay in blocksonly mode
if (args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) {
+ // disable whitelistrelay in blocksonly mode
if (args.SoftSetBoolArg("-whitelistrelay", false))
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__);
+ // Reduce default mempool size in blocksonly mode to avoid unexpected resource usage
+ if (args.SoftSetArg("-maxmempool", ToString(DEFAULT_BLOCKSONLY_MAX_MEMPOOL_SIZE_MB)))
+ LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -maxmempool=%d\n", __func__, DEFAULT_BLOCKSONLY_MAX_MEMPOOL_SIZE_MB);
}
// Forcing relay from whitelisted hosts implies we will accept relays from them in the first place.
@@ -1478,7 +1499,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
options.mempool = Assert(node.mempool.get());
options.reindex = node::fReindex;
options.reindex_chainstate = fReindexChainState;
- options.prune = node::fPruneMode;
+ options.prune = chainman.m_blockman.IsPruneMode();
options.check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
options.check_level = args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
options.check_interrupt = ShutdownRequested;
@@ -1588,7 +1609,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// if pruning, perform the initial blockstore prune
// after any wallet rescanning has taken place.
- if (fPruneMode) {
+ if (chainman.m_blockman.IsPruneMode()) {
if (!fReindex) {
LOCK(cs_main);
for (Chainstate* chainstate : chainman.GetAll()) {
@@ -1616,8 +1637,10 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// On first startup, warn on low block storage space
if (!fReindex && !fReindexChainState && chain_active_height <= 1) {
- uint64_t additional_bytes_needed = fPruneMode ? nPruneTarget
- : chainparams.AssumedBlockchainSize() * 1024 * 1024 * 1024;
+ uint64_t additional_bytes_needed{
+ chainman.m_blockman.IsPruneMode() ?
+ chainman.m_blockman.GetPruneTarget() :
+ chainparams.AssumedBlockchainSize() * 1024 * 1024 * 1024};
if (!CheckDiskSpace(args.GetBlocksDirPath(), additional_bytes_needed)) {
InitWarning(strprintf(_(
@@ -1829,7 +1852,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
SetReachable(NET_I2P, false);
}
- connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", true);
+ connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);
if (!node.connman->Start(*node.scheduler, connOptions)) {
return false;
diff --git a/src/init.h b/src/init.h
index e8e6a55eba..8c5b2e77d3 100644
--- a/src/init.h
+++ b/src/init.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/bitcoin-gui.cpp b/src/init/bitcoin-gui.cpp
index 2fa4add4e5..100b4ef7ee 100644
--- a/src/init/bitcoin-gui.cpp
+++ b/src/init/bitcoin-gui.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/bitcoin-node.cpp b/src/init/bitcoin-node.cpp
index 78bc3e5980..1418e63777 100644
--- a/src/init/bitcoin-node.cpp
+++ b/src/init/bitcoin-node.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/bitcoin-qt.cpp b/src/init/bitcoin-qt.cpp
index bb3bb945d0..e27be0e598 100644
--- a/src/init/bitcoin-qt.cpp
+++ b/src/init/bitcoin-qt.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/bitcoin-wallet.cpp b/src/init/bitcoin-wallet.cpp
index c8d499da10..f3a9ea267c 100644
--- a/src/init/bitcoin-wallet.cpp
+++ b/src/init/bitcoin-wallet.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/bitcoind.cpp b/src/init/bitcoind.cpp
index b473ebb805..7ad1f64e64 100644
--- a/src/init/bitcoind.cpp
+++ b/src/init/bitcoind.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/common.cpp b/src/init/common.cpp
index f2d2c5640a..e1a37d7db9 100644
--- a/src/init/common.cpp
+++ b/src/init/common.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/common.h b/src/init/common.h
index 53c860c297..44c3a502ee 100644
--- a/src/init/common.h
+++ b/src/init/common.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/interfaces/chain.h b/src/interfaces/chain.h
index 7a3d88b18f..a3fa753a98 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -268,8 +268,8 @@ public:
{
public:
virtual ~Notifications() {}
- virtual void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) {}
- virtual void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {}
+ virtual void transactionAddedToMempool(const CTransactionRef& tx) {}
+ virtual void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason) {}
virtual void blockConnected(const BlockInfo& block) {}
virtual void blockDisconnected(const BlockInfo& block) {}
virtual void updatedBlockTip() {}
diff --git a/src/interfaces/handler.h b/src/interfaces/handler.h
index f46f5e04a5..7751d82347 100644
--- a/src/interfaces/handler.h
+++ b/src/interfaces/handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/interfaces/init.h b/src/interfaces/init.h
index 5b8f61640e..addc45aa26 100644
--- a/src/interfaces/init.h
+++ b/src/interfaces/init.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/interfaces/node.h b/src/interfaces/node.h
index dbdb21eb91..ce6c44e2bc 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/interfaces/wallet.h b/src/interfaces/wallet.h
index 1148dc7e4c..86707b20b1 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/ipc/interfaces.cpp b/src/ipc/interfaces.cpp
index ee0d4123ce..396f3ddf25 100644
--- a/src/ipc/interfaces.cpp
+++ b/src/ipc/interfaces.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/ipc/process.cpp b/src/ipc/process.cpp
index 9474ad2c4a..4dc88ae44b 100644
--- a/src/ipc/process.cpp
+++ b/src/ipc/process.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/kernel/coinstats.cpp b/src/kernel/coinstats.cpp
index 06a4b8c974..82d7d8c46b 100644
--- a/src/kernel/coinstats.cpp
+++ b/src/kernel/coinstats.cpp
@@ -48,8 +48,9 @@ uint64_t GetBogoSize(const CScript& script_pub_key)
script_pub_key.size() /* scriptPubKey */;
}
-CDataStream TxOutSer(const COutPoint& outpoint, const Coin& coin) {
- CDataStream ss(SER_DISK, PROTOCOL_VERSION);
+DataStream TxOutSer(const COutPoint& outpoint, const Coin& coin)
+{
+ DataStream ss{};
ss << outpoint;
ss << static_cast<uint32_t>(coin.nHeight * 2 + coin.fCoinBase);
ss << coin.out;
diff --git a/src/kernel/coinstats.h b/src/kernel/coinstats.h
index b7c1328e93..54d0e4f664 100644
--- a/src/kernel/coinstats.h
+++ b/src/kernel/coinstats.h
@@ -72,7 +72,7 @@ struct CCoinsStats {
uint64_t GetBogoSize(const CScript& script_pub_key);
-CDataStream TxOutSer(const COutPoint& outpoint, const Coin& coin);
+DataStream TxOutSer(const COutPoint& outpoint, const Coin& coin);
std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsView* view, node::BlockManager& blockman, const std::function<void()>& interruption_point = {});
} // namespace kernel
diff --git a/src/kernel/context.cpp b/src/kernel/context.cpp
index 15413c1840..1205da869e 100644
--- a/src/kernel/context.cpp
+++ b/src/kernel/context.cpp
@@ -21,12 +21,10 @@ Context::Context()
LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo);
RandomInit();
ECC_Start();
- ecc_verify_handle.reset(new ECCVerifyHandle());
}
Context::~Context()
{
- ecc_verify_handle.reset();
ECC_Stop();
}
diff --git a/src/kernel/context.h b/src/kernel/context.h
index 9746ef994b..f11b7b54f0 100644
--- a/src/kernel/context.h
+++ b/src/kernel/context.h
@@ -7,8 +7,6 @@
#include <memory>
-class ECCVerifyHandle;
-
namespace kernel {
//! Context struct holding the kernel library's logically global state, and
//! passed to external libbitcoin_kernel functions which need access to this
@@ -18,8 +16,6 @@ namespace kernel {
//! State stored directly in this struct should be simple. More complex state
//! should be stored to std::unique_ptr members pointing to opaque types.
struct Context {
- std::unique_ptr<ECCVerifyHandle> ecc_verify_handle;
-
//! Declare default constructor and destructor that are not inline, so code
//! instantiating the kernel::Context struct doesn't need to #include class
//! definitions for all the unique_ptr members.
diff --git a/src/kernel/cs_main.cpp b/src/kernel/cs_main.cpp
new file mode 100644
index 0000000000..c3a08c9695
--- /dev/null
+++ b/src/kernel/cs_main.cpp
@@ -0,0 +1,7 @@
+// Copyright (c) 2023 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 <sync.h>
+
+RecursiveMutex cs_main;
diff --git a/src/kernel/cs_main.h b/src/kernel/cs_main.h
new file mode 100644
index 0000000000..8d03903b8e
--- /dev/null
+++ b/src/kernel/cs_main.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2023 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_KERNEL_CS_MAIN_H
+#define BITCOIN_KERNEL_CS_MAIN_H
+
+#include <sync.h>
+
+/**
+ * Mutex to guard access to validation specific variables, such as reading
+ * or changing the chainstate.
+ *
+ * This may also need to be locked when updating the transaction pool, e.g. on
+ * AcceptToMemoryPool. See CTxMemPool::cs comment for details.
+ *
+ * The transaction pool has a separate lock to allow reading from it and the
+ * chainstate at the same time.
+ */
+extern RecursiveMutex cs_main;
+
+#endif // BITCOIN_KERNEL_CS_MAIN_H
diff --git a/src/kernel/mempool_options.h b/src/kernel/mempool_options.h
index dad6f14c39..beb5fca5e9 100644
--- a/src/kernel/mempool_options.h
+++ b/src/kernel/mempool_options.h
@@ -18,6 +18,8 @@ class CBlockPolicyEstimator;
/** Default for -maxmempool, maximum megabytes of mempool memory usage */
static constexpr unsigned int DEFAULT_MAX_MEMPOOL_SIZE_MB{300};
+/** Default for -maxmempool when blocksonly is set */
+static constexpr unsigned int DEFAULT_BLOCKSONLY_MAX_MEMPOOL_SIZE_MB{5};
/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
static constexpr unsigned int DEFAULT_MEMPOOL_EXPIRY_HOURS{336};
/** Default for -mempoolfullrbf, if the transaction replaceability signaling is ignored */
diff --git a/src/key.cpp b/src/key.cpp
index 199808505d..3a3f0b2bc2 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.
@@ -233,7 +233,7 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, bool gr
secp256k1_pubkey pk;
ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pk, begin());
assert(ret);
- ret = secp256k1_ecdsa_verify(GetVerifyContext(), &sig, hash.begin(), &pk);
+ ret = secp256k1_ecdsa_verify(secp256k1_context_static, &sig, hash.begin(), &pk);
assert(ret);
return true;
}
@@ -245,8 +245,7 @@ bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
unsigned char rnd[8];
std::string str = "Bitcoin key verification\n";
GetRandBytes(rnd);
- uint256 hash;
- CHash256().Write(MakeUCharSpan(str)).Write(rnd).Finalize(hash);
+ uint256 hash{Hash(str, rnd)};
std::vector<unsigned char> vchSig;
Sign(hash, vchSig);
return pubkey.Verify(hash, vchSig);
@@ -268,9 +267,9 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
secp256k1_pubkey epk, rpk;
ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &epk, begin());
assert(ret);
- ret = secp256k1_ecdsa_recover(GetVerifyContext(), &rpk, &rsig, hash.begin());
+ ret = secp256k1_ecdsa_recover(secp256k1_context_static, &rpk, &rsig, hash.begin());
assert(ret);
- ret = secp256k1_ec_pubkey_cmp(GetVerifyContext(), &epk, &rpk);
+ ret = secp256k1_ec_pubkey_cmp(secp256k1_context_static, &epk, &rpk);
assert(ret == 0);
return true;
}
@@ -286,14 +285,14 @@ bool CKey::SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint2
unsigned char pubkey_bytes[32];
if (!secp256k1_xonly_pubkey_serialize(secp256k1_context_sign, pubkey_bytes, &pubkey)) return false;
uint256 tweak = XOnlyPubKey(pubkey_bytes).ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root);
- if (!secp256k1_keypair_xonly_tweak_add(GetVerifyContext(), &keypair, tweak.data())) return false;
+ if (!secp256k1_keypair_xonly_tweak_add(secp256k1_context_static, &keypair, tweak.data())) return false;
}
bool ret = secp256k1_schnorrsig_sign32(secp256k1_context_sign, sig.data(), hash.data(), &keypair, aux.data());
if (ret) {
// Additional verification step to prevent using a potentially corrupted signature
secp256k1_xonly_pubkey pubkey_verify;
- ret = secp256k1_keypair_xonly_pub(GetVerifyContext(), &pubkey_verify, nullptr, &keypair);
- ret &= secp256k1_schnorrsig_verify(GetVerifyContext(), sig.data(), hash.begin(), 32, &pubkey_verify);
+ ret = secp256k1_keypair_xonly_pub(secp256k1_context_static, &pubkey_verify, nullptr, &keypair);
+ ret &= secp256k1_schnorrsig_verify(secp256k1_context_static, sig.data(), hash.begin(), 32, &pubkey_verify);
}
if (!ret) memory_cleanse(sig.data(), sig.size());
memory_cleanse(&keypair, sizeof(keypair));
@@ -392,7 +391,7 @@ bool ECC_InitSanityCheck() {
void ECC_Start() {
assert(secp256k1_context_sign == nullptr);
- secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
+ secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
assert(ctx != nullptr);
{
diff --git a/src/key.h b/src/key.h
index e9b78ebd44..4e092fffea 100644
--- a/src/key.h
+++ b/src/key.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.
@@ -42,10 +42,10 @@ public:
private:
//! Whether this private key is valid. We check for correctness when modifying the key
//! data, so fValid should always correspond to the actual state.
- bool fValid;
+ bool fValid{false};
//! Whether the public key corresponding to this private key is (to be) compressed.
- bool fCompressed;
+ bool fCompressed{false};
//! The actual byte data
std::vector<unsigned char, secure_allocator<unsigned char> > keydata;
@@ -55,7 +55,7 @@ private:
public:
//! Construct an invalid private key.
- CKey() : fValid(false), fCompressed(false)
+ CKey()
{
// Important: vch must be 32 bytes in length to not break serialization
keydata.resize(32);
diff --git a/src/logging.cpp b/src/logging.cpp
index ed0c2a56a5..298ec9c013 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/logging.h b/src/logging.h
index 14a0f08f8d..35fb598cef 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/logging/timer.h b/src/logging/timer.h
index d954e46301..993ba99c25 100644
--- a/src/logging/timer.h
+++ b/src/logging/timer.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,6 +12,7 @@
#include <util/types.h>
#include <chrono>
+#include <optional>
#include <string>
@@ -28,14 +29,14 @@ public:
std::string prefix,
std::string end_msg,
BCLog::LogFlags log_category = BCLog::LogFlags::ALL,
- bool msg_on_completion = true) :
- m_prefix(std::move(prefix)),
- m_title(std::move(end_msg)),
- m_log_category(log_category),
- m_message_on_completion(msg_on_completion)
+ bool msg_on_completion = true)
+ : m_prefix(std::move(prefix)),
+ m_title(std::move(end_msg)),
+ m_log_category(log_category),
+ m_message_on_completion(msg_on_completion)
{
this->Log(strprintf("%s started", m_title));
- m_start_t = GetTime<std::chrono::microseconds>();
+ m_start_t = std::chrono::steady_clock::now();
}
~Timer()
@@ -60,24 +61,25 @@ public:
std::string LogMsg(const std::string& msg)
{
- const auto end_time = GetTime<std::chrono::microseconds>() - m_start_t;
- if (m_start_t.count() <= 0) {
+ const auto end_time{std::chrono::steady_clock::now()};
+ if (!m_start_t) {
return strprintf("%s: %s", m_prefix, msg);
}
+ const auto duration{end_time - *m_start_t};
if constexpr (std::is_same<TimeType, std::chrono::microseconds>::value) {
- return strprintf("%s: %s (%iÎĽs)", m_prefix, msg, end_time.count());
+ return strprintf("%s: %s (%iÎĽs)", m_prefix, msg, Ticks<std::chrono::microseconds>(duration));
} else if constexpr (std::is_same<TimeType, std::chrono::milliseconds>::value) {
- return strprintf("%s: %s (%.2fms)", m_prefix, msg, end_time.count() * 0.001);
+ return strprintf("%s: %s (%.2fms)", m_prefix, msg, Ticks<MillisecondsDouble>(duration));
} else if constexpr (std::is_same<TimeType, std::chrono::seconds>::value) {
- return strprintf("%s: %s (%.2fs)", m_prefix, msg, end_time.count() * 0.000001);
+ return strprintf("%s: %s (%.2fs)", m_prefix, msg, Ticks<SecondsDouble>(duration));
} else {
static_assert(ALWAYS_FALSE<TimeType>, "Error: unexpected time type");
}
}
private:
- std::chrono::microseconds m_start_t{};
+ std::optional<std::chrono::steady_clock::time_point> m_start_t{};
//! Log prefix; usually the name of the function this was created in.
const std::string m_prefix;
diff --git a/src/mapport.cpp b/src/mapport.cpp
index 975ec4da6a..e6a473c185 100644
--- a/src/mapport.cpp
+++ b/src/mapport.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/mapport.h b/src/mapport.h
index 279d65167f..6f55c46f6c 100644
--- a/src/mapport.h
+++ b/src/mapport.h
@@ -5,17 +5,9 @@
#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,
diff --git a/src/memusage.h b/src/memusage.h
index fd85a7956c..9755be0ff5 100644
--- a/src/memusage.h
+++ b/src/memusage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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.cpp b/src/net.cpp
index 374e93a2bd..98500bd30e 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1305,15 +1305,14 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
RecordBytesRecv(nBytes);
if (notify) {
size_t nSizeAdded = 0;
- auto it(pnode->vRecvMsg.begin());
- for (; it != pnode->vRecvMsg.end(); ++it) {
+ for (const auto& msg : pnode->vRecvMsg) {
// vRecvMsg contains only completed CNetMessage
// the single possible partially deserialized message are held by TransportDeserializer
- nSizeAdded += it->m_raw_message_size;
+ nSizeAdded += msg.m_raw_message_size;
}
{
LOCK(pnode->cs_vProcessMsg);
- pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
+ pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg);
pnode->nProcessQueueSize += nSizeAdded;
pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize;
}
@@ -1399,7 +1398,7 @@ void CConnman::ThreadDNSAddressSeed()
if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) {
// When -forcednsseed is provided, query all.
seeds_right_now = seeds.size();
- } else if (addrman.size() == 0) {
+ } else if (addrman.Size() == 0) {
// If we have no known peers, query all.
// This will occur on the first run, or if peers.dat has been
// deleted.
@@ -1418,13 +1417,13 @@ void CConnman::ThreadDNSAddressSeed()
// * If we continue having problems, eventually query all the
// DNS seeds, and if that fails too, also try the fixed seeds.
// (done in ThreadOpenConnections)
- const std::chrono::seconds seeds_wait_time = (addrman.size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
+ const std::chrono::seconds seeds_wait_time = (addrman.Size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
for (const std::string& seed : seeds) {
if (seeds_right_now == 0) {
seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
- if (addrman.size() > 0) {
+ if (addrman.Size() > 0) {
LogPrintf("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
std::chrono::seconds to_wait = seeds_wait_time;
while (to_wait.count() > 0) {
@@ -1504,7 +1503,7 @@ void CConnman::DumpAddresses()
DumpPeerAddresses(::gArgs, addrman);
LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat %dms\n",
- addrman.size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
+ addrman.Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
}
void CConnman::ProcessAddrFetch()
@@ -1575,6 +1574,19 @@ int CConnman::GetExtraBlockRelayCount() const
return std::max(block_relay_peers - m_max_outbound_block_relay, 0);
}
+std::unordered_set<Network> CConnman::GetReachableEmptyNetworks() const
+{
+ std::unordered_set<Network> networks{};
+ for (int n = 0; n < NET_MAX; n++) {
+ enum Network net = (enum Network)n;
+ if (net == NET_UNROUTABLE || net == NET_INTERNAL) continue;
+ if (IsReachable(net) && addrman.Size(net, std::nullopt) == 0) {
+ networks.insert(net);
+ }
+ }
+ return networks;
+}
+
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
{
SetSyscallSandboxPolicy(SyscallSandboxPolicy::NET_OPEN_CONNECTION);
@@ -1624,7 +1636,8 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
if (interruptNet)
return;
- if (add_fixed_seeds && addrman.size() == 0) {
+ const std::unordered_set<Network> fixed_seed_networks{GetReachableEmptyNetworks()};
+ if (add_fixed_seeds && !fixed_seed_networks.empty()) {
// When the node starts with an empty peers.dat, there are a few other sources of peers before
// we fallback on to fixed seeds: -dnsseed, -seednode, -addnode
// If none of those are available, we fallback on to fixed seeds immediately, else we allow
@@ -1633,7 +1646,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// It is cheapest to check if enough time has passed first.
if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
add_fixed_seeds_now = true;
- LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty\n");
+ LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
}
// Checking !dnsseed is cheaper before locking 2 mutexes.
@@ -1650,14 +1663,12 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// We will not make outgoing connections to peers that are unreachable
// (e.g. because of -onlynet configuration).
// Therefore, we do not add them to addrman in the first place.
- // Note that if you change -onlynet setting from one network to another,
- // peers.dat will contain only peers of unreachable networks and
- // manual intervention will be needed (either delete peers.dat after
- // configuration change or manually add some reachable peer using addnode),
- // see <https://github.com/bitcoin/bitcoin/issues/26035> for details.
+ // In case previously unreachable networks become reachable
+ // (e.g. in case of -onlynet changes by the user), fixed seeds will
+ // be loaded only for networks for which we have no addressses.
seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
- [](const CAddress& addr) { return !IsReachable(addr); }),
- seed_addrs.end());
+ [&fixed_seed_networks](const CAddress& addr) { return fixed_seed_networks.count(addr.GetNetwork()) == 0; }),
+ seed_addrs.end());
CNetAddr local;
local.SetInternal("fixedseeds");
addrman.Add(seed_addrs, local);
diff --git a/src/net.h b/src/net.h
index 44641fb47c..666e0f3b8a 100644
--- a/src/net.h
+++ b/src/net.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -39,6 +39,7 @@
#include <memory>
#include <optional>
#include <thread>
+#include <unordered_set>
#include <vector>
class AddrMan;
@@ -970,6 +971,12 @@ private:
void RecordBytesSent(uint64_t bytes) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex);
/**
+ Return reachable networks for which we have no addresses in addrman and therefore
+ may require loading fixed seeds.
+ */
+ std::unordered_set<Network> GetReachableEmptyNetworks() const;
+
+ /**
* Return vector of current BLOCK_RELAY peers.
*/
std::vector<CAddress> GetCurrentBlockRelayOnlyConns() const;
diff --git a/src/net_permissions.h b/src/net_permissions.h
index c9d5ec2989..b7f3bffe1c 100644
--- a/src/net_permissions.h
+++ b/src/net_permissions.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 27c426b811..a659300a0d 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -53,9 +53,6 @@
using node::ReadBlockFromDisk;
using node::ReadRawBlockFromDisk;
-using node::fImporting;
-using node::fPruneMode;
-using node::fReindex;
/** How long to cache transactions in mapRelay for normal relay */
static constexpr auto RELAY_TX_CACHE_TIME = 15min;
@@ -113,8 +110,11 @@ static constexpr auto GETDATA_TX_INTERVAL{60s};
static const unsigned int MAX_GETDATA_SZ = 1000;
/** Number of blocks that can be requested at any given time from a single peer. */
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
-/** Time during which a peer must stall block download progress before being disconnected. */
-static constexpr auto BLOCK_STALLING_TIMEOUT{2s};
+/** Default time during which a peer must stall block download progress before being disconnected.
+ * the actual timeout is increased temporarily if peers are disconnected for hitting the timeout */
+static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT{2s};
+/** Maximum timeout for stalling block download. */
+static constexpr auto BLOCK_STALLING_TIMEOUT_MAX{64s};
/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
* less than this number, we reached its tip. Changing this value is a protocol upgrade. */
static const unsigned int MAX_HEADERS_RESULTS = 2000;
@@ -584,14 +584,17 @@ private:
/**
* Reconsider orphan transactions after a parent has been accepted to the mempool.
*
- * @peer[in] peer The peer whose orphan transactions we will reconsider. Generally only one
- * orphan will be reconsidered on each call of this function. This set
- * may be added to if accepting an orphan causes its children to be
- * reconsidered.
- * @return True if there are still orphans in this peer's work set.
+ * @peer[in] peer The peer whose orphan transactions we will reconsider. Generally only
+ * one orphan will be reconsidered on each call of this function. If an
+ * accepted orphan has orphaned children, those will need to be
+ * reconsidered, creating more work, possibly for other peers.
+ * @return True if meaningful work was done (an orphan was accepted/rejected).
+ * If no meaningful work was done, then the work set for this peer
+ * will be empty.
*/
bool ProcessOrphanTx(Peer& peer)
- EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex, cs_main);
+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex);
+
/** Process a single headers message from a peer.
*
* @param[in] pfrom CNode of the peer
@@ -771,6 +774,9 @@ private:
/** Number of preferable block download peers. */
int m_num_preferred_download_peers GUARDED_BY(cs_main){0};
+ /** Stalling timeout for blocks in IBD */
+ std::atomic<std::chrono::seconds> m_block_stalling_timeout{BLOCK_STALLING_TIMEOUT_DEFAULT};
+
bool AlreadyHaveTx(const GenTxid& gtxid)
EXCLUSIVE_LOCKS_REQUIRED(cs_main, !m_recent_confirmed_transactions_mutex);
@@ -1730,8 +1736,7 @@ bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex)
std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const CBlockIndex& block_index)
{
- if (fImporting) return "Importing...";
- if (fReindex) return "Reindexing...";
+ if (m_chainman.m_blockman.LoadingBlocks()) return "Loading blocks ...";
// Ensure this peer exists and hasn't been disconnected
PeerRef peer = GetPeerRef(peer_id);
@@ -1809,7 +1814,8 @@ void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
/**
* Evict orphan txn pool entries based on a newly connected
* block, remember the recently confirmed transactions, and delete tracked
- * announcements for them. Also save the time of the last tip update.
+ * announcements for them. Also save the time of the last tip update and
+ * possibly reduce dynamic block stalling timeout.
*/
void PeerManagerImpl::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
{
@@ -1832,6 +1838,16 @@ void PeerManagerImpl::BlockConnected(const std::shared_ptr<const CBlock>& pblock
m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
}
}
+
+ // In case the dynamic timeout was doubled once or more, reduce it slowly back to its default value
+ auto stalling_timeout = m_block_stalling_timeout.load();
+ Assume(stalling_timeout >= BLOCK_STALLING_TIMEOUT_DEFAULT);
+ if (stalling_timeout != BLOCK_STALLING_TIMEOUT_DEFAULT) {
+ const auto new_timeout = std::max(std::chrono::duration_cast<std::chrono::seconds>(stalling_timeout * 0.85), BLOCK_STALLING_TIMEOUT_DEFAULT);
+ if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
+ LogPrint(BCLog::NET, "Decreased stalling timeout to %d seconds\n", count_seconds(new_timeout));
+ }
+ }
}
void PeerManagerImpl::BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex)
@@ -2897,13 +2913,11 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
{
AssertLockHeld(g_msgproc_mutex);
- AssertLockHeld(cs_main);
+ LOCK(cs_main);
CTransactionRef porphanTx = nullptr;
- NodeId from_peer = -1;
- bool more = false;
- while (CTransactionRef porphanTx = m_orphanage.GetTxToReconsider(peer.m_id, from_peer, more)) {
+ while (CTransactionRef porphanTx = m_orphanage.GetTxToReconsider(peer.m_id)) {
const MempoolAcceptResult result = m_chainman.ProcessTransaction(porphanTx);
const TxValidationState& state = result.m_state;
const uint256& orphanHash = porphanTx->GetHash();
@@ -2911,20 +2925,20 @@ bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanHash, porphanTx->GetWitnessHash());
- m_orphanage.AddChildrenToWorkSet(*porphanTx, peer.m_id);
+ m_orphanage.AddChildrenToWorkSet(*porphanTx);
m_orphanage.EraseTx(orphanHash);
for (const CTransactionRef& removedTx : result.m_replaced_transactions.value()) {
AddToCompactExtraTransactions(removedTx);
}
- break;
+ return true;
} else if (state.GetResult() != TxValidationResult::TX_MISSING_INPUTS) {
if (state.IsInvalid()) {
LogPrint(BCLog::MEMPOOL, " invalid orphan tx %s from peer=%d. %s\n",
orphanHash.ToString(),
- from_peer,
+ peer.m_id,
state.ToString());
// Maybe punish peer that gave us an invalid orphan tx
- MaybePunishNodeForTx(from_peer, state);
+ MaybePunishNodeForTx(peer.m_id, state);
}
// Has inputs but not accepted to mempool
// Probably non-standard or insufficient fee
@@ -2959,11 +2973,11 @@ bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
}
}
m_orphanage.EraseTx(orphanHash);
- break;
+ return true;
}
}
- return more;
+ return false;
}
bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& node, Peer& peer,
@@ -3303,39 +3317,20 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
m_num_preferred_download_peers += state->fPreferredDownload;
}
- // Self advertisement & GETADDR logic
- if (!pfrom.IsInboundConn() && SetupAddressRelay(pfrom, *peer)) {
- // For outbound peers, we try to relay our address (so that other
- // nodes can try to find us more quickly, as we have no guarantee
- // that an outbound peer is even aware of how to reach us) and do a
- // one-time address fetch (to help populate/update our addrman). If
- // we're starting up for the first time, our addrman may be pretty
- // empty and no one will know who we are, so these mechanisms are
- // important to help us connect to the network.
- //
+ // Attempt to initialize address relay for outbound peers and use result
+ // to decide whether to send GETADDR, so that we don't send it to
+ // inbound or outbound block-relay-only peers.
+ bool send_getaddr{false};
+ if (!pfrom.IsInboundConn()) {
+ send_getaddr = SetupAddressRelay(pfrom, *peer);
+ }
+ if (send_getaddr) {
+ // Do a one-time address fetch to help populate/update our addrman.
+ // If we're starting up for the first time, our addrman may be pretty
+ // empty, so this mechanism is important to help us connect to the network.
// We skip this for block-relay-only peers. We want to avoid
// potentially leaking addr information and we do not want to
// indicate to the peer that we will participate in addr relay.
- if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
- {
- CAddress addr{GetLocalAddress(pfrom.addr), peer->m_our_services, Now<NodeSeconds>()};
- FastRandomContext insecure_rand;
- if (addr.IsRoutable())
- {
- LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString());
- PushAddress(*peer, addr, insecure_rand);
- } else if (IsPeerAddrLocalGood(&pfrom)) {
- // Override just the address with whatever the peer sees us as.
- // Leave the port in addr as it was returned by GetLocalAddress()
- // above, as this is an outbound connection and the peer cannot
- // observe our listening port.
- addr.SetIP(addrMe);
- LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString());
- PushAddress(*peer, addr, insecure_rand);
- }
- }
-
- // Get recent addresses
m_connman.PushMessage(&pfrom, CNetMsgMaker(greatest_common_version).Make(NetMsgType::GETADDR));
peer->m_getaddr_sent = true;
// When requesting a getaddr, accept an additional MAX_ADDR_TO_SEND addresses in response
@@ -3380,7 +3375,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// If the peer is old enough to have the old alert system, send it the final alert.
if (greatest_common_version <= 70012) {
- CDataStream finalAlert(ParseHex("60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"), SER_NETWORK, PROTOCOL_VERSION);
+ DataStream finalAlert{ParseHex("60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50")};
m_connman.PushMessage(&pfrom, CNetMsgMaker(greatest_common_version).Make("alert", finalAlert));
}
@@ -3698,7 +3693,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom.GetId());
UpdateBlockAvailability(pfrom.GetId(), inv.hash);
- if (!fAlreadyHave && !fImporting && !fReindex && !IsBlockRequested(inv.hash)) {
+ if (!fAlreadyHave && !m_chainman.m_blockman.LoadingBlocks() && !IsBlockRequested(inv.hash)) {
// Headers-first is the primary method of announcement on
// the network. If a node fell back to sending blocks by
// inv, it may be for a re-org, or because we haven't
@@ -3831,8 +3826,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// If pruning, don't inv blocks unless we have on disk and are likely to still have
// for some reasonable time window (1 hour) that block relay might require.
const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / m_chainparams.GetConsensus().nPowTargetSpacing;
- if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= m_chainman.ActiveChain().Tip()->nHeight - nPrunedBlocksLikelyToHave))
- {
+ if (m_chainman.m_blockman.IsPruneMode() && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= m_chainman.ActiveChain().Tip()->nHeight - nPrunedBlocksLikelyToHave)) {
LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
break;
}
@@ -3908,7 +3902,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
}
- if (fImporting || fReindex) {
+ if (m_chainman.m_blockman.LoadingBlocks()) {
LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d while importing/reindexing\n", pfrom.GetId());
return;
}
@@ -4052,7 +4046,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
m_txrequest.ForgetTxHash(tx.GetHash());
m_txrequest.ForgetTxHash(tx.GetWitnessHash());
RelayTransaction(tx.GetHash(), tx.GetWitnessHash());
- m_orphanage.AddChildrenToWorkSet(tx, peer->m_id);
+ m_orphanage.AddChildrenToWorkSet(tx);
pfrom.m_last_tx_time = GetTime<std::chrono::seconds>();
@@ -4064,9 +4058,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
for (const CTransactionRef& removedTx : result.m_replaced_transactions.value()) {
AddToCompactExtraTransactions(removedTx);
}
-
- // Recursively process any orphan transactions that depended on this one
- ProcessOrphanTx(*peer);
}
else if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS)
{
@@ -4190,7 +4181,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (msg_type == NetMsgType::CMPCTBLOCK)
{
// Ignore cmpctblock received while importing
- if (fImporting || fReindex) {
+ if (m_chainman.m_blockman.LoadingBlocks()) {
LogPrint(BCLog::NET, "Unexpected cmpctblock message received from peer %d\n", pfrom.GetId());
return;
}
@@ -4406,7 +4397,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (msg_type == NetMsgType::BLOCKTXN)
{
// Ignore blocktxn received while importing
- if (fImporting || fReindex) {
+ if (m_chainman.m_blockman.LoadingBlocks()) {
LogPrint(BCLog::NET, "Unexpected blocktxn message received from peer %d\n", pfrom.GetId());
return;
}
@@ -4481,7 +4472,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (msg_type == NetMsgType::HEADERS)
{
// Ignore headers received while importing
- if (fImporting || fReindex) {
+ if (m_chainman.m_blockman.LoadingBlocks()) {
LogPrint(BCLog::NET, "Unexpected headers message received from peer %d\n", pfrom.GetId());
return;
}
@@ -4526,7 +4517,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (msg_type == NetMsgType::BLOCK)
{
// Ignore block received while importing
- if (fImporting || fReindex) {
+ if (m_chainman.m_blockman.LoadingBlocks()) {
LogPrint(BCLog::NET, "Unexpected block message received from peer %d\n", pfrom.GetId());
return;
}
@@ -4875,16 +4866,12 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
}
}
- bool has_more_orphans;
- {
- LOCK(cs_main);
- has_more_orphans = ProcessOrphanTx(*peer);
- }
+ const bool processed_orphan = ProcessOrphanTx(*peer);
if (pfrom->fDisconnect)
return false;
- if (has_more_orphans) return true;
+ if (processed_orphan) return true;
// this maintains the order of responses
// and prevents m_getdata_requests to grow unbounded
@@ -4930,6 +4917,12 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
LOCK(peer->m_getdata_requests_mutex);
if (!peer->m_getdata_requests.empty()) fMoreWork = true;
}
+ // Does this peer has an orphan ready to reconsider?
+ // (Note: we may have provided a parent for an orphan provided
+ // by another peer that was already processed; in that case,
+ // the extra work may not be noticed, possibly resulting in an
+ // unnecessary 100ms delay)
+ if (m_orphanage.HaveTxToReconsider(peer->m_id)) fMoreWork = true;
} catch (const std::exception& e) {
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' (%s) caught\n", __func__, SanitizeString(msg.m_type), msg.m_message_size, e.what(), typeid(e).name());
} catch (...) {
@@ -5111,7 +5104,7 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
if (now > m_stale_tip_check_time) {
// Check whether our tip is stale, and if so, allow using an extra
// outbound peer
- if (!fImporting && !fReindex && m_connman.GetNetworkActive() && m_connman.GetUseAddrmanOutgoing() && TipMayBeStale()) {
+ if (!m_chainman.m_blockman.LoadingBlocks() && m_connman.GetNetworkActive() && m_connman.GetUseAddrmanOutgoing() && TipMayBeStale()) {
LogPrintf("Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
count_seconds(now - m_last_tip_update.load()));
m_connman.SetTryNewOutboundPeer(true);
@@ -5342,8 +5335,9 @@ bool PeerManagerImpl::SetupAddressRelay(const CNode& node, Peer& peer)
if (node.IsBlockOnlyConn()) return false;
if (!peer.m_addr_relay_enabled.exchange(true)) {
- // First addr message we have received from the peer, initialize
- // m_addr_known
+ // During version message processing (non-block-relay-only outbound peers)
+ // or on first addr-related message we have received (inbound peers), initialize
+ // m_addr_known.
peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
}
@@ -5417,7 +5411,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
}
}
- if (!state.fSyncStarted && CanServeBlocks(*peer) && !fImporting && !fReindex) {
+ if (!state.fSyncStarted && CanServeBlocks(*peer) && !m_chainman.m_blockman.LoadingBlocks()) {
// Only actively request headers from a single peer, unless we're close to today.
if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() > GetAdjustedTime() - 24h) {
const CBlockIndex* pindexStart = m_chainman.m_best_header;
@@ -5731,12 +5725,19 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
// Detect whether we're stalling
- if (state.m_stalling_since.count() && state.m_stalling_since < current_time - BLOCK_STALLING_TIMEOUT) {
+ auto stalling_timeout = m_block_stalling_timeout.load();
+ if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
// Stalling only triggers when the block download window cannot move. During normal steady state,
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
// should only happen during initial block download.
LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->GetId());
pto->fDisconnect = true;
+ // Increase timeout for the next peer so that we don't disconnect multiple peers if our own
+ // bandwidth is insufficient.
+ const auto new_timeout = std::min(2 * stalling_timeout, BLOCK_STALLING_TIMEOUT_MAX);
+ if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
+ LogPrint(BCLog::NET, "Increased stalling timeout temporarily to %d seconds\n", count_seconds(new_timeout));
+ }
return true;
}
// In case there is a block that has been in flight from this peer for block_interval * (1 + 0.5 * N)
diff --git a/src/net_processing.h b/src/net_processing.h
index 0d0842fa8e..af9a02139b 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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_types.cpp b/src/net_types.cpp
index 90346715f0..2cdc10d8c9 100644
--- a/src/net_types.cpp
+++ b/src/net_types.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/netaddress.cpp b/src/netaddress.cpp
index eabab3dd99..782b692d30 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,7 +179,7 @@ bool CNetAddr::SetInternal(const std::string &name)
}
namespace torv3 {
-// https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt#n2135
+// https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt?id=7116c9cdaba248aae07a3f1d0e15d9dd102f62c5#n2175
static constexpr size_t CHECKSUM_LEN = 2;
static const unsigned char VERSION[] = {3};
static constexpr size_t TOTAL_LEN = ADDR_TORV3_SIZE + CHECKSUM_LEN + sizeof(VERSION);
diff --git a/src/netaddress.h b/src/netaddress.h
index 11086eaee0..7f782674d3 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/netbase.cpp b/src/netbase.cpp
index 8169b40ea6..fac4b3b5d5 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/netbase.h b/src/netbase.h
index f7816f5d1d..a43f22f240 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/netgroup.cpp b/src/netgroup.cpp
index 96b5e29684..87a1c4e036 100644
--- a/src/netgroup.cpp
+++ b/src/netgroup.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/blockstorage.cpp b/src/node/blockstorage.cpp
index 04d46f4361..a81099a26c 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -352,7 +352,7 @@ bool BlockManager::LoadBlockIndexDB(const Consensus::Params& consensus_params)
}
for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) {
FlatFilePos pos(*it, 0);
- if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) {
+ if (AutoFile{OpenBlockFile(pos, true)}.IsNull()) {
return false;
}
}
@@ -454,13 +454,13 @@ CBlockFileInfo* BlockManager::GetBlockFileInfo(size_t n)
static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
{
// Open history file to append
- CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
+ AutoFile fileout{OpenUndoFile(pos)};
if (fileout.IsNull()) {
return error("%s: OpenUndoFile failed", __func__);
}
// Write index header
- unsigned int nSize = GetSerializeSize(blockundo, fileout.GetVersion());
+ unsigned int nSize = GetSerializeSize(blockundo, CLIENT_VERSION);
fileout << messageStart << nSize;
// Write undo data
@@ -489,14 +489,14 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex)
}
// Open history file to read
- CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
+ AutoFile filein{OpenUndoFile(pos, true)};
if (filein.IsNull()) {
return error("%s: OpenUndoFile failed", __func__);
}
// Read block
uint256 hashChecksum;
- CHashVerifier<CAutoFile> verifier(&filein); // We need a CHashVerifier as reserializing may lose data
+ HashVerifier verifier{filein}; // Use HashVerifier as reserializing may lose data, c.f. commit d342424301013ec47dc146a4beb49d5c9319d80a
try {
verifier << pindex->pprev->GetBlockHash();
verifier >> blockundo;
@@ -768,7 +768,7 @@ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, c
{
FlatFilePos hpos = pos;
hpos.nPos -= 8; // Seek back 8 bytes for meta header
- CAutoFile filein(OpenBlockFile(hpos, true), SER_DISK, CLIENT_VERSION);
+ AutoFile filein{OpenBlockFile(hpos, true)};
if (filein.IsNull()) {
return error("%s: OpenBlockFile failed for %s", __func__, pos.ToString());
}
diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h
index 29501c1959..b6007897df 100644
--- a/src/node/blockstorage.h
+++ b/src/node/blockstorage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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,7 @@
#include <attributes.h>
#include <chain.h>
#include <fs.h>
+#include <kernel/cs_main.h>
#include <protocol.h>
#include <sync.h>
#include <txdb.h>
@@ -17,8 +18,6 @@
#include <unordered_map>
#include <vector>
-extern RecursiveMutex cs_main;
-
class ArgsManager;
class BlockValidationState;
class CBlock;
@@ -49,10 +48,7 @@ static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = CMessageHeader::MESSAG
extern std::atomic_bool fImporting;
extern std::atomic_bool fReindex;
-/** Pruning-related variables and constants */
-/** True if we're running in -prune mode. */
extern bool fPruneMode;
-/** Number of bytes of block files that we're trying to stay below. */
extern uint64_t nPruneTarget;
// Because validation code takes pointers to the map's CBlockIndex objects, if
@@ -177,6 +173,17 @@ public:
/** Store block on disk. If dbp is not nullptr, then it provides the known position of the block within a block file on disk. */
FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp);
+ /** Whether running in -prune mode. */
+ [[nodiscard]] bool IsPruneMode() const { return fPruneMode; }
+
+ /** Attempt to stay below this number of bytes of block files. */
+ [[nodiscard]] uint64_t GetPruneTarget() const { return nPruneTarget; }
+
+ [[nodiscard]] bool LoadingBlocks() const
+ {
+ return fImporting || fReindex;
+ }
+
/** Calculate the amount of disk space the block & undo files currently use */
uint64_t CalculateCurrentUsage();
diff --git a/src/node/caches.cpp b/src/node/caches.cpp
index a39ad7aeb6..7622a03e19 100644
--- a/src/node/caches.cpp
+++ b/src/node/caches.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/chainstate.cpp b/src/node/chainstate.cpp
index 60acb614b4..ba1024d22e 100644
--- a/src/node/chainstate.cpp
+++ b/src/node/chainstate.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -44,10 +44,10 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
if (chainman.MinimumChainWork() < UintToArith256(chainman.GetConsensus().nMinimumChainWork)) {
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainman.GetConsensus().nMinimumChainWork.GetHex());
}
- if (nPruneTarget == std::numeric_limits<uint64_t>::max()) {
+ if (chainman.m_blockman.GetPruneTarget() == std::numeric_limits<uint64_t>::max()) {
LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
- } else if (nPruneTarget) {
- LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);
+ } else if (chainman.m_blockman.GetPruneTarget()) {
+ LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", chainman.m_blockman.GetPruneTarget() / 1024 / 1024);
}
LOCK(cs_main);
diff --git a/src/node/chainstate.h b/src/node/chainstate.h
index 2289310ece..d3c7656bf2 100644
--- a/src/node/chainstate.h
+++ b/src/node/chainstate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/coin.h b/src/node/coin.h
index 3d534463e8..b32e410e1c 100644
--- a/src/node/coin.h
+++ b/src/node/coin.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-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.
diff --git a/src/node/context.cpp b/src/node/context.cpp
index d80b8ca7a7..af59ab932b 100644
--- a/src/node/context.cpp
+++ b/src/node/context.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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.h b/src/node/context.h
index 31be308787..84f4053c84 100644
--- a/src/node/context.h
+++ b/src/node/context.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/interface_ui.cpp b/src/node/interface_ui.cpp
index fa90d6fda7..08d1e03541 100644
--- a/src/node/interface_ui.cpp
+++ b/src/node/interface_ui.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2010-2021 The Bitcoin Core developers
+// Copyright (c) 2010-2022 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/interface_ui.h b/src/node/interface_ui.h
index 316d75167e..9f6503b4a1 100644
--- a/src/node/interface_ui.h
+++ b/src/node/interface_ui.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/interfaces.cpp b/src/node/interfaces.cpp
index 7a15f3649b..eda359568f 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -420,11 +420,11 @@ public:
virtual ~NotificationsProxy() = default;
void TransactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override
{
- m_notifications->transactionAddedToMempool(tx, mempool_sequence);
+ m_notifications->transactionAddedToMempool(tx);
}
void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
{
- m_notifications->transactionRemovedFromMempool(tx, reason, mempool_sequence);
+ m_notifications->transactionRemovedFromMempool(tx, reason);
}
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
{
@@ -672,12 +672,9 @@ public:
if (!m_node.mempool) return true;
LockPoints lp;
CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp);
- CTxMemPool::setEntries ancestors;
const CTxMemPool::Limits& limits{m_node.mempool->m_limits};
- std::string unused_error_string;
LOCK(m_node.mempool->cs);
- return m_node.mempool->CalculateMemPoolAncestors(
- entry, ancestors, limits, unused_error_string);
+ return m_node.mempool->CalculateMemPoolAncestors(entry, limits).has_value();
}
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
{
@@ -714,8 +711,9 @@ public:
LOCK(::cs_main);
return chainman().m_blockman.m_have_pruned;
}
- bool isReadyToBroadcast() override { return !node::fImporting && !node::fReindex && !isInitialBlockDownload(); }
- bool isInitialBlockDownload() override {
+ bool isReadyToBroadcast() override { return !chainman().m_blockman.LoadingBlocks() && !isInitialBlockDownload(); }
+ bool isInitialBlockDownload() override
+ {
return chainman().ActiveChainstate().IsInitialBlockDownload();
}
bool shutdownRequested() override { return ShutdownRequested(); }
@@ -779,7 +777,7 @@ public:
if (!m_node.mempool) return;
LOCK2(::cs_main, m_node.mempool->cs);
for (const CTxMemPoolEntry& entry : m_node.mempool->mapTx) {
- notifications.transactionAddedToMempool(entry.GetSharedTx(), 0 /* mempool_sequence */);
+ notifications.transactionAddedToMempool(entry.GetSharedTx());
}
}
bool hasAssumedValidChain() override
diff --git a/src/node/miner.cpp b/src/node/miner.cpp
index e11ec5b0f1..c2b6fd1dc3 100644
--- a/src/node/miner.cpp
+++ b/src/node/miner.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -60,10 +60,12 @@ BlockAssembler::Options::Options()
{
blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
+ test_block_validity = true;
}
BlockAssembler::BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options)
- : chainparams{chainstate.m_chainman.GetParams()},
+ : test_block_validity{options.test_block_validity},
+ chainparams{chainstate.m_chainman.GetParams()},
m_mempool(mempool),
m_chainstate(chainstate)
{
@@ -72,11 +74,10 @@ BlockAssembler::BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool
nBlockMaxWeight = std::max<size_t>(4000, std::min<size_t>(MAX_BLOCK_WEIGHT - 4000, options.nBlockMaxWeight));
}
-static BlockAssembler::Options DefaultOptions()
+void ApplyArgsManOptions(const ArgsManager& gArgs, BlockAssembler::Options& options)
{
// Block resource limits
// If -blockmaxweight is not given, limit to DEFAULT_BLOCK_MAX_WEIGHT
- BlockAssembler::Options options;
options.nBlockMaxWeight = gArgs.GetIntArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
if (gArgs.IsArgSet("-blockmintxfee")) {
std::optional<CAmount> parsed = ParseMoney(gArgs.GetArg("-blockmintxfee", ""));
@@ -84,11 +85,16 @@ static BlockAssembler::Options DefaultOptions()
} else {
options.blockMinFeeRate = CFeeRate{DEFAULT_BLOCK_MIN_TX_FEE};
}
+}
+static BlockAssembler::Options ConfiguredOptions()
+{
+ BlockAssembler::Options options;
+ ApplyArgsManOptions(gArgs, options);
return options;
}
BlockAssembler::BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool)
- : BlockAssembler(chainstate, mempool, DefaultOptions()) {}
+ : BlockAssembler(chainstate, mempool, ConfiguredOptions()) {}
void BlockAssembler::resetBlock()
{
@@ -170,7 +176,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
BlockValidationState state;
- if (!TestBlockValidity(state, chainparams, m_chainstate, *pblock, pindexPrev, GetAdjustedTime, false, false)) {
+ if (test_block_validity && !TestBlockValidity(state, chainparams, m_chainstate, *pblock, pindexPrev,
+ GetAdjustedTime, /*fCheckPOW=*/false, /*fCheckMerkleRoot=*/false)) {
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
}
const auto time_2{SteadyClock::now()};
@@ -394,9 +401,7 @@ void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSele
continue;
}
- CTxMemPool::setEntries ancestors;
- std::string dummy;
- mempool.CalculateMemPoolAncestors(*iter, ancestors, CTxMemPool::Limits::NoLimits(), dummy, false);
+ auto ancestors{mempool.AssumeCalculateMemPoolAncestors(__func__, *iter, CTxMemPool::Limits::NoLimits(), /*fSearchForParents=*/false)};
onlyUnconfirmed(ancestors);
ancestors.insert(iter);
diff --git a/src/node/miner.h b/src/node/miner.h
index 7269ce1186..ea9e470a64 100644
--- a/src/node/miner.h
+++ b/src/node/miner.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,6 +16,7 @@
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
+class ArgsManager;
class ChainstateManager;
class CBlockIndex;
class CChainParams;
@@ -135,6 +136,9 @@ private:
unsigned int nBlockMaxWeight;
CFeeRate blockMinFeeRate;
+ // Whether to call TestBlockValidity() at the end of CreateNewBlock().
+ const bool test_block_validity;
+
// Information on the current status of the block
uint64_t nBlockWeight;
uint64_t nBlockTx;
@@ -155,6 +159,7 @@ public:
Options();
size_t nBlockMaxWeight;
CFeeRate blockMinFeeRate;
+ bool test_block_validity;
};
explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool);
@@ -197,6 +202,9 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
void RegenerateCommitments(CBlock& block, ChainstateManager& chainman);
+
+/** Apply -blockmintxfee and -blockmaxweight options from ArgsManager to BlockAssembler options. */
+void ApplyArgsManOptions(const ArgsManager& gArgs, BlockAssembler::Options& options);
} // namespace node
#endif // BITCOIN_NODE_MINER_H
diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp
index ca3fc0955d..51e252bffc 100644
--- a/src/node/psbt.cpp
+++ b/src/node/psbt.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/transaction.h b/src/node/transaction.h
index 0604754a46..45f174f13c 100644
--- a/src/node/transaction.h
+++ b/src/node/transaction.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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.cpp b/src/node/utxo_snapshot.cpp
index bab1b75211..cccf95e552 100644
--- a/src/node/utxo_snapshot.cpp
+++ b/src/node/utxo_snapshot.cpp
@@ -7,12 +7,17 @@
#include <fs.h>
#include <logging.h>
#include <streams.h>
+#include <sync.h>
+#include <tinyformat.h>
+#include <txdb.h>
#include <uint256.h>
#include <util/system.h>
#include <validation.h>
+#include <cassert>
#include <cstdio>
#include <optional>
+#include <string>
namespace node {
diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h
index c94521792f..c5c018c9e8 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-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,13 +7,16 @@
#define BITCOIN_NODE_UTXO_SNAPSHOT_H
#include <fs.h>
-#include <uint256.h>
+#include <kernel/cs_main.h>
#include <serialize.h>
-#include <validation.h>
+#include <sync.h>
+#include <uint256.h>
+#include <cstdint>
#include <optional>
+#include <string_view>
-extern RecursiveMutex cs_main;
+class Chainstate;
namespace node {
//! Metadata describing a serialized version of a UTXO set from which an
diff --git a/src/noui.cpp b/src/noui.cpp
index 54cb5f3cbf..af5a180ce3 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/outputtype.cpp b/src/outputtype.cpp
index 9ab2902256..270212dca5 100644
--- a/src/outputtype.cpp
+++ b/src/outputtype.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/outputtype.h b/src/outputtype.h
index c59262591b..7c50f445fc 100644
--- a/src/outputtype.h
+++ b/src/outputtype.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.cpp b/src/policy/feerate.cpp
index 82b767793d..eb0cba5c67 100644
--- a/src/policy/feerate.cpp
+++ b/src/policy/feerate.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 a8d4d2fc63..6f859e2d0d 100644
--- a/src/policy/feerate.h
+++ b/src/policy/feerate.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 1cd9624000..d244de1bb2 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -528,7 +528,7 @@ bool CBlockPolicyEstimator::_removeTx(const uint256& hash, bool inBlock)
}
CBlockPolicyEstimator::CBlockPolicyEstimator(const fs::path& estimation_filepath)
- : m_estimation_filepath{estimation_filepath}, nBestSeenHeight{0}, firstRecordedHeight{0}, historicalFirst{0}, historicalBest{0}, trackedTxs{0}, untrackedTxs{0}
+ : m_estimation_filepath{estimation_filepath}
{
static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
size_t bucketIndex = 0;
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 204c4f2118..1c24b8c7c3 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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_POLICY_FEES_H
@@ -242,16 +242,16 @@ public:
private:
mutable Mutex m_cs_fee_estimator;
- unsigned int nBestSeenHeight GUARDED_BY(m_cs_fee_estimator);
- unsigned int firstRecordedHeight GUARDED_BY(m_cs_fee_estimator);
- unsigned int historicalFirst GUARDED_BY(m_cs_fee_estimator);
- unsigned int historicalBest GUARDED_BY(m_cs_fee_estimator);
+ unsigned int nBestSeenHeight GUARDED_BY(m_cs_fee_estimator){0};
+ unsigned int firstRecordedHeight GUARDED_BY(m_cs_fee_estimator){0};
+ unsigned int historicalFirst GUARDED_BY(m_cs_fee_estimator){0};
+ unsigned int historicalBest GUARDED_BY(m_cs_fee_estimator){0};
struct TxStatsInfo
{
- unsigned int blockHeight;
- unsigned int bucketIndex;
- TxStatsInfo() : blockHeight(0), bucketIndex(0) {}
+ unsigned int blockHeight{0};
+ unsigned int bucketIndex{0};
+ TxStatsInfo() {}
};
// map of txids to information about that transaction
@@ -262,8 +262,8 @@ private:
std::unique_ptr<TxConfirmStats> shortStats PT_GUARDED_BY(m_cs_fee_estimator);
std::unique_ptr<TxConfirmStats> longStats PT_GUARDED_BY(m_cs_fee_estimator);
- unsigned int trackedTxs GUARDED_BY(m_cs_fee_estimator);
- unsigned int untrackedTxs GUARDED_BY(m_cs_fee_estimator);
+ unsigned int trackedTxs GUARDED_BY(m_cs_fee_estimator){0};
+ unsigned int untrackedTxs GUARDED_BY(m_cs_fee_estimator){0};
std::vector<double> buckets GUARDED_BY(m_cs_fee_estimator); // The upper-bound of the range for the bucket (inclusive)
std::map<double, unsigned int> bucketMap GUARDED_BY(m_cs_fee_estimator); // Map of bucket upper-bound to index into all vectors by bucket
diff --git a/src/policy/fees_args.cpp b/src/policy/fees_args.cpp
index a3531153b5..1aeb2ab983 100644
--- a/src/policy/fees_args.cpp
+++ b/src/policy/fees_args.cpp
@@ -1,3 +1,7 @@
+// Copyright (c) 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.
+
#include <policy/fees_args.h>
#include <util/system.h>
diff --git a/src/policy/packages.cpp b/src/policy/packages.cpp
index 67918c9dec..6e70a94088 100644
--- a/src/policy/packages.cpp
+++ b/src/policy/packages.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/packages.h b/src/policy/packages.h
index 36c70e9e66..0a0e7cf6bb 100644
--- a/src/policy/packages.h
+++ b/src/policy/packages.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/policy.cpp b/src/policy/policy.cpp
index 5086542865..41b5b2d0f1 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/policy.h b/src/policy/policy.h
index 29764ea2d9..394fb34230 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -25,8 +25,8 @@ static constexpr unsigned int DEFAULT_BLOCK_MAX_WEIGHT{MAX_BLOCK_WEIGHT - 4000};
static constexpr unsigned int DEFAULT_BLOCK_MIN_TX_FEE{1000};
/** The maximum weight for transactions we're willing to relay/mine */
static constexpr unsigned int MAX_STANDARD_TX_WEIGHT{400000};
-/** The minimum non-witness size for transactions we're willing to relay/mine (1 segwit input + 1 P2WPKH output = 82 bytes) */
-static constexpr unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE{82};
+/** The minimum non-witness size for transactions we're willing to relay/mine: one larger than 64 */
+static constexpr unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE{65};
/** Maximum number of signature check operations in an IsStandard() P2SH script */
static constexpr unsigned int MAX_P2SH_SIGOPS{15};
/** The maximum number of sigops we're willing to relay/mine in a single tx */
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index 3a347b41ed..d032b74008 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -22,8 +22,6 @@ RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
{
AssertLockHeld(pool.cs);
- CTxMemPool::setEntries ancestors;
-
// First check the transaction itself.
if (SignalsOptInRBF(tx)) {
return RBFTransactionState::REPLACEABLE_BIP125;
@@ -37,9 +35,9 @@ RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
// If all the inputs have nSequence >= maxint-1, it still might be
// signaled for RBF if any unconfirmed parents have signaled.
- std::string dummy;
- CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
- pool.CalculateMemPoolAncestors(entry, ancestors, CTxMemPool::Limits::NoLimits(), dummy, false);
+ const CTxMemPoolEntry entry{*pool.mapTx.find(tx.GetHash())};
+ auto ancestors{pool.AssumeCalculateMemPoolAncestors(__func__, entry, CTxMemPool::Limits::NoLimits(),
+ /*fSearchForParents=*/false)};
for (CTxMemPool::txiter it : ancestors) {
if (SignalsOptInRBF(it->GetTx())) {
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index 28c4e4bf9b..fff9828482 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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/settings.cpp b/src/policy/settings.cpp
index 39e00f1111..722b12acf5 100644
--- a/src/policy/settings.cpp
+++ b/src/policy/settings.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/settings.h b/src/policy/settings.h
index f0d6f779ae..145454b0dd 100644
--- a/src/policy/settings.h
+++ b/src/policy/settings.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/pow.cpp b/src/pow.cpp
index c0449cac74..1e8d53de8b 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/pow.h b/src/pow.h
index 44b9d673ef..ec03f318a4 100644
--- a/src/pow.h
+++ b/src/pow.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/prevector.h b/src/prevector.h
index 7df5a067a2..f36cfe4ff6 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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 2e26e6c426..bd11279a6e 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 ec48194ee9..3060746909 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.h b/src/primitives/transaction.h
index f496ea022e..bd7eb16bec 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -17,6 +17,7 @@
#include <ios>
#include <limits>
#include <memory>
+#include <numeric>
#include <string>
#include <tuple>
#include <utility>
@@ -280,6 +281,12 @@ inline void SerializeTransaction(const TxType& tx, Stream& s) {
s << tx.nLockTime;
}
+template<typename TxType>
+inline CAmount CalculateOutputValue(const TxType& tx)
+{
+ return std::accumulate(tx.vout.cbegin(), tx.vout.cend(), CAmount{0}, [](CAmount sum, const auto& txout) { return sum + txout.nValue; });
+}
+
/** The basic transaction that is broadcasted on the network and contained in
* blocks. A transaction can contain multiple inputs and outputs.
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 23c68b335b..aa59bae6ff 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/protocol.h b/src/protocol.h
index 51fabf8da0..cbcd400fef 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/psbt.cpp b/src/psbt.cpp
index 461987c503..50ccd9e2c0 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/psbt.h b/src/psbt.h
index f1f04cccef..d848c9dd49 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -178,7 +178,7 @@ void SerializeHDKeypath(Stream& s, KeyOriginInfo hd_keypath)
template<typename Stream>
void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, KeyOriginInfo>& hd_keypaths, CompactSizeWriter type)
{
- for (auto keypath_pair : hd_keypaths) {
+ for (const auto& keypath_pair : hd_keypaths) {
if (!keypath_pair.first.IsValid()) {
throw std::ios_base::failure("Invalid CPubKey being serialized");
}
@@ -206,7 +206,7 @@ struct PSBTInput
// Taproot fields
std::vector<unsigned char> m_tap_key_sig;
std::map<std::pair<XOnlyPubKey, uint256>, std::vector<unsigned char>> m_tap_script_sigs;
- std::map<std::pair<CScript, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> m_tap_scripts;
+ std::map<std::pair<std::vector<unsigned char>, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> m_tap_scripts;
std::map<XOnlyPubKey, std::pair<std::set<uint256>, KeyOriginInfo>> m_tap_bip32_paths;
XOnlyPubKey m_tap_internal_key;
uint256 m_tap_merkle_root;
@@ -621,7 +621,7 @@ struct PSBTInput
}
uint8_t leaf_ver = script_v.back();
script_v.pop_back();
- const auto leaf_script = std::make_pair(CScript(script_v.begin(), script_v.end()), (int)leaf_ver);
+ const auto leaf_script = std::make_pair(script_v, (int)leaf_ver);
m_tap_scripts[leaf_script].insert(std::vector<unsigned char>(key.begin() + 1, key.end()));
break;
}
@@ -713,7 +713,7 @@ struct PSBTOutput
CScript witness_script;
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
XOnlyPubKey m_tap_internal_key;
- std::vector<std::tuple<uint8_t, uint8_t, CScript>> m_tap_tree;
+ std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> m_tap_tree;
std::map<XOnlyPubKey, std::pair<std::set<uint256>, KeyOriginInfo>> m_tap_bip32_paths;
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
std::set<PSBTProprietary> m_proprietary;
@@ -864,7 +864,7 @@ struct PSBTOutput
while (!s_tree.empty()) {
uint8_t depth;
uint8_t leaf_ver;
- CScript script;
+ std::vector<unsigned char> script;
s_tree >> depth;
s_tree >> leaf_ver;
s_tree >> script;
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index 2e37e16690..ae5dccfb5a 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.
@@ -16,10 +16,16 @@
#include <algorithm>
#include <cassert>
-namespace
+namespace {
+
+struct Secp256k1SelfTester
{
-/* Global secp256k1_context object used for verification. */
-secp256k1_context* secp256k1_context_verify = nullptr;
+ Secp256k1SelfTester() {
+ /* Run libsecp256k1 self-test before using the secp256k1_context_static. */
+ secp256k1_selftest();
+ }
+} SECP256K1_SELFTESTER;
+
} // namespace
/** This function is taken from the libsecp256k1 distribution and implements
@@ -32,7 +38,7 @@ secp256k1_context* secp256k1_context_verify = nullptr;
* strict DER before being passed to this module, and we know it supports all
* violations present in the blockchain before that point.
*/
-int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
+int ecdsa_signature_parse_der_lax(secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
size_t rpos, rlen, spos, slen;
size_t pos = 0;
size_t lenbyte;
@@ -40,7 +46,7 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_
int overflow = 0;
/* Hack to initialize sig with a correctly-parsed but invalid signature. */
- secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
+ secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static, sig, tmpsig);
/* Sequence tag byte */
if (pos == inputlen || input[pos] != 0x30) {
@@ -163,13 +169,13 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_
}
if (!overflow) {
- overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
+ overflow = !secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static, sig, tmpsig);
}
if (overflow) {
/* Overwrite the result again with a correctly-parsed but invalid
signature if parsing failed. */
memset(tmpsig, 0, 64);
- secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
+ secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static, sig, tmpsig);
}
return 1;
}
@@ -200,15 +206,15 @@ std::vector<CKeyID> XOnlyPubKey::GetKeyIDs() const
bool XOnlyPubKey::IsFullyValid() const
{
secp256k1_xonly_pubkey pubkey;
- return secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &pubkey, m_keydata.data());
+ return secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey, m_keydata.data());
}
bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const
{
assert(sigbytes.size() == 64);
secp256k1_xonly_pubkey pubkey;
- if (!secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &pubkey, m_keydata.data())) return false;
- return secp256k1_schnorrsig_verify(secp256k1_context_verify, sigbytes.data(), msg.begin(), 32, &pubkey);
+ if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey, m_keydata.data())) return false;
+ return secp256k1_schnorrsig_verify(secp256k1_context_static, sigbytes.data(), msg.begin(), 32, &pubkey);
}
static const HashWriter HASHER_TAPTWEAK{TaggedHash("TapTweak")};
@@ -227,23 +233,23 @@ uint256 XOnlyPubKey::ComputeTapTweakHash(const uint256* merkle_root) const
bool XOnlyPubKey::CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const
{
secp256k1_xonly_pubkey internal_key;
- if (!secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &internal_key, internal.data())) return false;
+ if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &internal_key, internal.data())) return false;
uint256 tweak = internal.ComputeTapTweakHash(&merkle_root);
- return secp256k1_xonly_pubkey_tweak_add_check(secp256k1_context_verify, m_keydata.begin(), parity, &internal_key, tweak.begin());
+ return secp256k1_xonly_pubkey_tweak_add_check(secp256k1_context_static, m_keydata.begin(), parity, &internal_key, tweak.begin());
}
std::optional<std::pair<XOnlyPubKey, bool>> XOnlyPubKey::CreateTapTweak(const uint256* merkle_root) const
{
secp256k1_xonly_pubkey base_point;
- if (!secp256k1_xonly_pubkey_parse(secp256k1_context_verify, &base_point, data())) return std::nullopt;
+ if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &base_point, data())) return std::nullopt;
secp256k1_pubkey out;
uint256 tweak = ComputeTapTweakHash(merkle_root);
- if (!secp256k1_xonly_pubkey_tweak_add(secp256k1_context_verify, &out, &base_point, tweak.data())) return std::nullopt;
+ if (!secp256k1_xonly_pubkey_tweak_add(secp256k1_context_static, &out, &base_point, tweak.data())) return std::nullopt;
int parity = -1;
std::pair<XOnlyPubKey, bool> ret;
secp256k1_xonly_pubkey out_xonly;
- if (!secp256k1_xonly_pubkey_from_pubkey(secp256k1_context_verify, &out_xonly, &parity, &out)) return std::nullopt;
- secp256k1_xonly_pubkey_serialize(secp256k1_context_verify, ret.first.begin(), &out_xonly);
+ if (!secp256k1_xonly_pubkey_from_pubkey(secp256k1_context_static, &out_xonly, &parity, &out)) return std::nullopt;
+ secp256k1_xonly_pubkey_serialize(secp256k1_context_static, ret.first.begin(), &out_xonly);
assert(parity == 0 || parity == 1);
ret.second = parity;
return ret;
@@ -255,17 +261,16 @@ bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchS
return false;
secp256k1_pubkey pubkey;
secp256k1_ecdsa_signature sig;
- assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
- if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) {
+ if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size())) {
return false;
}
- if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) {
+ if (!ecdsa_signature_parse_der_lax(&sig, vchSig.data(), vchSig.size())) {
return false;
}
/* libsecp256k1's ECDSA verification requires lower-S signatures, which have
* not historically been enforced in Bitcoin, so normalize them first. */
- secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, &sig, &sig);
- return secp256k1_ecdsa_verify(secp256k1_context_verify, &sig, hash.begin(), &pubkey);
+ secp256k1_ecdsa_signature_normalize(secp256k1_context_static, &sig, &sig);
+ return secp256k1_ecdsa_verify(secp256k1_context_static, &sig, hash.begin(), &pubkey);
}
bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
@@ -275,16 +280,15 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned cha
bool fComp = ((vchSig[0] - 27) & 4) != 0;
secp256k1_pubkey pubkey;
secp256k1_ecdsa_recoverable_signature sig;
- assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
- if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_verify, &sig, &vchSig[1], recid)) {
+ if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_static, &sig, &vchSig[1], recid)) {
return false;
}
- if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) {
+ if (!secp256k1_ecdsa_recover(secp256k1_context_static, &pubkey, &sig, hash.begin())) {
return false;
}
unsigned char pub[SIZE];
size_t publen = SIZE;
- secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
+ secp256k1_ec_pubkey_serialize(secp256k1_context_static, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
Set(pub, pub + publen);
return true;
}
@@ -293,21 +297,19 @@ bool CPubKey::IsFullyValid() const {
if (!IsValid())
return false;
secp256k1_pubkey pubkey;
- assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
- return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size());
+ return secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size());
}
bool CPubKey::Decompress() {
if (!IsValid())
return false;
secp256k1_pubkey pubkey;
- assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
- if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) {
+ if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size())) {
return false;
}
unsigned char pub[SIZE];
size_t publen = SIZE;
- secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
+ secp256k1_ec_pubkey_serialize(secp256k1_context_static, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
Set(pub, pub + publen);
return true;
}
@@ -320,16 +322,15 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi
BIP32Hash(cc, nChild, *begin(), begin()+1, out);
memcpy(ccChild.begin(), out+32, 32);
secp256k1_pubkey pubkey;
- assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
- if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch, size())) {
+ if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, vch, size())) {
return false;
}
- if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) {
+ if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_static, &pubkey, out)) {
return false;
}
unsigned char pub[COMPRESSED_SIZE];
size_t publen = COMPRESSED_SIZE;
- secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED);
+ secp256k1_ec_pubkey_serialize(secp256k1_context_static, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED);
pubkeyChild.Set(pub, pub + publen);
return true;
}
@@ -375,35 +376,8 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
secp256k1_ecdsa_signature sig;
- assert(secp256k1_context_verify && "secp256k1_context_verify must be initialized to use CPubKey.");
- if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) {
+ if (!ecdsa_signature_parse_der_lax(&sig, vchSig.data(), vchSig.size())) {
return false;
}
- return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, nullptr, &sig));
-}
-
-/* static */ int ECCVerifyHandle::refcount = 0;
-
-ECCVerifyHandle::ECCVerifyHandle()
-{
- if (refcount == 0) {
- assert(secp256k1_context_verify == nullptr);
- secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
- assert(secp256k1_context_verify != nullptr);
- }
- refcount++;
-}
-
-ECCVerifyHandle::~ECCVerifyHandle()
-{
- refcount--;
- if (refcount == 0) {
- assert(secp256k1_context_verify != nullptr);
- secp256k1_context_destroy(secp256k1_context_verify);
- secp256k1_context_verify = nullptr;
- }
-}
-
-const secp256k1_context* GetVerifyContext() {
- return secp256k1_context_verify;
+ return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_static, nullptr, &sig));
}
diff --git a/src/pubkey.h b/src/pubkey.h
index 0485a38f72..b3edafea7f 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.
@@ -330,21 +330,4 @@ struct CExtPubKey {
[[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const;
};
-/** Users of this module must hold an ECCVerifyHandle. The constructor and
- * destructor of these are not allowed to run in parallel, though. */
-class ECCVerifyHandle
-{
- static int refcount;
-
-public:
- ECCVerifyHandle();
- ~ECCVerifyHandle();
-};
-
-typedef struct secp256k1_context_struct secp256k1_context;
-
-/** Access to the internal secp256k1 context used for verification. Only intended to be used
- * by key.cpp. */
-const secp256k1_context* GetVerifyContext();
-
#endif // BITCOIN_PUBKEY_H
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index a82bd5f73e..b888fc43e2 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -64,7 +64,6 @@ protected:
AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) :
QDialog(parent, GUIUtil::dialog_flags),
ui(new Ui::AddressBookPage),
- model(nullptr),
mode(_mode),
tab(_tab)
{
diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h
index 144990f419..283209d00c 100644
--- a/src/qt/addressbookpage.h
+++ b/src/qt/addressbookpage.h
@@ -49,7 +49,7 @@ public Q_SLOTS:
private:
Ui::AddressBookPage *ui;
- AddressTableModel *model;
+ AddressTableModel* model{nullptr};
Mode mode;
Tabs tab;
QString returnValue;
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 8b5da7f9f0..e402c51ac4 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 f16700bfd9..d15aba5cdd 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -23,8 +23,6 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent, SecureStri
QDialog(parent, GUIUtil::dialog_flags),
ui(new Ui::AskPassphraseDialog),
mode(_mode),
- model(nullptr),
- fCapsLock(false),
m_passphrase_out(passphrase_out)
{
ui->setupUi(this);
diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h
index 66031b08d3..370ea1de7e 100644
--- a/src/qt/askpassphrasedialog.h
+++ b/src/qt/askpassphrasedialog.h
@@ -38,8 +38,8 @@ public:
private:
Ui::AskPassphraseDialog *ui;
Mode mode;
- WalletModel *model;
- bool fCapsLock;
+ WalletModel* model{nullptr};
+ bool fCapsLock{false};
SecureString* m_passphrase_out;
private Q_SLOTS:
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 3d0be69302..4f57cd4457 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/bitcoin.cpp b/src/qt/bitcoin.cpp
index cc01e4d54a..59f433749d 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -228,14 +228,8 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
static int qt_argc = 1;
static const char* qt_argv = "bitcoin-qt";
-BitcoinApplication::BitcoinApplication():
- QApplication(qt_argc, const_cast<char **>(&qt_argv)),
- optionsModel(nullptr),
- clientModel(nullptr),
- window(nullptr),
- pollShutdownTimer(nullptr),
- returnValue(0),
- platformStyle(nullptr)
+BitcoinApplication::BitcoinApplication()
+ : QApplication(qt_argc, const_cast<char**>(&qt_argv))
{
// Qt runs setlocale(LC_ALL, "") on initialization.
RegisterMetaTypes();
@@ -311,11 +305,7 @@ void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
{
assert(!m_splash);
m_splash = new SplashScreen(networkStyle);
- // We don't hold a direct pointer to the splash screen after creation, but the splash
- // screen will take care of deleting itself when finish() happens.
m_splash->show();
- connect(this, &BitcoinApplication::splashFinished, m_splash, &SplashScreen::finish);
- connect(this, &BitcoinApplication::requestedShutdown, m_splash, &QWidget::close);
}
void BitcoinApplication::createNode(interfaces::Init& init)
@@ -373,6 +363,9 @@ void BitcoinApplication::requestShutdown()
w->hide();
}
+ delete m_splash;
+ m_splash = nullptr;
+
// Show a simple window indicating shutdown status
// Do this first as some of the steps may take some time below,
// for example the RPC console may still be executing a command.
@@ -412,10 +405,13 @@ void BitcoinApplication::requestShutdown()
void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
{
qDebug() << __func__ << ": Initialization result: " << success;
+
// Set exit result.
returnValue = success ? EXIT_SUCCESS : EXIT_FAILURE;
- if(success)
- {
+ if(success) {
+ delete m_splash;
+ m_splash = nullptr;
+
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
qInfo() << "Platform customization:" << platformStyle->getName();
clientModel = new ClientModel(node(), optionsModel);
@@ -438,7 +434,6 @@ void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHead
} else {
window->showMinimized();
}
- Q_EMIT splashFinished();
Q_EMIT windowShown(window);
#ifdef ENABLE_WALLET
@@ -455,7 +450,6 @@ void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHead
#endif
pollShutdownTimer->start(SHUTDOWN_POLLING_DELAY);
} else {
- Q_EMIT splashFinished(); // Make sure splash screen doesn't stick around during shutdown
requestShutdown();
}
}
@@ -592,29 +586,30 @@ int GuiMain(int argc, char* argv[])
// Gracefully exit if the user cancels
if (!Intro::showIfNeeded(did_show_intro, prune_MiB)) return EXIT_SUCCESS;
- /// 6. Determine availability of data directory and parse bitcoin.conf
- /// - Do not call gArgs.GetDataDirNet() before this step finishes
+ /// 6a. Determine availability of data directory
if (!CheckDataDirOption()) {
InitError(strprintf(Untranslated("Specified data directory \"%s\" does not exist.\n"), gArgs.GetArg("-datadir", "")));
QMessageBox::critical(nullptr, PACKAGE_NAME,
QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", ""))));
return EXIT_FAILURE;
}
- if (!gArgs.ReadConfigFiles(error, true)) {
- InitError(strprintf(Untranslated("Error reading configuration file: %s\n"), error));
- QMessageBox::critical(nullptr, PACKAGE_NAME,
- QObject::tr("Error: Cannot parse configuration file: %1.").arg(QString::fromStdString(error)));
- return EXIT_FAILURE;
- }
+ try {
+ /// 6b. Parse bitcoin.conf
+ /// - Do not call gArgs.GetDataDirNet() before this step finishes
+ if (!gArgs.ReadConfigFiles(error, true)) {
+ InitError(strprintf(Untranslated("Error reading configuration file: %s\n"), error));
+ QMessageBox::critical(nullptr, PACKAGE_NAME,
+ QObject::tr("Error: Cannot parse configuration file: %1.").arg(QString::fromStdString(error)));
+ return EXIT_FAILURE;
+ }
- /// 7. Determine network (and switch to network specific options)
- // - Do not call Params() before this step
- // - Do this after parsing the configuration file, as the network can be switched there
- // - QSettings() will use the new application name after this, resulting in network-specific settings
- // - Needs to be done before createOptionsModel
+ /// 7. Determine network (and switch to network specific options)
+ // - Do not call Params() before this step
+ // - Do this after parsing the configuration file, as the network can be switched there
+ // - QSettings() will use the new application name after this, resulting in network-specific settings
+ // - Needs to be done before createOptionsModel
- // Check for chain settings (Params() calls are only valid after this clause)
- try {
+ // Check for chain settings (Params() calls are only valid after this clause)
SelectParams(gArgs.GetChainName());
} catch(std::exception &e) {
InitError(Untranslated(strprintf("%s\n", e.what())));
diff --git a/src/qt/bitcoin.h b/src/qt/bitcoin.h
index 9ad37ca6c9..9174e23de6 100644
--- a/src/qt/bitcoin.h
+++ b/src/qt/bitcoin.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -89,7 +89,6 @@ public Q_SLOTS:
Q_SIGNALS:
void requestedInitialize();
void requestedShutdown();
- void splashFinished();
void windowShown(BitcoinGUI* window);
protected:
@@ -97,16 +96,16 @@ protected:
private:
std::optional<InitExecutor> m_executor;
- OptionsModel *optionsModel;
- ClientModel *clientModel;
- BitcoinGUI *window;
- QTimer *pollShutdownTimer;
+ OptionsModel* optionsModel{nullptr};
+ ClientModel* clientModel{nullptr};
+ BitcoinGUI* window{nullptr};
+ QTimer* pollShutdownTimer{nullptr};
#ifdef ENABLE_WALLET
PaymentServer* paymentServer{nullptr};
WalletController* m_wallet_controller{nullptr};
#endif
- int returnValue;
- const PlatformStyle *platformStyle;
+ int returnValue{0};
+ const PlatformStyle* platformStyle{nullptr};
std::unique_ptr<QWidget> shutdownWindow;
SplashScreen* m_splash = nullptr;
std::unique_ptr<interfaces::Node> m_node;
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index c92aecd095..a7e2d22488 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -217,9 +217,8 @@ Q_SIGNALS:
#include <qt/bitcoinamountfield.moc>
-BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
- QWidget(parent),
- amount(nullptr)
+BitcoinAmountField::BitcoinAmountField(QWidget* parent)
+ : QWidget(parent)
{
amount = new AmountSpinBox(this);
amount->setLocale(QLocale::c());
diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h
index a40cd38332..f710915a49 100644
--- a/src/qt/bitcoinamountfield.h
+++ b/src/qt/bitcoinamountfield.h
@@ -74,7 +74,7 @@ protected:
bool eventFilter(QObject *object, QEvent *event) override;
private:
- AmountSpinBox *amount;
+ AmountSpinBox* amount{nullptr};
QValueComboBox *unit;
private Q_SLOTS:
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 2bd38103ed..a7ffd367d7 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1541,10 +1541,8 @@ bool BitcoinGUI::isPrivacyModeActivated() const
return m_mask_values_action->isChecked();
}
-UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle)
- : optionsModel(nullptr),
- menu(nullptr),
- m_platform_style{platformStyle}
+UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle* platformStyle)
+ : m_platform_style{platformStyle}
{
createContextMenu();
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 912e9b95aa..1a83057146 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -333,8 +333,8 @@ protected:
void changeEvent(QEvent* e) override;
private:
- OptionsModel *optionsModel;
- QMenu* menu;
+ OptionsModel* optionsModel{nullptr};
+ QMenu* menu{nullptr};
const PlatformStyle* m_platform_style;
/** Shows context menu with Display Unit options by the mouse coordinates */
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 092ffe7e5b..c0d1a0e226 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -34,8 +34,6 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO
QObject(parent),
m_node(node),
optionsModel(_optionsModel),
- peerTableModel(nullptr),
- banTableModel(nullptr),
m_thread(new QThread(this))
{
cachedBestHeaderHeight = -1;
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 4a6abd6a76..9ff64fe772 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -104,9 +104,9 @@ private:
std::unique_ptr<interfaces::Handler> m_handler_notify_block_tip;
std::unique_ptr<interfaces::Handler> m_handler_notify_header_tip;
OptionsModel *optionsModel;
- PeerTableModel *peerTableModel;
+ PeerTableModel* peerTableModel{nullptr};
PeerTableSortProxy* m_peer_table_sort_proxy{nullptr};
- BanTableModel *banTableModel;
+ BanTableModel* banTableModel{nullptr};
//! A thread to interact with m_node asynchronously
QThread* const m_thread;
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 3bedbf29d8..e1b1ae12e9 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp
index 656afb6e87..445ea41475 100644
--- a/src/qt/csvmodelwriter.cpp
+++ b/src/qt/csvmodelwriter.cpp
@@ -8,9 +8,9 @@
#include <QFile>
#include <QTextStream>
-CSVModelWriter::CSVModelWriter(const QString &_filename, QObject *parent) :
- QObject(parent),
- filename(_filename), model(nullptr)
+CSVModelWriter::CSVModelWriter(const QString& _filename, QObject* parent)
+ : QObject(parent),
+ filename(_filename)
{
}
diff --git a/src/qt/csvmodelwriter.h b/src/qt/csvmodelwriter.h
index ad247b6859..a1e77826a8 100644
--- a/src/qt/csvmodelwriter.h
+++ b/src/qt/csvmodelwriter.h
@@ -32,7 +32,7 @@ public:
private:
QString filename;
- const QAbstractItemModel *model;
+ const QAbstractItemModel* model{nullptr};
struct Column
{
diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp
index fa27635981..9b3319415d 100644
--- a/src/qt/editaddressdialog.cpp
+++ b/src/qt/editaddressdialog.cpp
@@ -12,12 +12,10 @@
#include <QMessageBox>
-EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) :
- QDialog(parent, GUIUtil::dialog_flags),
- ui(new Ui::EditAddressDialog),
- mapper(nullptr),
- mode(_mode),
- model(nullptr)
+EditAddressDialog::EditAddressDialog(Mode _mode, QWidget* parent)
+ : QDialog(parent, GUIUtil::dialog_flags),
+ ui(new Ui::EditAddressDialog),
+ mode(_mode)
{
ui->setupUi(this);
diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h
index f7ad80bb2d..7bfadcfbcc 100644
--- a/src/qt/editaddressdialog.h
+++ b/src/qt/editaddressdialog.h
@@ -49,9 +49,9 @@ private:
QString getDuplicateAddressWarning() const;
Ui::EditAddressDialog *ui;
- QDataWidgetMapper *mapper;
+ QDataWidgetMapper* mapper{nullptr};
Mode mode;
- AddressTableModel *model;
+ AddressTableModel* model{nullptr};
QString address;
};
diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h
index fcdf6056c9..0f76770772 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/guiutil.cpp b/src/qt/guiutil.cpp
index 6e88b57e08..bedf367f05 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/guiutil.h b/src/qt/guiutil.h
index acbe415a91..87a323bde9 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/initexecutor.cpp b/src/qt/initexecutor.cpp
index d269dfec71..b63e7ec01c 100644
--- a/src/qt/initexecutor.cpp
+++ b/src/qt/initexecutor.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2021 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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/intro.cpp b/src/qt/intro.cpp
index 4c8b33bf28..12aa02340a 100644
--- a/src/qt/intro.cpp
+++ b/src/qt/intro.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -122,8 +122,6 @@ int GetPruneTargetGB()
Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_size_gb) :
QDialog(parent, GUIUtil::dialog_flags),
ui(new Ui::Intro),
- thread(nullptr),
- signalled(false),
m_blockchain_size_gb(blockchain_size_gb),
m_chain_state_size_gb(chain_state_size_gb),
m_prune_target_gb{GetPruneTargetGB()}
diff --git a/src/qt/intro.h b/src/qt/intro.h
index d9c45007e1..900c657b27 100644
--- a/src/qt/intro.h
+++ b/src/qt/intro.h
@@ -64,9 +64,9 @@ private Q_SLOTS:
private:
Ui::Intro *ui;
- QThread *thread;
+ QThread* thread{nullptr};
QMutex mutex;
- bool signalled;
+ bool signalled{false};
QString pathToCheck;
const int64_t m_blockchain_size_gb;
const int64_t m_chain_state_size_gb;
diff --git a/src/qt/main.cpp b/src/qt/main.cpp
index 45131a1cf5..c84dd78b44 100644
--- a/src/qt/main.cpp
+++ b/src/qt/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/modaloverlay.cpp b/src/qt/modaloverlay.cpp
index dfa33764f6..b09e230bce 100644
--- a/src/qt/modaloverlay.cpp
+++ b/src/qt/modaloverlay.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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,13 +12,10 @@
#include <QPropertyAnimation>
#include <QResizeEvent>
-ModalOverlay::ModalOverlay(bool enable_wallet, QWidget *parent) :
-QWidget(parent),
-ui(new Ui::ModalOverlay),
-bestHeaderHeight(0),
-bestHeaderDate(QDateTime()),
-layerIsVisible(false),
-userClosed(false)
+ModalOverlay::ModalOverlay(bool enable_wallet, QWidget* parent)
+ : QWidget(parent),
+ ui(new Ui::ModalOverlay),
+ bestHeaderDate(QDateTime())
{
ui->setupUi(this);
connect(ui->closeButton, &QPushButton::clicked, this, &ModalOverlay::closeClicked);
diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h
index 682c94cd01..40e487b249 100644
--- a/src/qt/modaloverlay.h
+++ b/src/qt/modaloverlay.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -45,11 +45,11 @@ protected:
private:
Ui::ModalOverlay *ui;
- int bestHeaderHeight; //best known height (based on the headers)
+ int bestHeaderHeight{0}; // best known height (based on the headers)
QDateTime bestHeaderDate;
QVector<QPair<qint64, double> > blockProcessTime;
- bool layerIsVisible;
- bool userClosed;
+ bool layerIsVisible{false};
+ bool userClosed{false};
QPropertyAnimation m_animation;
void UpdateHeaderSyncLabel();
void UpdateHeaderPresyncLabel(int height, const QDateTime& blockDate);
diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp
index b2dc7fd65a..b789e6a958 100644
--- a/src/qt/networkstyle.cpp
+++ b/src/qt/networkstyle.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2020 The Bitcoin Core developers
+// Copyright (c) 2014-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.
diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp
index b311a9f32e..88bc33098a 100644
--- a/src/qt/notificator.cpp
+++ b/src/qt/notificator.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -32,11 +32,7 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon
QObject(_parent),
parent(_parent),
programName(_programName),
- mode(None),
trayIcon(_trayIcon)
-#ifdef USE_DBUS
- ,interface(nullptr)
-#endif
{
if(_trayIcon && _trayIcon->supportsMessages())
{
diff --git a/src/qt/notificator.h b/src/qt/notificator.h
index 642d2b29ae..1fd8181a22 100644
--- a/src/qt/notificator.h
+++ b/src/qt/notificator.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -61,10 +61,10 @@ private:
UserNotificationCenter /**< Use the 10.8+ User Notification Center (Mac only) */
};
QString programName;
- Mode mode;
+ Mode mode{None};
QSystemTrayIcon *trayIcon;
#ifdef USE_DBUS
- QDBusInterface *interface;
+ QDBusInterface* interface{nullptr};
void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
#endif
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 7c91eac37e..53b0c3832b 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -31,11 +31,9 @@
#include <QSystemTrayIcon>
#include <QTimer>
-OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
- QDialog(parent, GUIUtil::dialog_flags),
- ui(new Ui::OptionsDialog),
- model(nullptr),
- mapper(nullptr)
+OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
+ : QDialog(parent, GUIUtil::dialog_flags),
+ ui(new Ui::OptionsDialog)
{
ui->setupUi(this);
diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h
index e5a19d5025..031e4d3163 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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,8 +75,8 @@ Q_SIGNALS:
private:
Ui::OptionsDialog *ui;
ClientModel* m_client_model{nullptr};
- OptionsModel *model;
- QDataWidgetMapper *mapper;
+ OptionsModel* model{nullptr};
+ QDataWidgetMapper* mapper{nullptr};
};
#endif // BITCOIN_QT_OPTIONSDIALOG_H
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 0b4359a917..00b7952ca4 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -31,7 +31,7 @@
const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1";
-static const QString GetDefaultProxyAddress();
+static QString GetDefaultProxyAddress();
/** Map GUI option ID to node setting name. */
static const char* SettingName(OptionsModel::OptionID option)
@@ -308,7 +308,7 @@ static std::string ProxyString(bool is_set, QString ip, QString port)
return is_set ? QString(ip + ":" + port).toStdString() : "";
}
-static const QString GetDefaultProxyAddress()
+static QString GetDefaultProxyAddress()
{
return QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST).arg(DEFAULT_GUI_PROXY_PORT);
}
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 42b89c5029..e36fbc5b31 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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.cpp b/src/qt/overviewpage.cpp
index 85a3c36f39..3cd5f4061c 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -140,8 +140,6 @@ private:
OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent),
ui(new Ui::OverviewPage),
- clientModel(nullptr),
- walletModel(nullptr),
m_platform_style{platformStyle},
txdelegate(new TxViewDelegate(platformStyle, this))
{
@@ -264,7 +262,6 @@ void OverviewPage::setWalletModel(WalletModel *model)
// Set up transaction list
filter.reset(new TransactionFilterProxy());
filter->setSourceModel(model->getTransactionTableModel());
- filter->setLimit(NUM_ITEMS);
filter->setDynamicSortFilter(true);
filter->setSortRole(Qt::EditRole);
filter->setShowInactive(false);
@@ -273,6 +270,10 @@ void OverviewPage::setWalletModel(WalletModel *model)
ui->listTransactions->setModel(filter.get());
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
+ connect(filter.get(), &TransactionFilterProxy::rowsInserted, this, &OverviewPage::LimitTransactionRows);
+ connect(filter.get(), &TransactionFilterProxy::rowsRemoved, this, &OverviewPage::LimitTransactionRows);
+ connect(filter.get(), &TransactionFilterProxy::rowsMoved, this, &OverviewPage::LimitTransactionRows);
+ LimitTransactionRows();
// Keep up to date with wallet
setBalance(model->getCachedBalance());
connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
@@ -301,6 +302,16 @@ void OverviewPage::changeEvent(QEvent* e)
QWidget::changeEvent(e);
}
+// Only show most recent NUM_ITEMS rows
+void OverviewPage::LimitTransactionRows()
+{
+ if (filter && ui->listTransactions && ui->listTransactions->model() && filter.get() == ui->listTransactions->model()) {
+ for (int i = 0; i < filter->rowCount(); ++i) {
+ ui->listTransactions->setRowHidden(i, i >= NUM_ITEMS);
+ }
+ }
+}
+
void OverviewPage::updateDisplayUnit()
{
if (walletModel && walletModel->getOptionsModel()) {
diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h
index 56f45907db..5c487ee116 100644
--- a/src/qt/overviewpage.h
+++ b/src/qt/overviewpage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -50,8 +50,8 @@ protected:
private:
Ui::OverviewPage *ui;
- ClientModel *clientModel;
- WalletModel *walletModel;
+ ClientModel* clientModel{nullptr};
+ WalletModel* walletModel{nullptr};
bool m_privacy{false};
const PlatformStyle* m_platform_style;
@@ -60,6 +60,7 @@ private:
std::unique_ptr<TransactionFilterProxy> filter;
private Q_SLOTS:
+ void LimitTransactionRows();
void updateDisplayUnit();
void handleTransactionClicked(const QModelIndex &index);
void updateAlerts(const QString &warnings);
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 9f87c15c94..3f9d1b040b 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -126,11 +126,8 @@ bool PaymentServer::ipcSendCommandLine()
return fResult;
}
-PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
- QObject(parent),
- saveURIs(true),
- uriServer(nullptr),
- optionsModel(nullptr)
+PaymentServer::PaymentServer(QObject* parent, bool startLocalServer)
+ : QObject(parent)
{
// Install global event filter to catch QFileOpenEvents
// on Mac: sent when you click bitcoin: links
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index 08b83244ab..63f4faa772 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -101,9 +101,9 @@ protected:
bool eventFilter(QObject *object, QEvent *event) override;
private:
- bool saveURIs; // true during startup
- QLocalServer* uriServer;
- OptionsModel *optionsModel;
+ bool saveURIs{true}; // true during startup
+ QLocalServer* uriServer{nullptr};
+ OptionsModel* optionsModel{nullptr};
};
#endif // BITCOIN_QT_PAYMENTSERVER_H
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index b7de88225e..9f47213ed9 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,10 +14,9 @@
#include <QList>
#include <QTimer>
-PeerTableModel::PeerTableModel(interfaces::Node& node, QObject* parent) :
- QAbstractTableModel(parent),
- m_node(node),
- timer(nullptr)
+PeerTableModel::PeerTableModel(interfaces::Node& node, QObject* parent)
+ : QAbstractTableModel(parent),
+ m_node(node)
{
// set up timer for auto refresh
timer = new QTimer(this);
diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h
index e2515de775..a0174c3af4 100644
--- a/src/qt/peertablemodel.h
+++ b/src/qt/peertablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -110,7 +110,7 @@ private:
/*: Title of Peers Table column which contains the peer's
User Agent string. */
tr("User Agent")};
- QTimer *timer;
+ QTimer* timer{nullptr};
};
#endif // BITCOIN_QT_PEERTABLEMODEL_H
diff --git a/src/qt/peertablesortproxy.cpp b/src/qt/peertablesortproxy.cpp
index d87f10c365..a70b5d4e29 100644
--- a/src/qt/peertablesortproxy.cpp
+++ b/src/qt/peertablesortproxy.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/platformstyle.cpp b/src/qt/platformstyle.cpp
index 89e022a067..a430650096 100644
--- a/src/qt/platformstyle.cpp
+++ b/src/qt/platformstyle.cpp
@@ -83,8 +83,8 @@ QColor PlatformStyle::TextColor() const
QColor PlatformStyle::SingleColor() const
{
if (colorizeIcons) {
- const QColor colorHighlightBg(QApplication::palette().color(QPalette::Highlight));
- const QColor colorHighlightFg(QApplication::palette().color(QPalette::HighlightedText));
+ QColor colorHighlightBg(QApplication::palette().color(QPalette::Highlight));
+ QColor colorHighlightFg(QApplication::palette().color(QPalette::HighlightedText));
const QColor colorText(QApplication::palette().color(QPalette::WindowText));
const int colorTextLightness = colorText.lightness();
if (abs(colorHighlightBg.lightness() - colorTextLightness) < abs(colorHighlightFg.lightness() - colorTextLightness)) {
diff --git a/src/qt/psbtoperationsdialog.cpp b/src/qt/psbtoperationsdialog.cpp
index afffae0784..17a65be0fe 100644
--- a/src/qt/psbtoperationsdialog.cpp
+++ b/src/qt/psbtoperationsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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.cpp b/src/qt/qrimagewidget.cpp
index 05a67117b6..00f928b355 100644
--- a/src/qt/qrimagewidget.cpp
+++ b/src/qt/qrimagewidget.cpp
@@ -23,8 +23,8 @@
#include <qrencode.h>
#endif
-QRImageWidget::QRImageWidget(QWidget *parent):
- QLabel(parent), contextMenu(nullptr)
+QRImageWidget::QRImageWidget(QWidget* parent)
+ : QLabel(parent)
{
contextMenu = new QMenu(this);
contextMenu->addAction(tr("&Save Image…"), this, &QRImageWidget::saveImage);
diff --git a/src/qt/qrimagewidget.h b/src/qt/qrimagewidget.h
index 5dbba074a1..d9ca2b899f 100644
--- a/src/qt/qrimagewidget.h
+++ b/src/qt/qrimagewidget.h
@@ -41,7 +41,7 @@ protected:
virtual void contextMenuEvent(QContextMenuEvent *event) override;
private:
- QMenu *contextMenu;
+ QMenu* contextMenu{nullptr};
};
#endif // BITCOIN_QT_QRIMAGEWIDGET_H
diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp
index bd4df75d23..b646332001 100644
--- a/src/qt/qvalidatedlineedit.cpp
+++ b/src/qt/qvalidatedlineedit.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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,10 +7,8 @@
#include <qt/bitcoinaddressvalidator.h>
#include <qt/guiconstants.h>
-QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) :
- QLineEdit(parent),
- valid(true),
- checkValidator(nullptr)
+QValidatedLineEdit::QValidatedLineEdit(QWidget* parent)
+ : QLineEdit(parent)
{
connect(this, &QValidatedLineEdit::textChanged, this, &QValidatedLineEdit::markValid);
}
diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h
index 12d35aa264..b1ae013957 100644
--- a/src/qt/qvalidatedlineedit.h
+++ b/src/qt/qvalidatedlineedit.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -25,8 +25,8 @@ protected:
void focusOutEvent(QFocusEvent *evt) override;
private:
- bool valid;
- const QValidator *checkValidator;
+ bool valid{true};
+ const QValidator* checkValidator{nullptr};
public Q_SLOTS:
void setText(const QString&);
diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp
index f94486a2f3..c163ba56dc 100644
--- a/src/qt/qvaluecombobox.cpp
+++ b/src/qt/qvaluecombobox.cpp
@@ -4,8 +4,8 @@
#include <qt/qvaluecombobox.h>
-QValueComboBox::QValueComboBox(QWidget *parent) :
- QComboBox(parent), role(Qt::UserRole)
+QValueComboBox::QValueComboBox(QWidget* parent)
+ : QComboBox(parent)
{
connect(this, qOverload<int>(&QComboBox::currentIndexChanged), this, &QValueComboBox::handleSelectionChanged);
}
diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h
index bde9c0d1a6..14379dd612 100644
--- a/src/qt/qvaluecombobox.h
+++ b/src/qt/qvaluecombobox.h
@@ -28,7 +28,7 @@ Q_SIGNALS:
void valueChanged();
private:
- int role;
+ int role{Qt::UserRole};
private Q_SLOTS:
void handleSelectionChanged(int idx);
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index 3c80c01160..22eb642ecd 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -25,7 +25,6 @@
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent, GUIUtil::dialog_flags),
ui(new Ui::ReceiveCoinsDialog),
- model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h
index a089b8aa6a..0bb02ebcf2 100644
--- a/src/qt/receivecoinsdialog.h
+++ b/src/qt/receivecoinsdialog.h
@@ -51,7 +51,7 @@ public Q_SLOTS:
private:
Ui::ReceiveCoinsDialog *ui;
- WalletModel *model;
+ WalletModel* model{nullptr};
QMenu *contextMenu;
QAction* copyLabelAction;
QAction* copyMessageAction;
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index c0135283b1..3453857f98 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -18,10 +18,9 @@
#include <config/bitcoin-config.h> /* for USE_QRCODE */
#endif
-ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) :
- QDialog(parent, GUIUtil::dialog_flags),
- ui(new Ui::ReceiveRequestDialog),
- model(nullptr)
+ReceiveRequestDialog::ReceiveRequestDialog(QWidget* parent)
+ : QDialog(parent, GUIUtil::dialog_flags),
+ ui(new Ui::ReceiveRequestDialog)
{
ui->setupUi(this);
GUIUtil::handleCloseWindowShortcut(this);
diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h
index c861680761..d64fee3663 100644
--- a/src/qt/receiverequestdialog.h
+++ b/src/qt/receiverequestdialog.h
@@ -33,7 +33,7 @@ private Q_SLOTS:
private:
Ui::ReceiveRequestDialog *ui;
- WalletModel *model;
+ WalletModel* model{nullptr};
SendCoinsRecipient info;
};
diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp
index 061513b58f..52d4e45d49 100644
--- a/src/qt/recentrequeststablemodel.cpp
+++ b/src/qt/recentrequeststablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -175,7 +175,7 @@ void RecentRequestsTableModel::addNewRequest(const SendCoinsRecipient &recipient
newEntry.date = QDateTime::currentDateTime();
newEntry.recipient = recipient;
- CDataStream ss(SER_DISK, CLIENT_VERSION);
+ DataStream ss{};
ss << newEntry;
if (!walletModel->wallet().setAddressReceiveRequest(DecodeDestination(recipient.address.toStdString()), ToString(newEntry.id), ss.str()))
@@ -188,7 +188,7 @@ void RecentRequestsTableModel::addNewRequest(const SendCoinsRecipient &recipient
void RecentRequestsTableModel::addNewRequest(const std::string &recipient)
{
std::vector<uint8_t> data(recipient.begin(), recipient.end());
- CDataStream ss(data, SER_DISK, CLIENT_VERSION);
+ DataStream ss{data};
RecentRequestEntry entry;
ss >> entry;
diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h
index cf7cd24ce2..151f8322a8 100644
--- a/src/qt/recentrequeststablemodel.h
+++ b/src/qt/recentrequeststablemodel.h
@@ -18,11 +18,11 @@ class WalletModel;
class RecentRequestEntry
{
public:
- RecentRequestEntry() : nVersion(RecentRequestEntry::CURRENT_VERSION), id(0) { }
+ RecentRequestEntry() : nVersion(RecentRequestEntry::CURRENT_VERSION) {}
static const int CURRENT_VERSION = 1;
int nVersion;
- int64_t id;
+ int64_t id{0};
QDateTime date;
SendCoinsRecipient recipient;
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index a07686ab2b..b46a3c039b 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -780,8 +780,8 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
{
// use name for text and wallet model for internal data object (to allow to move to a wallet id later)
ui->WalletSelector->addItem(walletModel->getDisplayName(), QVariant::fromValue(walletModel));
- if (ui->WalletSelector->count() == 2 && !isVisible()) {
- // First wallet added, set to default so long as the window isn't presently visible (and potentially in use)
+ if (ui->WalletSelector->count() == 2) {
+ // First wallet added, set to default to match wallet RPC behavior
ui->WalletSelector->setCurrentIndex(1);
}
if (ui->WalletSelector->count() > 2) {
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index a3c713e966..32a7520491 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 57094fc857..33145cc48d 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -64,11 +64,7 @@ int getIndexForConfTarget(int target) {
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent, GUIUtil::dialog_flags),
ui(new Ui::SendCoinsDialog),
- clientModel(nullptr),
- model(nullptr),
m_coin_control(new CCoinControl),
- fNewRecipientAllowed(true),
- fFeeMinimized(true),
platformStyle(_platformStyle)
{
ui->setupUi(this);
@@ -703,7 +699,7 @@ void SendCoinsDialog::setBalance(const interfaces::WalletBalances& balances)
CAmount balance = balances.balance;
if (model->wallet().hasExternalSigner()) {
ui->labelBalanceName->setText(tr("External balance:"));
- } else if (model->wallet().privateKeysDisabled()) {
+ } else if (model->wallet().isLegacy() && model->wallet().privateKeysDisabled()) {
balance = balances.watch_only_balance;
ui->labelBalanceName->setText(tr("Watch-only balance:"));
}
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index dcdf189532..2fcdf5b32a 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -62,12 +62,12 @@ Q_SIGNALS:
private:
Ui::SendCoinsDialog *ui;
- ClientModel *clientModel;
- WalletModel *model;
+ ClientModel* clientModel{nullptr};
+ WalletModel* model{nullptr};
std::unique_ptr<wallet::CCoinControl> m_coin_control;
std::unique_ptr<WalletModelTransaction> m_current_transaction;
- bool fNewRecipientAllowed;
- bool fFeeMinimized;
+ bool fNewRecipientAllowed{true};
+ bool fFeeMinimized{true};
const PlatformStyle *platformStyle;
// Copy PSBT to clipboard and offer to save it.
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index af514d5a43..0536635c84 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -22,7 +22,6 @@
SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) :
QWidget(parent),
ui(new Ui::SendCoinsEntry),
- model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h
index ea9d58fbf8..0edc0d1203 100644
--- a/src/qt/sendcoinsentry.h
+++ b/src/qt/sendcoinsentry.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -73,7 +73,7 @@ protected:
private:
SendCoinsRecipient recipient;
Ui::SendCoinsEntry *ui;
- WalletModel *model;
+ WalletModel* model{nullptr};
const PlatformStyle *platformStyle;
bool updateLabel(const QString &address);
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 1f4b30534b..0e725acb33 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -21,7 +21,6 @@
SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent, GUIUtil::dialog_flags),
ui(new Ui::SignVerifyMessageDialog),
- model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
diff --git a/src/qt/signverifymessagedialog.h b/src/qt/signverifymessagedialog.h
index 1a3708bf8f..4072707b61 100644
--- a/src/qt/signverifymessagedialog.h
+++ b/src/qt/signverifymessagedialog.h
@@ -35,7 +35,7 @@ protected:
private:
Ui::SignVerifyMessageDialog *ui;
- WalletModel *model;
+ WalletModel* model{nullptr};
const PlatformStyle *platformStyle;
private Q_SLOTS:
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index bf04a6dd5f..096f8a0ded 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -28,7 +28,7 @@
SplashScreen::SplashScreen(const NetworkStyle* networkStyle)
- : QWidget(), curAlignment(0)
+ : QWidget()
{
// set reference point, paddings
int paddingRight = 50;
@@ -161,16 +161,6 @@ bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) {
return QObject::eventFilter(obj, ev);
}
-void SplashScreen::finish()
-{
- /* If the window is minimized, hide() will be ignored. */
- /* Make sure we de-minimize the splashscreen window before hiding */
- if (isMinimized())
- showNormal();
- hide();
- deleteLater(); // No more need for this
-}
-
static void InitMessage(SplashScreen *splash, const std::string &message)
{
bool invoked = QMetaObject::invokeMethod(splash, "showMessage",
diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h
index c14fc521a7..2356bbacd3 100644
--- a/src/qt/splashscreen.h
+++ b/src/qt/splashscreen.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -37,9 +37,6 @@ protected:
void closeEvent(QCloseEvent *event) override;
public Q_SLOTS:
- /** Hide the splash screen window and schedule the splash screen object for deletion */
- void finish();
-
/** Show message and progress */
void showMessage(const QString &message, int alignment, const QColor &color);
@@ -60,7 +57,7 @@ private:
QPixmap pixmap;
QString curMessage;
QColor curColor;
- int curAlignment;
+ int curAlignment{0};
interfaces::Node* m_node = nullptr;
bool m_shutdown = false;
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index 581735263d..049326070e 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/apptests.cpp b/src/qt/test/apptests.cpp
index a5cef9a1bb..000bbe65be 100644
--- a/src/qt/test/apptests.cpp
+++ b/src/qt/test/apptests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/optiontests.cpp b/src/qt/test/optiontests.cpp
index 17ffeb220b..dc7c8928c5 100644
--- a/src/qt/test/optiontests.cpp
+++ b/src/qt/test/optiontests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/optiontests.h b/src/qt/test/optiontests.h
index 57ec8bd0f2..0c458c97a6 100644
--- a/src/qt/test/optiontests.h
+++ b/src/qt/test/optiontests.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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 3f582e7cf6..2d069f76a0 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 635dbcd1c5..c5ed20d967 100644
--- a/src/qt/test/util.cpp
+++ b/src/qt/test/util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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 f50a6b6c61..13170c89ea 100644
--- a/src/qt/test/util.h
+++ b/src/qt/test/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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.cpp b/src/qt/test/wallettests.cpp
index c32525b607..15fe37c164 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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,7 +289,7 @@ void TestGUI(interfaces::Node& node)
std::vector<std::string> requests = walletModel.wallet().getAddressReceiveRequests();
QCOMPARE(requests.size(), size_t{1});
RecentRequestEntry entry;
- CDataStream{MakeUCharSpan(requests[0]), SER_DISK, CLIENT_VERSION} >> entry;
+ DataStream{MakeUCharSpan(requests[0])} >> entry;
QCOMPARE(entry.nVersion, int{1});
QCOMPARE(entry.id, int64_t{1});
QVERIFY(entry.date.isValid());
diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp
index aebd44d5f7..08789c1048 100644
--- a/src/qt/trafficgraphwidget.cpp
+++ b/src/qt/trafficgraphwidget.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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,15 +19,10 @@
#define XMARGIN 10
#define YMARGIN 10
-TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
- QWidget(parent),
- timer(nullptr),
- fMax(0.0f),
- vSamplesIn(),
- vSamplesOut(),
- nLastBytesIn(0),
- nLastBytesOut(0),
- clientModel(nullptr)
+TrafficGraphWidget::TrafficGraphWidget(QWidget* parent)
+ : QWidget(parent),
+ vSamplesIn(),
+ vSamplesOut()
{
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &TrafficGraphWidget::updateRates);
diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h
index a40b734540..5e5557ec82 100644
--- a/src/qt/trafficgraphwidget.h
+++ b/src/qt/trafficgraphwidget.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -37,14 +37,14 @@ public Q_SLOTS:
private:
void paintPath(QPainterPath &path, QQueue<float> &samples);
- QTimer *timer;
- float fMax;
+ QTimer* timer{nullptr};
+ float fMax{0.0f};
std::chrono::minutes m_range{0};
QQueue<float> vSamplesIn;
QQueue<float> vSamplesOut;
- quint64 nLastBytesIn;
- quint64 nLastBytesOut;
- ClientModel *clientModel;
+ quint64 nLastBytesIn{0};
+ quint64 nLastBytesOut{0};
+ ClientModel* clientModel{nullptr};
};
#endif // BITCOIN_QT_TRAFFICGRAPHWIDGET_H
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index a61d5407b3..2ced44241f 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/transactiondesc.h b/src/qt/transactiondesc.h
index 803e41b699..e64f2cace1 100644
--- a/src/qt/transactiondesc.h
+++ b/src/qt/transactiondesc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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.cpp b/src/qt/transactionfilterproxy.cpp
index 3be7e1a969..173fd326a3 100644
--- a/src/qt/transactionfilterproxy.cpp
+++ b/src/qt/transactionfilterproxy.cpp
@@ -11,14 +11,10 @@
#include <cstdlib>
#include <optional>
-TransactionFilterProxy::TransactionFilterProxy(QObject *parent) :
- QSortFilterProxyModel(parent),
- m_search_string(),
- typeFilter(ALL_TYPES),
- watchOnlyFilter(WatchOnlyFilter_All),
- minAmount(0),
- limitRows(-1),
- showInactive(true)
+TransactionFilterProxy::TransactionFilterProxy(QObject* parent)
+ : QSortFilterProxyModel(parent),
+ m_search_string(),
+ typeFilter(ALL_TYPES)
{
}
@@ -92,25 +88,8 @@ void TransactionFilterProxy::setWatchOnlyFilter(WatchOnlyFilter filter)
invalidateFilter();
}
-void TransactionFilterProxy::setLimit(int limit)
-{
- this->limitRows = limit;
-}
-
void TransactionFilterProxy::setShowInactive(bool _showInactive)
{
this->showInactive = _showInactive;
invalidateFilter();
}
-
-int TransactionFilterProxy::rowCount(const QModelIndex &parent) const
-{
- if(limitRows != -1)
- {
- return std::min(QSortFilterProxyModel::rowCount(parent), limitRows);
- }
- else
- {
- return QSortFilterProxyModel::rowCount(parent);
- }
-}
diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h
index fd9be52842..73c4f21426 100644
--- a/src/qt/transactionfilterproxy.h
+++ b/src/qt/transactionfilterproxy.h
@@ -42,14 +42,9 @@ public:
void setMinAmount(const CAmount& minimum);
void setWatchOnlyFilter(WatchOnlyFilter filter);
- /** Set maximum number of rows returned, -1 if unlimited. */
- void setLimit(int limit);
-
/** Set whether to show conflicted transactions. */
void setShowInactive(bool showInactive);
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-
protected:
bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override;
@@ -58,10 +53,9 @@ private:
std::optional<QDateTime> dateTo;
QString m_search_string;
quint32 typeFilter;
- WatchOnlyFilter watchOnlyFilter;
- CAmount minAmount;
- int limitRows;
- bool showInactive;
+ WatchOnlyFilter watchOnlyFilter{WatchOnlyFilter_All};
+ CAmount minAmount{0};
+ bool showInactive{true};
};
#endif // BITCOIN_QT_TRANSACTIONFILTERPROXY_H
diff --git a/src/qt/transactionoverviewwidget.cpp b/src/qt/transactionoverviewwidget.cpp
index 360a1364fb..24b96c861f 100644
--- a/src/qt/transactionoverviewwidget.cpp
+++ b/src/qt/transactionoverviewwidget.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/transactionoverviewwidget.h b/src/qt/transactionoverviewwidget.h
index 0572e84090..eb9d661996 100644
--- a/src/qt/transactionoverviewwidget.h
+++ b/src/qt/transactionoverviewwidget.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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 26144ba197..5f981ea250 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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.h b/src/qt/transactionrecord.h
index d8748d7dc9..36cfb422e8 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -76,12 +76,12 @@ public:
static const int RecommendedNumConfirmations = 6;
TransactionRecord():
- hash(), time(0), type(Other), address(""), debit(0), credit(0), idx(0)
+ hash(), time(0), type(Other), debit(0), credit(0), idx(0)
{
}
TransactionRecord(uint256 _hash, qint64 _time):
- hash(_hash), time(_time), type(Other), address(""), debit(0),
+ hash(_hash), time(_time), type(Other), debit(0),
credit(0), idx(0)
{
}
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 4312b3cd24..25d54bdce6 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -93,10 +93,7 @@ public:
TransactionTableModel *parent;
- /* Local cache of wallet.
- * As it is in the same order as the CWallet, by definition
- * this is sorted by sha256.
- */
+ //! Local cache of wallet sorted by transaction hash
QList<TransactionRecord> cachedWallet;
/** True when model finishes loading all wallet transactions on start */
@@ -253,7 +250,6 @@ TransactionTableModel::TransactionTableModel(const PlatformStyle *_platformStyle
QAbstractTableModel(parent),
walletModel(parent),
priv(new TransactionTablePriv(this)),
- fProcessingQueuedTransactions(false),
platformStyle(_platformStyle)
{
subscribeToCoreSignals();
diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h
index f8576edd59..92ba9bf894 100644
--- a/src/qt/transactiontablemodel.h
+++ b/src/qt/transactiontablemodel.h
@@ -89,7 +89,7 @@ private:
std::unique_ptr<interfaces::Handler> m_handler_show_progress;
QStringList columns;
TransactionTablePriv *priv;
- bool fProcessingQueuedTransactions;
+ bool fProcessingQueuedTransactions{false};
const PlatformStyle *platformStyle;
void subscribeToCoreSignals();
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index b7432a0d77..aa5c82ddb1 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -421,9 +421,6 @@ void TransactionView::abandonTx()
// Abandon the wallet transaction over the walletModel
model->wallet().abandonTransaction(hash);
-
- // Update the table
- model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false);
}
void TransactionView::bumpFee([[maybe_unused]] bool checked)
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 331487b51d..eb2ab12a66 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 8762ba9ab3..d782838d6f 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/walletframe.cpp b/src/qt/walletframe.cpp
index 8dc97e66a2..43411370a2 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -212,7 +212,7 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard)
return;
}
std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
- data.assign(std::istream_iterator<unsigned char>{in}, {});
+ data.assign(std::istreambuf_iterator<char>{in}, {});
// Some psbt files may be base64 strings in the file rather than binary data
std::string b64_str{data.begin(), data.end()};
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index ed0602594b..cb8491e27a 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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,10 +46,6 @@ WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, ClientModel
m_client_model(&client_model),
m_node(client_model.node()),
optionsModel(client_model.getOptionsModel()),
- addressTableModel(nullptr),
- transactionTableModel(nullptr),
- recentRequestsTableModel(nullptr),
- cachedEncryptionStatus(Unencrypted),
timer(new QTimer(this))
{
fHaveWatchOnly = m_wallet->haveWatchOnly();
@@ -212,7 +208,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
return AmountExceedsBalance;
}
- {
+ try {
CAmount nFeeRequired = 0;
int nChangePosRet = -1;
@@ -240,6 +236,11 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
if (nFeeRequired > m_wallet->getDefaultMaxTxFee()) {
return AbsurdFee;
}
+ } catch (const std::runtime_error& err) {
+ // Something unexpected happened, instruct user to report this bug.
+ Q_EMIT message(tr("Send Coins"), QString::fromStdString(err.what()),
+ CClientUIInterface::MSG_ERROR);
+ return TransactionCreationFailed;
}
return SendCoinsReturn(OK);
@@ -522,7 +523,9 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
questionString.append(tr("Warning: This may pay the additional fee by reducing change outputs or adding inputs, when necessary. It may add a new change output if one does not already exist. These changes may potentially leak privacy."));
}
- auto confirmationDialog = new SendConfirmationDialog(tr("Confirm fee bump"), questionString, "", "", SEND_CONFIRM_DELAY, !m_wallet->privateKeysDisabled(), getOptionsModel()->getEnablePSBTControls(), nullptr);
+ const bool enable_send{!wallet().privateKeysDisabled() || wallet().hasExternalSigner()};
+ const bool always_show_unsigned{getOptionsModel()->getEnablePSBTControls()};
+ auto confirmationDialog = new SendConfirmationDialog(tr("Confirm fee bump"), questionString, "", "", SEND_CONFIRM_DELAY, enable_send, always_show_unsigned, nullptr);
confirmationDialog->setAttribute(Qt::WA_DeleteOnClose);
// TODO: Replace QDialog::exec() with safer QDialog::show().
const auto retval = static_cast<QMessageBox::StandardButton>(confirmationDialog->exec());
@@ -540,6 +543,7 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
// Short-circuit if we are returning a bumped transaction PSBT to clipboard
if (retval == QMessageBox::Save) {
+ // "Create Unsigned" clicked
PartiallySignedTransaction psbtx(mtx);
bool complete = false;
const TransactionError err = wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, nullptr, psbtx, complete);
@@ -555,7 +559,7 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
return true;
}
- assert(!m_wallet->privateKeysDisabled());
+ assert(!m_wallet->privateKeysDisabled() || wallet().hasExternalSigner());
// sign bumped transaction
if (!m_wallet->signBumpTransaction(mtx)) {
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 73dfe0386a..604a9e03c8 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -181,13 +181,13 @@ private:
// (transaction fee, for example)
OptionsModel *optionsModel;
- AddressTableModel *addressTableModel;
- TransactionTableModel *transactionTableModel;
- RecentRequestsTableModel *recentRequestsTableModel;
+ AddressTableModel* addressTableModel{nullptr};
+ TransactionTableModel* transactionTableModel{nullptr};
+ RecentRequestsTableModel* recentRequestsTableModel{nullptr};
// Cache some values to be able to detect changes
interfaces::WalletBalances m_cached_balances;
- EncryptionStatus cachedEncryptionStatus;
+ EncryptionStatus cachedEncryptionStatus{Unencrypted};
QTimer* timer;
// Block hash denoting when the last balance update was done.
diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp
index b5538b644f..61ccd9dd82 100644
--- a/src/qt/walletmodeltransaction.cpp
+++ b/src/qt/walletmodeltransaction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-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.
@@ -10,9 +10,8 @@
#include <policy/policy.h>
-WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &_recipients) :
- recipients(_recipients),
- fee(0)
+WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient>& _recipients)
+ : recipients(_recipients)
{
}
diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h
index 28fb551364..0e6ed8be49 100644
--- a/src/qt/walletmodeltransaction.h
+++ b/src/qt/walletmodeltransaction.h
@@ -41,7 +41,7 @@ public:
private:
QList<SendCoinsRecipient> recipients;
CTransactionRef wtx;
- CAmount fee;
+ CAmount fee{0};
};
#endif // BITCOIN_QT_WALLETMODELTRANSACTION_H
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 10fc0fb6d0..e62821d5bd 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -31,7 +31,6 @@
WalletView::WalletView(WalletModel* wallet_model, const PlatformStyle* _platformStyle, QWidget* parent)
: QStackedWidget(parent),
- clientModel(nullptr),
walletModel(wallet_model),
platformStyle(_platformStyle)
{
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index 301084ffa9..ebceef9cf9 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -50,7 +50,7 @@ public:
void showOutOfSyncWarning(bool fShow);
private:
- ClientModel *clientModel;
+ ClientModel* clientModel{nullptr};
//!
//! The wallet model represents a bitcoin wallet, and offers access to
diff --git a/src/random.cpp b/src/random.cpp
index eab54630b1..23ea9ba6b7 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -62,7 +62,7 @@ static inline int64_t GetPerformanceCounter() noexcept
__asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx.
return (r2 << 32) | r1;
#else
- // Fall back to using C++11 clock (usually microsecond or nanosecond precision)
+ // Fall back to using standard library clock (usually microsecond or nanosecond precision)
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
#endif
}
@@ -438,7 +438,7 @@ public:
RNGState& GetRNGState() noexcept
{
- // This C++11 idiom relies on the guarantee that static variable are initialized
+ // This idiom relies on the guarantee that static variable are initialized
// on first call, even when multiple parallel calls are permitted.
static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
return g_rng[0];
diff --git a/src/random.h b/src/random.h
index 082ccd4047..bb8b5539a3 100644
--- a/src/random.h
+++ b/src/random.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -201,7 +201,7 @@ public:
return rand64() >> (64 - bits);
} else {
if (bitbuf_size < bits) FillBitBuffer();
- uint64_t ret = bitbuf & (~(uint64_t)0 >> (64 - bits));
+ uint64_t ret = bitbuf & (~uint64_t{0} >> (64 - bits));
bitbuf >>= bits;
bitbuf_size -= bits;
return ret;
@@ -251,7 +251,7 @@ public:
/* interval [0..0] */ Dur{0};
};
- // Compatibility with the C++11 UniformRandomBitGenerator concept
+ // Compatibility with the UniformRandomBitGenerator concept
typedef uint64_t result_type;
static constexpr uint64_t min() { return 0; }
static constexpr uint64_t max() { return std::numeric_limits<uint64_t>::max(); }
diff --git a/src/randomenv.cpp b/src/randomenv.cpp
index 9e58180b7a..3e4d5a587d 100644
--- a/src/randomenv.cpp
+++ b/src/randomenv.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,21 +13,21 @@
#include <compat/cpuid.h>
#include <crypto/sha512.h>
#include <support/cleanse.h>
-#include <util/time.h> // for GetTime()
-#ifdef WIN32
-#include <compat/compat.h>
-#endif
+#include <util/time.h>
#include <algorithm>
#include <atomic>
+#include <cstdint>
+#include <cstring>
#include <chrono>
#include <climits>
#include <thread>
#include <vector>
-#include <stdint.h>
-#include <string.h>
-#ifndef WIN32
+#ifdef WIN32
+#include <windows.h>
+#include <winreg.h>
+#else
#include <sys/types.h> // must go before a number of other headers
#include <fcntl.h>
#include <netinet/in.h>
@@ -250,7 +250,7 @@ void RandAddDynamicEnv(CSHA512& hasher)
gettimeofday(&tv, nullptr);
hasher << tv;
#endif
- // Probably redundant, but also use all the clocks C++11 provides:
+ // Probably redundant, but also use all the standard library clocks:
hasher << std::chrono::system_clock::now().time_since_epoch().count();
hasher << std::chrono::steady_clock::now().time_since_epoch().count();
hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count();
diff --git a/src/rest.cpp b/src/rest.cpp
index 033e93468e..a874f4eb6d 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -236,7 +236,7 @@ static bool rest_headers(const std::any& context,
switch (rf) {
case RESTResponseFormat::BINARY: {
- CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ssHeader{};
for (const CBlockIndex *pindex : headers) {
ssHeader << pindex->GetBlockHeader();
}
@@ -248,7 +248,7 @@ static bool rest_headers(const std::any& context,
}
case RESTResponseFormat::HEX: {
- CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ssHeader{};
for (const CBlockIndex *pindex : headers) {
ssHeader << pindex->GetBlockHeader();
}
@@ -435,7 +435,7 @@ static bool rest_filter_header(const std::any& context, HTTPRequest* req, const
switch (rf) {
case RESTResponseFormat::BINARY: {
- CDataStream ssHeader{SER_NETWORK, PROTOCOL_VERSION};
+ DataStream ssHeader{};
for (const uint256& header : filter_headers) {
ssHeader << header;
}
@@ -446,7 +446,7 @@ static bool rest_filter_header(const std::any& context, HTTPRequest* req, const
return true;
}
case RESTResponseFormat::HEX: {
- CDataStream ssHeader{SER_NETWORK, PROTOCOL_VERSION};
+ DataStream ssHeader{};
for (const uint256& header : filter_headers) {
ssHeader << header;
}
@@ -534,7 +534,7 @@ static bool rest_block_filter(const std::any& context, HTTPRequest* req, const s
switch (rf) {
case RESTResponseFormat::BINARY: {
- CDataStream ssResp{SER_NETWORK, PROTOCOL_VERSION};
+ DataStream ssResp{};
ssResp << filter;
std::string binaryResp = ssResp.str();
@@ -543,7 +543,7 @@ static bool rest_block_filter(const std::any& context, HTTPRequest* req, const s
return true;
}
case RESTResponseFormat::HEX: {
- CDataStream ssResp{SER_NETWORK, PROTOCOL_VERSION};
+ DataStream ssResp{};
ssResp << filter;
std::string strHex = HexStr(ssResp) + "\n";
@@ -793,7 +793,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
if (fInputParsed) //don't allow sending input over URI and HTTP RAW DATA
return RESTERR(req, HTTP_BAD_REQUEST, "Combination of URI scheme inputs and raw post data is not allowed");
- CDataStream oss(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream oss{};
oss << strRequestMutable;
oss >> fCheckMemPool;
oss >> vOutPoints;
@@ -866,7 +866,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
case RESTResponseFormat::BINARY: {
// serialize data
// use exact same output as mentioned in Bip64
- CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ssGetUTXOResponse{};
ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
std::string ssGetUTXOResponseString = ssGetUTXOResponse.str();
@@ -876,7 +876,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
}
case RESTResponseFormat::HEX: {
- CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ssGetUTXOResponse{};
ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
std::string strHex = HexStr(ssGetUTXOResponse) + "\n";
@@ -946,7 +946,7 @@ static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,
}
switch (rf) {
case RESTResponseFormat::BINARY: {
- CDataStream ss_blockhash(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ss_blockhash{};
ss_blockhash << pblockindex->GetBlockHash();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, ss_blockhash.str());
diff --git a/src/reverse_iterator.h b/src/reverse_iterator.h
index 729d8c11cc..4db001c04b 100644
--- a/src/reverse_iterator.h
+++ b/src/reverse_iterator.h
@@ -4,7 +4,7 @@
#define BITCOIN_REVERSE_ITERATOR_H
/**
- * Template used for reverse iteration in C++11 range-based for loops.
+ * Template used for reverse iteration in range-based for loops.
*
* std::vector<int> v = {1, 2, 3, 4, 5};
* for (auto x : reverse_iterate(v))
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 784fb64d36..8bee066ab8 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -25,6 +25,7 @@
#include <net_processing.h>
#include <node/blockstorage.h>
#include <node/context.h>
+#include <node/transaction.h>
#include <node/utxo_snapshot.h>
#include <primitives/transaction.h>
#include <rpc/server.h>
@@ -444,11 +445,6 @@ static RPCHelpMan getblockfrompeer()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {
- UniValue::VSTR, // blockhash
- UniValue::VNUM, // peer_id
- });
-
const NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node);
PeerManager& peerman = EnsurePeerman(node);
@@ -464,7 +460,7 @@ static RPCHelpMan getblockfrompeer()
// Fetching blocks before the node has syncing past their height can prevent block files from
// being pruned, so we avoid it if the node is in prune mode.
- if (node::fPruneMode && index->nHeight > WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip()->nHeight)) {
+ if (chainman.m_blockman.IsPruneMode() && index->nHeight > WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip()->nHeight)) {
throw JSONRPCError(RPC_MISC_ERROR, "In prune mode, only blocks that the node has already synced previously can be fetched from a peer");
}
@@ -569,7 +565,7 @@ static RPCHelpMan getblockheader()
if (!fVerbose)
{
- CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ssBlock{};
ssBlock << pblockindex->GetBlockHeader();
std::string strHex = HexStr(ssBlock);
return strHex;
@@ -654,7 +650,8 @@ static RPCHelpMan getblock()
"If verbosity is 3, returns an Object with information about block <hash> and information about each transaction, including prevout information for inputs (only for unpruned blocks in the current best chain).\n",
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
- {"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{1}, "0 for hex-encoded data, 1 for a JSON object, 2 for JSON object with transaction data, and 3 for JSON object with transaction data including prevout information for inputs"},
+ {"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{1}, "0 for hex-encoded data, 1 for a JSON object, 2 for JSON object with transaction data, and 3 for JSON object with transaction data including prevout information for inputs",
+ RPCArgOptions{.skip_type_check = true}},
},
{
RPCResult{"for verbosity = 0",
@@ -778,10 +775,11 @@ static RPCHelpMan pruneblockchain()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- if (!node::fPruneMode)
+ ChainstateManager& chainman = EnsureAnyChainman(request.context);
+ if (!chainman.m_blockman.IsPruneMode()) {
throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode.");
+ }
- ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
Chainstate& active_chainstate = chainman.ActiveChainstate();
CChain& active_chain = active_chainstate.m_chain;
@@ -872,7 +870,11 @@ static RPCHelpMan gettxoutsetinfo()
"Note this call may take some time if you are not using coinstatsindex.\n",
{
{"hash_type", RPCArg::Type::STR, RPCArg::Default{"hash_serialized_2"}, "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."},
- {"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).", RPCArgOptions{.type_str={"", "string or numeric"}}},
+ {"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).",
+ RPCArgOptions{
+ .skip_type_check = true,
+ .type_str = {"", "string or numeric"},
+ }},
{"use_index", RPCArg::Type::BOOL, RPCArg::Default{true}, "Use coinstatsindex, if available."},
},
RPCResult{
@@ -1265,15 +1267,15 @@ RPCHelpMan getblockchaininfo()
obj.pushKV("initialblockdownload", active_chainstate.IsInitialBlockDownload());
obj.pushKV("chainwork", tip.nChainWork.GetHex());
obj.pushKV("size_on_disk", chainman.m_blockman.CalculateCurrentUsage());
- obj.pushKV("pruned", node::fPruneMode);
- if (node::fPruneMode) {
+ obj.pushKV("pruned", chainman.m_blockman.IsPruneMode());
+ if (chainman.m_blockman.IsPruneMode()) {
obj.pushKV("pruneheight", chainman.m_blockman.GetFirstStoredBlock(tip)->nHeight);
// if 0, execution bypasses the whole if block.
bool automatic_pruning{args.GetIntArg("-prune", 0) != 1};
obj.pushKV("automatic_pruning", automatic_pruning);
if (automatic_pruning) {
- obj.pushKV("prune_target_size", node::nPruneTarget);
+ obj.pushKV("prune_target_size", chainman.m_blockman.GetPruneTarget());
}
}
@@ -1742,7 +1744,11 @@ static RPCHelpMan getblockstats()
"\nCompute per block statistics for a given window. All amounts are in satoshis.\n"
"It won't work for some heights with pruning.\n",
{
- {"hash_or_height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block hash or height of the target block", RPCArgOptions{.type_str={"", "string or numeric"}}},
+ {"hash_or_height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block hash or height of the target block",
+ RPCArgOptions{
+ .skip_type_check = true,
+ .type_str = {"", "string or numeric"},
+ }},
{"stats", RPCArg::Type::ARR, RPCArg::DefaultHint{"all values"}, "Values to plot (see result below)",
{
{"height", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"},
@@ -2144,8 +2150,6 @@ static RPCHelpMan scantxoutset()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});
-
UniValue result(UniValue::VOBJ);
if (request.params[0].get_str() == "status") {
CoinsViewScanReserver reserver;
@@ -2268,17 +2272,47 @@ public:
}
};
+static bool CheckBlockFilterMatches(BlockManager& blockman, const CBlockIndex& blockindex, const GCSFilter::ElementSet& needles)
+{
+ const CBlock block{GetBlockChecked(blockman, &blockindex)};
+ const CBlockUndo block_undo{GetUndoChecked(blockman, &blockindex)};
+
+ // Check if any of the outputs match the scriptPubKey
+ for (const auto& tx : block.vtx) {
+ if (std::any_of(tx->vout.cbegin(), tx->vout.cend(), [&](const auto& txout) {
+ return needles.count(std::vector<unsigned char>(txout.scriptPubKey.begin(), txout.scriptPubKey.end())) != 0;
+ })) {
+ return true;
+ }
+ }
+ // Check if any of the inputs match the scriptPubKey
+ for (const auto& txundo : block_undo.vtxundo) {
+ if (std::any_of(txundo.vprevout.cbegin(), txundo.vprevout.cend(), [&](const auto& coin) {
+ return needles.count(std::vector<unsigned char>(coin.out.scriptPubKey.begin(), coin.out.scriptPubKey.end())) != 0;
+ })) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static RPCHelpMan scanblocks()
{
return RPCHelpMan{"scanblocks",
- "\nReturn relevant blockhashes for given descriptors.\n"
+ "\nReturn relevant blockhashes for given descriptors (requires blockfilterindex).\n"
"This call may take several minutes. Make sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
{
scan_action_arg_desc,
scan_objects_arg_desc,
RPCArg{"start_height", RPCArg::Type::NUM, RPCArg::Default{0}, "Height to start to scan from"},
RPCArg{"stop_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"chain tip"}, "Height to stop to scan"},
- RPCArg{"filtertype", RPCArg::Type::STR, RPCArg::Default{BlockFilterTypeName(BlockFilterType::BASIC)}, "The type name of the filter"}
+ RPCArg{"filtertype", RPCArg::Type::STR, RPCArg::Default{BlockFilterTypeName(BlockFilterType::BASIC)}, "The type name of the filter"},
+ RPCArg{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"filter_false_positives", RPCArg::Type::BOOL, RPCArg::Default{false}, "Filter false positives (slower and may fail on pruned nodes). Otherwise they may occur at a rate of 1/M"},
+ },
+ RPCArgOptions{.oneline_description="\"options\""}},
},
{
scan_result_status_none,
@@ -2338,6 +2372,9 @@ static RPCHelpMan scanblocks()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown filtertype");
}
+ UniValue options{request.params[5].isNull() ? UniValue::VOBJ : request.params[5]};
+ bool filter_false_positives{options.exists("filter_false_positives") ? options["filter_false_positives"].get_bool() : false};
+
BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
if (!index) {
throw JSONRPCError(RPC_MISC_ERROR, "Index is not enabled for filtertype " + filtertype_name);
@@ -2408,6 +2445,15 @@ static RPCHelpMan scanblocks()
for (const BlockFilter& filter : filters) {
// compare the elements-set with each filter
if (filter.GetFilter().MatchAny(needle_set)) {
+ if (filter_false_positives) {
+ // Double check the filter matches by scanning the block
+ const CBlockIndex& blockindex = *CHECK_NONFATAL(WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(filter.GetBlockHash())));
+
+ if (!CheckBlockFilterMatches(chainman.m_blockman, blockindex, needle_set)) {
+ continue;
+ }
+ }
+
blocks.push_back(filter.GetBlockHash().GetHex());
LogPrint(BCLog::RPC, "scanblocks: found match in %s\n", filter.GetBlockHash().GetHex());
}
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index 6cdb5fa48b..9ccb87b78a 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,8 +16,6 @@
#include <stdint.h>
#include <vector>
-extern RecursiveMutex cs_main;
-
class CBlock;
class CBlockIndex;
class Chainstate;
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index b3434b80c7..5fe914f0a1 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -86,6 +86,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "scanblocks", 1, "scanobjects" },
{ "scanblocks", 2, "start_height" },
{ "scanblocks", 3, "stop_height" },
+ { "scanblocks", 5, "options" },
{ "scantxoutset", 1, "scanobjects" },
{ "addmultisigaddress", 0, "nrequired" },
{ "addmultisigaddress", 1, "keys" },
@@ -102,6 +103,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getchaintxstats", 0, "nblocks" },
{ "gettransaction", 1, "include_watchonly" },
{ "gettransaction", 2, "verbose" },
+ { "getrawtransaction", 1, "verbosity" },
{ "getrawtransaction", 1, "verbose" },
{ "createrawtransaction", 0, "inputs" },
{ "createrawtransaction", 1, "outputs" },
@@ -225,11 +227,16 @@ private:
public:
CRPCConvertTable();
- bool convert(const std::string& method, int idx) {
- return (members.count(std::make_pair(method, idx)) > 0);
+ /** Return arg_value as UniValue, and first parse it if it is a non-string parameter */
+ UniValue ArgToUniValue(const std::string& arg_value, const std::string& method, int param_idx)
+ {
+ return members.count(std::make_pair(method, param_idx)) > 0 ? ParseNonRFCJSONValue(arg_value) : arg_value;
}
- bool convert(const std::string& method, const std::string& name) {
- return (membersByName.count(std::make_pair(method, name)) > 0);
+
+ /** Return arg_value as UniValue, and first parse it if it is a non-string parameter */
+ UniValue ArgToUniValue(const std::string& arg_value, const std::string& method, const std::string& param_name)
+ {
+ return membersByName.count(std::make_pair(method, param_name)) > 0 ? ParseNonRFCJSONValue(arg_value) : arg_value;
}
};
@@ -261,14 +268,7 @@ UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::s
for (unsigned int idx = 0; idx < strParams.size(); idx++) {
const std::string& strVal = strParams[idx];
-
- if (!rpcCvtTable.convert(strMethod, idx)) {
- // insert string value directly
- params.push_back(strVal);
- } else {
- // parse string as JSON, insert bool/number/object/etc. value
- params.push_back(ParseNonRFCJSONValue(strVal));
- }
+ params.push_back(rpcCvtTable.ArgToUniValue(strVal, strMethod, idx));
}
return params;
@@ -282,24 +282,24 @@ UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector<s
for (const std::string &s: strParams) {
size_t pos = s.find('=');
if (pos == std::string::npos) {
- positional_args.push_back(rpcCvtTable.convert(strMethod, positional_args.size()) ? ParseNonRFCJSONValue(s) : s);
+ positional_args.push_back(rpcCvtTable.ArgToUniValue(s, strMethod, positional_args.size()));
continue;
}
std::string name = s.substr(0, pos);
std::string value = s.substr(pos+1);
- if (!rpcCvtTable.convert(strMethod, name)) {
- // insert string value directly
- params.pushKV(name, value);
- } else {
- // parse string as JSON, insert bool/number/object/etc. value
- params.pushKV(name, ParseNonRFCJSONValue(value));
- }
+ // Intentionally overwrite earlier named values with later ones as a
+ // convenience for scripts and command line users that want to merge
+ // options.
+ params.pushKV(name, rpcCvtTable.ArgToUniValue(value, strMethod, name));
}
if (!positional_args.empty()) {
- params.pushKV("args", positional_args);
+ // Use __pushKV instead of pushKV to avoid overwriting an explicit
+ // "args" value with an implicit one. Let the RPC server handle the
+ // request as given.
+ params.__pushKV("args", positional_args);
}
return params;
diff --git a/src/rpc/external_signer.cpp b/src/rpc/external_signer.cpp
index 4de7fc4205..f5a6913572 100644
--- a/src/rpc/external_signer.cpp
+++ b/src/rpc/external_signer.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/fees.cpp b/src/rpc/fees.cpp
index e50bf00473..62396d4c58 100644
--- a/src/rpc/fees.cpp
+++ b/src/rpc/fees.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -63,8 +63,6 @@ static RPCHelpMan estimatesmartfee()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
-
CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
const NodeContext& node = EnsureAnyNodeContext(request.context);
const CTxMemPool& mempool = EnsureMemPool(node);
@@ -155,8 +153,6 @@ static RPCHelpMan estimaterawfee()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
-
CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp
index 7a0c361ae0..44f7435a26 100644
--- a/src/rpc/mempool.cpp
+++ b/src/rpc/mempool.cpp
@@ -23,6 +23,8 @@
#include <util/moneystr.h>
#include <util/time.h>
+#include <utility>
+
using kernel::DumpMempool;
using node::DEFAULT_MAX_RAW_TX_FEE_RATE;
@@ -59,11 +61,6 @@ static RPCHelpMan sendrawtransaction()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {
- UniValue::VSTR,
- UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
- });
-
CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_str())) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
@@ -124,6 +121,10 @@ static RPCHelpMan testmempoolaccept()
{RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees (only present if 'allowed' is true)",
{
{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
+ {RPCResult::Type::STR_AMOUNT, "effective-feerate", /*optional=*/false, "the effective feerate in " + CURRENCY_UNIT + " per KvB. May differ from the base feerate if, for example, there are modified fees from prioritisetransaction or a package feerate was used."},
+ {RPCResult::Type::ARR, "effective-includes", /*optional=*/false, "transactions whose fees and vsizes are included in effective-feerate.",
+ {RPCResult{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
+ }},
}},
{RPCResult::Type::STR, "reject-reason", /*optional=*/true, "Rejection string (only present when 'allowed' is false)"},
}},
@@ -141,10 +142,6 @@ static RPCHelpMan testmempoolaccept()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {
- UniValue::VARR,
- UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
- });
const UniValue raw_transactions = request.params[0].get_array();
if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
@@ -215,6 +212,12 @@ static RPCHelpMan testmempoolaccept()
result_inner.pushKV("vsize", virtual_size);
UniValue fees(UniValue::VOBJ);
fees.pushKV("base", ValueFromAmount(fee));
+ fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK()));
+ UniValue effective_includes_res(UniValue::VARR);
+ for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) {
+ effective_includes_res.push_back(wtxid.ToString());
+ }
+ fees.pushKV("effective-includes", effective_includes_res);
result_inner.pushKV("fees", fees);
}
} else {
@@ -449,19 +452,17 @@ static RPCHelpMan getmempoolancestors()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
}
- CTxMemPool::setEntries setAncestors;
- std::string dummy;
- mempool.CalculateMemPoolAncestors(*it, setAncestors, CTxMemPool::Limits::NoLimits(), dummy, false);
+ auto ancestors{mempool.AssumeCalculateMemPoolAncestors(__func__, *it, CTxMemPool::Limits::NoLimits(), /*fSearchForParents=*/false)};
if (!fVerbose) {
UniValue o(UniValue::VARR);
- for (CTxMemPool::txiter ancestorIt : setAncestors) {
+ for (CTxMemPool::txiter ancestorIt : ancestors) {
o.push_back(ancestorIt->GetTx().GetHash().ToString());
}
return o;
} else {
UniValue o(UniValue::VOBJ);
- for (CTxMemPool::txiter ancestorIt : setAncestors) {
+ for (CTxMemPool::txiter ancestorIt : ancestors) {
const CTxMemPoolEntry &e = *ancestorIt;
const uint256& _hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
@@ -768,10 +769,13 @@ static RPCHelpMan submitpackage()
{RPCResult::Type::NUM, "vsize", "Virtual transaction size as defined in BIP 141."},
{RPCResult::Type::OBJ, "fees", "Transaction fees", {
{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
+ {RPCResult::Type::STR_AMOUNT, "effective-feerate", /*optional=*/true, "if the transaction was not already in the mempool, the effective feerate in " + CURRENCY_UNIT + " per KvB. For example, the package feerate and/or feerate with modified fees from prioritisetransaction."},
+ {RPCResult::Type::ARR, "effective-includes", /*optional=*/true, "if effective-feerate is provided, the wtxids of the transactions whose fees and vsizes are included in effective-feerate.",
+ {{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
+ }},
}},
}}
}},
- {RPCResult::Type::STR_AMOUNT, "package-feerate", /*optional=*/true, "package feerate used for feerate checks in " + CURRENCY_UNIT + " per KvB. Excludes transactions which were deduplicated or accepted individually."},
{RPCResult::Type::ARR, "replaced-transactions", /*optional=*/true, "List of txids of replaced transactions",
{
{RPCResult::Type::STR_HEX, "", "The transaction id"},
@@ -787,9 +791,6 @@ static RPCHelpMan submitpackage()
if (!Params().IsMockableChain()) {
throw std::runtime_error("submitpackage is for regression testing (-regtest mode) only");
}
- RPCTypeCheck(request.params, {
- UniValue::VARR,
- });
const UniValue raw_transactions = request.params[0].get_array();
if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
@@ -856,6 +857,7 @@ static RPCHelpMan submitpackage()
CHECK_NONFATAL(it != package_result.m_tx_results.end());
UniValue result_inner{UniValue::VOBJ};
result_inner.pushKV("txid", tx->GetHash().GetHex());
+ const auto& tx_result = it->second;
if (it->second.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS) {
result_inner.pushKV("other-wtxid", it->second.m_other_wtxid.value().GetHex());
}
@@ -864,6 +866,17 @@ static RPCHelpMan submitpackage()
result_inner.pushKV("vsize", int64_t{it->second.m_vsize.value()});
UniValue fees(UniValue::VOBJ);
fees.pushKV("base", ValueFromAmount(it->second.m_base_fees.value()));
+ if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
+ // Effective feerate is not provided for MEMPOOL_ENTRY transactions even
+ // though modified fees is known, because it is unknown whether package
+ // feerate was used when it was originally submitted.
+ fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK()));
+ UniValue effective_includes_res(UniValue::VARR);
+ for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) {
+ effective_includes_res.push_back(wtxid.ToString());
+ }
+ fees.pushKV("effective-includes", effective_includes_res);
+ }
result_inner.pushKV("fees", fees);
if (it->second.m_replaced_transactions.has_value()) {
for (const auto& ptx : it->second.m_replaced_transactions.value()) {
@@ -874,9 +887,6 @@ static RPCHelpMan submitpackage()
tx_result_map.pushKV(tx->GetWitnessHash().GetHex(), result_inner);
}
rpc_result.pushKV("tx-results", tx_result_map);
- if (package_result.m_package_feerate.has_value()) {
- rpc_result.pushKV("package-feerate", ValueFromAmount(package_result.m_package_feerate.value().GetFeePerK()));
- }
UniValue replaced_list(UniValue::VARR);
for (const uint256& hash : replaced_txids) replaced_list.push_back(hash.ToString());
rpc_result.pushKV("replaced-transactions", replaced_list);
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 98383fdaca..8753f845a5 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -441,7 +441,7 @@ static RPCHelpMan prioritisetransaction()
"Accepts the transaction into mined blocks at a higher (or lower) priority\n",
{
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id."},
- {"dummy", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "API-Compatibility for previous API. Must be zero or null.\n"
+ {"dummy", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "API-Compatibility for previous API. Must be zero or null.\n"
" DEPRECATED. For forward compatibility use named arguments and omit this parameter."},
{"fee_delta", RPCArg::Type::NUM, RPCArg::Optional::NO, "The fee value (in satoshis) to add (or subtract, if negative).\n"
" Note, that this value is not a fee rate. It is a value to modify absolute fee of the TX.\n"
@@ -513,8 +513,8 @@ static RPCHelpMan getblocktemplate()
{
{"template_request", RPCArg::Type::OBJ, RPCArg::Default{UniValue::VOBJ}, "Format of the template",
{
- {"mode", RPCArg::Type::STR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"},
- {"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "A list of strings",
+ {"mode", RPCArg::Type::STR, /* treat as named arg */ RPCArg::Optional::OMITTED, "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"},
+ {"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED, "A list of strings",
{
{"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported feature, 'longpoll', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"},
}},
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 1a4cd09284..f0e5b90509 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -114,7 +114,7 @@ static RPCHelpMan getpeerinfo()
{
{RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"}
}},
- {RPCResult::Type::BOOL, "relaytxes", /*optional=*/true, "Whether we relay transactions to this peer"},
+ {RPCResult::Type::BOOL, "relaytxes", "Whether we relay transactions to this peer"},
{RPCResult::Type::NUM_TIME, "lastsend", "The " + UNIX_EPOCH_TIME + " of the last send"},
{RPCResult::Type::NUM_TIME, "lastrecv", "The " + UNIX_EPOCH_TIME + " of the last receive"},
{RPCResult::Type::NUM_TIME, "last_transaction", "The " + UNIX_EPOCH_TIME + " of the last valid transaction received from this peer"},
@@ -131,17 +131,17 @@ static RPCHelpMan getpeerinfo()
{RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
{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", /*optional=*/true, "The starting height (block) of the peer"},
- {RPCResult::Type::NUM, "presynced_headers", /*optional=*/true, "The current height of header pre-synchronization with this peer, or -1 if no low-work sync is in progress"},
- {RPCResult::Type::NUM, "synced_headers", /*optional=*/true, "The last header we have in common with this peer"},
- {RPCResult::Type::NUM, "synced_blocks", /*optional=*/true, "The last block we have in common with this peer"},
- {RPCResult::Type::ARR, "inflight", /*optional=*/true, "",
+ {RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
+ {RPCResult::Type::NUM, "presynced_headers", "The current height of header pre-synchronization with this peer, or -1 if no low-work sync is in progress"},
+ {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, "addr_relay_enabled", /*optional=*/true, "Whether we participate in address relay with this peer"},
- {RPCResult::Type::NUM, "addr_processed", /*optional=*/true, "The total number of addresses processed, excluding those dropped due to rate limiting"},
- {RPCResult::Type::NUM, "addr_rate_limited", /*optional=*/true, "The total number of addresses dropped due to rate limiting"},
+ {RPCResult::Type::BOOL, "addr_relay_enabled", "Whether we participate in address relay with this peer"},
+ {RPCResult::Type::NUM, "addr_processed", "The total number of addresses processed, excluding those dropped due to rate limiting"},
+ {RPCResult::Type::NUM, "addr_rate_limited", "The total number of addresses dropped due to rate limiting"},
{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"},
@@ -185,6 +185,14 @@ static RPCHelpMan getpeerinfo()
UniValue obj(UniValue::VOBJ);
CNodeStateStats statestats;
bool fStateStats = peerman.GetNodeStateStats(stats.nodeid, statestats);
+ // GetNodeStateStats() requires the existence of a CNodeState and a Peer object
+ // to succeed for this peer. These are created at connection initialisation and
+ // exist for the duration of the connection - except if there is a race where the
+ // peer got disconnected in between the GetNodeStats() and the GetNodeStateStats()
+ // calls. In this case, the peer doesn't need to be reported here.
+ if (!fStateStats) {
+ continue;
+ }
obj.pushKV("id", stats.nodeid);
obj.pushKV("addr", stats.m_addr_name);
if (stats.addrBind.IsValid()) {
@@ -197,12 +205,10 @@ static RPCHelpMan getpeerinfo()
if (stats.m_mapped_as != 0) {
obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
}
- ServiceFlags services{fStateStats ? statestats.their_services : ServiceFlags::NODE_NONE};
+ ServiceFlags services{statestats.their_services};
obj.pushKV("services", strprintf("%016x", services));
obj.pushKV("servicesnames", GetServicesNames(services));
- if (fStateStats) {
- obj.pushKV("relaytxes", statestats.m_relay_txs);
- }
+ obj.pushKV("relaytxes", statestats.m_relay_txs);
obj.pushKV("lastsend", count_seconds(stats.m_last_send));
obj.pushKV("lastrecv", count_seconds(stats.m_last_recv));
obj.pushKV("last_transaction", count_seconds(stats.m_last_tx_time));
@@ -217,7 +223,7 @@ static RPCHelpMan getpeerinfo()
if (stats.m_min_ping_time < std::chrono::microseconds::max()) {
obj.pushKV("minping", Ticks<SecondsDouble>(stats.m_min_ping_time));
}
- if (fStateStats && statestats.m_ping_wait > 0s) {
+ if (statestats.m_ping_wait > 0s) {
obj.pushKV("pingwait", Ticks<SecondsDouble>(statestats.m_ping_wait));
}
obj.pushKV("version", stats.nVersion);
@@ -228,26 +234,24 @@ static RPCHelpMan getpeerinfo()
obj.pushKV("inbound", stats.fInbound);
obj.pushKV("bip152_hb_to", stats.m_bip152_highbandwidth_to);
obj.pushKV("bip152_hb_from", stats.m_bip152_highbandwidth_from);
- if (fStateStats) {
- obj.pushKV("startingheight", statestats.m_starting_height);
- obj.pushKV("presynced_headers", statestats.presync_height);
- obj.pushKV("synced_headers", statestats.nSyncHeight);
- obj.pushKV("synced_blocks", statestats.nCommonHeight);
- UniValue heights(UniValue::VARR);
- for (const int height : statestats.vHeightInFlight) {
- heights.push_back(height);
- }
- obj.pushKV("inflight", heights);
- obj.pushKV("addr_relay_enabled", statestats.m_addr_relay_enabled);
- obj.pushKV("addr_processed", statestats.m_addr_processed);
- obj.pushKV("addr_rate_limited", statestats.m_addr_rate_limited);
+ obj.pushKV("startingheight", statestats.m_starting_height);
+ obj.pushKV("presynced_headers", statestats.presync_height);
+ obj.pushKV("synced_headers", statestats.nSyncHeight);
+ obj.pushKV("synced_blocks", statestats.nCommonHeight);
+ UniValue heights(UniValue::VARR);
+ for (const int height : statestats.vHeightInFlight) {
+ heights.push_back(height);
}
+ obj.pushKV("inflight", heights);
+ obj.pushKV("addr_relay_enabled", statestats.m_addr_relay_enabled);
+ obj.pushKV("addr_processed", statestats.m_addr_processed);
+ obj.pushKV("addr_rate_limited", statestats.m_addr_rate_limited);
UniValue permissions(UniValue::VARR);
for (const auto& permission : NetPermissions::ToStrings(stats.m_permission_flags)) {
permissions.push_back(permission);
}
obj.pushKV("permissions", permissions);
- obj.pushKV("minfeefilter", fStateStats ? ValueFromAmount(statestats.m_fee_filter_received) : 0);
+ obj.pushKV("minfeefilter", ValueFromAmount(statestats.m_fee_filter_received));
UniValue sendPerMsgType(UniValue::VOBJ);
for (const auto& i : stats.mapSendBytesPerMsgType) {
@@ -354,7 +358,6 @@ static RPCHelpMan addconnection()
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{};
@@ -733,6 +736,10 @@ static RPCHelpMan setban()
const bool absolute{request.params[3].isNull() ? false : request.params[3].get_bool()};
+ if (absolute && banTime < GetTime()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Error: Absolute timestamp is in the past");
+ }
+
if (isSubnet) {
node.banman->Ban(subNet, banTime, absolute);
if (node.connman) {
diff --git a/src/rpc/node.cpp b/src/rpc/node.cpp
index 605ebc15a7..5918bc6e38 100644
--- a/src/rpc/node.cpp
+++ b/src/rpc/node.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,6 +12,7 @@
#include <interfaces/echo.h>
#include <interfaces/init.h>
#include <interfaces/ipc.h>
+#include <kernel/cs_main.h>
#include <node/context.h>
#include <rpc/server.h>
#include <rpc/server_util.h>
@@ -52,7 +53,6 @@ static RPCHelpMan setmocktime()
// ensure all call sites of GetTime() are accessing this safely.
LOCK(cs_main);
- RPCTypeCheck(request.params, {UniValue::VNUM});
const int64_t time{request.params[0].getInt<int64_t>()};
if (time < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Mocktime cannot be negative: %s.", time));
@@ -106,8 +106,6 @@ static RPCHelpMan mockscheduler()
throw std::runtime_error("mockscheduler is for regression testing (-regtest mode) only");
}
- // check params are valid values
- RPCTypeCheck(request.params, {UniValue::VNUM});
int64_t delta_seconds = request.params[0].getInt<int64_t>();
if (delta_seconds <= 0 || delta_seconds > 3600) {
throw std::runtime_error("delta_time must be between 1 and 3600 seconds (1 hr)");
@@ -242,11 +240,11 @@ static RPCHelpMan logging()
" - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n"
,
{
- {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The categories to add to debug logging",
+ {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The categories to add to debug logging",
{
{"include_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
}},
- {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The categories to remove from debug logging",
+ {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The categories to remove from debug logging",
{
{"exclude_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
}},
@@ -295,18 +293,18 @@ static RPCHelpMan echo(const std::string& name)
"\nIt will return an internal bug report when arg9='trigger_internal_bug' is passed.\n"
"\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in "
"bitcoin-cli and the GUI. There is no server-side difference.",
- {
- {"arg0", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg4", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg5", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg6", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg7", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg8", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- {"arg9", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
- },
+ {
+ {"arg0", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg4", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg5", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg6", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg7", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg8", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ {"arg9", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
+ },
RPCResult{RPCResult::Type::ANY, "", "Returns whatever was passed in"},
RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
@@ -378,7 +376,7 @@ static RPCHelpMan getindexinfo()
return RPCHelpMan{"getindexinfo",
"\nReturns the status of one or all available indices currently running in the node.\n",
{
- {"index_name", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Filter results for an index with a specific name."},
+ {"index_name", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Filter results for an index with a specific name."},
},
RPCResult{
RPCResult::Type::OBJ_DYN, "", "", {
diff --git a/src/rpc/output_script.cpp b/src/rpc/output_script.cpp
index 2ac6d6d76f..bb04f58424 100644
--- a/src/rpc/output_script.cpp
+++ b/src/rpc/output_script.cpp
@@ -195,8 +195,6 @@ static RPCHelpMan getdescriptorinfo()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR});
-
FlatSigningProvider provider;
std::string error;
auto desc = Parse(request.params[0].get_str(), provider, error);
@@ -232,7 +230,7 @@ static RPCHelpMan deriveaddresses()
"For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n"},
{
{"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."},
- {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."},
+ {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."},
},
RPCResult{
RPCResult::Type::ARR, "", "",
@@ -247,7 +245,6 @@ static RPCHelpMan deriveaddresses()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later
const std::string desc_str = request.params[0].get_str();
int64_t range_begin = 0;
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 400f2f1507..503099d8a9 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -32,6 +32,7 @@
#include <script/signingprovider.h>
#include <script/standard.h>
#include <uint256.h>
+#include <undo.h>
#include <util/bip32.h>
#include <util/check.h>
#include <util/strencodings.h>
@@ -50,15 +51,20 @@ using node::FindCoins;
using node::GetTransaction;
using node::NodeContext;
using node::PSBTAnalysis;
+using node::ReadBlockFromDisk;
+using node::UndoReadFromDisk;
-static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, Chainstate& active_chainstate)
+static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry,
+ Chainstate& active_chainstate, const CTxUndo* txundo = nullptr,
+ TxVerbosity verbosity = TxVerbosity::SHOW_DETAILS)
{
+ CHECK_NONFATAL(verbosity >= TxVerbosity::SHOW_DETAILS);
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
//
// Blockchain contextual information (confirmations and blocktime) is not
// available to code in bitcoin-common, so we query them here and push the
// data into the returned UniValue.
- TxToUniv(tx, /*block_hash=*/uint256(), entry, /*include_hex=*/true, RPCSerializationFlags());
+ TxToUniv(tx, /*block_hash=*/uint256(), entry, /*include_hex=*/true, RPCSerializationFlags(), txundo, verbosity);
if (!hashBlock.IsNull()) {
LOCK(cs_main);
@@ -77,6 +83,17 @@ static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue&
}
}
+static std::vector<RPCResult> ScriptPubKeyDoc() {
+ return
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the public key script"},
+ {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw public key script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::STR, "type", "The type (one of: " + GetAllOutputTypes() + ")"},
+ };
+}
+
static std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc)
{
return {
@@ -112,14 +129,7 @@ static std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc)
{
{RPCResult::Type::STR_AMOUNT, "value", "The value in " + CURRENCY_UNIT},
{RPCResult::Type::NUM, "n", "index"},
- {RPCResult::Type::OBJ, "scriptPubKey", "",
- {
- {RPCResult::Type::STR, "asm", "Disassembly of the public key script"},
- {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
- {RPCResult::Type::STR_HEX, "hex", "The raw public key script bytes, hex-encoded"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
- }},
+ {RPCResult::Type::OBJ, "scriptPubKey", "", ScriptPubKeyDoc()},
}},
}},
};
@@ -155,7 +165,7 @@ static std::vector<RPCArg> CreateTxDoc()
},
},
},
- },
+ RPCArgOptions{.skip_type_check = true}},
{"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
{"replaceable", RPCArg::Type::BOOL, RPCArg::Default{true}, "Marks this transaction as BIP125-replaceable.\n"
"Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
@@ -166,26 +176,27 @@ static RPCHelpMan getrawtransaction()
{
return RPCHelpMan{
"getrawtransaction",
- "Return the raw transaction data.\n"
- "\nBy default, this call only returns a transaction if it is in the mempool. If -txindex is enabled\n"
+ "By default, this call only returns a transaction if it is in the mempool. If -txindex is enabled\n"
"and no blockhash argument is passed, it will return the transaction if it is in the mempool or any block.\n"
"If a blockhash argument is passed, it will return the transaction if\n"
- "the specified block is available and the transaction is in that block.\n"
- "\nHint: Use gettransaction for wallet transactions.\n"
+ "the specified block is available and the transaction is in that block.\n\n"
+ "Hint: Use gettransaction for wallet transactions.\n\n"
- "\nIf verbose is 'true', returns an Object with information about 'txid'.\n"
- "If verbose is 'false' or omitted, returns a string that is serialized, hex-encoded data for 'txid'.",
+ "If verbosity is 0 or omitted, returns the serialized transaction as a hex-encoded string.\n"
+ "If verbosity is 1, returns a JSON Object with information about the transaction.\n"
+ "If verbosity is 2, returns a JSON Object with information about the transaction, including fee and prevout information.",
{
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
- {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If false, return a string, otherwise return a json object"},
- {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "The block in which to look for the transaction"},
+ {"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{0}, "0 for hex-encoded data, 1 for a JSON object, and 2 for JSON object with fee and prevout",
+ RPCArgOptions{.skip_type_check = true}},
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The block in which to look for the transaction"},
},
{
- RPCResult{"if verbose is not set or set to false",
- RPCResult::Type::STR, "data", "The serialized, hex-encoded data for 'txid'"
+ RPCResult{"if verbosity is not set or set to 0",
+ RPCResult::Type::STR, "data", "The serialized transaction as a hex-encoded string for 'txid'"
},
- RPCResult{"if verbose is set to true",
+ RPCResult{"if verbosity is set to 1",
RPCResult::Type::OBJ, "", "",
Cat<std::vector<RPCResult>>(
{
@@ -198,20 +209,40 @@ static RPCHelpMan getrawtransaction()
},
DecodeTxDoc(/*txid_field_doc=*/"The transaction id (same as provided)")),
},
+ RPCResult{"for verbosity = 2",
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"},
+ {RPCResult::Type::NUM, "fee", /*optional=*/true, "transaction fee in " + CURRENCY_UNIT + ", omitted if block undo data is not available"},
+ {RPCResult::Type::ARR, "vin", "",
+ {
+ {RPCResult::Type::OBJ, "", "utxo being spent, omitted if block undo data is not available",
+ {
+ {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"},
+ {RPCResult::Type::OBJ, "prevout", /*optional=*/true, "Only if undo information is available)",
+ {
+ {RPCResult::Type::BOOL, "generated", "Coinbase or not"},
+ {RPCResult::Type::NUM, "height", "The height of the prevout"},
+ {RPCResult::Type::STR_AMOUNT, "value", "The value in " + CURRENCY_UNIT},
+ {RPCResult::Type::OBJ, "scriptPubKey", "", ScriptPubKeyDoc()},
+ }},
+ }},
+ }},
+ }},
},
RPCExamples{
HelpExampleCli("getrawtransaction", "\"mytxid\"")
- + HelpExampleCli("getrawtransaction", "\"mytxid\" true")
- + HelpExampleRpc("getrawtransaction", "\"mytxid\", true")
- + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"")
- + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"")
+ + HelpExampleCli("getrawtransaction", "\"mytxid\" 1")
+ + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
+ + HelpExampleCli("getrawtransaction", "\"mytxid\" 0 \"myblockhash\"")
+ + HelpExampleCli("getrawtransaction", "\"mytxid\" 1 \"myblockhash\"")
+ + HelpExampleCli("getrawtransaction", "\"mytxid\" 2 \"myblockhash\"")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node);
- bool in_active_chain = true;
uint256 hash = ParseHashV(request.params[0], "parameter 1");
const CBlockIndex* blockindex = nullptr;
@@ -220,10 +251,14 @@ static RPCHelpMan getrawtransaction()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved");
}
- // Accept either a bool (true) or a num (>=1) to indicate verbose output.
- bool fVerbose = false;
+ // Accept either a bool (true) or a num (>=0) to indicate verbosity.
+ int verbosity{0};
if (!request.params[1].isNull()) {
- fVerbose = request.params[1].isNum() ? (request.params[1].getInt<int>() != 0) : request.params[1].get_bool();
+ if (request.params[1].isBool()) {
+ verbosity = request.params[1].get_bool();
+ } else {
+ verbosity = request.params[1].getInt<int>();
+ }
}
if (!request.params[2].isNull()) {
@@ -234,7 +269,6 @@ static RPCHelpMan getrawtransaction()
if (!blockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found");
}
- in_active_chain = chainman.ActiveChain().Contains(blockindex);
}
bool f_txindex_ready = false;
@@ -262,13 +296,43 @@ static RPCHelpMan getrawtransaction()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errmsg + ". Use gettransaction for wallet transactions.");
}
- if (!fVerbose) {
+ if (verbosity <= 0) {
return EncodeHexTx(*tx, RPCSerializationFlags());
}
UniValue result(UniValue::VOBJ);
- if (blockindex) result.pushKV("in_active_chain", in_active_chain);
- TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
+ if (blockindex) {
+ LOCK(cs_main);
+ result.pushKV("in_active_chain", chainman.ActiveChain().Contains(blockindex));
+ }
+ // If request is verbosity >= 1 but no blockhash was given, then look up the blockindex
+ if (request.params[2].isNull()) {
+ LOCK(cs_main);
+ blockindex = chainman.m_blockman.LookupBlockIndex(hash_block);
+ }
+ if (verbosity == 1) {
+ TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
+ return result;
+ }
+
+ CBlockUndo blockUndo;
+ CBlock block;
+ const bool is_block_pruned{WITH_LOCK(cs_main, return chainman.m_blockman.IsBlockPruned(blockindex))};
+
+ if (tx->IsCoinBase() ||
+ !blockindex || is_block_pruned ||
+ !(UndoReadFromDisk(blockUndo, blockindex) && ReadBlockFromDisk(block, blockindex, Params().GetConsensus()))) {
+ TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
+ return result;
+ }
+
+ CTxUndo* undoTX {nullptr};
+ auto it = std::find_if(block.vtx.begin(), block.vtx.end(), [tx](CTransactionRef t){ return *t == *tx; });
+ if (it != block.vtx.end()) {
+ // -1 as blockundo does not have coinbase tx
+ undoTX = &blockUndo.vtxundo.at(it - block.vtx.begin() - 1);
+ }
+ TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate(), undoTX, TxVerbosity::SHOW_DETAILS_AND_PREVOUT);
return result;
},
};
@@ -294,14 +358,6 @@ static RPCHelpMan createrawtransaction()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {
- UniValue::VARR,
- UniValueType(), // ARR or OBJ, checked later
- UniValue::VNUM,
- UniValue::VBOOL
- }, true
- );
-
std::optional<bool> rbf;
if (!request.params[3].isNull()) {
rbf = request.params[3].get_bool();
@@ -337,8 +393,6 @@ static RPCHelpMan decoderawtransaction()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
-
CMutableTransaction mtx;
bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool();
@@ -391,8 +445,6 @@ static RPCHelpMan decodescript()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR});
-
UniValue r(UniValue::VOBJ);
CScript script;
if (request.params[0].get_str().size() > 0){
@@ -470,15 +522,17 @@ static RPCHelpMan decodescript()
if (can_wrap_P2WSH) {
UniValue sr(UniValue::VOBJ);
CScript segwitScr;
+ FillableSigningProvider provider;
if (which_type == TxoutType::PUBKEY) {
segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0])));
} else if (which_type == TxoutType::PUBKEYHASH) {
segwitScr = GetScriptForDestination(WitnessV0KeyHash(uint160{solutions_data[0]}));
} else {
// Scripts that are not fit for P2WPKH are encoded as P2WSH.
+ provider.AddCScript(script);
segwitScr = GetScriptForDestination(WitnessV0ScriptHash(script));
}
- ScriptToUniv(segwitScr, /*out=*/sr, /*include_hex=*/true, /*include_address=*/true);
+ ScriptToUniv(segwitScr, /*out=*/sr, /*include_hex=*/true, /*include_address=*/true, /*provider=*/&provider);
sr.pushKV("p2sh-segwit", EncodeDestination(ScriptHash(segwitScr)));
r.pushKV("segwit", sr);
}
@@ -590,7 +644,7 @@ static RPCHelpMan signrawtransactionwithkey()
{"privatekey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "private key in base58-encoding"},
},
},
- {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The previous dependent transaction outputs",
+ {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The previous dependent transaction outputs",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -642,8 +696,6 @@ static RPCHelpMan signrawtransactionwithkey()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
-
CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_str())) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
@@ -921,8 +973,6 @@ static RPCHelpMan decodepsbt()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR});
-
// Unserialize the transactions
PartiallySignedTransaction psbtx;
std::string error;
@@ -1335,8 +1385,6 @@ static RPCHelpMan combinepsbt()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VARR}, true);
-
// Unserialize the transactions
std::vector<PartiallySignedTransaction> psbtxs;
UniValue txs = request.params[0].get_array();
@@ -1390,8 +1438,6 @@ static RPCHelpMan finalizepsbt()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true);
-
// Unserialize the transactions
PartiallySignedTransaction psbtx;
std::string error;
@@ -1439,14 +1485,6 @@ static RPCHelpMan createpsbt()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {
- UniValue::VARR,
- UniValueType(), // ARR or OBJ, checked later
- UniValue::VNUM,
- UniValue::VBOOL,
- }, true
- );
-
std::optional<bool> rbf;
if (!request.params[3].isNull()) {
rbf = request.params[3].get_bool();
@@ -1500,8 +1538,6 @@ static RPCHelpMan converttopsbt()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VBOOL}, true);
-
// parse hex string from parameter
CMutableTransaction tx;
bool permitsigdata = request.params[1].isNull() ? false : request.params[1].get_bool();
@@ -1547,7 +1583,7 @@ static RPCHelpMan utxoupdatepsbt()
"\nUpdates all segwit inputs and outputs in a PSBT with data from output descriptors, the UTXO set or the mempool.\n",
{
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"},
- {"descriptors", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "An array of either strings or objects", {
+ {"descriptors", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of either strings or objects", {
{"", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"},
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with an output descriptor and extra information", {
{"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"},
@@ -1563,8 +1599,6 @@ static RPCHelpMan utxoupdatepsbt()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}, true);
-
// Unserialize the transactions
PartiallySignedTransaction psbtx;
std::string error;
@@ -1654,8 +1688,6 @@ static RPCHelpMan joinpsbts()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VARR}, true);
-
// Unserialize the transactions
std::vector<PartiallySignedTransaction> psbtxs;
UniValue txs = request.params[0].get_array();
@@ -1782,8 +1814,6 @@ static RPCHelpMan analyzepsbt()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {UniValue::VSTR});
-
// Unserialize the transaction
PartiallySignedTransaction psbtx;
std::string error;
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index b078ee8b29..15b8e1dcd0 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
index 9b5c9f08d4..0c3823bc1e 100644
--- a/src/rpc/rawtransaction_util.h
+++ b/src/rpc/rawtransaction_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/register.h b/src/rpc/register.h
index 301f410da3..c88f49ecf0 100644
--- a/src/rpc/register.h
+++ b/src/rpc/register.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.cpp b/src/rpc/request.cpp
index 8595fa78bb..0bb5533d71 100644
--- a/src/rpc/request.cpp
+++ b/src/rpc/request.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.cpp b/src/rpc/server.cpp
index 80a22ff8ca..44d7e2676b 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -168,7 +168,7 @@ static RPCHelpMan stop()
// to the client (intended for testing)
"\nRequest a graceful shutdown of " PACKAGE_NAME ".",
{
- {"wait", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "how long to wait in ms", RPCArgOptions{.hidden=true}},
+ {"wait", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "how long to wait in ms", RPCArgOptions{.hidden=true}},
},
RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"},
RPCExamples{""},
@@ -399,7 +399,10 @@ static inline JSONRPCRequest transformNamedArguments(const JSONRPCRequest& in, c
const std::vector<UniValue>& values = in.params.getValues();
std::unordered_map<std::string, const UniValue*> argsIn;
for (size_t i=0; i<keys.size(); ++i) {
- argsIn[keys[i]] = &values[i];
+ auto [_, inserted] = argsIn.emplace(keys[i], &values[i]);
+ if (!inserted) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Parameter " + keys[i] + " specified multiple times");
+ }
}
// Process expected parameters. If any parameters were left unspecified in
// the request before a parameter that was specified, null values need to be
diff --git a/src/rpc/server_util.cpp b/src/rpc/server_util.cpp
index 6a1b41f066..50f9ce7b3c 100644
--- a/src/rpc/server_util.cpp
+++ b/src/rpc/server_util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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_util.h b/src/rpc/server_util.h
index 2cc710a803..fa008a8155 100644
--- a/src/rpc/server_util.h
+++ b/src/rpc/server_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/txoutproof.cpp b/src/rpc/txoutproof.cpp
index 8c5468634d..24b5d04115 100644
--- a/src/rpc/txoutproof.cpp
+++ b/src/rpc/txoutproof.cpp
@@ -34,7 +34,7 @@ static RPCHelpMan gettxoutproof()
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"},
},
},
- {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "If specified, looks for txid in the block with this hash"},
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "If specified, looks for txid in the block with this hash"},
},
RPCResult{
RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof."
@@ -112,7 +112,7 @@ static RPCHelpMan gettxoutproof()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not all transactions found in specified or retrieved block");
}
- CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
+ DataStream ssMB{};
CMerkleBlock mb(block, setTxids);
ssMB << mb;
std::string strHex = HexStr(ssMB);
@@ -138,7 +138,7 @@ static RPCHelpMan verifytxoutproof()
RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
+ DataStream ssMB{ParseHexV(request.params[0], "proof")};
CMerkleBlock merkleBlock;
ssMB >> merkleBlock;
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index dd5739faf7..a1020c3b2b 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -1,7 +1,8 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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 <clientversion.h>
#include <consensus/amount.h>
#include <key_io.h>
#include <outputtype.h>
@@ -30,31 +31,6 @@ std::string GetAllOutputTypes()
return Join(ret, ", ");
}
-void RPCTypeCheck(const UniValue& params,
- const std::list<UniValueType>& typesExpected,
- bool fAllowNull)
-{
- unsigned int i = 0;
- for (const UniValueType& t : typesExpected) {
- if (params.size() <= i)
- break;
-
- const UniValue& v = params[i];
- if (!(fAllowNull && v.isNull())) {
- RPCTypeCheckArgument(v, t);
- }
- i++;
- }
-}
-
-void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
-{
- if (!typeExpected.typeAny && value.type() != typeExpected.type) {
- throw JSONRPCError(RPC_TYPE_ERROR,
- strprintf("JSON value of type %s is not of expected type %s", uvTypeName(value.type()), uvTypeName(typeExpected.type)));
- }
-}
-
void RPCTypeCheckObj(const UniValue& o,
const std::map<std::string, UniValueType>& typesExpected,
bool fAllowNull,
@@ -405,6 +381,7 @@ struct Sections {
const auto indent = std::string(current_indent, ' ');
const auto indent_next = std::string(current_indent + 2, ' ');
const bool push_name{outer_type == OuterType::OBJ}; // Dictionary keys must have a name
+ const bool is_top_level_arg{outer_type == OuterType::NONE}; // True on the first recursion
switch (arg.m_type) {
case RPCArg::Type::STR_HEX:
@@ -413,7 +390,7 @@ struct Sections {
case RPCArg::Type::AMOUNT:
case RPCArg::Type::RANGE:
case RPCArg::Type::BOOL: {
- if (outer_type == OuterType::NONE) return; // Nothing more to do for non-recursive types on first recursion
+ if (is_top_level_arg) return; // Nothing more to do for non-recursive types on first recursion
auto left = indent;
if (arg.m_opts.type_str.size() != 0 && push_name) {
left += "\"" + arg.GetName() + "\": " + arg.m_opts.type_str.at(0);
@@ -421,12 +398,12 @@ struct Sections {
left += push_name ? arg.ToStringObj(/*oneline=*/false) : arg.ToString(/*oneline=*/false);
}
left += ",";
- PushSection({left, arg.ToDescriptionString()});
+ PushSection({left, arg.ToDescriptionString(/*is_named_arg=*/push_name)});
break;
}
case RPCArg::Type::OBJ:
case RPCArg::Type::OBJ_USER_KEYS: {
- const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
+ const auto right = is_top_level_arg ? "" : arg.ToDescriptionString(/*is_named_arg=*/push_name);
PushSection({indent + (push_name ? "\"" + arg.GetName() + "\": " : "") + "{", right});
for (const auto& arg_inner : arg.m_inner) {
Push(arg_inner, current_indent + 2, OuterType::OBJ);
@@ -434,20 +411,20 @@ struct Sections {
if (arg.m_type != RPCArg::Type::OBJ) {
PushSection({indent_next + "...", ""});
}
- PushSection({indent + "}" + (outer_type != OuterType::NONE ? "," : ""), ""});
+ PushSection({indent + "}" + (is_top_level_arg ? "" : ","), ""});
break;
}
case RPCArg::Type::ARR: {
auto left = indent;
left += push_name ? "\"" + arg.GetName() + "\": " : "";
left += "[";
- const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
+ const auto right = is_top_level_arg ? "" : arg.ToDescriptionString(/*is_named_arg=*/push_name);
PushSection({left, right});
for (const auto& arg_inner : arg.m_inner) {
Push(arg_inner, current_indent + 2, OuterType::ARR);
}
PushSection({indent_next + "...", ""});
- PushSection({indent + "]" + (outer_type != OuterType::NONE ? "," : ""), ""});
+ PushSection({indent + "]" + (is_top_level_arg ? "" : ","), ""});
break;
}
} // no default case, so the compiler can warn about missing cases
@@ -579,9 +556,39 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
if (request.mode == JSONRPCRequest::GET_HELP || !IsValidNumArgs(request.params.size())) {
throw std::runtime_error(ToString());
}
- const UniValue ret = m_fun(*this, request);
+ UniValue arg_mismatch{UniValue::VOBJ};
+ for (size_t i{0}; i < m_args.size(); ++i) {
+ const auto& arg{m_args.at(i)};
+ UniValue match{arg.MatchesType(request.params[i])};
+ if (!match.isTrue()) {
+ arg_mismatch.pushKV(strprintf("Position %s (%s)", i + 1, arg.m_names), std::move(match));
+ }
+ }
+ if (!arg_mismatch.empty()) {
+ throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Wrong type passed:\n%s", arg_mismatch.write(4)));
+ }
+ UniValue ret = m_fun(*this, request);
if (gArgs.GetBoolArg("-rpcdoccheck", DEFAULT_RPC_DOC_CHECK)) {
- CHECK_NONFATAL(std::any_of(m_results.m_results.begin(), m_results.m_results.end(), [&ret](const RPCResult& res) { return res.MatchesType(ret); }));
+ UniValue mismatch{UniValue::VARR};
+ for (const auto& res : m_results.m_results) {
+ UniValue match{res.MatchesType(ret)};
+ if (match.isTrue()) {
+ mismatch.setNull();
+ break;
+ }
+ mismatch.push_back(match);
+ }
+ if (!mismatch.isNull()) {
+ std::string explain{
+ mismatch.empty() ? "no possible results defined" :
+ mismatch.size() == 1 ? mismatch[0].write(4) :
+ mismatch.write(4)};
+ throw std::runtime_error{
+ strprintf("Internal bug detected: RPC call \"%s\" returned incorrect type:\n%s\n%s %s\nPlease report this issue here: %s\n",
+ m_name, explain,
+ PACKAGE_NAME, FormatFullVersion(),
+ PACKAGE_BUGREPORT)};
+ }
}
return ret;
}
@@ -641,7 +648,7 @@ std::string RPCHelpMan::ToString() const
if (i == 0) ret += "\nArguments:\n";
// Push named argument name and description
- sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.GetFirstName(), arg.ToDescriptionString());
+ sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.GetFirstName(), arg.ToDescriptionString(/*is_named_arg=*/true));
sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size());
// Recursively push nested args
@@ -677,6 +684,52 @@ UniValue RPCHelpMan::GetArgMap() const
return arr;
}
+static std::optional<UniValue::VType> ExpectedType(RPCArg::Type type)
+{
+ using Type = RPCArg::Type;
+ switch (type) {
+ case Type::STR_HEX:
+ case Type::STR: {
+ return UniValue::VSTR;
+ }
+ case Type::NUM: {
+ return UniValue::VNUM;
+ }
+ case Type::AMOUNT: {
+ // VNUM or VSTR, checked inside AmountFromValue()
+ return std::nullopt;
+ }
+ case Type::RANGE: {
+ // VNUM or VARR, checked inside ParseRange()
+ return std::nullopt;
+ }
+ case Type::BOOL: {
+ return UniValue::VBOOL;
+ }
+ case Type::OBJ:
+ case Type::OBJ_USER_KEYS: {
+ return UniValue::VOBJ;
+ }
+ case Type::ARR: {
+ return UniValue::VARR;
+ }
+ } // no default case, so the compiler can warn about missing cases
+ NONFATAL_UNREACHABLE();
+}
+
+UniValue RPCArg::MatchesType(const UniValue& request) const
+{
+ if (m_opts.skip_type_check) return true;
+ if (IsOptional() && request.isNull()) return true;
+ const auto exp_type{ExpectedType(m_type)};
+ if (!exp_type) return true; // nothing to check
+
+ if (*exp_type != request.getType()) {
+ return strprintf("JSON value of type %s is not of expected type %s", uvTypeName(request.getType()), uvTypeName(*exp_type));
+ }
+ return true;
+}
+
std::string RPCArg::GetFirstName() const
{
return m_names.substr(0, m_names.find("|"));
@@ -697,7 +750,7 @@ bool RPCArg::IsOptional() const
}
}
-std::string RPCArg::ToDescriptionString() const
+std::string RPCArg::ToDescriptionString(bool is_named_arg) const
{
std::string ret;
ret += "(";
@@ -744,13 +797,10 @@ std::string RPCArg::ToDescriptionString() const
} else {
switch (std::get<RPCArg::Optional>(m_fallback)) {
case RPCArg::Optional::OMITTED: {
+ if (is_named_arg) ret += ", optional"; // Default value is "null" in dicts. Otherwise,
// nothing to do. Element is treated as if not present and has no default value
break;
}
- case RPCArg::Optional::OMITTED_NAMED_ARG: {
- ret += ", optional"; // Default value is "null"
- break;
- }
case RPCArg::Optional::NO: {
ret += ", required";
break;
@@ -860,53 +910,77 @@ void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const
NONFATAL_UNREACHABLE();
}
-bool RPCResult::MatchesType(const UniValue& result) const
+static std::optional<UniValue::VType> ExpectedType(RPCResult::Type type)
{
- if (m_skip_type_check) {
- return true;
- }
- switch (m_type) {
+ using Type = RPCResult::Type;
+ switch (type) {
case Type::ELISION:
case Type::ANY: {
- return true;
+ return std::nullopt;
}
case Type::NONE: {
- return UniValue::VNULL == result.getType();
+ return UniValue::VNULL;
}
case Type::STR:
case Type::STR_HEX: {
- return UniValue::VSTR == result.getType();
+ return UniValue::VSTR;
}
case Type::NUM:
case Type::STR_AMOUNT:
case Type::NUM_TIME: {
- return UniValue::VNUM == result.getType();
+ return UniValue::VNUM;
}
case Type::BOOL: {
- return UniValue::VBOOL == result.getType();
+ return UniValue::VBOOL;
}
case Type::ARR_FIXED:
case Type::ARR: {
- if (UniValue::VARR != result.getType()) return false;
+ return UniValue::VARR;
+ }
+ case Type::OBJ_DYN:
+ case Type::OBJ: {
+ return UniValue::VOBJ;
+ }
+ } // no default case, so the compiler can warn about missing cases
+ NONFATAL_UNREACHABLE();
+}
+
+UniValue RPCResult::MatchesType(const UniValue& result) const
+{
+ if (m_skip_type_check) {
+ return true;
+ }
+
+ const auto exp_type = ExpectedType(m_type);
+ if (!exp_type) return true; // can be any type, so nothing to check
+
+ if (*exp_type != result.getType()) {
+ return strprintf("returned type is %s, but declared as %s in doc", uvTypeName(result.getType()), uvTypeName(*exp_type));
+ }
+
+ if (UniValue::VARR == result.getType()) {
+ UniValue errors(UniValue::VOBJ);
for (size_t i{0}; i < result.get_array().size(); ++i) {
// If there are more results than documented, re-use the last doc_inner.
const RPCResult& doc_inner{m_inner.at(std::min(m_inner.size() - 1, i))};
- if (!doc_inner.MatchesType(result.get_array()[i])) return false;
+ UniValue match{doc_inner.MatchesType(result.get_array()[i])};
+ if (!match.isTrue()) errors.pushKV(strprintf("%d", i), match);
}
- return true; // empty result array is valid
+ if (errors.empty()) return true; // empty result array is valid
+ return errors;
}
- case Type::OBJ_DYN:
- case Type::OBJ: {
- if (UniValue::VOBJ != result.getType()) return false;
+
+ if (UniValue::VOBJ == result.getType()) {
if (!m_inner.empty() && m_inner.at(0).m_type == Type::ELISION) return true;
+ UniValue errors(UniValue::VOBJ);
if (m_type == Type::OBJ_DYN) {
const RPCResult& doc_inner{m_inner.at(0)}; // Assume all types are the same, randomly pick the first
for (size_t i{0}; i < result.get_obj().size(); ++i) {
- if (!doc_inner.MatchesType(result.get_obj()[i])) {
- return false;
- }
+ UniValue match{doc_inner.MatchesType(result.get_obj()[i])};
+ if (!match.isTrue()) errors.pushKV(result.getKeys()[i], match);
}
- return true; // empty result obj is valid
+ if (errors.empty()) return true; // empty result obj is valid
+ return errors;
}
std::set<std::string> doc_keys;
for (const auto& doc_entry : m_inner) {
@@ -916,7 +990,7 @@ bool RPCResult::MatchesType(const UniValue& result) const
result.getObjMap(result_obj);
for (const auto& result_entry : result_obj) {
if (doc_keys.find(result_entry.first) == doc_keys.end()) {
- return false; // missing documentation
+ errors.pushKV(result_entry.first, "key returned that was not in doc");
}
}
@@ -924,18 +998,18 @@ bool RPCResult::MatchesType(const UniValue& result) const
const auto result_it{result_obj.find(doc_entry.m_key_name)};
if (result_it == result_obj.end()) {
if (!doc_entry.m_optional) {
- return false; // result is missing a required key
+ errors.pushKV(doc_entry.m_key_name, "key missing, despite not being optional in doc");
}
continue;
}
- if (!doc_entry.MatchesType(result_it->second)) {
- return false; // wrong type
- }
+ UniValue match{doc_entry.MatchesType(result_it->second)};
+ if (!match.isTrue()) errors.pushKV(doc_entry.m_key_name, match);
}
- return true;
+ if (errors.empty()) return true;
+ return errors;
}
- } // no default case, so the compiler can warn about missing cases
- NONFATAL_UNREACHABLE();
+
+ return true;
}
void RPCResult::CheckInnerDoc() const
diff --git a/src/rpc/util.h b/src/rpc/util.h
index 9aa5df00b1..e3783c8f76 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -62,18 +62,6 @@ struct UniValueType {
UniValue::VType type;
};
-/**
- * Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
- * the right number of arguments are passed, just that any passed are the correct type.
- */
-void RPCTypeCheck(const UniValue& params,
- const std::list<UniValueType>& typesExpected, bool fAllowNull=false);
-
-/**
- * Type-check one argument; throws JSONRPCError if wrong type given.
- */
-void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected);
-
/*
Check for expected keys/value types in an Object.
*/
@@ -138,6 +126,7 @@ enum class OuterType {
};
struct RPCArgOptions {
+ bool skip_type_check{false};
std::string oneline_description{}; //!< Should be empty unless it is supposed to override the auto-generated summary line
std::vector<std::string> type_str{}; //!< Should be empty unless it is supposed to override the auto-generated type strings. Vector length is either 0 or 2, m_opts.type_str.at(0) will override the type of the value in a key-value pair, m_opts.type_str.at(1) will override the type in the argument description.
bool hidden{false}; //!< For testing only
@@ -160,21 +149,20 @@ struct RPCArg {
/** Required arg */
NO,
/**
- * Optional arg that is a named argument and has a default value of
- * `null`. When possible, the default value should be specified.
- */
- OMITTED_NAMED_ARG,
- /**
- * Optional argument with default value omitted because they are
- * implicitly clear. That is, elements in an array or object may not
- * exist by default.
+ * Optional argument for which the default value is omitted from
+ * help text for one of two reasons:
+ * - It's a named argument and has a default value of `null`.
+ * - Its default value is implicitly clear. That is, elements in an
+ * array may not exist by default.
* When possible, the default value should be specified.
*/
OMITTED,
};
+ /** Hint for default value */
using DefaultHint = std::string;
+ /** Default constant value */
using Default = UniValue;
- using Fallback = std::variant<Optional, /* hint for default value */ DefaultHint, /* default constant value */ Default>;
+ using Fallback = std::variant<Optional, DefaultHint, Default>;
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;
@@ -184,10 +172,10 @@ struct RPCArg {
const RPCArgOptions m_opts;
RPCArg(
- const std::string name,
- const Type type,
- const Fallback fallback,
- const std::string description,
+ std::string name,
+ Type type,
+ Fallback fallback,
+ std::string description,
RPCArgOptions opts = {})
: m_names{std::move(name)},
m_type{std::move(type)},
@@ -199,11 +187,11 @@ struct RPCArg {
}
RPCArg(
- const std::string name,
- const Type type,
- const Fallback fallback,
- const std::string description,
- const std::vector<RPCArg> inner,
+ std::string name,
+ Type type,
+ Fallback fallback,
+ std::string description,
+ std::vector<RPCArg> inner,
RPCArgOptions opts = {})
: m_names{std::move(name)},
m_type{std::move(type)},
@@ -217,6 +205,12 @@ struct RPCArg {
bool IsOptional() const;
+ /**
+ * Check whether the request JSON type matches.
+ * Returns true if type matches, or object describing error(s) if not.
+ */
+ UniValue MatchesType(const UniValue& request) const;
+
/** Return the first of all aliases */
std::string GetFirstName() const;
@@ -237,7 +231,7 @@ struct RPCArg {
* Return the description string, including the argument type and whether
* the argument is required.
*/
- std::string ToDescriptionString() const;
+ std::string ToDescriptionString(bool is_named_arg) const;
};
struct RPCResult {
@@ -266,12 +260,12 @@ struct RPCResult {
const std::string m_cond;
RPCResult(
- const std::string cond,
- const Type type,
- const std::string m_key_name,
- const bool optional,
- const std::string description,
- const std::vector<RPCResult> inner = {})
+ std::string cond,
+ Type type,
+ std::string m_key_name,
+ bool optional,
+ std::string description,
+ std::vector<RPCResult> inner = {})
: m_type{std::move(type)},
m_key_name{std::move(m_key_name)},
m_inner{std::move(inner)},
@@ -285,19 +279,19 @@ struct RPCResult {
}
RPCResult(
- const std::string cond,
- const Type type,
- const std::string m_key_name,
- const std::string description,
- const std::vector<RPCResult> inner = {})
- : RPCResult{cond, type, m_key_name, false, description, inner} {}
+ std::string cond,
+ Type type,
+ std::string m_key_name,
+ std::string description,
+ std::vector<RPCResult> inner = {})
+ : RPCResult{std::move(cond), type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner)} {}
RPCResult(
- const Type type,
- const std::string m_key_name,
- const bool optional,
- const std::string description,
- const std::vector<RPCResult> inner = {},
+ Type type,
+ std::string m_key_name,
+ bool optional,
+ std::string description,
+ std::vector<RPCResult> inner = {},
bool skip_type_check = false)
: m_type{std::move(type)},
m_key_name{std::move(m_key_name)},
@@ -311,12 +305,12 @@ struct RPCResult {
}
RPCResult(
- const Type type,
- const std::string m_key_name,
- const std::string description,
- const std::vector<RPCResult> inner = {},
+ Type type,
+ std::string m_key_name,
+ std::string description,
+ std::vector<RPCResult> inner = {},
bool skip_type_check = false)
- : RPCResult{type, m_key_name, false, description, inner, skip_type_check} {}
+ : RPCResult{type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner), skip_type_check} {}
/** Append the sections of the result. */
void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, const int current_indent = 0) const;
@@ -324,8 +318,10 @@ struct RPCResult {
std::string ToStringObj() const;
/** Return the description string, including the result type. */
std::string ToDescriptionString() const;
- /** Check whether the result JSON type matches. */
- bool MatchesType(const UniValue& result) const;
+ /** Check whether the result JSON type matches.
+ * Returns true if type matches, or object describing error(s) if not.
+ */
+ UniValue MatchesType(const UniValue& result) const;
private:
void CheckInnerDoc() const;
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
index 3df1d48b3c..1c9aedc10b 100644
--- a/src/scheduler.cpp
+++ b/src/scheduler.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/scheduler.h b/src/scheduler.h
index 749e5442b0..9212582b97 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index f7f9dfc262..4fab481b39 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -62,12 +62,6 @@ inline int set_error(bitcoinconsensus_error* ret, bitcoinconsensus_error serror)
return 0;
}
-struct ECCryptoClosure
-{
- ECCVerifyHandle handle;
-};
-
-ECCryptoClosure instance_of_eccryptoclosure;
} // namespace
/** Check that all specified flags are part of the libconsensus interface. */
diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index 8fea42e4b9..f2f2ff8686 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-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.
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 864eb8864f..8991bda340 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -4,11 +4,13 @@
#include <script/descriptor.h>
+#include <hash.h>
#include <key_io.h>
#include <pubkey.h>
#include <script/miniscript.h>
#include <script/script.h>
#include <script/standard.h>
+#include <uint256.h>
#include <span.h>
#include <util/bip32.h>
@@ -1618,8 +1620,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
}
}
if (txntype == TxoutType::WITNESS_V0_SCRIPTHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH)) {
- CScriptID scriptid;
- CRIPEMD160().Write(data[0].data(), data[0].size()).Finalize(scriptid.begin());
+ CScriptID scriptid{RIPEMD160(data[0])};
CScript subscript;
if (provider.GetCScript(scriptid, subscript)) {
auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
@@ -1643,7 +1644,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
for (const auto& [depth, script, leaf_ver] : *tree) {
std::unique_ptr<DescriptorImpl> subdesc;
if (leaf_ver == TAPROOT_LEAF_TAPSCRIPT) {
- subdesc = InferScript(script, ParseScriptContext::P2TR, provider);
+ subdesc = InferScript(CScript(script.begin(), script.end()), ParseScriptContext::P2TR, provider);
}
if (!subdesc) {
ok = false;
@@ -1832,17 +1833,17 @@ DescriptorCache DescriptorCache::MergeAndDiff(const DescriptorCache& other)
return diff;
}
-const ExtPubKeyMap DescriptorCache::GetCachedParentExtPubKeys() const
+ExtPubKeyMap DescriptorCache::GetCachedParentExtPubKeys() const
{
return m_parent_xpubs;
}
-const std::unordered_map<uint32_t, ExtPubKeyMap> DescriptorCache::GetCachedDerivedExtPubKeys() const
+std::unordered_map<uint32_t, ExtPubKeyMap> DescriptorCache::GetCachedDerivedExtPubKeys() const
{
return m_derived_xpubs;
}
-const ExtPubKeyMap DescriptorCache::GetCachedLastHardenedExtPubKeys() const
+ExtPubKeyMap DescriptorCache::GetCachedLastHardenedExtPubKeys() const
{
return m_last_hardened_xpubs;
}
diff --git a/src/script/descriptor.h b/src/script/descriptor.h
index 16ee2f6d97..cb3b366acf 100644
--- a/src/script/descriptor.h
+++ b/src/script/descriptor.h
@@ -66,11 +66,11 @@ public:
bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const;
/** Retrieve all cached parent xpubs */
- const ExtPubKeyMap GetCachedParentExtPubKeys() const;
+ ExtPubKeyMap GetCachedParentExtPubKeys() const;
/** Retrieve all cached derived xpubs */
- const std::unordered_map<uint32_t, ExtPubKeyMap> GetCachedDerivedExtPubKeys() const;
+ std::unordered_map<uint32_t, ExtPubKeyMap> GetCachedDerivedExtPubKeys() const;
/** Retrieve all cached last hardened xpubs */
- const ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const;
+ ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const;
/** Combine another DescriptorCache into this one.
* Returns a cache containing the items from the other cache unknown to current cache
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 38bb11aad4..03b157a847 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1303,7 +1303,7 @@ public:
// Serialize the nSequence
if (nInput != nIn && (fHashSingle || fHashNone))
// let the others update at will
- ::Serialize(s, (int)0);
+ ::Serialize(s, int{0});
else
::Serialize(s, txTo.vin[nInput].nSequence);
}
@@ -1825,9 +1825,20 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
return true;
}
-uint256 ComputeTapleafHash(uint8_t leaf_version, const CScript& script)
+uint256 ComputeTapleafHash(uint8_t leaf_version, Span<const unsigned char> script)
{
- return (HashWriter{HASHER_TAPLEAF} << leaf_version << script).GetSHA256();
+ return (HashWriter{HASHER_TAPLEAF} << leaf_version << CompactSizeWriter(script.size()) << script).GetSHA256();
+}
+
+uint256 ComputeTapbranchHash(Span<const unsigned char> a, Span<const unsigned char> b)
+{
+ HashWriter ss_branch{HASHER_TAPBRANCH};
+ if (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())) {
+ ss_branch << a << b;
+ } else {
+ ss_branch << b << a;
+ }
+ return ss_branch.GetSHA256();
}
uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint256& tapleaf_hash)
@@ -1839,14 +1850,8 @@ uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint25
const int path_len = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
uint256 k = tapleaf_hash;
for (int i = 0; i < path_len; ++i) {
- HashWriter ss_branch{HASHER_TAPBRANCH};
Span node{Span{control}.subspan(TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * i, TAPROOT_CONTROL_NODE_SIZE)};
- if (std::lexicographical_compare(k.begin(), k.end(), node.begin(), node.end())) {
- ss_branch << k << node;
- } else {
- ss_branch << node << k;
- }
- k = ss_branch.GetSHA256();
+ k = ComputeTapbranchHash(k, node);
}
return k;
}
@@ -1917,18 +1922,18 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
} else {
// Script path spending (stack size is >1 after removing optional annex)
const valtype& control = SpanPopBack(stack);
- const valtype& script_bytes = SpanPopBack(stack);
- exec_script = CScript(script_bytes.begin(), script_bytes.end());
+ const valtype& script = SpanPopBack(stack);
if (control.size() < TAPROOT_CONTROL_BASE_SIZE || control.size() > TAPROOT_CONTROL_MAX_SIZE || ((control.size() - TAPROOT_CONTROL_BASE_SIZE) % TAPROOT_CONTROL_NODE_SIZE) != 0) {
return set_error(serror, SCRIPT_ERR_TAPROOT_WRONG_CONTROL_SIZE);
}
- execdata.m_tapleaf_hash = ComputeTapleafHash(control[0] & TAPROOT_LEAF_MASK, exec_script);
+ execdata.m_tapleaf_hash = ComputeTapleafHash(control[0] & TAPROOT_LEAF_MASK, script);
if (!VerifyTaprootCommitment(control, program, execdata.m_tapleaf_hash)) {
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
}
execdata.m_tapleaf_hash_init = true;
if ((control[0] & TAPROOT_LEAF_MASK) == TAPROOT_LEAF_TAPSCRIPT) {
// Tapscript (leaf version 0xc0)
+ exec_script = CScript(script.begin(), script.end());
execdata.m_validation_weight_left = ::GetSerializeSize(witness.stack, PROTOCOL_VERSION) + VALIDATION_WEIGHT_OFFSET;
execdata.m_validation_weight_left_init = true;
return ExecuteWitnessScript(stack, exec_script, flags, SigVersion::TAPSCRIPT, checker, execdata, serror);
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index ba910cc945..ac1013302d 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -333,7 +333,10 @@ public:
};
/** Compute the BIP341 tapleaf hash from leaf version & script. */
-uint256 ComputeTapleafHash(uint8_t leaf_version, const CScript& script);
+uint256 ComputeTapleafHash(uint8_t leaf_version, Span<const unsigned char> script);
+/** Compute the BIP341 tapbranch hash from two branches.
+ * Spans must be 32 bytes each. */
+uint256 ComputeTapbranchHash(Span<const unsigned char> a, Span<const unsigned char> b);
/** Compute the BIP341 taproot script tree Merkle root from control block and leaf hash.
* Requires control block to have valid length (33 + k*32, with k in {0,1,..,128}). */
uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint256& tapleaf_hash);
diff --git a/src/script/miniscript.cpp b/src/script/miniscript.cpp
index cb4d4cb783..5e471cbe89 100644
--- a/src/script/miniscript.cpp
+++ b/src/script/miniscript.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/miniscript.h b/src/script/miniscript.h
index 6faf2624fd..3a3f724f03 100644
--- a/src/script/miniscript.h
+++ b/src/script/miniscript.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1378,7 +1378,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
assert(constructed.size() == 1);
assert(constructed[0]->ScriptSize() == script_size);
if (in.size() > 0) return {};
- const NodeRef<Key> tl_node = std::move(constructed.front());
+ NodeRef<Key> tl_node = std::move(constructed.front());
tl_node->DuplicateKeyCheck(ctx);
return tl_node;
}
@@ -1813,7 +1813,7 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
}
}
if (constructed.size() != 1) return {};
- const NodeRef<Key> tl_node = std::move(constructed.front());
+ NodeRef<Key> tl_node = std::move(constructed.front());
tl_node->DuplicateKeyCheck(ctx);
// Note that due to how ComputeType works (only assign the type to the node if the
// subs' types are valid) this would fail if any node of tree is badly typed.
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 88b4bc2f44..79d19b9085 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-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.
diff --git a/src/script/script.h b/src/script/script.h
index 1e5f694d52..374ae1642e 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 e507ec7528..fef3601887 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.h b/src/script/sigcache.h
index 290955090d..d33d60d5bc 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 0d74a661a5..70df9ee62c 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -169,13 +169,14 @@ static bool CreateTaprootScriptSig(const BaseSignatureCreator& creator, Signatur
return false;
}
-static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatureCreator& creator, SignatureData& sigdata, int leaf_version, const CScript& script, std::vector<valtype>& result)
+static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatureCreator& creator, SignatureData& sigdata, int leaf_version, Span<const unsigned char> script_bytes, std::vector<valtype>& result)
{
// Only BIP342 tapscript signing is supported for now.
if (leaf_version != TAPROOT_LEAF_TAPSCRIPT) return false;
SigVersion sigversion = SigVersion::TAPSCRIPT;
- uint256 leaf_hash = (HashWriter{HASHER_TAPLEAF} << uint8_t(leaf_version) << script).GetSHA256();
+ uint256 leaf_hash = ComputeTapleafHash(leaf_version, script_bytes);
+ CScript script = CScript(script_bytes.begin(), script_bytes.end());
// <xonly pubkey> OP_CHECKSIG
if (script.size() == 34 && script[33] == OP_CHECKSIG && script[0] == 0x20) {
@@ -285,7 +286,6 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
std::vector<valtype>& ret, TxoutType& whichTypeRet, SigVersion sigversion, SignatureData& sigdata)
{
CScript scriptRet;
- uint160 h160;
ret.clear();
std::vector<unsigned char> sig;
@@ -314,8 +314,8 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
ret.push_back(ToByteVector(pubkey));
return true;
}
- case TxoutType::SCRIPTHASH:
- h160 = uint160(vSolutions[0]);
+ case TxoutType::SCRIPTHASH: {
+ uint160 h160{vSolutions[0]};
if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
@@ -323,7 +323,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
// Could not find redeemScript, add to missing
sigdata.missing_redeem_script = h160;
return false;
-
+ }
case TxoutType::MULTISIG: {
size_t required = vSolutions.front()[0];
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
@@ -349,8 +349,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
return true;
case TxoutType::WITNESS_V0_SCRIPTHASH:
- CRIPEMD160().Write(vSolutions[0].data(), vSolutions[0].size()).Finalize(h160.begin());
- if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
+ if (GetCScript(provider, sigdata, CScriptID{RIPEMD160(vSolutions[0])}, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
diff --git a/src/script/sign.h b/src/script/sign.h
index 813dfe04e3..263fb61fc5 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,7 @@
#include <script/interpreter.h>
#include <script/keyorigin.h>
#include <script/standard.h>
+#include <uint256.h>
class CKey;
class CKeyID;
diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp
index a82a8b252a..5123dd81ac 100644
--- a/src/script/signingprovider.cpp
+++ b/src/script/signingprovider.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/signingprovider.h b/src/script/signingprovider.h
index 2d4234ea0b..a5bbcff6a0 100644
--- a/src/script/signingprovider.h
+++ b/src/script/signingprovider.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/standard.cpp b/src/script/standard.cpp
index 6101738061..7c4a05b6e6 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -370,12 +370,7 @@ bool IsValidDestination(const CTxDestination& dest) {
leaf.merkle_branch.push_back(a.hash);
ret.leaves.emplace_back(std::move(leaf));
}
- /* Lexicographically sort a and b's hash, and compute parent hash. */
- if (a.hash < b.hash) {
- ret.hash = (HashWriter{HASHER_TAPBRANCH} << a.hash << b.hash).GetSHA256();
- } else {
- ret.hash = (HashWriter{HASHER_TAPBRANCH} << b.hash << a.hash).GetSHA256();
- }
+ ret.hash = ComputeTapbranchHash(a.hash, b.hash);
return ret;
}
@@ -443,14 +438,14 @@ void TaprootBuilder::Insert(TaprootBuilder::NodeInfo&& node, int depth)
return branch.size() == 0 || (branch.size() == 1 && branch[0]);
}
-TaprootBuilder& TaprootBuilder::Add(int depth, const CScript& script, int leaf_version, bool track)
+TaprootBuilder& TaprootBuilder::Add(int depth, Span<const unsigned char> script, int leaf_version, bool track)
{
assert((leaf_version & ~TAPROOT_LEAF_MASK) == 0);
if (!IsValid()) return *this;
/* Construct NodeInfo object with leaf hash and (if track is true) also leaf information. */
NodeInfo node;
- node.hash = (HashWriter{HASHER_TAPLEAF} << uint8_t(leaf_version) << script).GetSHA256();
- if (track) node.leaves.emplace_back(LeafInfo{script, leaf_version, {}});
+ node.hash = ComputeTapleafHash(leaf_version, script);
+ if (track) node.leaves.emplace_back(LeafInfo{std::vector<unsigned char>(script.begin(), script.end()), leaf_version, {}});
/* Insert into the branch. */
Insert(std::move(node), depth);
return *this;
@@ -506,13 +501,13 @@ TaprootSpendData TaprootBuilder::GetSpendData() const
return spd;
}
-std::optional<std::vector<std::tuple<int, CScript, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output)
+std::optional<std::vector<std::tuple<int, std::vector<unsigned char>, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output)
{
// Verify that the output matches the assumed Merkle root and internal key.
auto tweak = spenddata.internal_key.CreateTapTweak(spenddata.merkle_root.IsNull() ? nullptr : &spenddata.merkle_root);
if (!tweak || tweak->first != output) return std::nullopt;
// If the Merkle root is 0, the tree is empty, and we're done.
- std::vector<std::tuple<int, CScript, int>> ret;
+ std::vector<std::tuple<int, std::vector<unsigned char>, int>> ret;
if (spenddata.merkle_root.IsNull()) return ret;
/** Data structure to represent the nodes of the tree we're going to build. */
@@ -523,7 +518,7 @@ std::optional<std::vector<std::tuple<int, CScript, int>>> InferTaprootTree(const
std::unique_ptr<TreeNode> sub[2];
/** If this is known to be a leaf node, a pointer to the (script, leaf_ver) pair.
* nullptr otherwise. */
- const std::pair<CScript, int>* leaf = nullptr;
+ const std::pair<std::vector<unsigned char>, int>* leaf = nullptr;
/** Whether or not this node has been explored (is known to be a leaf, or known to have children). */
bool explored = false;
/** Whether or not this node is an inner node (unknown until explored = true). */
@@ -607,7 +602,7 @@ std::optional<std::vector<std::tuple<int, CScript, int>>> InferTaprootTree(const
node.done = true;
stack.pop_back();
} else if (node.sub[0]->done && !node.sub[1]->done && !node.sub[1]->explored && !node.sub[1]->hash.IsNull() &&
- (HashWriter{HASHER_TAPBRANCH} << node.sub[1]->hash << node.sub[1]->hash).GetSHA256() == node.hash) {
+ ComputeTapbranchHash(node.sub[1]->hash, node.sub[1]->hash) == node.hash) {
// Whenever there are nodes with two identical subtrees under it, we run into a problem:
// the control blocks for the leaves underneath those will be identical as well, and thus
// they will all be matched to the same path in the tree. The result is that at the location
@@ -641,10 +636,10 @@ std::optional<std::vector<std::tuple<int, CScript, int>>> InferTaprootTree(const
return ret;
}
-std::vector<std::tuple<uint8_t, uint8_t, CScript>> TaprootBuilder::GetTreeTuples() const
+std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> TaprootBuilder::GetTreeTuples() const
{
assert(IsComplete());
- std::vector<std::tuple<uint8_t, uint8_t, CScript>> tuples;
+ std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> tuples;
if (m_branch.size()) {
const auto& leaves = m_branch[0]->leaves;
for (const auto& leaf : leaves) {
diff --git a/src/script/standard.h b/src/script/standard.h
index 966a52b2c7..18cf5c8c88 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -217,7 +217,7 @@ struct TaprootSpendData
* inference can reconstruct the full tree. Within each set, the control
* blocks are sorted by size, so that the signing logic can easily
* prefer the cheapest one. */
- std::map<std::pair<CScript, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> scripts;
+ std::map<std::pair<std::vector<unsigned char>, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> scripts;
/** Merge other TaprootSpendData (for the same scriptPubKey) into this. */
void Merge(TaprootSpendData other);
};
@@ -229,7 +229,7 @@ private:
/** Information about a tracked leaf in the Merkle tree. */
struct LeafInfo
{
- CScript script; //!< The script.
+ std::vector<unsigned char> script; //!< The script.
int leaf_version; //!< The leaf version for that script.
std::vector<uint256> merkle_branch; //!< The hashing partners above this leaf.
};
@@ -296,7 +296,7 @@ public:
/** Add a new script at a certain depth in the tree. Add() operations must be called
* in depth-first traversal order of binary tree. If track is true, it will be included in
* the GetSpendData() output. */
- TaprootBuilder& Add(int depth, const CScript& script, int leaf_version, bool track = true);
+ TaprootBuilder& Add(int depth, Span<const unsigned char> script, int leaf_version, bool track = true);
/** Like Add(), but for a Merkle node with a given hash to the tree. */
TaprootBuilder& AddOmitted(int depth, const uint256& hash);
/** Finalize the construction. Can only be called when IsComplete() is true.
@@ -314,7 +314,7 @@ public:
/** Compute spending data (after Finalize()). */
TaprootSpendData GetSpendData() const;
/** Returns a vector of tuples representing the depth, leaf version, and script */
- std::vector<std::tuple<uint8_t, uint8_t, CScript>> GetTreeTuples() const;
+ std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> GetTreeTuples() const;
/** Returns true if there are any tapscripts */
bool HasScripts() const { return !m_branch.empty(); }
};
@@ -325,6 +325,6 @@ public:
* std::nullopt is returned. Otherwise, a vector of (depth, script, leaf_ver) tuples is
* returned, corresponding to a depth-first traversal of the script tree.
*/
-std::optional<std::vector<std::tuple<int, CScript, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output);
+std::optional<std::vector<std::tuple<int, std::vector<unsigned char>, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output);
#endif // BITCOIN_SCRIPT_STANDARD_H
diff --git a/src/secp256k1/.cirrus.yml b/src/secp256k1/.cirrus.yml
index a2e7f36d1f..51e3bc9484 100644
--- a/src/secp256k1/.cirrus.yml
+++ b/src/secp256k1/.cirrus.yml
@@ -26,6 +26,11 @@ env:
# Compile and run the tests
EXAMPLES: yes
+# https://cirrus-ci.org/pricing/#compute-credits
+credits_snippet: &CREDITS
+ # Don't use any credits for now.
+ use_compute_credits: false
+
cat_logs_snippet: &CAT_LOGS
always:
cat_tests_log_script:
@@ -36,7 +41,6 @@ cat_logs_snippet: &CAT_LOGS
- cat valgrind_ctime_test.log || true
cat_bench_log_script:
- cat bench.log || true
- on_failure:
cat_config_log_script:
- cat config.log || true
cat_test_env_script:
@@ -69,6 +73,7 @@ task:
- env: {WIDEMUL: int64, RECOVERY: yes}
- env: {WIDEMUL: int64, ECDH: yes, SCHNORRSIG: yes}
- env: {WIDEMUL: int128}
+ - env: {WIDEMUL: int128_struct}
- env: {WIDEMUL: int128, RECOVERY: yes, SCHNORRSIG: yes}
- env: {WIDEMUL: int128, ECDH: yes, SCHNORRSIG: yes}
- env: {WIDEMUL: int128, ASM: x86_64}
@@ -107,65 +112,32 @@ task:
<< : *CAT_LOGS
task:
- name: "x86_64: macOS Catalina"
+ name: "arm64: macOS Ventura"
macos_instance:
- image: catalina-base
+ image: ghcr.io/cirruslabs/macos-ventura-base:latest
env:
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
- # Cirrus gives us a fixed number of 12 virtual CPUs. Not that we even have that many jobs at the moment...
- MAKEFLAGS: -j13
+ # Cirrus gives us a fixed number of 4 virtual CPUs. Not that we even have that many jobs at the moment...
+ MAKEFLAGS: -j5
matrix:
<< : *ENV_MATRIX
+ env:
+ ASM: no
+ WITH_VALGRIND: no
+ CTIMETEST: no
matrix:
- env:
- CC: gcc-9
+ CC: gcc
- env:
CC: clang
- # Update Command Line Tools
- # Uncomment this if the Command Line Tools on the CirrusCI macOS image are too old to brew valgrind.
- # See https://apple.stackexchange.com/a/195963 for the implementation.
- ## update_clt_script:
- ## - system_profiler SPSoftwareDataType
- ## - touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
- ## - |-
- ## PROD=$(softwareupdate -l | grep "*.*Command Line" | tail -n 1 | awk -F"*" '{print $2}' | sed -e 's/^ *//' | sed 's/Label: //g' | tr -d '\n')
- ## # For debugging
- ## - softwareupdate -l && echo "PROD: $PROD"
- ## - softwareupdate -i "$PROD" --verbose
- ## - rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
- ##
- brew_valgrind_pre_script:
- # Retry a few times because this tends to fail randomly.
- - for i in {1..5}; do brew update && break || sleep 15; done
- - brew config
- - brew tap LouisBrunner/valgrind
- # Fetch valgrind source but don't build it yet.
- - brew fetch --HEAD LouisBrunner/valgrind/valgrind
- brew_valgrind_cache:
- # This is $(brew --cellar valgrind) but command substition does not work here.
- folder: /usr/local/Cellar/valgrind
- # Rebuild cache if ...
- fingerprint_script:
- # ... macOS version changes:
- - sw_vers
- # ... brew changes:
- - brew config
- # ... valgrind changes:
- - git -C "$(brew --cache)/valgrind--git" rev-parse HEAD
- populate_script:
- # If there's no hit in the cache, build and install valgrind.
- - brew install --HEAD LouisBrunner/valgrind/valgrind
- brew_valgrind_post_script:
- # If we have restored valgrind from the cache, tell brew to create symlink to the PATH.
- # If we haven't restored from cached (and just run brew install), this is a no-op.
- - brew link valgrind
brew_script:
- - brew install automake libtool gcc@9
+ - brew install automake libtool gcc
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
<< : *CAT_LOGS
+ << : *CREDITS
task:
name: "s390x (big-endian): Linux (Debian stable, QEMU)"
@@ -241,17 +213,63 @@ task:
<< : *CAT_LOGS
task:
- name: "x86_64 (mingw32-w64): Windows (Debian stable, Wine)"
<< : *LINUX_CONTAINER
env:
- WRAPPER_CMD: wine64-stable
- SECP256K1_TEST_ITERS: 16
- HOST: x86_64-w64-mingw32
+ WRAPPER_CMD: wine
WITH_VALGRIND: no
ECDH: yes
RECOVERY: yes
SCHNORRSIG: yes
CTIMETEST: no
+ matrix:
+ - name: "x86_64 (mingw32-w64): Windows (Debian stable, Wine)"
+ env:
+ HOST: x86_64-w64-mingw32
+ - name: "i686 (mingw32-w64): Windows (Debian stable, Wine)"
+ env:
+ HOST: i686-w64-mingw32
+ << : *MERGE_BASE
+ test_script:
+ - ./ci/cirrus.sh
+ << : *CAT_LOGS
+
+task:
+ << : *LINUX_CONTAINER
+ env:
+ WRAPPER_CMD: wine
+ WERROR_CFLAGS: -WX
+ WITH_VALGRIND: no
+ ECDH: yes
+ RECOVERY: yes
+ EXPERIMENTAL: yes
+ SCHNORRSIG: yes
+ CTIMETEST: no
+ # Use a MinGW-w64 host to tell ./configure we're building for Windows.
+ # This will detect some MinGW-w64 tools but then make will need only
+ # the MSVC tools CC, AR and NM as specified below.
+ HOST: x86_64-w64-mingw32
+ CC: /opt/msvc/bin/x64/cl
+ AR: /opt/msvc/bin/x64/lib
+ NM: /opt/msvc/bin/x64/dumpbin -symbols -headers
+ # Set non-essential options that affect the CLI messages here.
+ # (They depend on the user's taste, so we don't want to set them automatically in configure.ac.)
+ CFLAGS: -nologo -diagnostics:caret
+ LDFLAGS: -XCClinker -nologo -XCClinker -diagnostics:caret
+ matrix:
+ - name: "x86_64 (MSVC): Windows (Debian stable, Wine)"
+ - name: "x86_64 (MSVC): Windows (Debian stable, Wine, int128_struct)"
+ env:
+ WIDEMUL: int128_struct
+ - name: "x86_64 (MSVC): Windows (Debian stable, Wine, int128_struct with __(u)mulh)"
+ env:
+ WIDEMUL: int128_struct
+ CPPFLAGS: -DSECP256K1_MSVC_MULH_TEST_OVERRIDE
+ - name: "i686 (MSVC): Windows (Debian stable, Wine)"
+ env:
+ HOST: i686-w64-mingw32
+ CC: /opt/msvc/bin/x86/cl
+ AR: /opt/msvc/bin/x86/lib
+ NM: /opt/msvc/bin/x86/dumpbin -symbols -headers
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
@@ -301,14 +319,39 @@ task:
- ./ci/cirrus.sh
<< : *CAT_LOGS
+# Memory sanitizers
task:
- name: "C++ -fpermissive"
<< : *LINUX_CONTAINER
+ name: "MSan"
env:
- # ./configure correctly errors out when given CC=g++.
- # We hack around this by passing CC=g++ only to make.
- CC: gcc
- MAKEFLAGS: -j4 CC=g++ CFLAGS=-fpermissive\ -g
+ ECDH: yes
+ RECOVERY: yes
+ SCHNORRSIG: yes
+ CTIMETEST: no
+ CC: clang
+ SECP256K1_TEST_ITERS: 32
+ ASM: no
+ container:
+ memory: 2G
+ matrix:
+ - env:
+ CFLAGS: "-fsanitize=memory -g"
+ - env:
+ ECMULTGENPRECISION: 2
+ ECMULTWINDOW: 2
+ CFLAGS: "-fsanitize=memory -g -O3"
+ << : *MERGE_BASE
+ test_script:
+ - ./ci/cirrus.sh
+ << : *CAT_LOGS
+
+task:
+ name: "C++ -fpermissive (entire project)"
+ << : *LINUX_CONTAINER
+ env:
+ CC: g++
+ CFLAGS: -fpermissive -g
+ CPPFLAGS: -DSECP256K1_CPLUSPLUS_TEST_OVERRIDE
WERROR_CFLAGS:
ECDH: yes
RECOVERY: yes
@@ -319,6 +362,14 @@ task:
<< : *CAT_LOGS
task:
+ name: "C++ (public headers)"
+ << : *LINUX_CONTAINER
+ test_script:
+ - g++ -Werror include/*.h
+ - clang -Werror -x c++-header include/*.h
+ - /opt/msvc/bin/x64/cl.exe -c -WX -TP include/*.h
+
+task:
name: "sage prover"
<< : *LINUX_CONTAINER
test_script:
diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore
index d88627d72e..80c646b771 100644
--- a/src/secp256k1/.gitignore
+++ b/src/secp256k1/.gitignore
@@ -13,9 +13,9 @@ schnorr_example
*.so
*.a
*.csv
-!.gitignore
*.log
*.trs
+*.sage.py
Makefile
configure
@@ -34,8 +34,6 @@ libtool
*.lo
*.o
*~
-*.log
-*.trs
coverage/
coverage.html
diff --git a/src/secp256k1/CHANGELOG.md b/src/secp256k1/CHANGELOG.md
new file mode 100644
index 0000000000..7443483423
--- /dev/null
+++ b/src/secp256k1/CHANGELOG.md
@@ -0,0 +1,28 @@
+# Changelog
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+
+## [Unreleased]
+
+## [0.2.0] - 2022-12-12
+
+### Added
+ - Added `secp256k1_selftest`, to be used in conjunction with `secp256k1_context_static`.
+
+### Changed
+ - Enabled modules schnorrsig, extrakeys and ECDH by default in `./configure`.
+
+### Deprecated
+ - Deprecated context flags `SECP256K1_CONTEXT_VERIFY` and `SECP256K1_CONTEXT_SIGN`. Use `SECP256K1_CONTEXT_NONE` instead.
+ - Renamed `secp256k1_context_no_precomp` to `secp256k1_context_static`.
+
+### ABI Compatibility
+
+Since this is the first release, we do not compare application binary interfaces.
+However, there are unreleased versions of libsecp256k1 that are *not* ABI compatible with this version.
+
+## [0.1.0] - 2013-03-05 to 2021-12-25
+
+This version was in fact never released.
+The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6).
+Therefore, this version number does not uniquely identify a set of source files.
diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am
index 51c5960301..ad50504f7e 100644
--- a/src/secp256k1/Makefile.am
+++ b/src/secp256k1/Makefile.am
@@ -48,6 +48,12 @@ noinst_HEADERS += src/precomputed_ecmult.h
noinst_HEADERS += src/precomputed_ecmult_gen.h
noinst_HEADERS += src/assumptions.h
noinst_HEADERS += src/util.h
+noinst_HEADERS += src/int128.h
+noinst_HEADERS += src/int128_impl.h
+noinst_HEADERS += src/int128_native.h
+noinst_HEADERS += src/int128_native_impl.h
+noinst_HEADERS += src/int128_struct.h
+noinst_HEADERS += src/int128_struct_impl.h
noinst_HEADERS += src/scratch.h
noinst_HEADERS += src/scratch_impl.h
noinst_HEADERS += src/selftest.h
@@ -58,7 +64,6 @@ noinst_HEADERS += src/hash_impl.h
noinst_HEADERS += src/field.h
noinst_HEADERS += src/field_impl.h
noinst_HEADERS += src/bench.h
-noinst_HEADERS += src/basic-config.h
noinst_HEADERS += contrib/lax_der_parsing.h
noinst_HEADERS += contrib/lax_der_parsing.c
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
@@ -87,7 +92,7 @@ endif
endif
libsecp256k1_la_SOURCES = src/secp256k1.c
-libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES)
+libsecp256k1_la_CPPFLAGS = $(SECP_INCLUDES)
libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
libsecp256k1_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE)
@@ -112,7 +117,7 @@ TESTS =
if USE_TESTS
noinst_PROGRAMS += tests
tests_SOURCES = src/tests.c
-tests_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
+tests_CPPFLAGS = $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
if VALGRIND_ENABLED
tests_CPPFLAGS += -DVALGRIND
noinst_PROGRAMS += valgrind_ctime_test
@@ -211,7 +216,15 @@ maintainer-clean-local: clean-precomp
clean-precomp:
rm -f $(PRECOMP)
-EXTRA_DIST = autogen.sh SECURITY.md
+EXTRA_DIST = autogen.sh CHANGELOG.md SECURITY.md
+EXTRA_DIST += doc/release-process.md doc/safegcd_implementation.md
+EXTRA_DIST += examples/EXAMPLES_COPYING
+EXTRA_DIST += sage/gen_exhaustive_groups.sage
+EXTRA_DIST += sage/gen_split_lambda_constants.sage
+EXTRA_DIST += sage/group_prover.sage
+EXTRA_DIST += sage/prove_group_implementations.sage
+EXTRA_DIST += sage/secp256k1_params.sage
+EXTRA_DIST += sage/weierstrass_prover.sage
if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include
diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md
index f5db915e83..ffdc9aeaee 100644
--- a/src/secp256k1/README.md
+++ b/src/secp256k1/README.md
@@ -2,6 +2,8 @@ libsecp256k1
============
[![Build Status](https://api.cirrus-ci.com/github/bitcoin-core/secp256k1.svg?branch=master)](https://cirrus-ci.com/github/bitcoin-core/secp256k1)
+![Dependencies: None](https://img.shields.io/badge/dependencies-none-success)
+[![irc.libera.chat #secp256k1](https://img.shields.io/badge/irc.libera.chat-%23secp256k1-success)](https://web.libera.chat/#secp256k1)
Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1.
@@ -15,6 +17,7 @@ Features:
* Derandomized ECDSA (via RFC6979 or with a caller provided function.)
* Very efficient implementation.
* Suitable for embedded systems.
+* No runtime dependencies.
* Optional module for public key recovery.
* Optional module for ECDH key exchange.
* Optional module for Schnorr signatures according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki).
@@ -72,11 +75,12 @@ To compile optional modules (such as Schnorr signatures), you need to run `./con
Usage examples
-----------
- Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`.
+Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`.
* [ECDSA example](examples/ecdsa.c)
* [Schnorr signatures example](examples/schnorr.c)
* [Deriving a shared secret (ECDH) example](examples/ecdh.c)
- To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`.
+
+To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`.
Test coverage
-----------
diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
index 9cb54de098..98be915b67 100644
--- a/src/secp256k1/build-aux/m4/bitcoin_secp.m4
+++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
@@ -10,6 +10,7 @@ AC_MSG_RESULT([$has_64bit_asm])
])
AC_DEFUN([SECP_VALGRIND_CHECK],[
+AC_MSG_CHECKING([for valgrind support])
if test x"$has_valgrind" != x"yes"; then
CPPFLAGS_TEMP="$CPPFLAGS"
CPPFLAGS="$VALGRIND_CPPFLAGS $CPPFLAGS"
@@ -21,6 +22,7 @@ if test x"$has_valgrind" != x"yes"; then
#endif
]])], [has_valgrind=yes; AC_DEFINE(HAVE_VALGRIND,1,[Define this symbol if valgrind is installed, and it supports the host platform])])
fi
+AC_MSG_RESULT($has_valgrind)
])
dnl SECP_TRY_APPEND_CFLAGS(flags, VAR)
diff --git a/src/secp256k1/ci/cirrus.sh b/src/secp256k1/ci/cirrus.sh
index b85f012d3f..fb5854a777 100755
--- a/src/secp256k1/ci/cirrus.sh
+++ b/src/secp256k1/ci/cirrus.sh
@@ -5,10 +5,47 @@ set -x
export LC_ALL=C
+# Print relevant CI environment to allow reproducing the job outside of CI.
+print_environment() {
+ # Turn off -x because it messes up the output
+ set +x
+ # There are many ways to print variable names and their content. This one
+ # does not rely on bash.
+ for i in WERROR_CFLAGS MAKEFLAGS BUILD \
+ ECMULTWINDOW ECMULTGENPRECISION ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \
+ EXPERIMENTAL ECDH RECOVERY SCHNORRSIG \
+ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETEST\
+ EXAMPLES \
+ WRAPPER_CMD CC AR NM HOST
+ do
+ eval 'printf "%s %s " "$i=\"${'"$i"'}\""'
+ done
+ echo "$0"
+ set -x
+}
+print_environment
+
+# Start persistent wineserver if necessary.
+# This speeds up jobs with many invocations of wine (e.g., ./configure with MSVC) tremendously.
+case "$WRAPPER_CMD" in
+ *wine*)
+ # This is apparently only reliable when we run a dummy command such as "hh.exe" afterwards.
+ wineserver -p && wine hh.exe
+ ;;
+esac
+
env >> test_env.log
-$CC -v || true
-valgrind --version || true
+if [ -n "$CC" ]; then
+ # The MSVC compiler "cl" doesn't understand "-v"
+ $CC -v || true
+fi
+if [ "$WITH_VALGRIND" = "yes" ]; then
+ valgrind --version
+fi
+if [ -n "$WRAPPER_CMD" ]; then
+ $WRAPPER_CMD --version
+fi
./autogen.sh
@@ -63,6 +100,9 @@ then
make precomp
fi
+# Shutdown wineserver again
+wineserver -k || true
+
# Check that no repo files have been modified by the build.
# (This fails for example if the precomp files need to be updated in the repo.)
git diff --exit-code
diff --git a/src/secp256k1/ci/linux-debian.Dockerfile b/src/secp256k1/ci/linux-debian.Dockerfile
index 5cccbb5565..a83a4e36db 100644
--- a/src/secp256k1/ci/linux-debian.Dockerfile
+++ b/src/secp256k1/ci/linux-debian.Dockerfile
@@ -1,15 +1,14 @@
FROM debian:stable
-RUN dpkg --add-architecture i386
-RUN dpkg --add-architecture s390x
-RUN dpkg --add-architecture armhf
-RUN dpkg --add-architecture arm64
-RUN dpkg --add-architecture ppc64el
-RUN apt-get update
+RUN dpkg --add-architecture i386 && \
+ dpkg --add-architecture s390x && \
+ dpkg --add-architecture armhf && \
+ dpkg --add-architecture arm64 && \
+ dpkg --add-architecture ppc64el
# dkpg-dev: to make pkg-config work in cross-builds
# llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces
-RUN apt-get install --no-install-recommends --no-upgrade -y \
+RUN apt-get update && apt-get install --no-install-recommends -y \
git ca-certificates \
make automake libtool pkg-config dpkg-dev valgrind qemu-user \
gcc clang llvm libc6-dbg \
@@ -19,8 +18,20 @@ RUN apt-get install --no-install-recommends --no-upgrade -y \
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \
gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 \
gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross libc6-dbg:ppc64el \
- wine gcc-mingw-w64-x86-64 \
+ gcc-mingw-w64-x86-64-win32 wine64 wine \
+ gcc-mingw-w64-i686-win32 wine32 \
sagemath
-# Run a dummy command in wine to make it set up configuration
-RUN wine64-stable xcopy || true
+WORKDIR /root
+# The "wine" package provides a convience wrapper that we need
+RUN apt-get update && apt-get install --no-install-recommends -y \
+ git ca-certificates wine64 wine python3-simplejson python3-six msitools winbind procps && \
+ git clone https://github.com/mstorsjo/msvc-wine && \
+ mkdir /opt/msvc && \
+ python3 msvc-wine/vsdownload.py --accept-license --dest /opt/msvc Microsoft.VisualStudio.Workload.VCTools && \
+ msvc-wine/install.sh /opt/msvc
+
+# Initialize the wine environment. Wait until the wineserver process has
+# exited before closing the session, to avoid corrupting the wine prefix.
+RUN wine64 wineboot --init && \
+ while (ps -A | grep wineserver) > /dev/null; do sleep 1; done
diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac
index 2db59a8ff3..68f279b17b 100644
--- a/src/secp256k1/configure.ac
+++ b/src/secp256k1/configure.ac
@@ -4,20 +4,20 @@ AC_PREREQ([2.60])
# the API. All changes in experimental modules are treated as
# backwards-compatible and therefore at most increase the minor version.
define(_PKG_VERSION_MAJOR, 0)
-define(_PKG_VERSION_MINOR, 1)
-define(_PKG_VERSION_BUILD, 0)
-define(_PKG_VERSION_IS_RELEASE, false)
+define(_PKG_VERSION_MINOR, 2)
+define(_PKG_VERSION_PATCH, 0)
+define(_PKG_VERSION_IS_RELEASE, true)
# The library version is based on libtool versioning of the ABI. The set of
# rules for updating the version can be found here:
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
# All changes in experimental modules are treated as if they don't affect the
# interface and therefore only increase the revision.
-define(_LIB_VERSION_CURRENT, 0)
+define(_LIB_VERSION_CURRENT, 1)
define(_LIB_VERSION_REVISION, 0)
define(_LIB_VERSION_AGE, 0)
-AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_BUILD)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-pre]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1])
+AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([build-aux/m4])
@@ -33,12 +33,14 @@ AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_PROG_CC
-if test x"$ac_cv_prog_cc_c89" = x"no"; then
- AC_MSG_ERROR([c89 compiler support required])
-fi
AM_PROG_AS
AM_PROG_AR
+# Clear some cache variables as a workaround for a bug that appears due to a bad
+# interaction between AM_PROG_AR and LT_INIT when combining MSVC's archiver lib.exe.
+# https://debbugs.gnu.org/cgi/bugreport.cgi?bug=54421
+AS_UNSET(ac_cv_prog_AR)
+AS_UNSET(ac_cv_prog_ac_ct_AR)
LT_INIT([win32-dll])
build_windows=no
@@ -87,23 +89,35 @@ esac
#
# TODO We should analogously not touch CPPFLAGS and LDFLAGS but currently there are no issues.
AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
- # Try to append -Werror=unknown-warning-option to CFLAGS temporarily. Otherwise clang will
- # not error out if it gets unknown warning flags and the checks here will always succeed
- # no matter if clang knows the flag or not.
- SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS="$CFLAGS"
- SECP_TRY_APPEND_CFLAGS([-Werror=unknown-warning-option], CFLAGS)
-
- SECP_TRY_APPEND_CFLAGS([-std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef], $1) # GCC >= 3.0, -Wlong-long is implied by -pedantic.
- SECP_TRY_APPEND_CFLAGS([-Wno-overlength-strings], $1) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic.
- SECP_TRY_APPEND_CFLAGS([-Wall], $1) # GCC >= 2.95 and probably many other compilers
- SECP_TRY_APPEND_CFLAGS([-Wno-unused-function], $1) # GCC >= 3.0, -Wunused-function is implied by -Wall.
- SECP_TRY_APPEND_CFLAGS([-Wextra], $1) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions.
- SECP_TRY_APPEND_CFLAGS([-Wcast-align], $1) # GCC >= 2.95
- SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0
- SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only
- SECP_TRY_APPEND_CFLAGS([-fvisibility=hidden], $1) # GCC >= 4.0
-
- CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS"
+ # GCC and compatible (incl. clang)
+ if test "x$GCC" = "xyes"; then
+ # Try to append -Werror=unknown-warning-option to CFLAGS temporarily. Otherwise clang will
+ # not error out if it gets unknown warning flags and the checks here will always succeed
+ # no matter if clang knows the flag or not.
+ SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS="$CFLAGS"
+ SECP_TRY_APPEND_CFLAGS([-Werror=unknown-warning-option], CFLAGS)
+
+ SECP_TRY_APPEND_CFLAGS([-std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef], $1) # GCC >= 3.0, -Wlong-long is implied by -pedantic.
+ SECP_TRY_APPEND_CFLAGS([-Wno-overlength-strings], $1) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic.
+ SECP_TRY_APPEND_CFLAGS([-Wall], $1) # GCC >= 2.95 and probably many other compilers
+ SECP_TRY_APPEND_CFLAGS([-Wno-unused-function], $1) # GCC >= 3.0, -Wunused-function is implied by -Wall.
+ SECP_TRY_APPEND_CFLAGS([-Wextra], $1) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions.
+ SECP_TRY_APPEND_CFLAGS([-Wcast-align], $1) # GCC >= 2.95
+ SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0
+ SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only
+ SECP_TRY_APPEND_CFLAGS([-fvisibility=hidden], $1) # GCC >= 4.0
+
+ CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS"
+ fi
+
+ # MSVC
+ # Assume MSVC if we're building for Windows but not with GCC or compatible;
+ # libtool makes the same assumption internally.
+ # Note that "/opt" and "-opt" are equivalent for MSVC; we use "-opt" because "/opt" looks like a path.
+ if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then
+ SECP_TRY_APPEND_CFLAGS([-W2 -wd4146], $1) # Moderate warning level, disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned"
+ SECP_TRY_APPEND_CFLAGS([-external:anglebrackets -external:W0], $1) # Suppress warnings from #include <...> files
+ fi
])
SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS)
@@ -141,27 +155,31 @@ AC_ARG_ENABLE(examples,
[SECP_SET_DEFAULT([enable_examples], [no], [yes])])
AC_ARG_ENABLE(module_ecdh,
- AS_HELP_STRING([--enable-module-ecdh],[enable ECDH module [default=no]]), [],
- [SECP_SET_DEFAULT([enable_module_ecdh], [no], [yes])])
+ AS_HELP_STRING([--enable-module-ecdh],[enable ECDH module [default=yes]]), [],
+ [SECP_SET_DEFAULT([enable_module_ecdh], [yes], [yes])])
AC_ARG_ENABLE(module_recovery,
AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]), [],
[SECP_SET_DEFAULT([enable_module_recovery], [no], [yes])])
AC_ARG_ENABLE(module_extrakeys,
- AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module [default=no]]), [],
- [SECP_SET_DEFAULT([enable_module_extrakeys], [no], [yes])])
+ AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module [default=yes]]), [],
+ [SECP_SET_DEFAULT([enable_module_extrakeys], [yes], [yes])])
AC_ARG_ENABLE(module_schnorrsig,
- AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=no]]), [],
- [SECP_SET_DEFAULT([enable_module_schnorrsig], [no], [yes])])
+ AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=yes]]), [],
+ [SECP_SET_DEFAULT([enable_module_schnorrsig], [yes], [yes])])
AC_ARG_ENABLE(external_default_callbacks,
AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), [],
[SECP_SET_DEFAULT([enable_external_default_callbacks], [no], [no])])
# Test-only override of the (autodetected by the C code) "widemul" setting.
-# Legal values are int64 (for [u]int64_t), int128 (for [unsigned] __int128), and auto (the default).
+# Legal values are:
+# * int64 (for [u]int64_t),
+# * int128 (for [unsigned] __int128),
+# * int128_struct (for int128 implemented as a structure),
+# * and auto (the default).
AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto])
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto],
@@ -271,6 +289,9 @@ fi
# Select wide multiplication implementation
case $set_widemul in
+int128_struct)
+ AC_DEFINE(USE_FORCE_WIDEMUL_INT128_STRUCT, 1, [Define this symbol to force the use of the structure for simulating (unsigned) int128 based wide multiplication])
+ ;;
int128)
AC_DEFINE(USE_FORCE_WIDEMUL_INT128, 1, [Define this symbol to force the use of the (unsigned) __int128 based wide multiplication implementation])
;;
@@ -326,7 +347,9 @@ if test x"$enable_valgrind" = x"yes"; then
SECP_INCLUDES="$SECP_INCLUDES $VALGRIND_CPPFLAGS"
fi
-# Add -Werror and similar flags passed from the outside (for testing, e.g., in CI)
+# Add -Werror and similar flags passed from the outside (for testing, e.g., in CI).
+# We don't want to set the user variable CFLAGS in CI because this would disable
+# autoconf's logic for setting default CFLAGS, which we would like to test in CI.
SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS"
###
diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.h b/src/secp256k1/contrib/lax_der_privatekey_parsing.h
index 1a8ad8ae0c..3749e418fe 100644
--- a/src/secp256k1/contrib/lax_der_privatekey_parsing.h
+++ b/src/secp256k1/contrib/lax_der_privatekey_parsing.h
@@ -43,8 +43,7 @@ extern "C" {
/** Export a private key in DER format.
*
* Returns: 1 if the private key was valid.
- * Args: ctx: pointer to a context object, initialized for signing (cannot
- * be NULL)
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: privkey: pointer to an array for storing the private key in BER.
* Should have space for 279 bytes, and cannot be NULL.
* privkeylen: Pointer to an int where the length of the private key in
diff --git a/src/secp256k1/doc/CHANGELOG.md b/src/secp256k1/doc/CHANGELOG.md
deleted file mode 100644
index 3c4c2e4583..0000000000
--- a/src/secp256k1/doc/CHANGELOG.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Changelog
-
-This file is currently only a template for future use.
-
-Each change falls into one of the following categories: Added, Changed, Deprecated, Removed, Fixed or Security.
-
-## [Unreleased]
-
-## [MAJOR.MINOR.PATCH] - YYYY-MM-DD
-
-### Added/Changed/Deprecated/Removed/Fixed/Security
-- [Title with link to Pull Request](https://link-to-pr)
diff --git a/src/secp256k1/doc/release-process.md b/src/secp256k1/doc/release-process.md
index a35b8a9db3..91e3616915 100644
--- a/src/secp256k1/doc/release-process.md
+++ b/src/secp256k1/doc/release-process.md
@@ -1,14 +1,52 @@
# Release Process
-1. Open PR to master that
- 1. adds release notes to `doc/CHANGELOG.md` and
- 2. if this is **not** a patch release, updates `_PKG_VERSION_{MAJOR,MINOR}` and `_LIB_VERSIONS_*` in `configure.ac`
-2. After the PR is merged,
- * if this is **not** a patch release, create a release branch with name `MAJOR.MINOR`.
- Make sure that the branch contains the right commits.
- Create commit on the release branch that sets `_PKG_VERSION_IS_RELEASE` in `configure.ac` to `true`.
- * if this **is** a patch release, open a pull request with the bugfixes to the `MAJOR.MINOR` branch.
- Also include the release note commit bump `_PKG_VERSION_BUILD` and `_LIB_VERSIONS_*` in `configure.ac`.
-4. Tag the commit with `git tag -s vMAJOR.MINOR.PATCH`.
-5. Push branch and tag with `git push origin --tags`.
-6. Create a new GitHub release with a link to the corresponding entry in `doc/CHANGELOG.md`.
+This document outlines the process for releasing versions of the form `$MAJOR.$MINOR.$PATCH`.
+
+We distinguish between two types of releases: *regular* and *maintenance* releases.
+Regular releases are releases of a new major or minor version as well as patches of the most recent release.
+Maintenance releases, on the other hand, are required for patches of older releases.
+
+You should coordinate with the other maintainers on the release date, if possible.
+This date will be part of the release entry in [CHANGELOG.md](../CHANGELOG.md) and it should match the dates of the remaining steps in the release process (including the date of the tag and the GitHub release).
+It is best if the maintainers are present during the release, so they can help ensure that the process is followed correctly and, in the case of a regular release, they are aware that they should not modify the master branch between merging the PR in step 1 and the PR in step 3.
+
+This process also assumes that there will be no minor releases for old major releases.
+
+## Regular release
+
+1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that
+ * finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) (make sure to include an entry for `### ABI Compatibility`) and
+ * updates `_PKG_VERSION_*`, `_LIB_VERSION_*`, and sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`.
+2. After the PR is merged, tag the commit and push it:
+ ```
+ RELEASE_COMMIT=<merge commit of step 1>
+ git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH" $RELEASE_COMMIT
+ git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH
+ ```
+3. Open a PR to the master branch with a commit (using message `"release: bump version after $MAJOR.$MINOR.$PATCH"`, for example) that sets `_PKG_VERSION_IS_RELEASE` to `false` and `_PKG_VERSION_PATCH` to `$PATCH + 1` and increases `_LIB_VERSION_REVISION`. If other maintainers are not present to approve the PR, it can be merged without ACKs.
+4. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md).
+
+## Maintenance release
+
+Note that bugfixes only need to be backported to releases for which no compatible release without the bug exists.
+
+1. If `$PATCH = 1`, create maintenance branch `$MAJOR.$MINOR`:
+ ```
+ git checkout -b $MAJOR.$MINOR v$MAJOR.$MINOR.0
+ git push git@github.com:bitcoin-core/secp256k1.git $MAJOR.$MINOR
+ ```
+2. Open a pull request to the `$MAJOR.$MINOR` branch that
+ * includes the bugfixes,
+ * finalizes the release notes,
+ * bumps `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac` (with commit message `"release: update PKG_ and LIB_VERSION for $MAJOR.$MINOR.$PATCH"`, for example).
+3. After the PRs are merged, update the release branch and tag the commit:
+ ```
+ git checkout $MAJOR.$MINOR && git pull
+ git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH"
+ ```
+4. Push tag:
+ ```
+ git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH
+ ```
+5. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md).
+6. Open PR to the master branch that includes a commit (with commit message `"release notes: add $MAJOR.$MINOR.$PATCH"`, for example) that adds release notes to [CHANGELOG.md](../CHANGELOG.md).
diff --git a/src/secp256k1/examples/ecdh.c b/src/secp256k1/examples/ecdh.c
index d7e8add361..027d52fd5f 100644
--- a/src/secp256k1/examples/ecdh.c
+++ b/src/secp256k1/examples/ecdh.c
@@ -30,12 +30,8 @@ int main(void) {
secp256k1_pubkey pubkey1;
secp256k1_pubkey pubkey2;
- /* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create`
- * needs a context object initialized for signing, which is why we create
- * a context with the SECP256K1_CONTEXT_SIGN flag.
- * (The docs for `secp256k1_ecdh` don't require any special context, just
- * some initialized context) */
- secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
+ /* Before we can call actual API functions, we need to create a "context". */
+ secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (!fill_random(randomize, sizeof(randomize))) {
printf("Failed to generate randomness\n");
return 1;
diff --git a/src/secp256k1/examples/ecdsa.c b/src/secp256k1/examples/ecdsa.c
index 434c856ba0..7e4f1b13ac 100644
--- a/src/secp256k1/examples/ecdsa.c
+++ b/src/secp256k1/examples/ecdsa.c
@@ -38,12 +38,8 @@ int main(void) {
int return_val;
secp256k1_pubkey pubkey;
secp256k1_ecdsa_signature sig;
- /* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create` needs
- * a context object initialized for signing and `secp256k1_ecdsa_verify` needs
- * a context initialized for verification, which is why we create a context
- * for both signing and verification with the SECP256K1_CONTEXT_SIGN and
- * SECP256K1_CONTEXT_VERIFY flags. */
- secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ /* Before we can call actual API functions, we need to create a "context". */
+ secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (!fill_random(randomize, sizeof(randomize))) {
printf("Failed to generate randomness\n");
return 1;
diff --git a/src/secp256k1/examples/schnorr.c b/src/secp256k1/examples/schnorr.c
index 82eb07d5d7..207c45c422 100644
--- a/src/secp256k1/examples/schnorr.c
+++ b/src/secp256k1/examples/schnorr.c
@@ -30,12 +30,8 @@ int main(void) {
int return_val;
secp256k1_xonly_pubkey pubkey;
secp256k1_keypair keypair;
- /* The specification in secp256k1_extrakeys.h states that `secp256k1_keypair_create`
- * needs a context object initialized for signing. And in secp256k1_schnorrsig.h
- * they state that `secp256k1_schnorrsig_verify` needs a context initialized for
- * verification, which is why we create a context for both signing and verification
- * with the SECP256K1_CONTEXT_SIGN and SECP256K1_CONTEXT_VERIFY flags. */
- secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ /* Before we can call actual API functions, we need to create a "context". */
+ secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (!fill_random(randomize, sizeof(randomize))) {
printf("Failed to generate randomness\n");
return 1;
diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h
index dddab346ae..826ab75850 100644
--- a/src/secp256k1/include/secp256k1.h
+++ b/src/secp256k1/include/secp256k1.h
@@ -7,7 +7,7 @@ extern "C" {
#include <stddef.h>
-/* Unless explicitly stated all pointer arguments must not be NULL.
+/** Unless explicitly stated all pointer arguments must not be NULL.
*
* The following rules specify the order of arguments in API calls:
*
@@ -24,15 +24,19 @@ extern "C" {
* 5. Opaque data pointers follow the function pointer they are to be passed to.
*/
-/** Opaque data structure that holds context information (precomputed tables etc.).
+/** Opaque data structure that holds context information
*
- * The purpose of context structures is to cache large precomputed data tables
- * that are expensive to construct, and also to maintain the randomization data
- * for blinding.
+ * The primary purpose of context objects is to store randomization data for
+ * enhanced protection against side-channel leakage. This protection is only
+ * effective if the context is randomized after its creation. See
+ * secp256k1_context_create for creation of contexts and
+ * secp256k1_context_randomize for randomization.
*
- * Do not create a new context object for each operation, as construction is
- * far slower than all other API calls (~100 times slower than an ECDSA
- * verification).
+ * A secondary purpose of context objects is to store pointers to callback
+ * functions that the library will call when certain error states arise. See
+ * secp256k1_context_set_error_callback as well as
+ * secp256k1_context_set_illegal_callback for details. Future library versions
+ * may use context objects for additional purposes.
*
* A constructed context can safely be used from multiple threads
* simultaneously, but API calls that take a non-const pointer to a context
@@ -45,7 +49,7 @@ extern "C" {
*/
typedef struct secp256k1_context_struct secp256k1_context;
-/** Opaque data structure that holds rewriteable "scratch space"
+/** Opaque data structure that holds rewritable "scratch space"
*
* The purpose of this structure is to replace dynamic memory allocations,
* because we target architectures where this may not be available. It is
@@ -130,7 +134,7 @@ typedef int (*secp256k1_nonce_function)(
# define SECP256K1_INLINE inline
# endif
-/** When this header is used at build-time the SECP256K1_BUILD define needs to be set
+/* When this header is used at build-time the SECP256K1_BUILD define needs to be set
* to correctly setup export attributes and nullness checks. This is normally done
* by secp256k1.c but to guard against this header being included before secp256k1.c
* has had a chance to set the define (e.g. via test harnesses that just includes
@@ -159,9 +163,9 @@ typedef int (*secp256k1_nonce_function)(
# endif
#endif
-/**Warning attributes
- * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
- * some paranoid null checks. */
+/* Warning attributes
+ * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
+ * some paranoid null checks. */
# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
# else
@@ -173,7 +177,7 @@ typedef int (*secp256k1_nonce_function)(
# define SECP256K1_ARG_NONNULL(_x)
# endif
-/** Attribute for marking functions, types, and variables as deprecated */
+/* Attribute for marking functions, types, and variables as deprecated */
#if !defined(SECP256K1_BUILD) && defined(__has_attribute)
# if __has_attribute(__deprecated__)
# define SECP256K1_DEPRECATED(_msg) __attribute__ ((__deprecated__(_msg)))
@@ -184,22 +188,26 @@ typedef int (*secp256k1_nonce_function)(
# define SECP256K1_DEPRECATED(_msg)
#endif
-/** All flags' lower 8 bits indicate what they're for. Do not use directly. */
+/* All flags' lower 8 bits indicate what they're for. Do not use directly. */
#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1)
#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0)
#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1)
-/** The higher bits contain the actual data. Do not use directly. */
+/* The higher bits contain the actual data. Do not use directly. */
#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8)
#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9)
#define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10)
#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8)
-/** Flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and
+/** Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and
* secp256k1_context_preallocated_create. */
+#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
+
+/** Deprecated context flags. These flags are treated equivalent to SECP256K1_CONTEXT_NONE. */
#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
+
+/* Testing flag. Do not use. */
#define SECP256K1_CONTEXT_DECLASSIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY)
-#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
/** Flag to pass to secp256k1_ec_pubkey_serialize. */
#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
@@ -212,23 +220,66 @@ typedef int (*secp256k1_nonce_function)(
#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06
#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07
-/** A simple secp256k1 context object with no precomputed tables. These are useful for
- * type serialization/parsing functions which require a context object to maintain
- * API consistency, but currently do not require expensive precomputations or dynamic
- * allocations.
+/** A built-in constant secp256k1 context object with static storage duration, to be
+ * used in conjunction with secp256k1_selftest.
+ *
+ * This context object offers *only limited functionality* , i.e., it cannot be used
+ * for API functions that perform computations involving secret keys, e.g., signing
+ * and public key generation. If this restriction applies to a specific API function,
+ * it is mentioned in its documentation. See secp256k1_context_create if you need a
+ * full context object that supports all functionality offered by the library.
+ *
+ * It is highly recommended to call secp256k1_selftest before using this context.
+ */
+SECP256K1_API extern const secp256k1_context *secp256k1_context_static;
+
+/** Deprecated alias for secp256k1_context_static. */
+SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp
+SECP256K1_DEPRECATED("Use secp256k1_context_static instead");
+
+/** Perform basic self tests (to be used in conjunction with secp256k1_context_static)
+ *
+ * This function performs self tests that detect some serious usage errors and
+ * similar conditions, e.g., when the library is compiled for the wrong endianness.
+ * This is a last resort measure to be used in production. The performed tests are
+ * very rudimentary and are not intended as a replacement for running the test
+ * binaries.
+ *
+ * It is highly recommended to call this before using secp256k1_context_static.
+ * It is not necessary to call this function before using a context created with
+ * secp256k1_context_create (or secp256k1_context_preallocated_create), which will
+ * take care of performing the self tests.
+ *
+ * If the tests fail, this function will call the default error handler to abort the
+ * program (see secp256k1_context_set_error_callback).
*/
-SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp;
+SECP256K1_API void secp256k1_selftest(void);
+
/** Create a secp256k1 context object (in dynamically allocated memory).
*
* This function uses malloc to allocate memory. It is guaranteed that malloc is
* called at most once for every call of this function. If you need to avoid dynamic
- * memory allocation entirely, see the functions in secp256k1_preallocated.h.
+ * memory allocation entirely, see secp256k1_context_static and the functions in
+ * secp256k1_preallocated.h.
*
* Returns: a newly created context object.
- * In: flags: which parts of the context to initialize.
+ * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below).
+ *
+ * The only valid non-deprecated flag in recent library versions is
+ * SECP256K1_CONTEXT_NONE, which will create a context sufficient for all functionality
+ * offered by the library. All other (deprecated) flags will be treated as equivalent
+ * to the SECP256K1_CONTEXT_NONE flag. Though the flags parameter primarily exists for
+ * historical reasons, future versions of the library may introduce new flags.
*
- * See also secp256k1_context_randomize.
+ * If the context is intended to be used for API functions that perform computations
+ * involving secret keys, e.g., signing and public key generation, then it is highly
+ * recommended to call secp256k1_context_randomize on the context before calling
+ * those API functions. This will provide enhanced protection against side-channel
+ * leakage, see secp256k1_context_randomize for details.
+ *
+ * Do not create a new context object for each operation, as construction and
+ * randomization can take non-negligible time.
*/
SECP256K1_API secp256k1_context* secp256k1_context_create(
unsigned int flags
@@ -308,7 +359,10 @@ SECP256K1_API void secp256k1_context_set_illegal_callback(
) SECP256K1_ARG_NONNULL(1);
/** Set a callback function to be called when an internal consistency check
- * fails. The default is crashing.
+ * fails.
+ *
+ * The default callback writes an error message to stderr and calls abort
+ * to abort the program.
*
* This can only trigger in case of a hardware failure, miscompilation,
* memory corruption, serious bug in the library, or other error would can
@@ -426,8 +480,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_cmp(
* encoding is invalid. R and S with value 0 are allowed in the encoding.
*
* After the call, sig will always be initialized. If parsing failed or R or
- * S are zero, the resulting sig value is guaranteed to fail validation for any
- * message and public key.
+ * S are zero, the resulting sig value is guaranteed to fail verification for
+ * any message and public key.
*/
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
const secp256k1_context* ctx,
@@ -447,7 +501,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
* encoded numbers are out of range.
*
* After the call, sig will always be initialized. If parsing failed or the
- * encoded numbers are out of range, signature validation with it is
+ * encoded numbers are out of range, signature verification with it is
* guaranteed to fail for every message and public key.
*/
SECP256K1_API int secp256k1_ecdsa_signature_parse_der(
@@ -494,7 +548,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
*
* Returns: 1: correct signature
* 0: incorrect or unparseable signature
- * Args: ctx: a secp256k1 context object, initialized for verification.
+ * Args: ctx: a secp256k1 context object.
* In: sig: the signature being verified.
* msghash32: the 32-byte message hash being verified.
* The verifier must make sure to apply a cryptographic
@@ -511,7 +565,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
*
* If you need to accept ECDSA signatures from sources that do not obey this
* rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to
- * validation, but be aware that doing so results in malleable signatures.
+ * verification, but be aware that doing so results in malleable signatures.
*
* For details, see the comments for that function.
*/
@@ -582,7 +636,7 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def
*
* Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid.
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig: pointer to an array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key.
@@ -626,7 +680,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
*
* Returns: 1: secret was valid, public key stores.
* 0: secret was invalid, try again.
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: pubkey: pointer to the created public key.
* In: seckey: pointer to a 32-byte secret key.
*/
@@ -705,7 +759,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
* Returns: 0 if the arguments are invalid or the resulting public key would be
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
- * Args: ctx: pointer to a context object initialized for validation.
+ * Args: ctx: pointer to a context object.
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
* invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
@@ -750,7 +804,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
/** Tweak a public key by multiplying it by a tweak value.
*
* Returns: 0 if the arguments are invalid. 1 otherwise.
- * Args: ctx: pointer to a context object initialized for validation.
+ * Args: ctx: pointer to a context object.
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an
* invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
@@ -764,30 +818,41 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
-/** Updates the context randomization to protect against side-channel leakage.
- * Returns: 1: randomization successfully updated or nothing to randomize
+/** Randomizes the context to provide enhanced protection against side-channel leakage.
+ *
+ * Returns: 1: randomization successful (or called on copy of secp256k1_context_static)
* 0: error
* Args: ctx: pointer to a context object.
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
*
- * While secp256k1 code is written to be constant-time no matter what secret
- * values are, it's possible that a future compiler may output code which isn't,
+ * While secp256k1 code is written and tested to be constant-time no matter what
+ * secret values are, it is possible that a compiler may output code which is not,
* and also that the CPU may not emit the same radio frequencies or draw the same
- * amount power for all values.
- *
- * This function provides a seed which is combined into the blinding value: that
- * blinding value is added before each multiplication (and removed afterwards) so
- * that it does not affect function results, but shields against attacks which
- * rely on any input-dependent behaviour.
- *
- * This function has currently an effect only on contexts initialized for signing
- * because randomization is currently used only for signing. However, this is not
- * guaranteed and may change in the future. It is safe to call this function on
- * contexts not initialized for signing; then it will have no effect and return 1.
- *
- * You should call this after secp256k1_context_create or
- * secp256k1_context_clone (and secp256k1_context_preallocated_create or
- * secp256k1_context_clone, resp.), and you may call this repeatedly afterwards.
+ * amount of power for all values. Randomization of the context shields against
+ * side-channel observations which aim to exploit secret-dependent behaviour in
+ * certain computations which involve secret keys.
+ *
+ * It is highly recommended to call this function on contexts returned from
+ * secp256k1_context_create or secp256k1_context_clone (or from the corresponding
+ * functions in secp256k1_preallocated.h) before using these contexts to call API
+ * functions that perform computations involving secret keys, e.g., signing and
+ * public key generation. It is possible to call this function more than once on
+ * the same context, and doing so before every few computations involving secret
+ * keys is recommended as a defense-in-depth measure.
+ *
+ * Currently, the random seed is mainly used for blinding multiplications of a
+ * secret scalar with the elliptic curve base point. Multiplications of this
+ * kind are performed by exactly those API functions which are documented to
+ * require a context that is not the secp256k1_context_static. As a rule of thumb,
+ * these are all functions which take a secret key (or a keypair) as an input.
+ * A notable exception to that rule is the ECDH module, which relies on a different
+ * kind of elliptic curve point multiplication and thus does not benefit from
+ * enhanced protection against side-channel leakage currently.
+ *
+ * It is safe call this function on a copy of secp256k1_context_static in writable
+ * memory (e.g., obtained via secp256k1_context_clone). In that case, this
+ * function is guaranteed to return 1, but the call will have no effect because
+ * the static context (or a copy thereof) is not meant to be randomized.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
secp256k1_context* ctx,
diff --git a/src/secp256k1/include/secp256k1_extrakeys.h b/src/secp256k1/include/secp256k1_extrakeys.h
index 09cbeaaa80..3591bc0012 100644
--- a/src/secp256k1/include/secp256k1_extrakeys.h
+++ b/src/secp256k1/include/secp256k1_extrakeys.h
@@ -108,7 +108,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
*
- * Args: ctx: pointer to a context object initialized for verification.
+ * Args: ctx: pointer to a context object.
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0.
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
@@ -137,7 +137,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
*
* Returns: 0 if the arguments are invalid or the tweaked pubkey is not the
* result of tweaking the internal_pubkey with tweak32. 1 otherwise.
- * Args: ctx: pointer to a context object initialized for verification.
+ * Args: ctx: pointer to a context object.
* In: tweaked_pubkey32: pointer to a serialized xonly_pubkey.
* tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization
* is passed in as tweaked_pubkey32). This must match the
@@ -159,7 +159,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_
*
* Returns: 1: secret was valid, keypair is ready to use
* 0: secret was invalid, try again with a different secret
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: keypair: pointer to the created keypair.
* In: seckey: pointer to a 32-byte secret key.
*/
@@ -228,7 +228,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
* invalid (only when the tweak is the negation of the keypair's
* secret key). 1 otherwise.
*
- * Args: ctx: pointer to a context object initialized for verification.
+ * Args: ctx: pointer to a context object.
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
* an invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according
diff --git a/src/secp256k1/include/secp256k1_preallocated.h b/src/secp256k1/include/secp256k1_preallocated.h
index d2d9014f02..ed846f75f9 100644
--- a/src/secp256k1/include/secp256k1_preallocated.h
+++ b/src/secp256k1/include/secp256k1_preallocated.h
@@ -58,6 +58,8 @@ SECP256K1_API size_t secp256k1_context_preallocated_size(
* bytes, as detailed above.
* flags: which parts of the context to initialize.
*
+ * See secp256k1_context_create (in secp256k1.h) for further details.
+ *
* See also secp256k1_context_randomize (in secp256k1.h)
* and secp256k1_context_preallocated_destroy.
*/
diff --git a/src/secp256k1/include/secp256k1_recovery.h b/src/secp256k1/include/secp256k1_recovery.h
index 0e2847db96..824c604025 100644
--- a/src/secp256k1/include/secp256k1_recovery.h
+++ b/src/secp256k1/include/secp256k1_recovery.h
@@ -72,7 +72,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
*
* Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid.
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig: pointer to an array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key.
@@ -94,7 +94,7 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
*
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise.
- * Args: ctx: pointer to a context object, initialized for verification.
+ * Args: ctx: pointer to a context object.
* Out: pubkey: pointer to the recovered public key.
* In: sig: pointer to initialized signature that supports pubkey recovery.
* msghash32: the 32-byte message hash assumed to be signed.
diff --git a/src/secp256k1/include/secp256k1_schnorrsig.h b/src/secp256k1/include/secp256k1_schnorrsig.h
index 5fedcb07b0..e579e1b1d8 100644
--- a/src/secp256k1/include/secp256k1_schnorrsig.h
+++ b/src/secp256k1/include/secp256k1_schnorrsig.h
@@ -106,7 +106,7 @@ typedef struct {
* signatures from being valid in multiple contexts by accident.
*
* Returns 1 on success, 0 on failure.
- * Args: ctx: pointer to a context object, initialized for signing.
+ * Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig64: pointer to a 64-byte array to store the serialized signature.
* In: msg32: the 32-byte message being signed.
* keypair: pointer to an initialized keypair.
@@ -161,7 +161,7 @@ SECP256K1_API int secp256k1_schnorrsig_sign_custom(
*
* Returns: 1: correct signature
* 0: incorrect signature
- * Args: ctx: a secp256k1 context object, initialized for verification.
+ * Args: ctx: a secp256k1 context object.
* In: sig64: pointer to the 64-byte signature to verify.
* msg: the message being verified. Can only be NULL if msglen is 0.
* msglen: length of the message
diff --git a/src/secp256k1/src/assumptions.h b/src/secp256k1/src/assumptions.h
index 6dc527b288..8ed04209e9 100644
--- a/src/secp256k1/src/assumptions.h
+++ b/src/secp256k1/src/assumptions.h
@@ -10,6 +10,9 @@
#include <limits.h>
#include "util.h"
+#if defined(SECP256K1_INT128_NATIVE)
+#include "int128_native.h"
+#endif
/* This library, like most software, relies on a number of compiler implementation defined (but not undefined)
behaviours. Although the behaviours we require are essentially universal we test them specifically here to
@@ -55,7 +58,7 @@ struct secp256k1_assumption_checker {
/* To int64_t. */
((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL) &&
-#if defined(SECP256K1_WIDEMUL_INT128)
+#if defined(SECP256K1_INT128_NATIVE)
((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL) &&
(((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL) &&
(((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL) &&
@@ -71,7 +74,7 @@ struct secp256k1_assumption_checker {
((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A) &&
((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48) &&
((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL) &&
-#if defined(SECP256K1_WIDEMUL_INT128)
+#if defined(SECP256K1_INT128_NATIVE)
((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)) &&
#endif
1) * 2 - 1];
diff --git a/src/secp256k1/src/basic-config.h b/src/secp256k1/src/basic-config.h
deleted file mode 100644
index 6f7693cb8f..0000000000
--- a/src/secp256k1/src/basic-config.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/***********************************************************************
- * Copyright (c) 2013, 2014 Pieter Wuille *
- * Distributed under the MIT software license, see the accompanying *
- * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
- ***********************************************************************/
-
-#ifndef SECP256K1_BASIC_CONFIG_H
-#define SECP256K1_BASIC_CONFIG_H
-
-#ifdef USE_BASIC_CONFIG
-
-#define ECMULT_WINDOW_SIZE 15
-#define ECMULT_GEN_PREC_BITS 4
-
-#endif /* USE_BASIC_CONFIG */
-
-#endif /* SECP256K1_BASIC_CONFIG_H */
diff --git a/src/secp256k1/src/bench.c b/src/secp256k1/src/bench.c
index d5937b763f..e68021aa28 100644
--- a/src/secp256k1/src/bench.c
+++ b/src/secp256k1/src/bench.c
@@ -164,7 +164,7 @@ int main(int argc, char** argv) {
/* Check if the user tries to benchmark optional module without building it */
#ifndef ENABLE_MODULE_ECDH
- if (have_flag(argc, argv, "ecdh")) {
+ if (have_flag(argc, argv, "ecdh")) {
fprintf(stderr, "./bench: ECDH module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n");
return 1;
@@ -172,7 +172,7 @@ int main(int argc, char** argv) {
#endif
#ifndef ENABLE_MODULE_RECOVERY
- if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
+ if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) {
fprintf(stderr, "./bench: Public key recovery module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n");
return 1;
@@ -180,15 +180,15 @@ int main(int argc, char** argv) {
#endif
#ifndef ENABLE_MODULE_SCHNORRSIG
- if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
+ if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) {
fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n");
fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n");
return 1;
}
#endif
- /* ECDSA verification benchmark */
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ /* ECDSA benchmark */
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
for (i = 0; i < 32; i++) {
data.msg[i] = 1 + i;
@@ -206,11 +206,6 @@ int main(int argc, char** argv) {
print_output_table_header_row();
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "ecdsa_verify")) run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters);
- secp256k1_context_destroy(data.ctx);
-
- /* ECDSA signing benchmark */
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
-
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "ecdsa_sign")) run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters);
secp256k1_context_destroy(data.ctx);
diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h
index aa275fe919..611ba11f04 100644
--- a/src/secp256k1/src/bench.h
+++ b/src/secp256k1/src/bench.h
@@ -7,15 +7,31 @@
#ifndef SECP256K1_BENCH_H
#define SECP256K1_BENCH_H
+#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
-#include "sys/time.h"
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1900)
+# include <time.h>
+#else
+# include "sys/time.h"
+#endif
static int64_t gettime_i64(void) {
+#if (defined(_MSC_VER) && _MSC_VER >= 1900)
+ /* C11 way to get wallclock time */
+ struct timespec tv;
+ if (!timespec_get(&tv, TIME_UTC)) {
+ fputs("timespec_get failed!", stderr);
+ exit(1);
+ }
+ return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL;
+#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL;
+#endif
}
#define FP_EXP (6)
diff --git a/src/secp256k1/src/bench_ecmult.c b/src/secp256k1/src/bench_ecmult.c
index 4030e0263f..9d0db340e1 100644
--- a/src/secp256k1/src/bench_ecmult.c
+++ b/src/secp256k1/src/bench_ecmult.c
@@ -84,9 +84,7 @@ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset
}
}
secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars);
- secp256k1_gej_neg(&tmp, &tmp);
- secp256k1_gej_add_var(&tmp, &tmp, &sum_output, NULL);
- CHECK(secp256k1_gej_is_infinity(&tmp));
+ CHECK(secp256k1_gej_eq_var(&tmp, &sum_output));
}
static void bench_ecmult_setup(void* arg) {
@@ -308,7 +306,7 @@ int main(int argc, char **argv) {
}
}
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16;
if (!have_flag(argc, argv, "simple")) {
data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size);
diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c
index 7eb3af28d7..2224058f64 100644
--- a/src/secp256k1/src/bench_internal.c
+++ b/src/secp256k1/src/bench_internal.c
@@ -343,19 +343,11 @@ void bench_rfc6979_hmac_sha256(void* arg, int iters) {
}
}
-void bench_context_verify(void* arg, int iters) {
+void bench_context(void* arg, int iters) {
int i;
(void)arg;
for (i = 0; i < iters; i++) {
- secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY));
- }
-}
-
-void bench_context_sign(void* arg, int iters) {
- int i;
- (void)arg;
- for (i = 0; i < iters; i++) {
- secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN));
+ secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_NONE));
}
}
@@ -395,8 +387,7 @@ int main(int argc, char **argv) {
if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, iters);
if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, iters);
- if (d || have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 1 + iters/1000);
- if (d || have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 1 + iters/100);
+ if (d || have_flag(argc, argv, "context")) run_benchmark("context_create", bench_context, bench_setup, NULL, &data, 10, iters);
return 0;
}
diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h
index b47d8f494a..e28c602506 100644
--- a/src/secp256k1/src/ecmult.h
+++ b/src/secp256k1/src/ecmult.h
@@ -11,6 +11,17 @@
#include "scalar.h"
#include "scratch.h"
+#ifndef ECMULT_WINDOW_SIZE
+# define ECMULT_WINDOW_SIZE 15
+# ifdef DEBUG_CONFIG
+# pragma message DEBUG_CONFIG_MSG("ECMULT_WINDOW_SIZE undefined, assuming default value")
+# endif
+#endif
+
+#ifdef DEBUG_CONFIG
+# pragma message DEBUG_CONFIG_DEF(ECMULT_WINDOW_SIZE)
+#endif
+
/* Noone will ever need more than a window size of 24. The code might
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
* tested.
diff --git a/src/secp256k1/src/ecmult_gen.h b/src/secp256k1/src/ecmult_gen.h
index f48f266461..a430e8d5d9 100644
--- a/src/secp256k1/src/ecmult_gen.h
+++ b/src/secp256k1/src/ecmult_gen.h
@@ -10,9 +10,21 @@
#include "scalar.h"
#include "group.h"
+#ifndef ECMULT_GEN_PREC_BITS
+# define ECMULT_GEN_PREC_BITS 4
+# ifdef DEBUG_CONFIG
+# pragma message DEBUG_CONFIG_MSG("ECMULT_GEN_PREC_BITS undefined, assuming default value")
+# endif
+#endif
+
+#ifdef DEBUG_CONFIG
+# pragma message DEBUG_CONFIG_DEF(ECMULT_GEN_PREC_BITS)
+#endif
+
#if ECMULT_GEN_PREC_BITS != 2 && ECMULT_GEN_PREC_BITS != 4 && ECMULT_GEN_PREC_BITS != 8
# error "Set ECMULT_GEN_PREC_BITS to 2, 4 or 8."
#endif
+
#define ECMULT_GEN_PREC_G(bits) (1 << bits)
#define ECMULT_GEN_PREC_N(bits) (256 / bits)
diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h
index 2c8a503acc..4f5ea9f3c0 100644
--- a/src/secp256k1/src/ecmult_gen_impl.h
+++ b/src/secp256k1/src/ecmult_gen_impl.h
@@ -88,31 +88,31 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
unsigned char nonce32[32];
secp256k1_rfc6979_hmac_sha256 rng;
int overflow;
- unsigned char keydata[64] = {0};
+ unsigned char keydata[64];
if (seed32 == NULL) {
/* When seed is NULL, reset the initial point and blinding value. */
secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g);
secp256k1_gej_neg(&ctx->initial, &ctx->initial);
secp256k1_scalar_set_int(&ctx->blind, 1);
+ return;
}
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */
- secp256k1_scalar_get_b32(nonce32, &ctx->blind);
+ secp256k1_scalar_get_b32(keydata, &ctx->blind);
/** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data,
* and guards against weak or adversarial seeds. This is a simpler and safer interface than
* asking the caller for blinding values directly and expecting them to retry on failure.
*/
- memcpy(keydata, nonce32, 32);
- if (seed32 != NULL) {
- memcpy(keydata + 32, seed32, 32);
- }
- secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32);
+ VERIFY_CHECK(seed32 != NULL);
+ memcpy(keydata + 32, seed32, 32);
+ secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64);
memset(keydata, 0, sizeof(keydata));
/* Accept unobservably small non-uniformity. */
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
overflow = !secp256k1_fe_set_b32(&s, nonce32);
overflow |= secp256k1_fe_is_zero(&s);
secp256k1_fe_cmov(&s, &secp256k1_fe_one, overflow);
- /* Randomize the projection to defend against multiplier sidechannels. */
+ /* Randomize the projection to defend against multiplier sidechannels.
+ Do this before our own call to secp256k1_ecmult_gen below. */
secp256k1_gej_rescale(&ctx->initial, &s);
secp256k1_fe_clear(&s);
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
@@ -121,6 +121,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b));
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
memset(nonce32, 0, 32);
+ /* The random projection in ctx->initial ensures that gb will have a random projection. */
secp256k1_ecmult_gen(ctx, &gb, &b);
secp256k1_scalar_negate(&b, &b);
ctx->blind = b;
diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h
index bbc820c77c..3776fe73fc 100644
--- a/src/secp256k1/src/ecmult_impl.h
+++ b/src/secp256k1/src/ecmult_impl.h
@@ -200,9 +200,15 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
bit += now;
}
#ifdef VERIFY
- CHECK(carry == 0);
- while (bit < 256) {
- CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0);
+ {
+ int verify_bit = bit;
+
+ VERIFY_CHECK(carry == 0);
+
+ while (verify_bit < 256) {
+ VERIFY_CHECK(secp256k1_scalar_get_bits(&s, verify_bit, 1) == 0);
+ verify_bit++;
+ }
}
#endif
return last_set_bit + 1;
diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h
index 0ed6118cc9..18567b95f3 100644
--- a/src/secp256k1/src/field_5x52_int128_impl.h
+++ b/src/secp256k1/src/field_5x52_int128_impl.h
@@ -9,14 +9,18 @@
#include <stdint.h>
+#include "int128.h"
+
#ifdef VERIFY
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
+#define VERIFY_BITS_128(x, n) VERIFY_CHECK(secp256k1_u128_check_bits((x), (n)))
#else
#define VERIFY_BITS(x, n) do { } while(0)
+#define VERIFY_BITS_128(x, n) do { } while(0)
#endif
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
- uint128_t c, d;
+ secp256k1_uint128 c, d;
uint64_t t3, t4, tx, u0;
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
@@ -40,121 +44,119 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
* Note that [x 0 0 0 0 0] = [x*R].
*/
- d = (uint128_t)a0 * b[3]
- + (uint128_t)a1 * b[2]
- + (uint128_t)a2 * b[1]
- + (uint128_t)a3 * b[0];
- VERIFY_BITS(d, 114);
+ secp256k1_u128_mul(&d, a0, b[3]);
+ secp256k1_u128_accum_mul(&d, a1, b[2]);
+ secp256k1_u128_accum_mul(&d, a2, b[1]);
+ secp256k1_u128_accum_mul(&d, a3, b[0]);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 0 0] = [p3 0 0 0] */
- c = (uint128_t)a4 * b[4];
- VERIFY_BITS(c, 112);
+ secp256k1_u128_mul(&c, a4, b[4]);
+ VERIFY_BITS_128(&c, 112);
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- d += (uint128_t)R * (uint64_t)c; c >>= 64;
- VERIFY_BITS(d, 115);
- VERIFY_BITS(c, 48);
+ secp256k1_u128_accum_mul(&d, R, secp256k1_u128_to_u64(&c)); secp256k1_u128_rshift(&c, 64);
+ VERIFY_BITS_128(&d, 115);
+ VERIFY_BITS_128(&c, 48);
/* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- t3 = d & M; d >>= 52;
+ t3 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(t3, 52);
- VERIFY_BITS(d, 63);
+ VERIFY_BITS_128(&d, 63);
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- d += (uint128_t)a0 * b[4]
- + (uint128_t)a1 * b[3]
- + (uint128_t)a2 * b[2]
- + (uint128_t)a3 * b[1]
- + (uint128_t)a4 * b[0];
- VERIFY_BITS(d, 115);
+ secp256k1_u128_accum_mul(&d, a0, b[4]);
+ secp256k1_u128_accum_mul(&d, a1, b[3]);
+ secp256k1_u128_accum_mul(&d, a2, b[2]);
+ secp256k1_u128_accum_mul(&d, a3, b[1]);
+ secp256k1_u128_accum_mul(&d, a4, b[0]);
+ VERIFY_BITS_128(&d, 115);
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- d += (uint128_t)(R << 12) * (uint64_t)c;
- VERIFY_BITS(d, 116);
+ secp256k1_u128_accum_mul(&d, R << 12, secp256k1_u128_to_u64(&c));
+ VERIFY_BITS_128(&d, 116);
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- t4 = d & M; d >>= 52;
+ t4 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(t4, 52);
- VERIFY_BITS(d, 64);
+ VERIFY_BITS_128(&d, 64);
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
tx = (t4 >> 48); t4 &= (M >> 4);
VERIFY_BITS(tx, 4);
VERIFY_BITS(t4, 48);
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- c = (uint128_t)a0 * b[0];
- VERIFY_BITS(c, 112);
+ secp256k1_u128_mul(&c, a0, b[0]);
+ VERIFY_BITS_128(&c, 112);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
- d += (uint128_t)a1 * b[4]
- + (uint128_t)a2 * b[3]
- + (uint128_t)a3 * b[2]
- + (uint128_t)a4 * b[1];
- VERIFY_BITS(d, 115);
+ secp256k1_u128_accum_mul(&d, a1, b[4]);
+ secp256k1_u128_accum_mul(&d, a2, b[3]);
+ secp256k1_u128_accum_mul(&d, a3, b[2]);
+ secp256k1_u128_accum_mul(&d, a4, b[1]);
+ VERIFY_BITS_128(&d, 115);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- u0 = d & M; d >>= 52;
+ u0 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(u0, 52);
- VERIFY_BITS(d, 63);
+ VERIFY_BITS_128(&d, 63);
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
/* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
u0 = (u0 << 4) | tx;
VERIFY_BITS(u0, 56);
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (uint128_t)u0 * (R >> 4);
- VERIFY_BITS(c, 115);
+ secp256k1_u128_accum_mul(&c, u0, R >> 4);
+ VERIFY_BITS_128(&c, 115);
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- r[0] = c & M; c >>= 52;
+ r[0] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[0], 52);
- VERIFY_BITS(c, 61);
+ VERIFY_BITS_128(&c, 61);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (uint128_t)a0 * b[1]
- + (uint128_t)a1 * b[0];
- VERIFY_BITS(c, 114);
+ secp256k1_u128_accum_mul(&c, a0, b[1]);
+ secp256k1_u128_accum_mul(&c, a1, b[0]);
+ VERIFY_BITS_128(&c, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
- d += (uint128_t)a2 * b[4]
- + (uint128_t)a3 * b[3]
- + (uint128_t)a4 * b[2];
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a2, b[4]);
+ secp256k1_u128_accum_mul(&d, a3, b[3]);
+ secp256k1_u128_accum_mul(&d, a4, b[2]);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (d & M) * R; d >>= 52;
- VERIFY_BITS(c, 115);
- VERIFY_BITS(d, 62);
+ secp256k1_u128_accum_mul(&c, secp256k1_u128_to_u64(&d) & M, R); secp256k1_u128_rshift(&d, 52);
+ VERIFY_BITS_128(&c, 115);
+ VERIFY_BITS_128(&d, 62);
/* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- r[1] = c & M; c >>= 52;
+ r[1] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[1], 52);
- VERIFY_BITS(c, 63);
+ VERIFY_BITS_128(&c, 63);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (uint128_t)a0 * b[2]
- + (uint128_t)a1 * b[1]
- + (uint128_t)a2 * b[0];
- VERIFY_BITS(c, 114);
+ secp256k1_u128_accum_mul(&c, a0, b[2]);
+ secp256k1_u128_accum_mul(&c, a1, b[1]);
+ secp256k1_u128_accum_mul(&c, a2, b[0]);
+ VERIFY_BITS_128(&c, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
- d += (uint128_t)a3 * b[4]
- + (uint128_t)a4 * b[3];
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a3, b[4]);
+ secp256k1_u128_accum_mul(&d, a4, b[3]);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += (uint128_t)R * (uint64_t)d; d >>= 64;
- VERIFY_BITS(c, 115);
- VERIFY_BITS(d, 50);
+ secp256k1_u128_accum_mul(&c, R, secp256k1_u128_to_u64(&d)); secp256k1_u128_rshift(&d, 64);
+ VERIFY_BITS_128(&c, 115);
+ VERIFY_BITS_128(&d, 50);
/* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[2] = c & M; c >>= 52;
+ r[2] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[2], 52);
- VERIFY_BITS(c, 63);
+ VERIFY_BITS_128(&c, 63);
/* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += (uint128_t)(R << 12) * (uint64_t)d + t3;
- VERIFY_BITS(c, 100);
+ secp256k1_u128_accum_mul(&c, R << 12, secp256k1_u128_to_u64(&d));
+ secp256k1_u128_accum_u64(&c, t3);
+ VERIFY_BITS_128(&c, 100);
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[3] = c & M; c >>= 52;
+ r[3] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[3], 52);
- VERIFY_BITS(c, 48);
+ VERIFY_BITS_128(&c, 48);
/* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += t4;
- VERIFY_BITS(c, 49);
- /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[4] = c;
+ r[4] = secp256k1_u128_to_u64(&c) + t4;
VERIFY_BITS(r[4], 49);
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
- uint128_t c, d;
+ secp256k1_uint128 c, d;
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
int64_t t3, t4, tx, u0;
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
@@ -170,107 +172,105 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
* Note that [x 0 0 0 0 0] = [x*R].
*/
- d = (uint128_t)(a0*2) * a3
- + (uint128_t)(a1*2) * a2;
- VERIFY_BITS(d, 114);
+ secp256k1_u128_mul(&d, a0*2, a3);
+ secp256k1_u128_accum_mul(&d, a1*2, a2);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 0 0] = [p3 0 0 0] */
- c = (uint128_t)a4 * a4;
- VERIFY_BITS(c, 112);
+ secp256k1_u128_mul(&c, a4, a4);
+ VERIFY_BITS_128(&c, 112);
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- d += (uint128_t)R * (uint64_t)c; c >>= 64;
- VERIFY_BITS(d, 115);
- VERIFY_BITS(c, 48);
+ secp256k1_u128_accum_mul(&d, R, secp256k1_u128_to_u64(&c)); secp256k1_u128_rshift(&c, 64);
+ VERIFY_BITS_128(&d, 115);
+ VERIFY_BITS_128(&c, 48);
/* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- t3 = d & M; d >>= 52;
+ t3 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(t3, 52);
- VERIFY_BITS(d, 63);
+ VERIFY_BITS_128(&d, 63);
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
a4 *= 2;
- d += (uint128_t)a0 * a4
- + (uint128_t)(a1*2) * a3
- + (uint128_t)a2 * a2;
- VERIFY_BITS(d, 115);
+ secp256k1_u128_accum_mul(&d, a0, a4);
+ secp256k1_u128_accum_mul(&d, a1*2, a3);
+ secp256k1_u128_accum_mul(&d, a2, a2);
+ VERIFY_BITS_128(&d, 115);
/* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- d += (uint128_t)(R << 12) * (uint64_t)c;
- VERIFY_BITS(d, 116);
+ secp256k1_u128_accum_mul(&d, R << 12, secp256k1_u128_to_u64(&c));
+ VERIFY_BITS_128(&d, 116);
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- t4 = d & M; d >>= 52;
+ t4 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(t4, 52);
- VERIFY_BITS(d, 64);
+ VERIFY_BITS_128(&d, 64);
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
tx = (t4 >> 48); t4 &= (M >> 4);
VERIFY_BITS(tx, 4);
VERIFY_BITS(t4, 48);
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- c = (uint128_t)a0 * a0;
- VERIFY_BITS(c, 112);
+ secp256k1_u128_mul(&c, a0, a0);
+ VERIFY_BITS_128(&c, 112);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
- d += (uint128_t)a1 * a4
- + (uint128_t)(a2*2) * a3;
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a1, a4);
+ secp256k1_u128_accum_mul(&d, a2*2, a3);
+ VERIFY_BITS_128(&d, 114);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- u0 = d & M; d >>= 52;
+ u0 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
VERIFY_BITS(u0, 52);
- VERIFY_BITS(d, 62);
+ VERIFY_BITS_128(&d, 62);
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
/* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
u0 = (u0 << 4) | tx;
VERIFY_BITS(u0, 56);
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (uint128_t)u0 * (R >> 4);
- VERIFY_BITS(c, 113);
+ secp256k1_u128_accum_mul(&c, u0, R >> 4);
+ VERIFY_BITS_128(&c, 113);
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- r[0] = c & M; c >>= 52;
+ r[0] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[0], 52);
- VERIFY_BITS(c, 61);
+ VERIFY_BITS_128(&c, 61);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
a0 *= 2;
- c += (uint128_t)a0 * a1;
- VERIFY_BITS(c, 114);
+ secp256k1_u128_accum_mul(&c, a0, a1);
+ VERIFY_BITS_128(&c, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
- d += (uint128_t)a2 * a4
- + (uint128_t)a3 * a3;
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a2, a4);
+ secp256k1_u128_accum_mul(&d, a3, a3);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (d & M) * R; d >>= 52;
- VERIFY_BITS(c, 115);
- VERIFY_BITS(d, 62);
+ secp256k1_u128_accum_mul(&c, secp256k1_u128_to_u64(&d) & M, R); secp256k1_u128_rshift(&d, 52);
+ VERIFY_BITS_128(&c, 115);
+ VERIFY_BITS_128(&d, 62);
/* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- r[1] = c & M; c >>= 52;
+ r[1] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[1], 52);
- VERIFY_BITS(c, 63);
+ VERIFY_BITS_128(&c, 63);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (uint128_t)a0 * a2
- + (uint128_t)a1 * a1;
- VERIFY_BITS(c, 114);
+ secp256k1_u128_accum_mul(&c, a0, a2);
+ secp256k1_u128_accum_mul(&c, a1, a1);
+ VERIFY_BITS_128(&c, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
- d += (uint128_t)a3 * a4;
- VERIFY_BITS(d, 114);
+ secp256k1_u128_accum_mul(&d, a3, a4);
+ VERIFY_BITS_128(&d, 114);
/* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += (uint128_t)R * (uint64_t)d; d >>= 64;
- VERIFY_BITS(c, 115);
- VERIFY_BITS(d, 50);
+ secp256k1_u128_accum_mul(&c, R, secp256k1_u128_to_u64(&d)); secp256k1_u128_rshift(&d, 64);
+ VERIFY_BITS_128(&c, 115);
+ VERIFY_BITS_128(&d, 50);
/* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[2] = c & M; c >>= 52;
+ r[2] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[2], 52);
- VERIFY_BITS(c, 63);
+ VERIFY_BITS_128(&c, 63);
/* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += (uint128_t)(R << 12) * (uint64_t)d + t3;
- VERIFY_BITS(c, 100);
+ secp256k1_u128_accum_mul(&c, R << 12, secp256k1_u128_to_u64(&d));
+ secp256k1_u128_accum_u64(&c, t3);
+ VERIFY_BITS_128(&c, 100);
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[3] = c & M; c >>= 52;
+ r[3] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
VERIFY_BITS(r[3], 52);
- VERIFY_BITS(c, 48);
+ VERIFY_BITS_128(&c, 48);
/* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- c += t4;
- VERIFY_BITS(c, 49);
- /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[4] = c;
+ r[4] = secp256k1_u128_to_u64(&c) + t4;
VERIFY_BITS(r[4], 49);
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h
index bb7dae1cf7..b79ba597db 100644
--- a/src/secp256k1/src/group.h
+++ b/src/secp256k1/src/group.h
@@ -23,7 +23,7 @@ typedef struct {
#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1}
/** A group element of the secp256k1 curve, in jacobian coordinates.
- * Note: For exhastive test mode, sepc256k1 is replaced by a small subgroup of a different curve.
+ * Note: For exhastive test mode, secp256k1 is replaced by a small subgroup of a different curve.
*/
typedef struct {
secp256k1_fe x; /* actual X: x/z^2 */
@@ -97,6 +97,9 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r);
/** Set a group element (jacobian) equal to another which is given in affine coordinates. */
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a);
+/** Check two group elements (jacobian) for equality in variable time. */
+static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b);
+
/** Compare the X coordinate of a group element (jacobian). */
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a);
diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h
index 63735ab682..dfe6e32c7f 100644
--- a/src/secp256k1/src/group_impl.h
+++ b/src/secp256k1/src/group_impl.h
@@ -236,6 +236,13 @@ static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
secp256k1_fe_set_int(&r->z, 1);
}
+static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) {
+ secp256k1_gej tmp;
+ secp256k1_gej_neg(&tmp, a);
+ secp256k1_gej_add_var(&tmp, &tmp, b, NULL);
+ return secp256k1_gej_is_infinity(&tmp);
+}
+
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
secp256k1_fe r, r2;
VERIFY_CHECK(!a->infinity);
diff --git a/src/secp256k1/src/int128.h b/src/secp256k1/src/int128.h
new file mode 100644
index 0000000000..84d969a236
--- /dev/null
+++ b/src/secp256k1/src/int128.h
@@ -0,0 +1,85 @@
+#ifndef SECP256K1_INT128_H
+#define SECP256K1_INT128_H
+
+#include "util.h"
+
+#if defined(SECP256K1_WIDEMUL_INT128)
+# if defined(SECP256K1_INT128_NATIVE)
+# include "int128_native.h"
+# elif defined(SECP256K1_INT128_STRUCT)
+# include "int128_struct.h"
+# else
+# error "Please select int128 implementation"
+# endif
+
+/* Construct an unsigned 128-bit value from a high and a low 64-bit value. */
+static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo);
+
+/* Multiply two unsigned 64-bit values a and b and write the result to r. */
+static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b);
+
+/* Multiply two unsigned 64-bit values a and b and add the result to r.
+ * The final result is taken modulo 2^128.
+ */
+static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b);
+
+/* Add an unsigned 64-bit value a to r.
+ * The final result is taken modulo 2^128.
+ */
+static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a);
+
+/* Unsigned (logical) right shift.
+ * Non-constant time in n.
+ */
+static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n);
+
+/* Return the low 64-bits of a 128-bit value as an unsigned 64-bit value. */
+static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a);
+
+/* Return the high 64-bits of a 128-bit value as an unsigned 64-bit value. */
+static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a);
+
+/* Write an unsigned 64-bit value to r. */
+static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a);
+
+/* Tests if r is strictly less than to 2^n.
+ * n must be strictly less than 128.
+ */
+static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n);
+
+/* Construct an signed 128-bit value from a high and a low 64-bit value. */
+static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo);
+
+/* Multiply two signed 64-bit values a and b and write the result to r. */
+static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b);
+
+/* Multiply two signed 64-bit values a and b and add the result to r.
+ * Overflow or underflow from the addition is undefined behaviour.
+ */
+static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b);
+
+/* Compute a*d - b*c from signed 64-bit values and write the result to r. */
+static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d);
+
+/* Signed (arithmetic) right shift.
+ * Non-constant time in b.
+ */
+static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int b);
+
+/* Return the low 64-bits of a 128-bit value interpreted as an signed 64-bit value. */
+static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a);
+
+/* Write a signed 64-bit value to r. */
+static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a);
+
+/* Compare two 128-bit values for equality. */
+static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b);
+
+/* Tests if r is equal to 2^n.
+ * n must be strictly less than 127.
+ */
+static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n);
+
+#endif
+
+#endif
diff --git a/src/secp256k1/src/int128_impl.h b/src/secp256k1/src/int128_impl.h
new file mode 100644
index 0000000000..cfc573408a
--- /dev/null
+++ b/src/secp256k1/src/int128_impl.h
@@ -0,0 +1,18 @@
+#ifndef SECP256K1_INT128_IMPL_H
+#define SECP256K1_INT128_IMPL_H
+
+#include "util.h"
+
+#include "int128.h"
+
+#if defined(SECP256K1_WIDEMUL_INT128)
+# if defined(SECP256K1_INT128_NATIVE)
+# include "int128_native_impl.h"
+# elif defined(SECP256K1_INT128_STRUCT)
+# include "int128_struct_impl.h"
+# else
+# error "Please select int128 implementation"
+# endif
+#endif
+
+#endif
diff --git a/src/secp256k1/src/int128_native.h b/src/secp256k1/src/int128_native.h
new file mode 100644
index 0000000000..7c97aafc74
--- /dev/null
+++ b/src/secp256k1/src/int128_native.h
@@ -0,0 +1,19 @@
+#ifndef SECP256K1_INT128_NATIVE_H
+#define SECP256K1_INT128_NATIVE_H
+
+#include <stdint.h>
+#include "util.h"
+
+#if !defined(UINT128_MAX) && defined(__SIZEOF_INT128__)
+SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
+SECP256K1_GNUC_EXT typedef __int128 int128_t;
+# define UINT128_MAX ((uint128_t)(-1))
+# define INT128_MAX ((int128_t)(UINT128_MAX >> 1))
+# define INT128_MIN (-INT128_MAX - 1)
+/* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */
+#endif
+
+typedef uint128_t secp256k1_uint128;
+typedef int128_t secp256k1_int128;
+
+#endif
diff --git a/src/secp256k1/src/int128_native_impl.h b/src/secp256k1/src/int128_native_impl.h
new file mode 100644
index 0000000000..e4b7f4106c
--- /dev/null
+++ b/src/secp256k1/src/int128_native_impl.h
@@ -0,0 +1,87 @@
+#ifndef SECP256K1_INT128_NATIVE_IMPL_H
+#define SECP256K1_INT128_NATIVE_IMPL_H
+
+#include "int128.h"
+
+static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) {
+ *r = (((uint128_t)hi) << 64) + lo;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
+ *r = (uint128_t)a * b;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
+ *r += (uint128_t)a * b;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) {
+ *r += a;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ *r >>= n;
+}
+
+static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) {
+ return (uint64_t)(*a);
+}
+
+static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a) {
+ return (uint64_t)(*a >> 64);
+}
+
+static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) {
+ *r = a;
+}
+
+static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ return (*r >> n == 0);
+}
+
+static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo) {
+ *r = (((uint128_t)(uint64_t)hi) << 64) + lo;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ *r = (int128_t)a * b;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ int128_t ab = (int128_t)a * b;
+ VERIFY_CHECK(0 <= ab ? *r <= INT128_MAX - ab : INT128_MIN - ab <= *r);
+ *r += ab;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) {
+ int128_t ad = (int128_t)a * d;
+ int128_t bc = (int128_t)b * c;
+ VERIFY_CHECK(0 <= bc ? INT128_MIN + bc <= ad : ad <= INT128_MAX + bc);
+ *r = ad - bc;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ *r >>= n;
+}
+
+static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) {
+ return *a;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) {
+ *r = a;
+}
+
+static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b) {
+ return *a == *b;
+}
+
+static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 127);
+ return (*r == (int128_t)1 << n);
+}
+
+#endif
diff --git a/src/secp256k1/src/int128_struct.h b/src/secp256k1/src/int128_struct.h
new file mode 100644
index 0000000000..6156f82cc2
--- /dev/null
+++ b/src/secp256k1/src/int128_struct.h
@@ -0,0 +1,14 @@
+#ifndef SECP256K1_INT128_STRUCT_H
+#define SECP256K1_INT128_STRUCT_H
+
+#include <stdint.h>
+#include "util.h"
+
+typedef struct {
+ uint64_t lo;
+ uint64_t hi;
+} secp256k1_uint128;
+
+typedef secp256k1_uint128 secp256k1_int128;
+
+#endif
diff --git a/src/secp256k1/src/int128_struct_impl.h b/src/secp256k1/src/int128_struct_impl.h
new file mode 100644
index 0000000000..b5f8fb7b65
--- /dev/null
+++ b/src/secp256k1/src/int128_struct_impl.h
@@ -0,0 +1,192 @@
+#ifndef SECP256K1_INT128_STRUCT_IMPL_H
+#define SECP256K1_INT128_STRUCT_IMPL_H
+
+#include "int128.h"
+
+#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) /* MSVC */
+# include <intrin.h>
+# if defined(_M_ARM64) || defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE)
+/* On ARM64 MSVC, use __(u)mulh for the upper half of 64x64 multiplications.
+ (Define SECP256K1_MSVC_MULH_TEST_OVERRIDE to test this code path on X64,
+ which supports both __(u)mulh and _umul128.) */
+# if defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE)
+# pragma message(__FILE__ ": SECP256K1_MSVC_MULH_TEST_OVERRIDE is defined, forcing use of __(u)mulh.")
+# endif
+static SECP256K1_INLINE uint64_t secp256k1_umul128(uint64_t a, uint64_t b, uint64_t* hi) {
+ *hi = __umulh(a, b);
+ return a * b;
+}
+
+static SECP256K1_INLINE int64_t secp256k1_mul128(int64_t a, int64_t b, int64_t* hi) {
+ *hi = __mulh(a, b);
+ return (uint64_t)a * (uint64_t)b;
+}
+# else
+/* On x84_64 MSVC, use native _(u)mul128 for 64x64->128 multiplications. */
+# define secp256k1_umul128 _umul128
+# define secp256k1_mul128 _mul128
+# endif
+#else
+/* On other systems, emulate 64x64->128 multiplications using 32x32->64 multiplications. */
+static SECP256K1_INLINE uint64_t secp256k1_umul128(uint64_t a, uint64_t b, uint64_t* hi) {
+ uint64_t ll = (uint64_t)(uint32_t)a * (uint32_t)b;
+ uint64_t lh = (uint32_t)a * (b >> 32);
+ uint64_t hl = (a >> 32) * (uint32_t)b;
+ uint64_t hh = (a >> 32) * (b >> 32);
+ uint64_t mid34 = (ll >> 32) + (uint32_t)lh + (uint32_t)hl;
+ *hi = hh + (lh >> 32) + (hl >> 32) + (mid34 >> 32);
+ return (mid34 << 32) + (uint32_t)ll;
+}
+
+static SECP256K1_INLINE int64_t secp256k1_mul128(int64_t a, int64_t b, int64_t* hi) {
+ uint64_t ll = (uint64_t)(uint32_t)a * (uint32_t)b;
+ int64_t lh = (uint32_t)a * (b >> 32);
+ int64_t hl = (a >> 32) * (uint32_t)b;
+ int64_t hh = (a >> 32) * (b >> 32);
+ uint64_t mid34 = (ll >> 32) + (uint32_t)lh + (uint32_t)hl;
+ *hi = hh + (lh >> 32) + (hl >> 32) + (mid34 >> 32);
+ return (mid34 << 32) + (uint32_t)ll;
+}
+#endif
+
+static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) {
+ r->hi = hi;
+ r->lo = lo;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
+ r->lo = secp256k1_umul128(a, b, &r->hi);
+}
+
+static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) {
+ uint64_t lo, hi;
+ lo = secp256k1_umul128(a, b, &hi);
+ r->lo += lo;
+ r->hi += hi + (r->lo < lo);
+}
+
+static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) {
+ r->lo += a;
+ r->hi += r->lo < a;
+}
+
+/* Unsigned (logical) right shift.
+ * Non-constant time in n.
+ */
+static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ if (n >= 64) {
+ r->lo = r->hi >> (n-64);
+ r->hi = 0;
+ } else if (n > 0) {
+ r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n;
+ r->hi >>= n;
+ }
+}
+
+static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) {
+ return a->lo;
+}
+
+static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a) {
+ return a->hi;
+}
+
+static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) {
+ r->hi = 0;
+ r->lo = a;
+}
+
+static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ return n >= 64 ? r->hi >> (n - 64) == 0
+ : r->hi == 0 && r->lo >> n == 0;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo) {
+ r->hi = hi;
+ r->lo = lo;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ int64_t hi;
+ r->lo = (uint64_t)secp256k1_mul128(a, b, &hi);
+ r->hi = (uint64_t)hi;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ int64_t hi;
+ uint64_t lo = (uint64_t)secp256k1_mul128(a, b, &hi);
+ r->lo += lo;
+ hi += r->lo < lo;
+ /* Verify no overflow.
+ * If r represents a positive value (the sign bit is not set) and the value we are adding is a positive value (the sign bit is not set),
+ * then we require that the resulting value also be positive (the sign bit is not set).
+ * Note that (X <= Y) means (X implies Y) when X and Y are boolean values (i.e. 0 or 1).
+ */
+ VERIFY_CHECK((r->hi <= 0x7fffffffffffffffu && (uint64_t)hi <= 0x7fffffffffffffffu) <= (r->hi + (uint64_t)hi <= 0x7fffffffffffffffu));
+ /* Verify no underflow.
+ * If r represents a negative value (the sign bit is set) and the value we are adding is a negative value (the sign bit is set),
+ * then we require that the resulting value also be negative (the sign bit is set).
+ */
+ VERIFY_CHECK((r->hi > 0x7fffffffffffffffu && (uint64_t)hi > 0x7fffffffffffffffu) <= (r->hi + (uint64_t)hi > 0x7fffffffffffffffu));
+ r->hi += hi;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_dissip_mul(secp256k1_int128 *r, int64_t a, int64_t b) {
+ int64_t hi;
+ uint64_t lo = (uint64_t)secp256k1_mul128(a, b, &hi);
+ hi += r->lo < lo;
+ /* Verify no overflow.
+ * If r represents a positive value (the sign bit is not set) and the value we are subtracting is a negative value (the sign bit is set),
+ * then we require that the resulting value also be positive (the sign bit is not set).
+ */
+ VERIFY_CHECK((r->hi <= 0x7fffffffffffffffu && (uint64_t)hi > 0x7fffffffffffffffu) <= (r->hi - (uint64_t)hi <= 0x7fffffffffffffffu));
+ /* Verify no underflow.
+ * If r represents a negative value (the sign bit is set) and the value we are subtracting is a positive value (the sign sign bit is not set),
+ * then we require that the resulting value also be negative (the sign bit is set).
+ */
+ VERIFY_CHECK((r->hi > 0x7fffffffffffffffu && (uint64_t)hi <= 0x7fffffffffffffffu) <= (r->hi - (uint64_t)hi > 0x7fffffffffffffffu));
+ r->hi -= hi;
+ r->lo -= lo;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) {
+ secp256k1_i128_mul(r, a, d);
+ secp256k1_i128_dissip_mul(r, b, c);
+}
+
+/* Signed (arithmetic) right shift.
+ * Non-constant time in n.
+ */
+static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 128);
+ if (n >= 64) {
+ r->lo = (uint64_t)((int64_t)(r->hi) >> (n-64));
+ r->hi = (uint64_t)((int64_t)(r->hi) >> 63);
+ } else if (n > 0) {
+ r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n;
+ r->hi = (uint64_t)((int64_t)(r->hi) >> n);
+ }
+}
+
+static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) {
+ return (int64_t)a->lo;
+}
+
+static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) {
+ r->hi = (uint64_t)(a >> 63);
+ r->lo = (uint64_t)a;
+}
+
+static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b) {
+ return a->hi == b->hi && a->lo == b->lo;
+}
+
+static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n) {
+ VERIFY_CHECK(n < 127);
+ return n >= 64 ? r->hi == (uint64_t)1 << (n - 64) && r->lo == 0
+ : r->hi == 0 && r->lo == (uint64_t)1 << n;
+}
+
+#endif
diff --git a/src/secp256k1/src/modinv64_impl.h b/src/secp256k1/src/modinv64_impl.h
index 0743a9c821..50be2e5e78 100644
--- a/src/secp256k1/src/modinv64_impl.h
+++ b/src/secp256k1/src/modinv64_impl.h
@@ -7,10 +7,9 @@
#ifndef SECP256K1_MODINV64_IMPL_H
#define SECP256K1_MODINV64_IMPL_H
+#include "int128.h"
#include "modinv64.h"
-#include "util.h"
-
/* This file implements modular inversion based on the paper "Fast constant-time gcd computation and
* modular inversion" by Daniel J. Bernstein and Bo-Yin Yang.
*
@@ -18,6 +17,15 @@
* implementation for N=62, using 62-bit signed limbs represented as int64_t.
*/
+/* Data type for transition matrices (see section 3 of explanation).
+ *
+ * t = [ u v ]
+ * [ q r ]
+ */
+typedef struct {
+ int64_t u, v, q, r;
+} secp256k1_modinv64_trans2x2;
+
#ifdef VERIFY
/* Helper function to compute the absolute value of an int64_t.
* (we don't use abs/labs/llabs as it depends on the int sizes). */
@@ -32,15 +40,17 @@ static const secp256k1_modinv64_signed62 SECP256K1_SIGNED62_ONE = {{1}};
/* Compute a*factor and put it in r. All but the top limb in r will be in range [0,2^62). */
static void secp256k1_modinv64_mul_62(secp256k1_modinv64_signed62 *r, const secp256k1_modinv64_signed62 *a, int alen, int64_t factor) {
const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
- int128_t c = 0;
+ secp256k1_int128 c, d;
int i;
+ secp256k1_i128_from_i64(&c, 0);
for (i = 0; i < 4; ++i) {
- if (i < alen) c += (int128_t)a->v[i] * factor;
- r->v[i] = (int64_t)c & M62; c >>= 62;
+ if (i < alen) secp256k1_i128_accum_mul(&c, a->v[i], factor);
+ r->v[i] = secp256k1_i128_to_i64(&c) & M62; secp256k1_i128_rshift(&c, 62);
}
- if (4 < alen) c += (int128_t)a->v[4] * factor;
- VERIFY_CHECK(c == (int64_t)c);
- r->v[4] = (int64_t)c;
+ if (4 < alen) secp256k1_i128_accum_mul(&c, a->v[4], factor);
+ secp256k1_i128_from_i64(&d, secp256k1_i128_to_i64(&c));
+ VERIFY_CHECK(secp256k1_i128_eq_var(&c, &d));
+ r->v[4] = secp256k1_i128_to_i64(&c);
}
/* Return -1 for a<b*factor, 0 for a==b*factor, 1 for a>b*factor. A has alen limbs; b has 5. */
@@ -60,6 +70,13 @@ static int secp256k1_modinv64_mul_cmp_62(const secp256k1_modinv64_signed62 *a, i
}
return 0;
}
+
+/* Check if the determinant of t is equal to 1 << n. */
+static int secp256k1_modinv64_det_check_pow2(const secp256k1_modinv64_trans2x2 *t, unsigned int n) {
+ secp256k1_int128 a;
+ secp256k1_i128_det(&a, t->u, t->v, t->q, t->r);
+ return secp256k1_i128_check_pow2(&a, n);
+}
#endif
/* Take as input a signed62 number in range (-2*modulus,modulus), and add a multiple of the modulus
@@ -136,15 +153,6 @@ static void secp256k1_modinv64_normalize_62(secp256k1_modinv64_signed62 *r, int6
#endif
}
-/* Data type for transition matrices (see section 3 of explanation).
- *
- * t = [ u v ]
- * [ q r ]
- */
-typedef struct {
- int64_t u, v, q, r;
-} secp256k1_modinv64_trans2x2;
-
/* Compute the transition matrix and eta for 59 divsteps (where zeta=-(delta+1/2)).
* Note that the transformation matrix is scaled by 2^62 and not 2^59.
*
@@ -203,13 +211,15 @@ static int64_t secp256k1_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_
t->v = (int64_t)v;
t->q = (int64_t)q;
t->r = (int64_t)r;
+#ifdef VERIFY
/* The determinant of t must be a power of two. This guarantees that multiplication with t
* does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
* will be divided out again). As each divstep's individual matrix has determinant 2, the
* aggregate of 59 of them will have determinant 2^59. Multiplying with the initial
* 8*identity (which has determinant 2^6) means the overall outputs has determinant
* 2^65. */
- VERIFY_CHECK((int128_t)t->u * t->r - (int128_t)t->v * t->q == ((int128_t)1) << 65);
+ VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 65));
+#endif
return zeta;
}
@@ -286,11 +296,13 @@ static int64_t secp256k1_modinv64_divsteps_62_var(int64_t eta, uint64_t f0, uint
t->v = (int64_t)v;
t->q = (int64_t)q;
t->r = (int64_t)r;
+#ifdef VERIFY
/* The determinant of t must be a power of two. This guarantees that multiplication with t
* does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
* will be divided out again). As each divstep's individual matrix has determinant 2, the
* aggregate of 62 of them will have determinant 2^62. */
- VERIFY_CHECK((int128_t)t->u * t->r - (int128_t)t->v * t->q == ((int128_t)1) << 62);
+ VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 62));
+#endif
return eta;
}
@@ -307,7 +319,7 @@ static void secp256k1_modinv64_update_de_62(secp256k1_modinv64_signed62 *d, secp
const int64_t e0 = e->v[0], e1 = e->v[1], e2 = e->v[2], e3 = e->v[3], e4 = e->v[4];
const int64_t u = t->u, v = t->v, q = t->q, r = t->r;
int64_t md, me, sd, se;
- int128_t cd, ce;
+ secp256k1_int128 cd, ce;
#ifdef VERIFY
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */
@@ -324,54 +336,64 @@ static void secp256k1_modinv64_update_de_62(secp256k1_modinv64_signed62 *d, secp
md = (u & sd) + (v & se);
me = (q & sd) + (r & se);
/* Begin computing t*[d,e]. */
- cd = (int128_t)u * d0 + (int128_t)v * e0;
- ce = (int128_t)q * d0 + (int128_t)r * e0;
+ secp256k1_i128_mul(&cd, u, d0);
+ secp256k1_i128_accum_mul(&cd, v, e0);
+ secp256k1_i128_mul(&ce, q, d0);
+ secp256k1_i128_accum_mul(&ce, r, e0);
/* Correct md,me so that t*[d,e]+modulus*[md,me] has 62 zero bottom bits. */
- md -= (modinfo->modulus_inv62 * (uint64_t)cd + md) & M62;
- me -= (modinfo->modulus_inv62 * (uint64_t)ce + me) & M62;
+ md -= (modinfo->modulus_inv62 * (uint64_t)secp256k1_i128_to_i64(&cd) + md) & M62;
+ me -= (modinfo->modulus_inv62 * (uint64_t)secp256k1_i128_to_i64(&ce) + me) & M62;
/* Update the beginning of computation for t*[d,e]+modulus*[md,me] now md,me are known. */
- cd += (int128_t)modinfo->modulus.v[0] * md;
- ce += (int128_t)modinfo->modulus.v[0] * me;
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[0], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[0], me);
/* Verify that the low 62 bits of the computation are indeed zero, and then throw them away. */
- VERIFY_CHECK(((int64_t)cd & M62) == 0); cd >>= 62;
- VERIFY_CHECK(((int64_t)ce & M62) == 0); ce >>= 62;
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cd) & M62) == 0); secp256k1_i128_rshift(&cd, 62);
+ VERIFY_CHECK((secp256k1_i128_to_i64(&ce) & M62) == 0); secp256k1_i128_rshift(&ce, 62);
/* Compute limb 1 of t*[d,e]+modulus*[md,me], and store it as output limb 0 (= down shift). */
- cd += (int128_t)u * d1 + (int128_t)v * e1;
- ce += (int128_t)q * d1 + (int128_t)r * e1;
+ secp256k1_i128_accum_mul(&cd, u, d1);
+ secp256k1_i128_accum_mul(&cd, v, e1);
+ secp256k1_i128_accum_mul(&ce, q, d1);
+ secp256k1_i128_accum_mul(&ce, r, e1);
if (modinfo->modulus.v[1]) { /* Optimize for the case where limb of modulus is zero. */
- cd += (int128_t)modinfo->modulus.v[1] * md;
- ce += (int128_t)modinfo->modulus.v[1] * me;
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[1], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[1], me);
}
- d->v[0] = (int64_t)cd & M62; cd >>= 62;
- e->v[0] = (int64_t)ce & M62; ce >>= 62;
+ d->v[0] = secp256k1_i128_to_i64(&cd) & M62; secp256k1_i128_rshift(&cd, 62);
+ e->v[0] = secp256k1_i128_to_i64(&ce) & M62; secp256k1_i128_rshift(&ce, 62);
/* Compute limb 2 of t*[d,e]+modulus*[md,me], and store it as output limb 1. */
- cd += (int128_t)u * d2 + (int128_t)v * e2;
- ce += (int128_t)q * d2 + (int128_t)r * e2;
+ secp256k1_i128_accum_mul(&cd, u, d2);
+ secp256k1_i128_accum_mul(&cd, v, e2);
+ secp256k1_i128_accum_mul(&ce, q, d2);
+ secp256k1_i128_accum_mul(&ce, r, e2);
if (modinfo->modulus.v[2]) { /* Optimize for the case where limb of modulus is zero. */
- cd += (int128_t)modinfo->modulus.v[2] * md;
- ce += (int128_t)modinfo->modulus.v[2] * me;
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[2], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[2], me);
}
- d->v[1] = (int64_t)cd & M62; cd >>= 62;
- e->v[1] = (int64_t)ce & M62; ce >>= 62;
+ d->v[1] = secp256k1_i128_to_i64(&cd) & M62; secp256k1_i128_rshift(&cd, 62);
+ e->v[1] = secp256k1_i128_to_i64(&ce) & M62; secp256k1_i128_rshift(&ce, 62);
/* Compute limb 3 of t*[d,e]+modulus*[md,me], and store it as output limb 2. */
- cd += (int128_t)u * d3 + (int128_t)v * e3;
- ce += (int128_t)q * d3 + (int128_t)r * e3;
+ secp256k1_i128_accum_mul(&cd, u, d3);
+ secp256k1_i128_accum_mul(&cd, v, e3);
+ secp256k1_i128_accum_mul(&ce, q, d3);
+ secp256k1_i128_accum_mul(&ce, r, e3);
if (modinfo->modulus.v[3]) { /* Optimize for the case where limb of modulus is zero. */
- cd += (int128_t)modinfo->modulus.v[3] * md;
- ce += (int128_t)modinfo->modulus.v[3] * me;
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[3], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[3], me);
}
- d->v[2] = (int64_t)cd & M62; cd >>= 62;
- e->v[2] = (int64_t)ce & M62; ce >>= 62;
+ d->v[2] = secp256k1_i128_to_i64(&cd) & M62; secp256k1_i128_rshift(&cd, 62);
+ e->v[2] = secp256k1_i128_to_i64(&ce) & M62; secp256k1_i128_rshift(&ce, 62);
/* Compute limb 4 of t*[d,e]+modulus*[md,me], and store it as output limb 3. */
- cd += (int128_t)u * d4 + (int128_t)v * e4;
- ce += (int128_t)q * d4 + (int128_t)r * e4;
- cd += (int128_t)modinfo->modulus.v[4] * md;
- ce += (int128_t)modinfo->modulus.v[4] * me;
- d->v[3] = (int64_t)cd & M62; cd >>= 62;
- e->v[3] = (int64_t)ce & M62; ce >>= 62;
+ secp256k1_i128_accum_mul(&cd, u, d4);
+ secp256k1_i128_accum_mul(&cd, v, e4);
+ secp256k1_i128_accum_mul(&ce, q, d4);
+ secp256k1_i128_accum_mul(&ce, r, e4);
+ secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[4], md);
+ secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[4], me);
+ d->v[3] = secp256k1_i128_to_i64(&cd) & M62; secp256k1_i128_rshift(&cd, 62);
+ e->v[3] = secp256k1_i128_to_i64(&ce) & M62; secp256k1_i128_rshift(&ce, 62);
/* What remains is limb 5 of t*[d,e]+modulus*[md,me]; store it as output limb 4. */
- d->v[4] = (int64_t)cd;
- e->v[4] = (int64_t)ce;
+ d->v[4] = secp256k1_i128_to_i64(&cd);
+ e->v[4] = secp256k1_i128_to_i64(&ce);
#ifdef VERIFY
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */
VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */
@@ -389,36 +411,46 @@ static void secp256k1_modinv64_update_fg_62(secp256k1_modinv64_signed62 *f, secp
const int64_t f0 = f->v[0], f1 = f->v[1], f2 = f->v[2], f3 = f->v[3], f4 = f->v[4];
const int64_t g0 = g->v[0], g1 = g->v[1], g2 = g->v[2], g3 = g->v[3], g4 = g->v[4];
const int64_t u = t->u, v = t->v, q = t->q, r = t->r;
- int128_t cf, cg;
+ secp256k1_int128 cf, cg;
/* Start computing t*[f,g]. */
- cf = (int128_t)u * f0 + (int128_t)v * g0;
- cg = (int128_t)q * f0 + (int128_t)r * g0;
+ secp256k1_i128_mul(&cf, u, f0);
+ secp256k1_i128_accum_mul(&cf, v, g0);
+ secp256k1_i128_mul(&cg, q, f0);
+ secp256k1_i128_accum_mul(&cg, r, g0);
/* Verify that the bottom 62 bits of the result are zero, and then throw them away. */
- VERIFY_CHECK(((int64_t)cf & M62) == 0); cf >>= 62;
- VERIFY_CHECK(((int64_t)cg & M62) == 0); cg >>= 62;
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cf) & M62) == 0); secp256k1_i128_rshift(&cf, 62);
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cg) & M62) == 0); secp256k1_i128_rshift(&cg, 62);
/* Compute limb 1 of t*[f,g], and store it as output limb 0 (= down shift). */
- cf += (int128_t)u * f1 + (int128_t)v * g1;
- cg += (int128_t)q * f1 + (int128_t)r * g1;
- f->v[0] = (int64_t)cf & M62; cf >>= 62;
- g->v[0] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, f1);
+ secp256k1_i128_accum_mul(&cf, v, g1);
+ secp256k1_i128_accum_mul(&cg, q, f1);
+ secp256k1_i128_accum_mul(&cg, r, g1);
+ f->v[0] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[0] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
/* Compute limb 2 of t*[f,g], and store it as output limb 1. */
- cf += (int128_t)u * f2 + (int128_t)v * g2;
- cg += (int128_t)q * f2 + (int128_t)r * g2;
- f->v[1] = (int64_t)cf & M62; cf >>= 62;
- g->v[1] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, f2);
+ secp256k1_i128_accum_mul(&cf, v, g2);
+ secp256k1_i128_accum_mul(&cg, q, f2);
+ secp256k1_i128_accum_mul(&cg, r, g2);
+ f->v[1] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[1] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
/* Compute limb 3 of t*[f,g], and store it as output limb 2. */
- cf += (int128_t)u * f3 + (int128_t)v * g3;
- cg += (int128_t)q * f3 + (int128_t)r * g3;
- f->v[2] = (int64_t)cf & M62; cf >>= 62;
- g->v[2] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, f3);
+ secp256k1_i128_accum_mul(&cf, v, g3);
+ secp256k1_i128_accum_mul(&cg, q, f3);
+ secp256k1_i128_accum_mul(&cg, r, g3);
+ f->v[2] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[2] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
/* Compute limb 4 of t*[f,g], and store it as output limb 3. */
- cf += (int128_t)u * f4 + (int128_t)v * g4;
- cg += (int128_t)q * f4 + (int128_t)r * g4;
- f->v[3] = (int64_t)cf & M62; cf >>= 62;
- g->v[3] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, f4);
+ secp256k1_i128_accum_mul(&cf, v, g4);
+ secp256k1_i128_accum_mul(&cg, q, f4);
+ secp256k1_i128_accum_mul(&cg, r, g4);
+ f->v[3] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[3] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
/* What remains is limb 5 of t*[f,g]; store it as output limb 4. */
- f->v[4] = (int64_t)cf;
- g->v[4] = (int64_t)cg;
+ f->v[4] = secp256k1_i128_to_i64(&cf);
+ g->v[4] = secp256k1_i128_to_i64(&cg);
}
/* Compute (t/2^62) * [f, g], where t is a transition matrix for 62 divsteps.
@@ -431,30 +463,34 @@ static void secp256k1_modinv64_update_fg_62_var(int len, secp256k1_modinv64_sign
const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
const int64_t u = t->u, v = t->v, q = t->q, r = t->r;
int64_t fi, gi;
- int128_t cf, cg;
+ secp256k1_int128 cf, cg;
int i;
VERIFY_CHECK(len > 0);
/* Start computing t*[f,g]. */
fi = f->v[0];
gi = g->v[0];
- cf = (int128_t)u * fi + (int128_t)v * gi;
- cg = (int128_t)q * fi + (int128_t)r * gi;
+ secp256k1_i128_mul(&cf, u, fi);
+ secp256k1_i128_accum_mul(&cf, v, gi);
+ secp256k1_i128_mul(&cg, q, fi);
+ secp256k1_i128_accum_mul(&cg, r, gi);
/* Verify that the bottom 62 bits of the result are zero, and then throw them away. */
- VERIFY_CHECK(((int64_t)cf & M62) == 0); cf >>= 62;
- VERIFY_CHECK(((int64_t)cg & M62) == 0); cg >>= 62;
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cf) & M62) == 0); secp256k1_i128_rshift(&cf, 62);
+ VERIFY_CHECK((secp256k1_i128_to_i64(&cg) & M62) == 0); secp256k1_i128_rshift(&cg, 62);
/* Now iteratively compute limb i=1..len of t*[f,g], and store them in output limb i-1 (shifting
* down by 62 bits). */
for (i = 1; i < len; ++i) {
fi = f->v[i];
gi = g->v[i];
- cf += (int128_t)u * fi + (int128_t)v * gi;
- cg += (int128_t)q * fi + (int128_t)r * gi;
- f->v[i - 1] = (int64_t)cf & M62; cf >>= 62;
- g->v[i - 1] = (int64_t)cg & M62; cg >>= 62;
+ secp256k1_i128_accum_mul(&cf, u, fi);
+ secp256k1_i128_accum_mul(&cf, v, gi);
+ secp256k1_i128_accum_mul(&cg, q, fi);
+ secp256k1_i128_accum_mul(&cg, r, gi);
+ f->v[i - 1] = secp256k1_i128_to_i64(&cf) & M62; secp256k1_i128_rshift(&cf, 62);
+ g->v[i - 1] = secp256k1_i128_to_i64(&cg) & M62; secp256k1_i128_rshift(&cg, 62);
}
/* What remains is limb (len) of t*[f,g]; store it as output limb (len-1). */
- f->v[len - 1] = (int64_t)cf;
- g->v[len - 1] = (int64_t)cg;
+ f->v[len - 1] = secp256k1_i128_to_i64(&cf);
+ g->v[len - 1] = secp256k1_i128_to_i64(&cg);
}
/* Compute the inverse of x modulo modinfo->modulus, and replace x with it (constant time in x). */
diff --git a/src/secp256k1/src/modules/ecdh/bench_impl.h b/src/secp256k1/src/modules/ecdh/bench_impl.h
index 94d833462f..8df15bcf43 100644
--- a/src/secp256k1/src/modules/ecdh/bench_impl.h
+++ b/src/secp256k1/src/modules/ecdh/bench_impl.h
@@ -7,7 +7,7 @@
#ifndef SECP256K1_MODULE_ECDH_BENCH_H
#define SECP256K1_MODULE_ECDH_BENCH_H
-#include "../include/secp256k1_ecdh.h"
+#include "../../../include/secp256k1_ecdh.h"
typedef struct {
secp256k1_context *ctx;
diff --git a/src/secp256k1/src/modules/ecdh/tests_impl.h b/src/secp256k1/src/modules/ecdh/tests_impl.h
index 10b7075c38..ce644d572a 100644
--- a/src/secp256k1/src/modules/ecdh/tests_impl.h
+++ b/src/secp256k1/src/modules/ecdh/tests_impl.h
@@ -26,7 +26,7 @@ int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, con
void test_ecdh_api(void) {
/* Setup context that just counts errors */
- secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
+ secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_pubkey point;
unsigned char res[32];
unsigned char s_one[32] = { 0 };
diff --git a/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h b/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h
index d4a2f5bdf4..5ecc90d50f 100644
--- a/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h
+++ b/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h
@@ -7,8 +7,8 @@
#ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H
#define SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H
-#include "src/modules/extrakeys/main_impl.h"
#include "../../../include/secp256k1_extrakeys.h"
+#include "main_impl.h"
static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp256k1_ge* group) {
secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1];
diff --git a/src/secp256k1/src/modules/extrakeys/tests_impl.h b/src/secp256k1/src/modules/extrakeys/tests_impl.h
index c8a99f4466..8030aedad6 100644
--- a/src/secp256k1/src/modules/extrakeys/tests_impl.h
+++ b/src/secp256k1/src/modules/extrakeys/tests_impl.h
@@ -9,11 +9,9 @@
#include "../../../include/secp256k1_extrakeys.h"
-static secp256k1_context* api_test_context(int flags, int *ecount) {
- secp256k1_context *ctx0 = secp256k1_context_create(flags);
+static void set_counting_callbacks(secp256k1_context *ctx0, int *ecount) {
secp256k1_context_set_error_callback(ctx0, counting_illegal_callback_fn, ecount);
secp256k1_context_set_illegal_callback(ctx0, counting_illegal_callback_fn, ecount);
- return ctx0;
}
void test_xonly_pubkey(void) {
@@ -31,28 +29,25 @@ void test_xonly_pubkey(void) {
int i;
int ecount;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ set_counting_callbacks(ctx, &ecount);
secp256k1_testrand256(sk);
memset(ones32, 0xFF, 32);
secp256k1_testrand256(xy_sk);
- CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
/* Test xonly_pubkey_from_pubkey */
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(sign, &xonly_pk, &pk_parity, &pk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &xonly_pk, &pk_parity, &pk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, NULL, &pk_parity, &pk) == 0);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, NULL, &pk_parity, &pk) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, NULL) == 0);
CHECK(ecount == 2);
memset(&pk, 0, sizeof(pk));
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 0);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 0);
CHECK(ecount == 3);
/* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */
@@ -78,9 +73,9 @@ void test_xonly_pubkey(void) {
/* Test xonly_pubkey_serialize and xonly_pubkey_parse */
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, NULL, &xonly_pk) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, NULL) == 0);
CHECK(secp256k1_memcmp_var(buf32, zeros64, 32) == 0);
CHECK(ecount == 2);
{
@@ -88,20 +83,20 @@ void test_xonly_pubkey(void) {
* special casing. */
secp256k1_xonly_pubkey pk_tmp;
memset(&pk_tmp, 0, sizeof(pk_tmp));
- CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &pk_tmp) == 0);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &pk_tmp) == 0);
}
/* pubkey_load called illegal callback */
CHECK(ecount == 3);
- CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &xonly_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1);
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_parse(none, NULL, buf32) == 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, NULL, buf32) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, NULL) == 0);
CHECK(ecount == 2);
/* Serialization and parse roundtrip */
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1);
CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk_tmp, buf32) == 1);
CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0);
@@ -109,11 +104,11 @@ void test_xonly_pubkey(void) {
/* Test parsing invalid field elements */
memset(&xonly_pk, 1, sizeof(xonly_pk));
/* Overflowing field element */
- CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, ones32) == 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, ones32) == 0);
CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
memset(&xonly_pk, 1, sizeof(xonly_pk));
/* There's no point with x-coordinate 0 on secp256k1 */
- CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, zeros64) == 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, zeros64) == 0);
CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
/* If a random 32-byte string can not be parsed with ec_pubkey_parse
* (because interpreted as X coordinate it does not correspond to a point on
@@ -131,10 +126,6 @@ void test_xonly_pubkey(void) {
}
}
CHECK(ecount == 2);
-
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
}
void test_xonly_pubkey_comparison(void) {
@@ -149,29 +140,28 @@ void test_xonly_pubkey_comparison(void) {
secp256k1_xonly_pubkey pk1;
secp256k1_xonly_pubkey pk2;
int ecount = 0;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- CHECK(secp256k1_xonly_pubkey_parse(none, &pk1, pk1_ser) == 1);
- CHECK(secp256k1_xonly_pubkey_parse(none, &pk2, pk2_ser) == 1);
+ set_counting_callbacks(ctx, &ecount);
- CHECK(secp256k1_xonly_pubkey_cmp(none, NULL, &pk2) < 0);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk1, pk1_ser) == 1);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk2, pk2_ser) == 1);
+
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, NULL, &pk2) < 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, NULL) > 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, NULL) > 0);
CHECK(ecount == 2);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk2) < 0);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk1) > 0);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk1) == 0);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk2) == 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk2) < 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk2, &pk1) > 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk1) == 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk2, &pk2) == 0);
CHECK(ecount == 2);
memset(&pk1, 0, sizeof(pk1)); /* illegal pubkey */
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk2) < 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk2) < 0);
CHECK(ecount == 3);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk1) == 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk1) == 0);
CHECK(ecount == 5);
- CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk1) > 0);
+ CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk2, &pk1) > 0);
CHECK(ecount == 6);
-
- secp256k1_context_destroy(none);
}
void test_xonly_pubkey_tweak(void) {
@@ -186,39 +176,38 @@ void test_xonly_pubkey_tweak(void) {
int i;
int ecount;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ set_counting_callbacks(ctx, &ecount);
memset(overflows, 0xff, sizeof(overflows));
secp256k1_testrand256(tweak);
secp256k1_testrand256(sk);
CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, NULL, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, NULL, tweak) == 0);
CHECK(ecount == 2);
/* NULL internal_xonly_pk zeroes the output_pk */
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 3);
/* NULL tweak zeroes the output_pk */
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
/* Invalid tweak zeroes the output_pk */
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
/* A zero tweak is fine */
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, zeros64) == 1);
/* Fails if the resulting key was infinity */
for (i = 0; i < count; i++) {
@@ -228,8 +217,8 @@ void test_xonly_pubkey_tweak(void) {
secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL);
secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak);
secp256k1_scalar_get_b32(tweak, &scalar_tweak);
- CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0)
- || (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0));
+ CHECK((secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, sk) == 0)
+ || (secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 0));
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
}
@@ -237,13 +226,9 @@ void test_xonly_pubkey_tweak(void) {
memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk));
secp256k1_testrand256(tweak);
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
-
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
}
void test_xonly_pubkey_tweak_check(void) {
@@ -260,33 +245,32 @@ void test_xonly_pubkey_tweak_check(void) {
unsigned char tweak[32];
int ecount;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ set_counting_callbacks(ctx, &ecount);
memset(overflows, 0xff, sizeof(overflows));
secp256k1_testrand256(tweak);
secp256k1_testrand256(sk);
CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
ecount = 0;
- CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &output_xonly_pk, &pk_parity, &output_pk) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, NULL, pk_parity, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
/* invalid pk_parity value */
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, 2, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, NULL, tweak) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 3);
memset(tweak, 1, sizeof(tweak));
@@ -307,10 +291,6 @@ void test_xonly_pubkey_tweak_check(void) {
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
CHECK(ecount == 3);
-
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
}
/* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1
@@ -356,12 +336,10 @@ void test_keypair(void) {
secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp;
int pk_parity, pk_parity_tmp;
int ecount;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
- secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
- secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
+ secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
+
+ set_counting_callbacks(ctx, &ecount);
+ set_counting_callbacks(sttc, &ecount);
CHECK(sizeof(zeros96) == sizeof(keypair));
memset(overflows, 0xFF, sizeof(overflows));
@@ -369,75 +347,75 @@ void test_keypair(void) {
/* Test keypair_create */
ecount = 0;
secp256k1_testrand256(sk);
- CHECK(secp256k1_keypair_create(none, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
CHECK(ecount == 0);
- CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
CHECK(ecount == 0);
- CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
+ CHECK(secp256k1_keypair_create(ctx, NULL, sk) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, NULL) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(ecount == 2);
CHECK(secp256k1_keypair_create(sttc, &keypair, sk) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
CHECK(ecount == 3);
/* Invalid secret key */
- CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, zeros96) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
- CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, overflows) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
/* Test keypair_pub */
ecount = 0;
secp256k1_testrand256(sk);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1);
- CHECK(secp256k1_keypair_pub(none, NULL, &keypair) == 0);
+ CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair) == 1);
+ CHECK(secp256k1_keypair_pub(ctx, NULL, &keypair) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0);
+ CHECK(secp256k1_keypair_pub(ctx, &pk, NULL) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0);
/* Using an invalid keypair is fine for keypair_pub */
memset(&keypair, 0, sizeof(keypair));
- CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1);
+ CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair) == 1);
CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0);
/* keypair holds the same pubkey as pubkey_create */
- CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
- CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_pub(ctx, &pk_tmp, &keypair) == 1);
CHECK(secp256k1_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0);
/** Test keypair_xonly_pub **/
ecount = 0;
secp256k1_testrand256(sk);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, NULL, &pk_parity, &keypair) == 0);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, NULL, &pk_parity, &keypair) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, NULL, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, NULL) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0);
/* Using an invalid keypair will set the xonly_pk to 0 (first reset
* xonly_pk). */
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, &keypair) == 1);
memset(&keypair, 0, sizeof(keypair));
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, &keypair) == 0);
CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0);
CHECK(ecount == 3);
/** keypair holds the same xonly pubkey as pubkey_create **/
- CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
- CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
- CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1);
CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0);
CHECK(pk_parity == pk_parity_tmp);
@@ -445,27 +423,23 @@ void test_keypair(void) {
ecount = 0;
secp256k1_testrand256(sk);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1);
- CHECK(secp256k1_keypair_sec(none, NULL, &keypair) == 0);
+ CHECK(secp256k1_keypair_sec(ctx, sk_tmp, &keypair) == 1);
+ CHECK(secp256k1_keypair_sec(ctx, NULL, &keypair) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_sec(none, sk_tmp, NULL) == 0);
+ CHECK(secp256k1_keypair_sec(ctx, sk_tmp, NULL) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0);
/* keypair returns the same seckey it got */
- CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_sec(ctx, sk_tmp, &keypair) == 1);
CHECK(secp256k1_memcmp_var(sk, sk_tmp, sizeof(sk_tmp)) == 0);
/* Using an invalid keypair is fine for keypair_seckey */
memset(&keypair, 0, sizeof(keypair));
- CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1);
+ CHECK(secp256k1_keypair_sec(ctx, sk_tmp, &keypair) == 1);
CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0);
-
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
secp256k1_context_destroy(sttc);
}
@@ -477,9 +451,8 @@ void test_keypair_add(void) {
unsigned char tweak[32];
int i;
int ecount = 0;
- secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
- secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
- secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ set_counting_callbacks(ctx, &ecount);
CHECK(sizeof(zeros96) == sizeof(keypair));
secp256k1_testrand256(sk);
@@ -487,14 +460,14 @@ void test_keypair_add(void) {
memset(overflows, 0xFF, 32);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
- CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, NULL, tweak) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, NULL) == 0);
CHECK(ecount == 2);
/* This does not set the keypair to zeroes */
CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0);
@@ -530,18 +503,18 @@ void test_keypair_add(void) {
memset(&keypair, 0, sizeof(keypair));
secp256k1_testrand256(tweak);
ecount = 0;
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0);
/* Only seckey part of keypair invalid */
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
memset(&keypair, 0, 32);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 0);
CHECK(ecount == 2);
/* Only pubkey part of keypair invalid */
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
memset(&keypair.data[32], 0, 64);
- CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 0);
CHECK(ecount == 3);
/* Check that the keypair_tweak_add implementation is correct */
@@ -570,13 +543,10 @@ void test_keypair_add(void) {
CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0);
/* Check that the secret key in the keypair is tweaked correctly */
- CHECK(secp256k1_keypair_sec(none, sk32, &keypair) == 1);
+ CHECK(secp256k1_keypair_sec(ctx, sk32, &keypair) == 1);
CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, sk32) == 1);
CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0);
}
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(verify);
}
void run_extrakeys_tests(void) {
diff --git a/src/secp256k1/src/modules/recovery/bench_impl.h b/src/secp256k1/src/modules/recovery/bench_impl.h
index 4a9e886910..ffa00df479 100644
--- a/src/secp256k1/src/modules/recovery/bench_impl.h
+++ b/src/secp256k1/src/modules/recovery/bench_impl.h
@@ -7,7 +7,7 @@
#ifndef SECP256K1_MODULE_RECOVERY_BENCH_H
#define SECP256K1_MODULE_RECOVERY_BENCH_H
-#include "../include/secp256k1_recovery.h"
+#include "../../../include/secp256k1_recovery.h"
typedef struct {
secp256k1_context *ctx;
@@ -52,7 +52,7 @@ void run_recovery_bench(int iters, int argc, char** argv) {
bench_recover_data data;
int d = argc == 1;
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters);
diff --git a/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h b/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h
index 590a972ed3..ed9386b6f8 100644
--- a/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h
+++ b/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h
@@ -7,7 +7,7 @@
#ifndef SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H
#define SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H
-#include "src/modules/recovery/main_impl.h"
+#include "main_impl.h"
#include "../../../include/secp256k1_recovery.h"
void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group) {
diff --git a/src/secp256k1/src/modules/recovery/tests_impl.h b/src/secp256k1/src/modules/recovery/tests_impl.h
index abf62f7f3a..0ff9294e38 100644
--- a/src/secp256k1/src/modules/recovery/tests_impl.h
+++ b/src/secp256k1/src/modules/recovery/tests_impl.h
@@ -30,11 +30,7 @@ static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned c
void test_ecdsa_recovery_api(void) {
/* Setup contexts that just count errors */
- secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
- secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
- secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
- secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
+ secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
secp256k1_pubkey pubkey;
secp256k1_pubkey recpubkey;
secp256k1_ecdsa_signature normal_sig;
@@ -50,15 +46,9 @@ void test_ecdsa_recovery_api(void) {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(ctx, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
/* Construct and verify corresponding public key. */
@@ -67,89 +57,73 @@ void test_ecdsa_recovery_api(void) {
/* Check bad contexts and NULLs for signing */
ecount = 0;
- CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, NULL, message, privkey, NULL, NULL) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, NULL, privkey, NULL, NULL) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, NULL, NULL, NULL) == 0);
CHECK(ecount == 3);
CHECK(secp256k1_ecdsa_sign_recoverable(sttc, &recsig, message, privkey, NULL, NULL) == 0);
CHECK(ecount == 4);
/* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */
- secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL);
+ secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, recovery_test_nonce_function, NULL);
CHECK(ecount == 4);
/* These will all fail, but not in ARG_CHECK way */
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0);
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, zero_privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, over_privkey, NULL, NULL) == 0);
/* This one will succeed. */
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
CHECK(ecount == 4);
/* Check signing with a goofy nonce function */
/* Check bad contexts and NULLs for recovery */
ecount = 0;
- CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1);
+ CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0);
+ CHECK(secp256k1_ecdsa_recover(ctx, NULL, &recsig, message) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0);
+ CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, NULL, message) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0);
+ CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &recsig, NULL) == 0);
CHECK(ecount == 3);
/* Check NULLs for conversion */
- CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(ctx, &normal_sig, message, privkey, NULL, NULL) == 1);
ecount = 0;
- CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, NULL, &recsig) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &normal_sig, NULL) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &normal_sig, &recsig) == 1);
/* Check NULLs for de/serialization */
- CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
ecount = 0;
- CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, NULL, &recid, &recsig) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, NULL, &recsig) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, NULL) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recsig) == 1);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, NULL, sig, recid) == 0);
CHECK(ecount == 4);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, NULL, recid) == 0);
CHECK(ecount == 5);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, sig, -1) == 0);
CHECK(ecount == 6);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, sig, 5) == 0);
CHECK(ecount == 7);
/* overflow in signature will fail but not affect ecount */
memcpy(sig, over_privkey, 32);
- CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, sig, recid) == 0);
CHECK(ecount == 7);
/* cleanup */
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(vrfy);
- secp256k1_context_destroy(both);
secp256k1_context_destroy(sttc);
}
diff --git a/src/secp256k1/src/modules/schnorrsig/bench_impl.h b/src/secp256k1/src/modules/schnorrsig/bench_impl.h
index 41f393c84d..f0b0d3de75 100644
--- a/src/secp256k1/src/modules/schnorrsig/bench_impl.h
+++ b/src/secp256k1/src/modules/schnorrsig/bench_impl.h
@@ -50,7 +50,7 @@ void run_schnorrsig_bench(int iters, int argc, char** argv) {
bench_schnorrsig_data data;
int d = argc == 1;
- data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *));
data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
@@ -91,10 +91,12 @@ void run_schnorrsig_bench(int iters, int argc, char** argv) {
free((void *)data.msgs[i]);
free((void *)data.sigs[i]);
}
- free(data.keypairs);
- free(data.pk);
- free(data.msgs);
- free(data.sigs);
+
+ /* Casting to (void *) avoids a stupid warning in MSVC. */
+ free((void *)data.keypairs);
+ free((void *)data.pk);
+ free((void *)data.msgs);
+ free((void *)data.sigs);
secp256k1_context_destroy(data.ctx);
}
diff --git a/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h
index d8df9dd2df..55f9028a63 100644
--- a/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h
+++ b/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h
@@ -8,7 +8,7 @@
#define SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_H
#include "../../../include/secp256k1_schnorrsig.h"
-#include "src/modules/schnorrsig/main_impl.h"
+#include "main_impl.h"
static const unsigned char invalid_pubkey_bytes[][32] = {
/* 0 */
diff --git a/src/secp256k1/src/modules/schnorrsig/tests_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_impl.h
index 25840b8fa7..06cc097cc1 100644
--- a/src/secp256k1/src/modules/schnorrsig/tests_impl.h
+++ b/src/secp256k1/src/modules/schnorrsig/tests_impl.h
@@ -128,22 +128,12 @@ void test_schnorrsig_api(void) {
secp256k1_schnorrsig_extraparams invalid_extraparams = {{ 0 }, NULL, NULL};
/** setup **/
- secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
- secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
- secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
- secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
+ secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
int ecount;
- secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(ctx, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_error_callback(sttc, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
secp256k1_testrand256(sk1);
@@ -160,70 +150,54 @@ void test_schnorrsig_api(void) {
/** main test body **/
ecount = 0;
- CHECK(secp256k1_schnorrsig_sign32(none, sig, msg, &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypairs[0], NULL) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign32(vrfy, sig, msg, &keypairs[0], NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &keypairs[0], NULL) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign32(sign, NULL, msg, &keypairs[0], NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, NULL, msg, &keypairs[0], NULL) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, NULL, &keypairs[0], NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, NULL, &keypairs[0], NULL) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, NULL, NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, NULL, NULL) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &invalid_keypair, NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &invalid_keypair, NULL) == 0);
CHECK(ecount == 4);
CHECK(secp256k1_schnorrsig_sign32(sttc, sig, msg, &keypairs[0], NULL) == 0);
CHECK(ecount == 5);
ecount = 0;
- CHECK(secp256k1_schnorrsig_sign_custom(none, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign_custom(vrfy, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, NULL, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, NULL, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, sizeof(msg), &keypairs[0], &extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, NULL, sizeof(msg), &keypairs[0], &extraparams) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, 0, &keypairs[0], &extraparams) == 1);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, NULL, 0, &keypairs[0], &extraparams) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), NULL, &extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), NULL, &extraparams) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &invalid_keypair, &extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &invalid_keypair, &extraparams) == 0);
CHECK(ecount == 4);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1);
CHECK(ecount == 4);
- CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams) == 0);
+ CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams) == 0);
CHECK(ecount == 5);
CHECK(secp256k1_schnorrsig_sign_custom(sttc, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 0);
CHECK(ecount == 6);
ecount = 0;
- CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &keypairs[0], NULL) == 1);
- CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 1);
- CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &pk[0]) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, sizeof(msg), &pk[0]) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, NULL, msg, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, sizeof(msg), &pk[0]) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, NULL, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, 0, &pk[0]) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, NULL, 0, &pk[0]) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), NULL) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), NULL) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &zero_pk) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &zero_pk) == 0);
CHECK(ecount == 4);
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(vrfy);
- secp256k1_context_destroy(both);
secp256k1_context_destroy(sttc);
}
diff --git a/src/secp256k1/src/precompute_ecmult.c b/src/secp256k1/src/precompute_ecmult.c
index 5ccbcb3c57..2aa37b8fe3 100644
--- a/src/secp256k1/src/precompute_ecmult.c
+++ b/src/secp256k1/src/precompute_ecmult.c
@@ -14,10 +14,13 @@
#endif
#include "../include/secp256k1.h"
+
#include "assumptions.h"
#include "util.h"
+
#include "field_impl.h"
#include "group_impl.h"
+#include "int128_impl.h"
#include "ecmult.h"
#include "ecmult_compute_table_impl.h"
diff --git a/src/secp256k1/src/precompute_ecmult_gen.c b/src/secp256k1/src/precompute_ecmult_gen.c
index 7c6359c402..a4ec8e0dc6 100644
--- a/src/secp256k1/src/precompute_ecmult_gen.c
+++ b/src/secp256k1/src/precompute_ecmult_gen.c
@@ -8,9 +8,12 @@
#include <stdio.h>
#include "../include/secp256k1.h"
+
#include "assumptions.h"
#include "util.h"
+
#include "group.h"
+#include "int128_impl.h"
#include "ecmult_gen.h"
#include "ecmult_gen_compute_table_impl.h"
diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h
index a1def26fca..4588219d3a 100644
--- a/src/secp256k1/src/scalar_4x64_impl.h
+++ b/src/secp256k1/src/scalar_4x64_impl.h
@@ -7,6 +7,7 @@
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H
+#include "int128.h"
#include "modinv64_impl.h"
/* Limbs of the secp256k1 order. */
@@ -69,50 +70,61 @@ SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scal
}
SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) {
- uint128_t t;
+ secp256k1_uint128 t;
VERIFY_CHECK(overflow <= 1);
- t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0;
- r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1;
- r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2;
- r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint64_t)r->d[3];
- r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL;
+ secp256k1_u128_from_u64(&t, r->d[0]);
+ secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_0);
+ r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[1]);
+ secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_1);
+ r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[2]);
+ secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_2);
+ r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[3]);
+ r->d[3] = secp256k1_u128_to_u64(&t);
return overflow;
}
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
int overflow;
- uint128_t t = (uint128_t)a->d[0] + b->d[0];
- r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)a->d[1] + b->d[1];
- r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)a->d[2] + b->d[2];
- r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)a->d[3] + b->d[3];
- r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- overflow = t + secp256k1_scalar_check_overflow(r);
+ secp256k1_uint128 t;
+ secp256k1_u128_from_u64(&t, a->d[0]);
+ secp256k1_u128_accum_u64(&t, b->d[0]);
+ r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, a->d[1]);
+ secp256k1_u128_accum_u64(&t, b->d[1]);
+ r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, a->d[2]);
+ secp256k1_u128_accum_u64(&t, b->d[2]);
+ r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, a->d[3]);
+ secp256k1_u128_accum_u64(&t, b->d[3]);
+ r->d[3] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ overflow = secp256k1_u128_to_u64(&t) + secp256k1_scalar_check_overflow(r);
VERIFY_CHECK(overflow == 0 || overflow == 1);
secp256k1_scalar_reduce(r, overflow);
return overflow;
}
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
- uint128_t t;
+ secp256k1_uint128 t;
VERIFY_CHECK(bit < 256);
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */
- t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
- r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
- r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F));
- r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F));
- r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL;
+ secp256k1_u128_from_u64(&t, r->d[0]);
+ secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
+ r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[1]);
+ secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
+ r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[2]);
+ secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F));
+ r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[3]);
+ secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F));
+ r->d[3] = secp256k1_u128_to_u64(&t);
#ifdef VERIFY
- VERIFY_CHECK((t >> 64) == 0);
- VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
+ VERIFY_CHECK(secp256k1_u128_hi_u64(&t) == 0);
#endif
}
@@ -141,14 +153,19 @@ SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a)
static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) {
uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0);
- uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1;
- r->d[0] = t & nonzero; t >>= 64;
- t += (uint128_t)(~a->d[1]) + SECP256K1_N_1;
- r->d[1] = t & nonzero; t >>= 64;
- t += (uint128_t)(~a->d[2]) + SECP256K1_N_2;
- r->d[2] = t & nonzero; t >>= 64;
- t += (uint128_t)(~a->d[3]) + SECP256K1_N_3;
- r->d[3] = t & nonzero;
+ secp256k1_uint128 t;
+ secp256k1_u128_from_u64(&t, ~a->d[0]);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_0 + 1);
+ r->d[0] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, ~a->d[1]);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_1);
+ r->d[1] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, ~a->d[2]);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_2);
+ r->d[2] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, ~a->d[3]);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_3);
+ r->d[3] = secp256k1_u128_to_u64(&t) & nonzero;
}
SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) {
@@ -172,14 +189,19 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
* if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */
uint64_t mask = !flag - 1;
uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1;
- uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask);
- r->d[0] = t & nonzero; t >>= 64;
- t += (uint128_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask);
- r->d[1] = t & nonzero; t >>= 64;
- t += (uint128_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask);
- r->d[2] = t & nonzero; t >>= 64;
- t += (uint128_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask);
- r->d[3] = t & nonzero;
+ secp256k1_uint128 t;
+ secp256k1_u128_from_u64(&t, r->d[0] ^ mask);
+ secp256k1_u128_accum_u64(&t, (SECP256K1_N_0 + 1) & mask);
+ r->d[0] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[1] ^ mask);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_1 & mask);
+ r->d[1] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[2] ^ mask);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_2 & mask);
+ r->d[2] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64);
+ secp256k1_u128_accum_u64(&t, r->d[3] ^ mask);
+ secp256k1_u128_accum_u64(&t, SECP256K1_N_3 & mask);
+ r->d[3] = secp256k1_u128_to_u64(&t) & nonzero;
return 2 * (mask == 0) - 1;
}
@@ -189,9 +211,10 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
#define muladd(a,b) { \
uint64_t tl, th; \
{ \
- uint128_t t = (uint128_t)a * b; \
- th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
- tl = t; \
+ secp256k1_uint128 t; \
+ secp256k1_u128_mul(&t, a, b); \
+ th = secp256k1_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \
+ tl = secp256k1_u128_to_u64(&t); \
} \
c0 += tl; /* overflow is handled on the next line */ \
th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
@@ -204,9 +227,10 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
#define muladd_fast(a,b) { \
uint64_t tl, th; \
{ \
- uint128_t t = (uint128_t)a * b; \
- th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
- tl = t; \
+ secp256k1_uint128 t; \
+ secp256k1_u128_mul(&t, a, b); \
+ th = secp256k1_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \
+ tl = secp256k1_u128_to_u64(&t); \
} \
c0 += tl; /* overflow is handled on the next line */ \
th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
@@ -484,8 +508,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
: "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1)
: "rax", "rdx", "r8", "r9", "r10", "cc", "memory");
#else
- uint128_t c;
- uint64_t c0, c1, c2;
+ secp256k1_uint128 c128;
+ uint64_t c, c0, c1, c2;
uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7];
uint64_t m0, m1, m2, m3, m4, m5;
uint32_t m6;
@@ -542,14 +566,18 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
/* Reduce 258 bits into 256. */
/* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */
- c = p0 + (uint128_t)SECP256K1_N_C_0 * p4;
- r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
- c += p1 + (uint128_t)SECP256K1_N_C_1 * p4;
- r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
- c += p2 + (uint128_t)p4;
- r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
- c += p3;
- r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
+ secp256k1_u128_from_u64(&c128, p0);
+ secp256k1_u128_accum_mul(&c128, SECP256K1_N_C_0, p4);
+ r->d[0] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64);
+ secp256k1_u128_accum_u64(&c128, p1);
+ secp256k1_u128_accum_mul(&c128, SECP256K1_N_C_1, p4);
+ r->d[1] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64);
+ secp256k1_u128_accum_u64(&c128, p2);
+ secp256k1_u128_accum_u64(&c128, p4);
+ r->d[2] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64);
+ secp256k1_u128_accum_u64(&c128, p3);
+ r->d[3] = secp256k1_u128_to_u64(&c128);
+ c = secp256k1_u128_hi_u64(&c128);
#endif
/* Final reduction of r. */
diff --git a/src/secp256k1/src/scratch_impl.h b/src/secp256k1/src/scratch_impl.h
index 688e18eb66..f71a20b963 100644
--- a/src/secp256k1/src/scratch_impl.h
+++ b/src/secp256k1/src/scratch_impl.h
@@ -25,11 +25,11 @@ static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* err
static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) {
if (scratch != NULL) {
- VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */
if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) {
secp256k1_callback_call(error_callback, "invalid scratch space");
return;
}
+ VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */
memset(scratch->magic, 0, sizeof(scratch->magic));
free(scratch);
}
diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c
index 8f34c35283..5ed3824161 100644
--- a/src/secp256k1/src/secp256k1.c
+++ b/src/secp256k1/src/secp256k1.c
@@ -4,6 +4,17 @@
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
***********************************************************************/
+/* This is a C project. It should not be compiled with a C++ compiler,
+ * and we error out if we detect one.
+ *
+ * We still want to be able to test the project with a C++ compiler
+ * because it is still good to know if this will lead to real trouble, so
+ * there is a possibility to override the check. But be warned that
+ * compiling with a C++ compiler is not supported. */
+#if defined(__cplusplus) && !defined(SECP256K1_CPLUSPLUS_TEST_OVERRIDE)
+#error Trying to compile a C project with a C++ compiler.
+#endif
+
#define SECP256K1_BUILD
#include "../include/secp256k1.h"
@@ -11,6 +22,7 @@
#include "assumptions.h"
#include "util.h"
+
#include "field_impl.h"
#include "scalar_impl.h"
#include "group_impl.h"
@@ -20,6 +32,7 @@
#include "ecdsa_impl.h"
#include "eckey_impl.h"
#include "hash_impl.h"
+#include "int128_impl.h"
#include "scratch_impl.h"
#include "selftest.h"
@@ -44,6 +57,8 @@
} \
} while(0)
+/* Note that whenever you change the context struct, you must also change the
+ * context_eq function. */
struct secp256k1_context_struct {
secp256k1_ecmult_gen_context ecmult_gen_ctx;
secp256k1_callback illegal_callback;
@@ -51,13 +66,20 @@ struct secp256k1_context_struct {
int declassify;
};
-static const secp256k1_context secp256k1_context_no_precomp_ = {
+static const secp256k1_context secp256k1_context_static_ = {
{ 0 },
{ secp256k1_default_illegal_callback_fn, 0 },
{ secp256k1_default_error_callback_fn, 0 },
0
};
-const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
+const secp256k1_context *secp256k1_context_static = &secp256k1_context_static_;
+const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_static_;
+
+void secp256k1_selftest(void) {
+ if (!secp256k1_selftest_passes()) {
+ secp256k1_callback_call(&default_error_callback, "self test failed");
+ }
+}
size_t secp256k1_context_preallocated_size(unsigned int flags) {
size_t ret = sizeof(secp256k1_context);
@@ -83,9 +105,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
size_t prealloc_size;
secp256k1_context* ret;
- if (!secp256k1_selftest()) {
- secp256k1_callback_call(&default_error_callback, "self test failed");
- }
+ secp256k1_selftest();
prealloc_size = secp256k1_context_preallocated_size(flags);
if (prealloc_size == 0) {
@@ -137,7 +157,7 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
}
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
- ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
+ ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
if (ctx != NULL) {
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
}
@@ -151,7 +171,7 @@ void secp256k1_context_destroy(secp256k1_context* ctx) {
}
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
- ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
+ ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
if (fun == NULL) {
fun = secp256k1_default_illegal_callback_fn;
}
@@ -160,7 +180,7 @@ void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(
}
void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
- ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
+ ARG_CHECK_NO_RETURN(ctx != secp256k1_context_static);
if (fun == NULL) {
fun = secp256k1_default_error_callback_fn;
}
diff --git a/src/secp256k1/src/selftest.h b/src/secp256k1/src/selftest.h
index 52f1b8442e..d083ac9524 100644
--- a/src/secp256k1/src/selftest.h
+++ b/src/secp256k1/src/selftest.h
@@ -25,7 +25,7 @@ static int secp256k1_selftest_sha256(void) {
return secp256k1_memcmp_var(out, output32, 32) == 0;
}
-static int secp256k1_selftest(void) {
+static int secp256k1_selftest_passes(void) {
return secp256k1_selftest_sha256();
}
diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c
index dd53173930..53613f420a 100644
--- a/src/secp256k1/src/tests.c
+++ b/src/secp256k1/src/tests.c
@@ -26,6 +26,7 @@
#include "modinv32_impl.h"
#ifdef SECP256K1_WIDEMUL_INT128
#include "modinv64_impl.h"
+#include "int128_impl.h"
#endif
#define CONDITIONAL_TEST(cnt, nam) if (count < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else
@@ -140,6 +141,43 @@ void random_scalar_order_b32(unsigned char *b32) {
secp256k1_scalar_get_b32(b32, &num);
}
+void run_selftest_tests(void) {
+ /* Test public API */
+ secp256k1_selftest();
+}
+
+int ecmult_gen_context_eq(const secp256k1_ecmult_gen_context *a, const secp256k1_ecmult_gen_context *b) {
+ return a->built == b->built
+ && secp256k1_scalar_eq(&a->blind, &b->blind)
+ && secp256k1_gej_eq_var(&a->initial, &b->initial);
+}
+
+int context_eq(const secp256k1_context *a, const secp256k1_context *b) {
+ return a->declassify == b->declassify
+ && ecmult_gen_context_eq(&a->ecmult_gen_ctx, &b->ecmult_gen_ctx)
+ && a->illegal_callback.fn == b->illegal_callback.fn
+ && a->illegal_callback.data == b->illegal_callback.
+data
+ && a->error_callback.fn == b->error_callback.fn
+ && a->error_callback.data == b->error_callback.data;
+}
+
+void test_deprecated_flags(void) {
+ unsigned int flags[] = { SECP256K1_CONTEXT_SIGN,
+ SECP256K1_CONTEXT_VERIFY,
+ SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY };
+ int i;
+ /* Check that a context created with any of the flags in the flags array is
+ * identical to the NONE context. */
+ for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++) {
+ secp256k1_context *tmp_ctx;
+ CHECK(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE) == secp256k1_context_preallocated_size(flags[i]));
+ tmp_ctx = secp256k1_context_create(flags[i]);
+ CHECK(context_eq(ctx, tmp_ctx));
+ secp256k1_context_destroy(tmp_ctx);
+ }
+}
+
void run_context_tests(int use_prealloc) {
secp256k1_pubkey pubkey;
secp256k1_pubkey zero_pubkey;
@@ -147,15 +185,8 @@ void run_context_tests(int use_prealloc) {
unsigned char ctmp[32];
int32_t ecount;
int32_t ecount2;
- secp256k1_context *none;
- secp256k1_context *sign;
- secp256k1_context *vrfy;
- secp256k1_context *both;
secp256k1_context *sttc;
- void *none_prealloc = NULL;
- void *sign_prealloc = NULL;
- void *vrfy_prealloc = NULL;
- void *both_prealloc = NULL;
+ void *ctx_prealloc = NULL;
void *sttc_prealloc = NULL;
secp256k1_gej pubj;
@@ -163,46 +194,36 @@ void run_context_tests(int use_prealloc) {
secp256k1_scalar msg, key, nonce;
secp256k1_scalar sigr, sigs;
+ /* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */
+ CHECK(secp256k1_context_no_precomp == secp256k1_context_static);
+
if (use_prealloc) {
- none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
- sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
- vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
- both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
- sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_no_precomp));
- CHECK(none_prealloc != NULL);
- CHECK(sign_prealloc != NULL);
- CHECK(vrfy_prealloc != NULL);
- CHECK(both_prealloc != NULL);
+ ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
+ CHECK(ctx_prealloc != NULL);
+ ctx = secp256k1_context_preallocated_create(ctx_prealloc, SECP256K1_CONTEXT_NONE);
+ sttc_prealloc = malloc(secp256k1_context_preallocated_clone_size(secp256k1_context_static));
CHECK(sttc_prealloc != NULL);
- none = secp256k1_context_preallocated_create(none_prealloc, SECP256K1_CONTEXT_NONE);
- sign = secp256k1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN);
- vrfy = secp256k1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY);
- both = secp256k1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- sttc = secp256k1_context_preallocated_clone(secp256k1_context_no_precomp, sttc_prealloc);
+ sttc = secp256k1_context_preallocated_clone(secp256k1_context_static, sttc_prealloc);
} else {
- none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
- sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
- vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
- both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- sttc = secp256k1_context_clone(secp256k1_context_no_precomp);
+ sttc = secp256k1_context_clone(secp256k1_context_static);
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
}
+ test_deprecated_flags();
+
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
ecount = 0;
ecount2 = 10;
secp256k1_context_set_illegal_callback(sttc, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount2);
/* set error callback (to a function that still aborts in case malloc() fails in secp256k1_context_clone() below) */
- secp256k1_context_set_error_callback(sign, secp256k1_default_illegal_callback_fn, NULL);
- CHECK(sign->error_callback.fn != vrfy->error_callback.fn);
- CHECK(sign->error_callback.fn == secp256k1_default_illegal_callback_fn);
+ secp256k1_context_set_error_callback(ctx, secp256k1_default_illegal_callback_fn, NULL);
+ CHECK(ctx->error_callback.fn != sttc->error_callback.fn);
+ CHECK(ctx->error_callback.fn == secp256k1_default_illegal_callback_fn);
/* check if sizes for cloning are consistent */
- CHECK(secp256k1_context_preallocated_clone_size(none) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
- CHECK(secp256k1_context_preallocated_clone_size(sign) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
- CHECK(secp256k1_context_preallocated_clone_size(vrfy) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
- CHECK(secp256k1_context_preallocated_clone_size(both) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
+ CHECK(secp256k1_context_preallocated_clone_size(ctx) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
CHECK(secp256k1_context_preallocated_clone_size(sttc) >= sizeof(secp256k1_context));
/*** clone and destroy all of them to make sure cloning was complete ***/
@@ -211,58 +232,31 @@ void run_context_tests(int use_prealloc) {
if (use_prealloc) {
/* clone into a non-preallocated context and then again into a new preallocated one. */
- ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(none_prealloc); none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(none_prealloc != NULL);
- ctx_tmp = none; none = secp256k1_context_preallocated_clone(none, none_prealloc); secp256k1_context_destroy(ctx_tmp);
-
- ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(sign_prealloc); sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(sign_prealloc != NULL);
- ctx_tmp = sign; sign = secp256k1_context_preallocated_clone(sign, sign_prealloc); secp256k1_context_destroy(ctx_tmp);
-
- ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(vrfy_prealloc); vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(vrfy_prealloc != NULL);
- ctx_tmp = vrfy; vrfy = secp256k1_context_preallocated_clone(vrfy, vrfy_prealloc); secp256k1_context_destroy(ctx_tmp);
-
- ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(both_prealloc); both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(both_prealloc != NULL);
- ctx_tmp = both; both = secp256k1_context_preallocated_clone(both, both_prealloc); secp256k1_context_destroy(ctx_tmp);
+ ctx_tmp = ctx; ctx = secp256k1_context_clone(ctx); secp256k1_context_preallocated_destroy(ctx_tmp);
+ free(ctx_prealloc); ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(ctx_prealloc != NULL);
+ ctx_tmp = ctx; ctx = secp256k1_context_preallocated_clone(ctx, ctx_prealloc); secp256k1_context_destroy(ctx_tmp);
} else {
/* clone into a preallocated context and then again into a new non-preallocated one. */
void *prealloc_tmp;
prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(prealloc_tmp != NULL);
- ctx_tmp = none; none = secp256k1_context_preallocated_clone(none, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
- ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(prealloc_tmp);
-
- prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(prealloc_tmp != NULL);
- ctx_tmp = sign; sign = secp256k1_context_preallocated_clone(sign, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
- ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(prealloc_tmp);
-
- prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL);
- ctx_tmp = vrfy; vrfy = secp256k1_context_preallocated_clone(vrfy, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
- ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_preallocated_destroy(ctx_tmp);
- free(prealloc_tmp);
-
- prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL);
- ctx_tmp = both; both = secp256k1_context_preallocated_clone(both, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
- ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_preallocated_destroy(ctx_tmp);
+ ctx_tmp = ctx; ctx = secp256k1_context_preallocated_clone(ctx, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
+ ctx_tmp = ctx; ctx = secp256k1_context_clone(ctx); secp256k1_context_preallocated_destroy(ctx_tmp);
free(prealloc_tmp);
}
}
/* Verify that the error callback makes it across the clone. */
- CHECK(sign->error_callback.fn != vrfy->error_callback.fn);
- CHECK(sign->error_callback.fn == secp256k1_default_illegal_callback_fn);
+ CHECK(ctx->error_callback.fn != sttc->error_callback.fn);
+ CHECK(ctx->error_callback.fn == secp256k1_default_illegal_callback_fn);
/* And that it resets back to default. */
- secp256k1_context_set_error_callback(sign, NULL, NULL);
- CHECK(vrfy->error_callback.fn == sign->error_callback.fn);
+ secp256k1_context_set_error_callback(ctx, NULL, NULL);
+ CHECK(ctx->error_callback.fn == sttc->error_callback.fn);
/*** attempt to use them ***/
random_scalar_order_test(&msg);
random_scalar_order_test(&key);
- secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key);
+ secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key);
secp256k1_ge_set_gej(&pub, &pubj);
/* Verify context-type checking illegal-argument errors. */
@@ -270,29 +264,29 @@ void run_context_tests(int use_prealloc) {
CHECK(secp256k1_ec_pubkey_create(sttc, &pubkey, ctmp) == 0);
CHECK(ecount == 1);
VG_UNDEF(&pubkey, sizeof(pubkey));
- CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ecdsa_sign(sttc, &sig, ctmp, ctmp, NULL, NULL) == 0);
CHECK(ecount == 2);
VG_UNDEF(&sig, sizeof(sig));
- CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);
+ CHECK(secp256k1_ecdsa_sign(ctx, &sig, ctmp, ctmp, NULL, NULL) == 1);
VG_CHECK(&sig, sizeof(sig));
CHECK(ecount2 == 10);
- CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 1);
+ CHECK(secp256k1_ecdsa_verify(ctx, &sig, ctmp, &pubkey) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ecdsa_verify(sttc, &sig, ctmp, &pubkey) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 1);
+ CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ec_pubkey_tweak_add(sttc, &pubkey, ctmp) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 1);
+ CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp) == 1);
CHECK(ecount2 == 10);
CHECK(secp256k1_ec_pubkey_negate(sttc, &pubkey) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
+ CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey) == 1);
CHECK(ecount == 2);
- CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
+ CHECK(secp256k1_ec_pubkey_negate(ctx, NULL) == 0);
CHECK(ecount2 == 11);
CHECK(secp256k1_ec_pubkey_negate(sttc, &zero_pubkey) == 0);
CHECK(ecount == 3);
@@ -302,49 +296,37 @@ void run_context_tests(int use_prealloc) {
CHECK(ecount == 3);
CHECK(secp256k1_context_randomize(sttc, NULL) == 1);
CHECK(ecount == 3);
- CHECK(secp256k1_context_randomize(sign, ctmp) == 1);
+ CHECK(secp256k1_context_randomize(ctx, ctmp) == 1);
CHECK(ecount2 == 11);
- CHECK(secp256k1_context_randomize(sign, NULL) == 1);
+ CHECK(secp256k1_context_randomize(ctx, NULL) == 1);
CHECK(ecount2 == 11);
secp256k1_context_set_illegal_callback(sttc, NULL, NULL);
- secp256k1_context_set_illegal_callback(sign, NULL, NULL);
+ secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
/* obtain a working nonce */
do {
random_scalar_order_test(&nonce);
- } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
+ } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
/* try signing */
- CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
- CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
+ CHECK(secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
/* try verifying */
CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
- CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
/* cleanup */
if (use_prealloc) {
- secp256k1_context_preallocated_destroy(none);
- secp256k1_context_preallocated_destroy(sign);
- secp256k1_context_preallocated_destroy(vrfy);
- secp256k1_context_preallocated_destroy(both);
+ secp256k1_context_preallocated_destroy(ctx);
secp256k1_context_preallocated_destroy(sttc);
- free(none_prealloc);
- free(sign_prealloc);
- free(vrfy_prealloc);
- free(both_prealloc);
+ free(ctx_prealloc);
free(sttc_prealloc);
} else {
- secp256k1_context_destroy(none);
- secp256k1_context_destroy(sign);
- secp256k1_context_destroy(vrfy);
- secp256k1_context_destroy(both);
+ secp256k1_context_destroy(ctx);
secp256k1_context_destroy(sttc);
}
/* Defined as no-op. */
secp256k1_context_destroy(NULL);
secp256k1_context_preallocated_destroy(NULL);
-
}
void run_scratch_tests(void) {
@@ -353,83 +335,85 @@ void run_scratch_tests(void) {
int32_t ecount = 0;
size_t checkpoint;
size_t checkpoint_2;
- secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_scratch_space *scratch;
secp256k1_scratch_space local_scratch;
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+
/* Test public API */
- secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
- secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(ctx, counting_illegal_callback_fn, &ecount);
- scratch = secp256k1_scratch_space_create(none, 1000);
+ scratch = secp256k1_scratch_space_create(ctx, 1000);
CHECK(scratch != NULL);
CHECK(ecount == 0);
/* Test internal API */
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1));
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1));
CHECK(scratch->alloc_size == 0);
CHECK(scratch->alloc_size % ALIGNMENT == 0);
/* Allocating 500 bytes succeeds */
- checkpoint = secp256k1_scratch_checkpoint(&none->error_callback, scratch);
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) != NULL);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
+ checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 500) != NULL);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000 - adj_alloc);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
CHECK(scratch->alloc_size != 0);
CHECK(scratch->alloc_size % ALIGNMENT == 0);
/* Allocating another 501 bytes fails */
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 501) == NULL);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 501) == NULL);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000 - adj_alloc);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
CHECK(scratch->alloc_size != 0);
CHECK(scratch->alloc_size % ALIGNMENT == 0);
/* ...but it succeeds once we apply the checkpoint to undo it */
- secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint);
+ secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint);
CHECK(scratch->alloc_size == 0);
- CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000);
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) != NULL);
+ CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000);
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 500) != NULL);
CHECK(scratch->alloc_size != 0);
/* try to apply a bad checkpoint */
- checkpoint_2 = secp256k1_scratch_checkpoint(&none->error_callback, scratch);
- secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint);
+ checkpoint_2 = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
+ secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint);
CHECK(ecount == 0);
- secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint_2); /* checkpoint_2 is after checkpoint */
+ secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint_2); /* checkpoint_2 is after checkpoint */
CHECK(ecount == 1);
- secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, (size_t) -1); /* this is just wildly invalid */
+ secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, (size_t) -1); /* this is just wildly invalid */
CHECK(ecount == 2);
/* try to use badly initialized scratch space */
- secp256k1_scratch_space_destroy(none, scratch);
+ secp256k1_scratch_space_destroy(ctx, scratch);
memset(&local_scratch, 0, sizeof(local_scratch));
scratch = &local_scratch;
- CHECK(!secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0));
+ CHECK(!secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0));
CHECK(ecount == 3);
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) == NULL);
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 500) == NULL);
CHECK(ecount == 4);
- secp256k1_scratch_space_destroy(none, scratch);
+ secp256k1_scratch_space_destroy(ctx, scratch);
CHECK(ecount == 5);
/* Test that large integers do not wrap around in a bad way */
- scratch = secp256k1_scratch_space_create(none, 1000);
+ scratch = secp256k1_scratch_space_create(ctx, 1000);
/* Try max allocation with a large number of objects. Only makes sense if
* ALIGNMENT is greater than 1 because otherwise the objects take no extra
* space. */
- CHECK(ALIGNMENT <= 1 || !secp256k1_scratch_max_allocation(&none->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1));
+ CHECK(ALIGNMENT <= 1 || !secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1));
/* Try allocating SIZE_MAX to test wrap around which only happens if
* ALIGNMENT > 1, otherwise it returns NULL anyway because the scratch
* space is too small. */
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, SIZE_MAX) == NULL);
- secp256k1_scratch_space_destroy(none, scratch);
+ CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, SIZE_MAX) == NULL);
+ secp256k1_scratch_space_destroy(ctx, scratch);
/* cleanup */
- secp256k1_scratch_space_destroy(none, NULL); /* no-op */
- secp256k1_context_destroy(none);
+ secp256k1_scratch_space_destroy(ctx, NULL); /* no-op */
+ secp256k1_context_destroy(ctx);
}
+
void run_ctz_tests(void) {
static const uint32_t b32[] = {1, 0xffffffff, 0x5e56968f, 0xe0d63129};
static const uint64_t b64[] = {1, 0xffffffffffffffff, 0xbcd02462139b3fc3, 0x98b5f80c769693ef};
@@ -697,7 +681,6 @@ void run_rfc6979_hmac_sha256_tests(void) {
void run_tagged_sha256_tests(void) {
int ecount = 0;
- secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
unsigned char tag[32] = { 0 };
unsigned char msg[32] = { 0 };
unsigned char hash32[32];
@@ -708,23 +691,22 @@ void run_tagged_sha256_tests(void) {
0xE2, 0x76, 0x55, 0x9A, 0x3B, 0xDE, 0x55, 0xB3
};
- secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
/* API test */
- CHECK(secp256k1_tagged_sha256(none, hash32, tag, sizeof(tag), msg, sizeof(msg)) == 1);
- CHECK(secp256k1_tagged_sha256(none, NULL, tag, sizeof(tag), msg, sizeof(msg)) == 0);
+ CHECK(secp256k1_tagged_sha256(ctx, hash32, tag, sizeof(tag), msg, sizeof(msg)) == 1);
+ CHECK(secp256k1_tagged_sha256(ctx, NULL, tag, sizeof(tag), msg, sizeof(msg)) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_tagged_sha256(none, hash32, NULL, 0, msg, sizeof(msg)) == 0);
+ CHECK(secp256k1_tagged_sha256(ctx, hash32, NULL, 0, msg, sizeof(msg)) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_tagged_sha256(none, hash32, tag, sizeof(tag), NULL, 0) == 0);
+ CHECK(secp256k1_tagged_sha256(ctx, hash32, tag, sizeof(tag), NULL, 0) == 0);
CHECK(ecount == 3);
/* Static test vector */
memcpy(tag, "tag", 3);
memcpy(msg, "msg", 3);
- CHECK(secp256k1_tagged_sha256(none, hash32, tag, 3, msg, 3) == 1);
+ CHECK(secp256k1_tagged_sha256(ctx, hash32, tag, 3, msg, 3) == 1);
CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
- secp256k1_context_destroy(none);
}
/***** RANDOM TESTS *****/
@@ -814,7 +796,8 @@ uint64_t modinv2p64(uint64_t x) {
return w;
}
-/* compute out = (a*b) mod m; if b=NULL, treat b=1.
+
+/* compute out = (a*b) mod m; if b=NULL, treat b=1; if m=NULL, treat m=infinity.
*
* Out is a 512-bit number (represented as 32 uint16_t's in LE order). The other
* arguments are 256-bit numbers (represented as 16 uint16_t's in LE order). */
@@ -856,46 +839,48 @@ void mulmod256(uint16_t* out, const uint16_t* a, const uint16_t* b, const uint16
}
}
- /* Compute the highest set bit in m. */
- for (i = 255; i >= 0; --i) {
- if ((m[i >> 4] >> (i & 15)) & 1) {
- m_bitlen = i;
- break;
+ if (m) {
+ /* Compute the highest set bit in m. */
+ for (i = 255; i >= 0; --i) {
+ if ((m[i >> 4] >> (i & 15)) & 1) {
+ m_bitlen = i;
+ break;
+ }
}
- }
- /* Try do mul -= m<<i, for i going down to 0, whenever the result is not negative */
- for (i = mul_bitlen - m_bitlen; i >= 0; --i) {
- uint16_t mul2[32];
- int64_t cs;
-
- /* Compute mul2 = mul - m<<i. */
- cs = 0; /* accumulator */
- for (j = 0; j < 32; ++j) { /* j loops over the output limbs in mul2. */
- /* Compute sub: the 16 bits in m that will be subtracted from mul2[j]. */
- uint16_t sub = 0;
- int p;
- for (p = 0; p < 16; ++p) { /* p loops over the bit positions in mul2[j]. */
- int bitpos = j * 16 - i + p; /* bitpos is the correspond bit position in m. */
- if (bitpos >= 0 && bitpos < 256) {
- sub |= ((m[bitpos >> 4] >> (bitpos & 15)) & 1) << p;
+ /* Try do mul -= m<<i, for i going down to 0, whenever the result is not negative */
+ for (i = mul_bitlen - m_bitlen; i >= 0; --i) {
+ uint16_t mul2[32];
+ int64_t cs;
+
+ /* Compute mul2 = mul - m<<i. */
+ cs = 0; /* accumulator */
+ for (j = 0; j < 32; ++j) { /* j loops over the output limbs in mul2. */
+ /* Compute sub: the 16 bits in m that will be subtracted from mul2[j]. */
+ uint16_t sub = 0;
+ int p;
+ for (p = 0; p < 16; ++p) { /* p loops over the bit positions in mul2[j]. */
+ int bitpos = j * 16 - i + p; /* bitpos is the correspond bit position in m. */
+ if (bitpos >= 0 && bitpos < 256) {
+ sub |= ((m[bitpos >> 4] >> (bitpos & 15)) & 1) << p;
+ }
}
+ /* Add mul[j]-sub to accumulator, and shift bottom 16 bits out to mul2[j]. */
+ cs += mul[j];
+ cs -= sub;
+ mul2[j] = (cs & 0xFFFF);
+ cs >>= 16;
+ }
+ /* If remainder of subtraction is 0, set mul = mul2. */
+ if (cs == 0) {
+ memcpy(mul, mul2, sizeof(mul));
}
- /* Add mul[j]-sub to accumulator, and shift bottom 16 bits out to mul2[j]. */
- cs += mul[j];
- cs -= sub;
- mul2[j] = (cs & 0xFFFF);
- cs >>= 16;
}
- /* If remainder of subtraction is 0, set mul = mul2. */
- if (cs == 0) {
- memcpy(mul, mul2, sizeof(mul));
+ /* Sanity check: test that all limbs higher than m's highest are zero */
+ for (i = (m_bitlen >> 4) + 1; i < 32; ++i) {
+ CHECK(mul[i] == 0);
}
}
- /* Sanity check: test that all limbs higher than m's highest are zero */
- for (i = (m_bitlen >> 4) + 1; i < 32; ++i) {
- CHECK(mul[i] == 0);
- }
memcpy(out, mul, 32);
}
@@ -1710,8 +1695,305 @@ void run_modinv_tests(void) {
}
}
-/***** SCALAR TESTS *****/
+/***** INT128 TESTS *****/
+
+#ifdef SECP256K1_WIDEMUL_INT128
+/* Add two 256-bit numbers (represented as 16 uint16_t's in LE order) together mod 2^256. */
+void add256(uint16_t* out, const uint16_t* a, const uint16_t* b) {
+ int i;
+ uint32_t carry = 0;
+ for (i = 0; i < 16; ++i) {
+ carry += a[i];
+ carry += b[i];
+ out[i] = carry;
+ carry >>= 16;
+ }
+}
+
+/* Negate a 256-bit number (represented as 16 uint16_t's in LE order) mod 2^256. */
+void neg256(uint16_t* out, const uint16_t* a) {
+ int i;
+ uint32_t carry = 1;
+ for (i = 0; i < 16; ++i) {
+ carry += (uint16_t)~a[i];
+ out[i] = carry;
+ carry >>= 16;
+ }
+}
+
+/* Right-shift a 256-bit number (represented as 16 uint16_t's in LE order). */
+void rshift256(uint16_t* out, const uint16_t* a, int n, int sign_extend) {
+ uint16_t sign = sign_extend && (a[15] >> 15);
+ int i, j;
+ for (i = 15; i >= 0; --i) {
+ uint16_t v = 0;
+ for (j = 0; j < 16; ++j) {
+ int frompos = i*16 + j + n;
+ if (frompos >= 256) {
+ v |= sign << j;
+ } else {
+ v |= ((uint16_t)((a[frompos >> 4] >> (frompos & 15)) & 1)) << j;
+ }
+ }
+ out[i] = v;
+ }
+}
+
+/* Load a 64-bit unsigned integer into an array of 16 uint16_t's in LE order representing a 256-bit value. */
+void load256u64(uint16_t* out, uint64_t v, int is_signed) {
+ int i;
+ uint64_t sign = is_signed && (v >> 63) ? UINT64_MAX : 0;
+ for (i = 0; i < 4; ++i) {
+ out[i] = v >> (16 * i);
+ }
+ for (i = 4; i < 16; ++i) {
+ out[i] = sign;
+ }
+}
+
+/* Load a 128-bit unsigned integer into an array of 16 uint16_t's in LE order representing a 256-bit value. */
+void load256two64(uint16_t* out, uint64_t hi, uint64_t lo, int is_signed) {
+ int i;
+ uint64_t sign = is_signed && (hi >> 63) ? UINT64_MAX : 0;
+ for (i = 0; i < 4; ++i) {
+ out[i] = lo >> (16 * i);
+ }
+ for (i = 4; i < 8; ++i) {
+ out[i] = hi >> (16 * (i - 4));
+ }
+ for (i = 8; i < 16; ++i) {
+ out[i] = sign;
+ }
+}
+
+/* Check whether the 256-bit value represented by array of 16-bit values is in range -2^127 < v < 2^127. */
+int int256is127(const uint16_t* v) {
+ int all_0 = ((v[7] & 0x8000) == 0), all_1 = ((v[7] & 0x8000) == 0x8000);
+ int i;
+ for (i = 8; i < 16; ++i) {
+ if (v[i] != 0) all_0 = 0;
+ if (v[i] != 0xffff) all_1 = 0;
+ }
+ return all_0 || all_1;
+}
+void load256u128(uint16_t* out, const secp256k1_uint128* v) {
+ uint64_t lo = secp256k1_u128_to_u64(v), hi = secp256k1_u128_hi_u64(v);
+ load256two64(out, hi, lo, 0);
+}
+
+void load256i128(uint16_t* out, const secp256k1_int128* v) {
+ uint64_t lo;
+ int64_t hi;
+ secp256k1_int128 c = *v;
+ lo = secp256k1_i128_to_i64(&c);
+ secp256k1_i128_rshift(&c, 64);
+ hi = secp256k1_i128_to_i64(&c);
+ load256two64(out, hi, lo, 1);
+}
+
+void run_int128_test_case(void) {
+ unsigned char buf[32];
+ uint64_t v[4];
+ secp256k1_int128 swa, swz;
+ secp256k1_uint128 uwa, uwz;
+ uint64_t ub, uc;
+ int64_t sb, sc;
+ uint16_t rswa[16], rswz[32], rswr[32], ruwa[16], ruwz[32], ruwr[32];
+ uint16_t rub[16], ruc[16], rsb[16], rsc[16];
+ int i;
+
+ /* Generate 32-byte random value. */
+ secp256k1_testrand256_test(buf);
+ /* Convert into 4 64-bit integers. */
+ for (i = 0; i < 4; ++i) {
+ uint64_t vi = 0;
+ int j;
+ for (j = 0; j < 8; ++j) vi = (vi << 8) + buf[8*i + j];
+ v[i] = vi;
+ }
+ /* Convert those into a 128-bit value and two 64-bit values (signed and unsigned). */
+ secp256k1_u128_load(&uwa, v[1], v[0]);
+ secp256k1_i128_load(&swa, v[1], v[0]);
+ ub = v[2];
+ sb = v[2];
+ uc = v[3];
+ sc = v[3];
+ /* Load those also into 16-bit array representations. */
+ load256u128(ruwa, &uwa);
+ load256i128(rswa, &swa);
+ load256u64(rub, ub, 0);
+ load256u64(rsb, sb, 1);
+ load256u64(ruc, uc, 0);
+ load256u64(rsc, sc, 1);
+ /* test secp256k1_u128_mul */
+ mulmod256(ruwr, rub, ruc, NULL);
+ secp256k1_u128_mul(&uwz, ub, uc);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0);
+ /* test secp256k1_u128_accum_mul */
+ mulmod256(ruwr, rub, ruc, NULL);
+ add256(ruwr, ruwr, ruwa);
+ uwz = uwa;
+ secp256k1_u128_accum_mul(&uwz, ub, uc);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0);
+ /* test secp256k1_u128_accum_u64 */
+ add256(ruwr, rub, ruwa);
+ uwz = uwa;
+ secp256k1_u128_accum_u64(&uwz, ub);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0);
+ /* test secp256k1_u128_rshift */
+ rshift256(ruwr, ruwa, uc % 128, 0);
+ uwz = uwa;
+ secp256k1_u128_rshift(&uwz, uc % 128);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0);
+ /* test secp256k1_u128_to_u64 */
+ CHECK(secp256k1_u128_to_u64(&uwa) == v[0]);
+ /* test secp256k1_u128_hi_u64 */
+ CHECK(secp256k1_u128_hi_u64(&uwa) == v[1]);
+ /* test secp256k1_u128_from_u64 */
+ secp256k1_u128_from_u64(&uwz, ub);
+ load256u128(ruwz, &uwz);
+ CHECK(secp256k1_memcmp_var(rub, ruwz, 16) == 0);
+ /* test secp256k1_u128_check_bits */
+ {
+ int uwa_bits = 0;
+ int j;
+ for (j = 0; j < 128; ++j) {
+ if (ruwa[j / 16] >> (j % 16)) uwa_bits = 1 + j;
+ }
+ for (j = 0; j < 128; ++j) {
+ CHECK(secp256k1_u128_check_bits(&uwa, j) == (uwa_bits <= j));
+ }
+ }
+ /* test secp256k1_i128_mul */
+ mulmod256(rswr, rsb, rsc, NULL);
+ secp256k1_i128_mul(&swz, sb, sc);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0);
+ /* test secp256k1_i128_accum_mul */
+ mulmod256(rswr, rsb, rsc, NULL);
+ add256(rswr, rswr, rswa);
+ if (int256is127(rswr)) {
+ swz = swa;
+ secp256k1_i128_accum_mul(&swz, sb, sc);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0);
+ }
+ /* test secp256k1_i128_det */
+ {
+ uint16_t rsd[16], rse[16], rst[32];
+ int64_t sd = v[0], se = v[1];
+ load256u64(rsd, sd, 1);
+ load256u64(rse, se, 1);
+ mulmod256(rst, rsc, rsd, NULL);
+ neg256(rst, rst);
+ mulmod256(rswr, rsb, rse, NULL);
+ add256(rswr, rswr, rst);
+ secp256k1_i128_det(&swz, sb, sc, sd, se);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0);
+ }
+ /* test secp256k1_i128_rshift */
+ rshift256(rswr, rswa, uc % 127, 1);
+ swz = swa;
+ secp256k1_i128_rshift(&swz, uc % 127);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0);
+ /* test secp256k1_i128_to_i64 */
+ CHECK((uint64_t)secp256k1_i128_to_i64(&swa) == v[0]);
+ /* test secp256k1_i128_from_i64 */
+ secp256k1_i128_from_i64(&swz, sb);
+ load256i128(rswz, &swz);
+ CHECK(secp256k1_memcmp_var(rsb, rswz, 16) == 0);
+ /* test secp256k1_i128_eq_var */
+ {
+ int expect = (uc & 1);
+ swz = swa;
+ if (!expect) {
+ /* Make sure swz != swa */
+ uint64_t v0c = v[0], v1c = v[1];
+ if (ub & 64) {
+ v1c ^= (((uint64_t)1) << (ub & 63));
+ } else {
+ v0c ^= (((uint64_t)1) << (ub & 63));
+ }
+ secp256k1_i128_load(&swz, v1c, v0c);
+ }
+ CHECK(secp256k1_i128_eq_var(&swa, &swz) == expect);
+ }
+ /* test secp256k1_i128_check_pow2 */
+ {
+ int expect = (uc & 1);
+ int pos = ub % 127;
+ if (expect) {
+ /* If expect==1, set swz to exactly (2 << pos). */
+ uint64_t hi = 0;
+ uint64_t lo = 0;
+ if (pos & 64) {
+ hi = (((uint64_t)1) << (pos & 63));
+ } else {
+ lo = (((uint64_t)1) << (pos & 63));
+ }
+ secp256k1_i128_load(&swz, hi, lo);
+ } else {
+ /* If expect==0, set swz = swa, but update expect=1 if swa happens to equal (2 << pos). */
+ if (pos & 64) {
+ if ((v[1] == (((uint64_t)1) << (pos & 63))) && v[0] == 0) expect = 1;
+ } else {
+ if ((v[0] == (((uint64_t)1) << (pos & 63))) && v[1] == 0) expect = 1;
+ }
+ swz = swa;
+ }
+ CHECK(secp256k1_i128_check_pow2(&swz, pos) == expect);
+ }
+}
+
+void run_int128_tests(void) {
+ { /* secp256k1_u128_accum_mul */
+ secp256k1_uint128 res;
+
+ /* Check secp256k1_u128_accum_mul overflow */
+ secp256k1_u128_mul(&res, UINT64_MAX, UINT64_MAX);
+ secp256k1_u128_accum_mul(&res, UINT64_MAX, UINT64_MAX);
+ CHECK(secp256k1_u128_to_u64(&res) == 2);
+ CHECK(secp256k1_u128_hi_u64(&res) == 18446744073709551612U);
+ }
+ { /* secp256k1_u128_accum_mul */
+ secp256k1_int128 res;
+
+ /* Compute INT128_MAX = 2^127 - 1 with secp256k1_i128_accum_mul */
+ secp256k1_i128_mul(&res, INT64_MAX, INT64_MAX);
+ secp256k1_i128_accum_mul(&res, INT64_MAX, INT64_MAX);
+ CHECK(secp256k1_i128_to_i64(&res) == 2);
+ secp256k1_i128_accum_mul(&res, 4, 9223372036854775807);
+ secp256k1_i128_accum_mul(&res, 1, 1);
+ CHECK((uint64_t)secp256k1_i128_to_i64(&res) == UINT64_MAX);
+ secp256k1_i128_rshift(&res, 64);
+ CHECK(secp256k1_i128_to_i64(&res) == INT64_MAX);
+
+ /* Compute INT128_MIN = - 2^127 with secp256k1_i128_accum_mul */
+ secp256k1_i128_mul(&res, INT64_MAX, INT64_MIN);
+ CHECK(secp256k1_i128_to_i64(&res) == INT64_MIN);
+ secp256k1_i128_accum_mul(&res, INT64_MAX, INT64_MIN);
+ CHECK(secp256k1_i128_to_i64(&res) == 0);
+ secp256k1_i128_accum_mul(&res, 2, INT64_MIN);
+ CHECK(secp256k1_i128_to_i64(&res) == 0);
+ secp256k1_i128_rshift(&res, 64);
+ CHECK(secp256k1_i128_to_i64(&res) == INT64_MIN);
+ }
+ {
+ /* Randomized tests. */
+ int i;
+ for (i = 0; i < 256 * count; ++i) run_int128_test_case();
+ }
+}
+#endif
+
+/***** SCALAR TESTS *****/
void scalar_test(void) {
secp256k1_scalar s;
@@ -3562,6 +3844,22 @@ void run_gej(void) {
test_gej_cmov(&a, &b);
test_gej_cmov(&b, &a);
}
+
+ /* Tests for secp256k1_gej_eq_var */
+ for (i = 0; i < count; i++) {
+ secp256k1_fe fe;
+ random_gej_test(&a);
+ random_gej_test(&b);
+ CHECK(!secp256k1_gej_eq_var(&a, &b));
+
+ b = a;
+ random_field_element_test(&fe);
+ if (secp256k1_fe_is_zero(&fe)) {
+ continue;
+ }
+ secp256k1_gej_rescale(&a, &fe);
+ CHECK(secp256k1_gej_eq_var(&a, &b));
+ }
}
void test_ec_combine(void) {
@@ -3767,17 +4065,12 @@ void run_ecmult_chain(void) {
0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D,
0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88
);
-
- secp256k1_gej_neg(&rp, &rp);
- secp256k1_gej_add_var(&rp, &rp, &x, NULL);
- CHECK(secp256k1_gej_is_infinity(&rp));
+ CHECK(secp256k1_gej_eq_var(&rp, &x));
}
}
/* redo the computation, but directly with the resulting ae and ge coefficients: */
secp256k1_ecmult(&x2, &a, &ae, &ge);
- secp256k1_gej_neg(&x2, &x2);
- secp256k1_gej_add_var(&x2, &x2, &x, NULL);
- CHECK(secp256k1_gej_is_infinity(&x2));
+ CHECK(secp256k1_gej_eq_var(&x, &x2));
}
void test_point_times_order(const secp256k1_gej *point) {
@@ -4070,16 +4363,12 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
/* only G scalar */
secp256k1_ecmult(&r2, &ptgj, &szero, &sc[0]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
/* 1-point */
secp256k1_ecmult(&r2, &ptgj, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
/* Try to multiply 1 point, but callback returns false */
CHECK(!ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
@@ -4087,16 +4376,12 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
/* 2-point */
secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
/* 2-point with G scalar */
secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
}
/* Check infinite outputs of various forms */
@@ -4181,9 +4466,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_ecmult(&r2, &r, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
}
/* Check random scalars, constant point */
@@ -4204,9 +4487,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_gej_set_ge(&p0j, &pt[0]);
secp256k1_ecmult(&r2, &p0j, &rs, &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
- secp256k1_gej_neg(&r2, &r2);
- secp256k1_gej_add_var(&r, &r, &r2, NULL);
- CHECK(secp256k1_gej_is_infinity(&r));
+ CHECK(secp256k1_gej_eq_var(&r, &r2));
}
/* Sanity check that zero scalars don't cause problems */
@@ -4268,9 +4549,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_ecmult(&expected, &ptgj, &tmp1, &szero);
CHECK(ecmult_multi(&ctx->error_callback, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
- secp256k1_gej_neg(&expected, &expected);
- secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
- CHECK(secp256k1_gej_is_infinity(&actual));
+ CHECK(secp256k1_gej_eq_var(&actual, &expected));
}
}
}
@@ -4440,9 +4719,7 @@ int test_ecmult_multi_random(secp256k1_scratch *scratch) {
CHECK(ecmult_multi(&ctx->error_callback, scratch, &computed, g_scalar_ptr, ecmult_multi_callback, &data, filled));
mults += num_nonzero + g_nonzero;
/* Compare with expected result. */
- secp256k1_gej_neg(&computed, &computed);
- secp256k1_gej_add_var(&computed, &computed, &expected, NULL);
- CHECK(secp256k1_gej_is_infinity(&computed));
+ CHECK(secp256k1_gej_eq_var(&computed, &expected));
return mults;
}
@@ -5497,7 +5774,7 @@ void run_ec_pubkey_parse_test(void) {
ecount = 0;
VG_UNDEF(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1);
- CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, &pubkey, pubkeyc, 65) == 1);
+ CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, pubkeyc, 65) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
VG_UNDEF(&ge, sizeof(ge));
@@ -7083,19 +7360,27 @@ int main(int argc, char **argv) {
secp256k1_testrand_init(argc > 2 ? argv[2] : NULL);
/* initialize */
+ run_selftest_tests();
run_context_tests(0);
run_context_tests(1);
run_scratch_tests();
- ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
- if (secp256k1_testrand_bits(1)) {
+
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+ /* Randomize the context only with probability 15/16
+ to make sure we test without context randomization from time to time.
+ TODO Reconsider this when recalibrating the tests. */
+ if (secp256k1_testrand_bits(4)) {
unsigned char rand32[32];
secp256k1_testrand256(rand32);
- CHECK(secp256k1_context_randomize(ctx, secp256k1_testrand_bits(1) ? rand32 : NULL));
+ CHECK(secp256k1_context_randomize(ctx, rand32));
}
run_rand_bits();
run_rand_int();
+#ifdef SECP256K1_WIDEMUL_INT128
+ run_int128_tests();
+#endif
run_ctz_tests();
run_modinv_tests();
run_inverse_tests();
diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c
index 6a4e2340f2..c001dcb80b 100644
--- a/src/secp256k1/src/tests_exhaustive.c
+++ b/src/secp256k1/src/tests_exhaustive.c
@@ -342,15 +342,15 @@ void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *grou
}
#ifdef ENABLE_MODULE_RECOVERY
-#include "src/modules/recovery/tests_exhaustive_impl.h"
+#include "modules/recovery/tests_exhaustive_impl.h"
#endif
#ifdef ENABLE_MODULE_EXTRAKEYS
-#include "src/modules/extrakeys/tests_exhaustive_impl.h"
+#include "modules/extrakeys/tests_exhaustive_impl.h"
#endif
#ifdef ENABLE_MODULE_SCHNORRSIG
-#include "src/modules/schnorrsig/tests_exhaustive_impl.h"
+#include "modules/schnorrsig/tests_exhaustive_impl.h"
#endif
int main(int argc, char** argv) {
@@ -396,7 +396,7 @@ int main(int argc, char** argv) {
while (count--) {
/* Build context */
- ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_testrand256(rand32);
CHECK(secp256k1_context_randomize(ctx, rand32));
diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h
index dac86bd77f..864baaee4d 100644
--- a/src/secp256k1/src/util.h
+++ b/src/secp256k1/src/util.h
@@ -16,6 +16,11 @@
#include <stdio.h>
#include <limits.h>
+#define STR_(x) #x
+#define STR(x) STR_(x)
+#define DEBUG_CONFIG_MSG(x) "DEBUG_CONFIG: " x
+#define DEBUG_CONFIG_DEF(x) DEBUG_CONFIG_MSG(#x "=" STR(x))
+
typedef struct {
void (*fn)(const char *text, void* data);
const void* data;
@@ -225,28 +230,36 @@ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag)
*r = (int)(r_masked | a_masked);
}
-/* If USE_FORCE_WIDEMUL_{INT128,INT64} is set, use that wide multiplication implementation.
- * Otherwise use the presence of __SIZEOF_INT128__ to decide.
- */
-#if defined(USE_FORCE_WIDEMUL_INT128)
+#if defined(USE_FORCE_WIDEMUL_INT128_STRUCT)
+/* If USE_FORCE_WIDEMUL_INT128_STRUCT is set, use int128_struct. */
# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_STRUCT 1
+#elif defined(USE_FORCE_WIDEMUL_INT128)
+/* If USE_FORCE_WIDEMUL_INT128 is set, use int128. */
+# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_NATIVE 1
#elif defined(USE_FORCE_WIDEMUL_INT64)
+/* If USE_FORCE_WIDEMUL_INT64 is set, use int64. */
# define SECP256K1_WIDEMUL_INT64 1
#elif defined(UINT128_MAX) || defined(__SIZEOF_INT128__)
+/* If a native 128-bit integer type exists, use int128. */
+# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_NATIVE 1
+#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
+/* On 64-bit MSVC targets (x86_64 and arm64), use int128_struct
+ * (which has special logic to implement using intrinsics on those systems). */
# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_STRUCT 1
+#elif SIZE_MAX > 0xffffffff
+/* Systems with 64-bit pointers (and thus registers) very likely benefit from
+ * using 64-bit based arithmetic (even if we need to fall back to 32x32->64 based
+ * multiplication logic). */
+# define SECP256K1_WIDEMUL_INT128 1
+# define SECP256K1_INT128_STRUCT 1
#else
+/* Lastly, fall back to int64 based arithmetic. */
# define SECP256K1_WIDEMUL_INT64 1
#endif
-#if defined(SECP256K1_WIDEMUL_INT128)
-# if !defined(UINT128_MAX) && defined(__SIZEOF_INT128__)
-SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
-SECP256K1_GNUC_EXT typedef __int128 int128_t;
-#define UINT128_MAX ((uint128_t)(-1))
-#define INT128_MAX ((int128_t)(UINT128_MAX >> 1))
-#define INT128_MIN (-INT128_MAX - 1)
-/* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */
-# endif
-#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
diff --git a/src/secp256k1/src/valgrind_ctime_test.c b/src/secp256k1/src/valgrind_ctime_test.c
index 6ff0085d34..a0f888b00f 100644
--- a/src/secp256k1/src/valgrind_ctime_test.c
+++ b/src/secp256k1/src/valgrind_ctime_test.c
@@ -39,9 +39,7 @@ int main(void) {
fprintf(stderr, "Usage: libtool --mode=execute valgrind ./valgrind_ctime_test\n");
return 1;
}
- ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN
- | SECP256K1_CONTEXT_VERIFY
- | SECP256K1_CONTEXT_DECLASSIFY);
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY);
/** In theory, testing with a single secret input should be sufficient:
* If control flow depended on secrets the tool would generate an error.
*/
diff --git a/src/serialize.h b/src/serialize.h
index 89a9f32240..7bc7b10779 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1005,11 +1005,11 @@ struct CSerActionUnserialize
class CSizeComputer
{
protected:
- size_t nSize;
+ size_t nSize{0};
const int nVersion;
public:
- explicit CSizeComputer(int nVersionIn) : nSize(0), nVersion(nVersionIn) {}
+ explicit CSizeComputer(int nVersionIn) : nVersion(nVersionIn) {}
void write(Span<const std::byte> src)
{
diff --git a/src/shutdown.cpp b/src/shutdown.cpp
index 1dbc55aeb5..57d6d2325d 100644
--- a/src/shutdown.cpp
+++ b/src/shutdown.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/span.h b/src/span.h
index 444d63001f..4692eca7fb 100644
--- a/src/span.h
+++ b/src/span.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -96,7 +96,7 @@ template<typename C>
class Span
{
C* m_data;
- std::size_t m_size;
+ std::size_t m_size{0};
template <class T>
struct is_Span_int : public std::false_type {};
@@ -107,7 +107,7 @@ class Span
public:
- constexpr Span() noexcept : m_data(nullptr), m_size(0) {}
+ constexpr Span() noexcept : m_data(nullptr) {}
/** Construct a span from a begin pointer and a size.
*
diff --git a/src/streams.h b/src/streams.h
index 84b12f65aa..8788343809 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -182,16 +182,13 @@ public:
* >> and << read and write unformatted data using the above serialization templates.
* Fills with data in linear time; some stringstream implementations take N^2 time.
*/
-class CDataStream
+class DataStream
{
protected:
using vector_type = SerializeData;
vector_type vch;
vector_type::size_type m_read_pos{0};
- int nType;
- int nVersion;
-
public:
typedef vector_type::allocator_type allocator_type;
typedef vector_type::size_type size_type;
@@ -203,23 +200,9 @@ public:
typedef vector_type::const_iterator const_iterator;
typedef vector_type::reverse_iterator reverse_iterator;
- explicit CDataStream(int nTypeIn, int nVersionIn)
- : nType{nTypeIn},
- nVersion{nVersionIn} {}
-
- explicit CDataStream(Span<const uint8_t> sp, int type, int version) : CDataStream{AsBytes(sp), type, version} {}
- explicit CDataStream(Span<const value_type> sp, int nTypeIn, int nVersionIn)
- : vch(sp.data(), sp.data() + sp.size()),
- nType{nTypeIn},
- nVersion{nVersionIn} {}
-
- template <typename... Args>
- CDataStream(int nTypeIn, int nVersionIn, Args&&... args)
- : nType{nTypeIn},
- nVersion{nVersionIn}
- {
- ::SerializeMany(*this, std::forward<Args>(args)...);
- }
+ explicit DataStream() {}
+ explicit DataStream(Span<const uint8_t> sp) : DataStream{AsBytes(sp)} {}
+ explicit DataStream(Span<const value_type> sp) : vch(sp.data(), sp.data() + sp.size()) {}
std::string str() const
{
@@ -271,11 +254,6 @@ public:
bool eof() const { return size() == 0; }
int in_avail() const { return size(); }
- void SetType(int n) { nType = n; }
- int GetType() const { return nType; }
- void SetVersion(int n) { nVersion = n; }
- int GetVersion() const { return nVersion; }
-
void read(Span<value_type> dst)
{
if (dst.size() == 0) return;
@@ -283,7 +261,7 @@ public:
// Read from the beginning of the buffer
auto next_read_pos{CheckedAdd(m_read_pos, dst.size())};
if (!next_read_pos.has_value() || next_read_pos.value() > vch.size()) {
- throw std::ios_base::failure("CDataStream::read(): end of data");
+ throw std::ios_base::failure("DataStream::read(): end of data");
}
memcpy(dst.data(), &vch[m_read_pos], dst.size());
if (next_read_pos.value() == vch.size()) {
@@ -299,7 +277,7 @@ public:
// Ignore from the beginning of the buffer
auto next_read_pos{CheckedAdd(m_read_pos, num_ignore)};
if (!next_read_pos.has_value() || next_read_pos.value() > vch.size()) {
- throw std::ios_base::failure("CDataStream::ignore(): end of data");
+ throw std::ios_base::failure("DataStream::ignore(): end of data");
}
if (next_read_pos.value() == vch.size()) {
m_read_pos = 0;
@@ -324,7 +302,7 @@ public:
}
template<typename T>
- CDataStream& operator<<(const T& obj)
+ DataStream& operator<<(const T& obj)
{
// Serialize to this stream
::Serialize(*this, obj);
@@ -332,7 +310,7 @@ public:
}
template<typename T>
- CDataStream& operator>>(T&& obj)
+ DataStream& operator>>(T&& obj)
{
// Unserialize from this stream
::Unserialize(*this, obj);
@@ -363,6 +341,42 @@ public:
}
};
+class CDataStream : public DataStream
+{
+private:
+ int nType;
+ int nVersion;
+
+public:
+ explicit CDataStream(int nTypeIn, int nVersionIn)
+ : nType{nTypeIn},
+ nVersion{nVersionIn} {}
+
+ explicit CDataStream(Span<const uint8_t> sp, int type, int version) : CDataStream{AsBytes(sp), type, version} {}
+ explicit CDataStream(Span<const value_type> sp, int nTypeIn, int nVersionIn)
+ : DataStream{sp},
+ nType{nTypeIn},
+ nVersion{nVersionIn} {}
+
+ int GetType() const { return nType; }
+ void SetVersion(int n) { nVersion = n; }
+ int GetVersion() const { return nVersion; }
+
+ template <typename T>
+ CDataStream& operator<<(const T& obj)
+ {
+ ::Serialize(*this, obj);
+ return *this;
+ }
+
+ template <typename T>
+ CDataStream& operator>>(T&& obj)
+ {
+ ::Unserialize(*this, obj);
+ return *this;
+ }
+};
+
template <typename IStream>
class BitStreamReader
{
@@ -606,8 +620,8 @@ private:
const int nVersion;
FILE *src; //!< source file
- uint64_t nSrcPos; //!< how many bytes have been read from source
- uint64_t m_read_pos; //!< how many bytes have been read from this
+ uint64_t nSrcPos{0}; //!< how many bytes have been read from source
+ uint64_t m_read_pos{0}; //!< how many bytes have been read from this
uint64_t nReadLimit; //!< up to which position we're allowed to read
uint64_t nRewind; //!< how many bytes we guarantee to rewind
std::vector<std::byte> vchBuf; //!< the buffer
@@ -653,7 +667,7 @@ private:
public:
CBufferedFile(FILE* fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn)
- : nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), m_read_pos(0), nReadLimit(std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn), vchBuf(nBufSize, std::byte{0})
+ : nType(nTypeIn), nVersion(nVersionIn), nReadLimit(std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn), vchBuf(nBufSize, std::byte{0})
{
if (nRewindIn >= nBufSize)
throw std::ios_base::failure("Rewind limit must be less than buffer size");
diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h
index 0befe0ffcd..795eea3bc0 100644
--- a/src/support/allocators/zeroafterfree.h
+++ b/src/support/allocators/zeroafterfree.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/cleanse.h b/src/support/cleanse.h
index b1227770c7..161f3cc388 100644
--- a/src/support/cleanse.h
+++ b/src/support/cleanse.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 e48accf0a4..24ae4bdd1e 100644
--- a/src/support/lockedpool.cpp
+++ b/src/support/lockedpool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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,6 +19,9 @@
#endif
#include <algorithm>
+#include <limits>
+#include <stdexcept>
+#include <utility>
#ifdef ARENA_DEBUG
#include <iomanip>
#include <iostream>
@@ -277,8 +280,8 @@ size_t PosixLockedPageAllocator::GetLimit()
/*******************************************************************************/
// Implementation: LockedPool
-LockedPool::LockedPool(std::unique_ptr<LockedPageAllocator> allocator_in, LockingFailed_Callback lf_cb_in):
- allocator(std::move(allocator_in)), lf_cb(lf_cb_in), cumulative_bytes_locked(0)
+LockedPool::LockedPool(std::unique_ptr<LockedPageAllocator> allocator_in, LockingFailed_Callback lf_cb_in)
+ : allocator(std::move(allocator_in)), lf_cb(lf_cb_in)
{
}
diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h
index 03e4e371a3..1bba459377 100644
--- a/src/support/lockedpool.h
+++ b/src/support/lockedpool.h
@@ -5,11 +5,11 @@
#ifndef BITCOIN_SUPPORT_LOCKEDPOOL_H
#define BITCOIN_SUPPORT_LOCKEDPOOL_H
-#include <stdint.h>
+#include <cstddef>
#include <list>
#include <map>
-#include <mutex>
#include <memory>
+#include <mutex>
#include <unordered_map>
/**
@@ -198,7 +198,7 @@ private:
std::list<LockedPageArena> arenas;
LockingFailed_Callback lf_cb;
- size_t cumulative_bytes_locked;
+ size_t cumulative_bytes_locked{0};
/** Mutex protects access to this pool's data structures, including arenas.
*/
mutable std::mutex mutex;
diff --git a/src/sync.h b/src/sync.h
index 1f4e191214..7242a793ab 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 <logging/timer.h>
#endif
-#include <threadsafety.h>
+#include <threadsafety.h> // IWYU pragma: export
#include <util/macros.h>
#include <condition_variable>
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index b10d32ccec..586cec4081 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -67,14 +67,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
CNetAddr source = ResolveIP("252.2.2.2");
// Test: Does Addrman respond correctly when empty.
- BOOST_CHECK_EQUAL(addrman->size(), 0U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 0U);
auto addr_null = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
// Test: Does Addrman::Add work as expected.
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
auto addr_ret1 = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
@@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
// Expected dup IP should not be added.
CService addr1_dup = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(!addrman->Add({CAddress(addr1_dup, NODE_NONE)}, source));
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// Test: New table has one addr and we add a diff addr we should
@@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
CService addr2 = ResolveService("250.1.1.2", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
- BOOST_CHECK(addrman->size() >= 1);
+ BOOST_CHECK(addrman->Size() >= 1);
// Test: reset addrman and test AddrMan::Add multiple addresses works as expected
addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
BOOST_CHECK(addrman->Add(vAddr, source));
- BOOST_CHECK(addrman->size() >= 1);
+ BOOST_CHECK(addrman->Size() >= 1);
}
BOOST_AUTO_TEST_CASE(addrman_ports)
@@ -110,23 +110,23 @@ BOOST_AUTO_TEST_CASE(addrman_ports)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK_EQUAL(addrman->size(), 0U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 0U);
// Test 7; Addr with same IP but diff port does not replace existing addr.
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
CService addr1_port = ResolveService("250.1.1.1", 8334);
BOOST_CHECK(addrman->Add({CAddress(addr1_port, NODE_NONE)}, source));
- BOOST_CHECK_EQUAL(addrman->size(), 2U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 2U);
auto addr_ret2 = addrman->Select().first;
BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333" || addr_ret2.ToString() == "250.1.1.1:8334");
// Test: Add same IP but diff port to tried table; this converts the entry with
// the specified port to tried, but not the other.
addrman->Good(CAddress(addr1_port, NODE_NONE));
- BOOST_CHECK_EQUAL(addrman->size(), 2U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 2U);
bool newOnly = true;
auto addr_ret3 = addrman->Select(newOnly).first;
BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
@@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE(addrman_select)
// Test: Select from new with 1 addr in new.
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
bool newOnly = true;
auto addr_ret1 = addrman->Select(newOnly).first;
@@ -150,14 +150,14 @@ BOOST_AUTO_TEST_CASE(addrman_select)
// Test: move addr to tried, select from new expected nothing returned.
BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
auto addr_ret2 = addrman->Select(newOnly).first;
BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0");
auto addr_ret3 = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// Add three addresses to new table.
@@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE(addrman_select)
BOOST_CHECK(addrman->Good(CAddress(addr7, NODE_NONE)));
// Test: 6 addrs + 1 addr from last test = 7.
- BOOST_CHECK_EQUAL(addrman->size(), 7U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 7U);
// Test: Select pulls from new and tried regardless of port number.
std::set<uint16_t> ports;
@@ -200,25 +200,25 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
uint32_t num_addrs{0};
- BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
+ BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
while (num_addrs < 22) { // Magic number! 250.1.1.1 - 250.1.1.22 do not collide with deterministic key = 1
CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
// Test: No collision in new table yet.
- BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
+ BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
}
// Test: new table collision!
CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
uint32_t collisions{1};
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
- BOOST_CHECK_EQUAL(addrman->size(), num_addrs - collisions);
+ BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
- BOOST_CHECK_EQUAL(addrman->size(), num_addrs - collisions);
+ BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
}
BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
@@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
}
AddressPosition addr_pos = addrman->FindAddressEntry(addr).value();
BOOST_CHECK_EQUAL(addr_pos.multiplicity, 1U);
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// if nTime increases, an addr can occur in up to 8 buckets
// The acceptance probability decreases exponentially with existing multiplicity -
@@ -250,7 +250,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();
BOOST_CHECK_EQUAL(addr_pos_multi.multiplicity, 8U);
// multiplicity doesn't affect size
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
}
BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
@@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
uint32_t num_addrs{0};
- BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
+ BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
while (num_addrs < 35) { // Magic number! 250.1.1.1 - 250.1.1.35 do not collide in tried with deterministic key = 1
CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
@@ -290,7 +290,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
// Test: Sanity check, GetAddr should never return anything if addrman
// is empty.
- BOOST_CHECK_EQUAL(addrman->size(), 0U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 0U);
std::vector<CAddress> vAddr1 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
@@ -336,11 +336,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
}
std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);
- size_t percent23 = (addrman->size() * 23) / 100;
+ size_t percent23 = (addrman->Size() * 23) / 100;
BOOST_CHECK_EQUAL(vAddr.size(), percent23);
BOOST_CHECK_EQUAL(vAddr.size(), 461U);
- // (Addrman.size() < number of addresses added) due to address collisions.
- BOOST_CHECK_EQUAL(addrman->size(), 2006U);
+ // (addrman.Size() < number of addresses added) due to address collisions.
+ BOOST_CHECK_EQUAL(addrman->Size(), 2006U);
}
@@ -681,7 +681,7 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});
addrman->Good(tried1);
addrman->Good(tried2);
- BOOST_REQUIRE_EQUAL(addrman->size(), 4);
+ BOOST_REQUIRE_EQUAL(addrman->Size(), 4);
stream << *addrman;
@@ -704,14 +704,14 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
stream >> *addrman;
- BOOST_CHECK_EQUAL(addrman->size(), 2);
+ BOOST_CHECK_EQUAL(addrman->Size(), 2);
}
BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
- BOOST_CHECK(addrman->size() == 0);
+ BOOST_CHECK(addrman->Size() == 0);
// Empty addrman should return blank addrman info.
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
@@ -796,7 +796,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
- BOOST_CHECK(addrman->size() == 0);
+ BOOST_CHECK(addrman->Size() == 0);
// Empty addrman should return blank addrman info.
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
@@ -878,14 +878,14 @@ BOOST_AUTO_TEST_CASE(load_addrman)
BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false));
std::vector<CAddress> addresses{CAddress(addr1, NODE_NONE), CAddress(addr2, NODE_NONE), CAddress(addr3, NODE_NONE)};
BOOST_CHECK(addrman.Add(addresses, source));
- BOOST_CHECK(addrman.size() == 3);
+ BOOST_CHECK(addrman.Size() == 3);
// Test that the de-serialization does not throw an exception.
CDataStream ssPeers1 = AddrmanToStream(addrman);
bool exceptionThrown = false;
AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
- BOOST_CHECK(addrman1.size() == 0);
+ BOOST_CHECK(addrman1.Size() == 0);
try {
unsigned char pchMsgTmp[4];
ssPeers1 >> pchMsgTmp;
@@ -894,16 +894,16 @@ BOOST_AUTO_TEST_CASE(load_addrman)
exceptionThrown = true;
}
- BOOST_CHECK(addrman1.size() == 3);
+ BOOST_CHECK(addrman1.Size() == 3);
BOOST_CHECK(exceptionThrown == false);
// Test that ReadFromStream creates an addrman with the correct number of addrs.
CDataStream ssPeers2 = AddrmanToStream(addrman);
AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
- BOOST_CHECK(addrman2.size() == 0);
+ BOOST_CHECK(addrman2.Size() == 0);
ReadFromStream(addrman2, ssPeers2);
- BOOST_CHECK(addrman2.size() == 3);
+ BOOST_CHECK(addrman2.Size() == 3);
}
// Produce a corrupt peers.dat that claims 20 addrs when it only has one addr.
@@ -939,7 +939,7 @@ BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
CDataStream ssPeers1 = MakeCorruptPeersDat();
bool exceptionThrown = false;
AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
- BOOST_CHECK(addrman1.size() == 0);
+ BOOST_CHECK(addrman1.Size() == 0);
try {
unsigned char pchMsgTmp[4];
ssPeers1 >> pchMsgTmp;
@@ -947,15 +947,13 @@ BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
} catch (const std::exception&) {
exceptionThrown = true;
}
- // Even though de-serialization failed addrman is not left in a clean state.
- BOOST_CHECK(addrman1.size() == 1);
BOOST_CHECK(exceptionThrown);
// Test that ReadFromStream fails if peers.dat is corrupt
CDataStream ssPeers2 = MakeCorruptPeersDat();
AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
- BOOST_CHECK(addrman2.size() == 0);
+ BOOST_CHECK(addrman2.Size() == 0);
BOOST_CHECK_THROW(ReadFromStream(addrman2, ssPeers2), std::ios_base::failure);
}
@@ -969,7 +967,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
const auto start_time{Now<NodeSeconds>() - 10000s};
addr.nTime = start_time;
BOOST_CHECK(addrman->Add({addr}, source));
- BOOST_CHECK_EQUAL(addrman->size(), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// Updating an addrman entry with a different port doesn't change it
CAddress addr_diff_port{CAddress(ResolveService("250.1.1.1", 8334), NODE_NONE)};
@@ -990,4 +988,42 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
}
+BOOST_AUTO_TEST_CASE(addrman_size)
+{
+ auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
+ const CNetAddr source = ResolveIP("252.2.2.2");
+
+ // empty addrman
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 0U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 0U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 0U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 0U);
+
+ // add two ipv4 addresses, one to tried and new
+ const CAddress addr1{ResolveService("250.1.1.1", 8333), NODE_NONE};
+ BOOST_CHECK(addrman->Add({addr1}, source));
+ BOOST_CHECK(addrman->Good(addr1));
+ const CAddress addr2{ResolveService("250.1.1.2", 8333), NODE_NONE};
+ BOOST_CHECK(addrman->Add({addr2}, source));
+
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 2U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/true), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 1U);
+
+ // add one i2p address to new
+ CService i2p_addr;
+ i2p_addr.SetSpecial("UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P");
+ const CAddress addr3{i2p_addr, NODE_NONE};
+ BOOST_CHECK(addrman->Add({addr3}, source));
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 3U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/std::nullopt), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/true), 1U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 2U);
+ BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp
index a923d38467..6a37b7d83b 100644
--- a/src/test/arith_uint256_tests.cpp
+++ b/src/test/arith_uint256_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/banman_tests.cpp b/src/test/banman_tests.cpp
index ecf60834ce..cebe3629d4 100644
--- a/src/test/banman_tests.cpp
+++ b/src/test/banman_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/base32_tests.cpp b/src/test/base32_tests.cpp
index c6109dfeb0..4617beecd9 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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 249f89ae2f..601caf8102 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 <test/data/base58_encode_decode.json.h>
#include <base58.h>
+#include <test/util/json.h>
#include <test/util/setup_common.h>
#include <util/strencodings.h>
#include <util/vector.h>
@@ -16,8 +17,6 @@
using namespace std::literals;
-UniValue read_json(const std::string& jsondata);
-
BOOST_FIXTURE_TEST_SUITE(base58_tests, BasicTestingSetup)
// Goal: test low-level base58 encoding functionality
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index 54a02c6bf8..6462aa82fb 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 75b29ae0aa..fe3d8995e9 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2021 The Bitcoin Core developers
+// Copyright (c) 2013-2022 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/blockchain_tests.cpp b/src/test/blockchain_tests.cpp
index 0157e25071..b590467a43 100644
--- a/src/test/blockchain_tests.cpp
+++ b/src/test/blockchain_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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 1c13c0a909..e23b7228e7 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -310,7 +310,7 @@ BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) {
req1.indexes[2] = 3;
req1.indexes[3] = 4;
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << req1;
BlockTransactionsRequest req2;
@@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationMaxTest) {
req0.blockhash = InsecureRand256();
req0.indexes.resize(1);
req0.indexes[0] = 0xffff;
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << req0;
BlockTransactionsRequest req1;
@@ -350,7 +350,7 @@ BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationOverflowTest) {
req0.indexes[0] = 0x7000;
req0.indexes[1] = 0x10000 - 0x7000 - 2;
req0.indexes[2] = 0;
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << req0.blockhash;
WriteCompactSize(stream, req0.indexes.size());
WriteCompactSize(stream, req0.indexes[0]);
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
index 2798e998af..a572bb02b9 100644
--- a/src/test/blockfilter_index_tests.cpp
+++ b/src/test/blockfilter_index_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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 0831188327..9388b4c96a 100644
--- a/src/test/blockfilter_tests.cpp
+++ b/src/test/blockfilter_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE(blockfilter_basic_test)
// Test serialization/unserialization.
BlockFilter block_filter2;
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << block_filter;
stream >> block_filter2;
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 35c4108caa..4888041204 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "Bloom filter doesn't contain just-inserted object (3)!");
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << filter;
std::vector<uint8_t> expected = ParseHex("03614e9b050000000000000001");
@@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "Bloom filter doesn't contain just-inserted object (3)!");
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << filter;
std::vector<uint8_t> expected = ParseHex("03ce4299050000000100008001");
@@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
uint160 hash = pubkey.GetID();
filter.insert(hash);
- CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream stream{};
stream << filter;
std::vector<unsigned char> expected = ParseHex("038fc16b080000000000000001");
@@ -340,7 +340,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_3_and_serialize)
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
- CDataStream merkleStream(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream merkleStream{};
merkleStream << merkleBlock;
std::vector<uint8_t> expected = ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101");
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index 875522d744..53fbc26e15 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -194,7 +194,7 @@ static void Correct_Queue_range(std::vector<size_t> range)
BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Zero)
{
std::vector<size_t> range;
- range.push_back((size_t)0);
+ range.push_back(size_t{0});
Correct_Queue_range(range);
}
/** Test that 1 check is correct
@@ -202,7 +202,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Zero)
BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_One)
{
std::vector<size_t> range;
- range.push_back((size_t)1);
+ range.push_back(size_t{1});
Correct_Queue_range(range);
}
/** Test that MAX check is correct
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index b333a9f72d..55ecd41af1 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2021 The Bitcoin Core developers
+// Copyright (c) 2014-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -53,9 +53,9 @@ public:
uint256 GetBestBlock() const override { return hashBestBlock_; }
- bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) override
+ bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock, bool erase = true) override
{
- for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) {
+ for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = erase ? mapCoins.erase(it) : std::next(it)) {
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
// Same optimization used in CCoinsViewDB is to only write dirty entries.
map_[it->first] = it->second.coin;
@@ -64,7 +64,6 @@ public:
map_.erase(it->first);
}
}
- mapCoins.erase(it++);
}
if (!hashBlock.IsNull())
hashBestBlock_ = hashBlock;
@@ -126,13 +125,14 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
bool found_an_entry = false;
bool missed_an_entry = false;
bool uncached_an_entry = false;
+ bool flushed_without_erase = false;
// A simple map to track what we expect the cache stack to represent.
std::map<COutPoint, Coin> result;
// The cache stack.
- std::vector<CCoinsViewCacheTest*> stack; // A stack of CCoinsViewCaches on top.
- stack.push_back(new CCoinsViewCacheTest(base)); // Start with one cache.
+ std::vector<std::unique_ptr<CCoinsViewCacheTest>> stack; // A stack of CCoinsViewCaches on top.
+ stack.push_back(std::make_unique<CCoinsViewCacheTest>(base)); // Start with one cache.
// Use a limited set of random transaction ids, so we do test overwriting entries.
std::vector<uint256> txids;
@@ -154,9 +154,16 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
bool test_havecoin_after = InsecureRandBits(2) == 0;
bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false;
- const Coin& entry = (InsecureRandRange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0));
+
+ // Infrequently, test usage of AccessByTxid instead of AccessCoin - the
+ // former just delegates to the latter and returns the first unspent in a txn.
+ const Coin& entry = (InsecureRandRange(500) == 0) ?
+ AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0));
BOOST_CHECK(coin == entry);
- BOOST_CHECK(!test_havecoin_before || result_havecoin == !entry.IsSpent());
+
+ if (test_havecoin_before) {
+ BOOST_CHECK(result_havecoin == !entry.IsSpent());
+ }
if (test_havecoin_after) {
bool ret = stack.back()->HaveCoin(COutPoint(txid, 0));
@@ -167,24 +174,29 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
Coin newcoin;
newcoin.out.nValue = InsecureRand32();
newcoin.nHeight = 1;
+
+ // Infrequently test adding unspendable coins.
if (InsecureRandRange(16) == 0 && coin.IsSpent()) {
newcoin.out.scriptPubKey.assign(1 + InsecureRandBits(6), OP_RETURN);
BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable());
added_an_unspendable_entry = true;
} else {
- newcoin.out.scriptPubKey.assign(InsecureRandBits(6), 0); // Random sizes so we can test memory usage accounting
+ // Random sizes so we can test memory usage accounting
+ newcoin.out.scriptPubKey.assign(InsecureRandBits(6), 0);
(coin.IsSpent() ? added_an_entry : updated_an_entry) = true;
coin = newcoin;
}
- stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), !coin.IsSpent() || InsecureRand32() & 1);
+ bool is_overwrite = !coin.IsSpent() || InsecureRand32() & 1;
+ stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), is_overwrite);
} else {
+ // Spend the coin.
removed_an_entry = true;
coin.Clear();
BOOST_CHECK(stack.back()->SpendCoin(COutPoint(txid, 0)));
}
}
- // One every 10 iterations, remove a random entry from the cache
+ // Once every 10 iterations, remove a random entry from the cache
if (InsecureRandRange(10) == 0) {
COutPoint out(txids[InsecureRand32() % txids.size()], 0);
int cacheid = InsecureRand32() % stack.size();
@@ -206,7 +218,7 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
found_an_entry = true;
}
}
- for (const CCoinsViewCacheTest *test : stack) {
+ for (const auto& test : stack) {
test->SelfTest();
}
}
@@ -216,7 +228,9 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
if (stack.size() > 1 && InsecureRandBool() == 0) {
unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
if (fake_best_block) stack[flushIndex]->SetBestBlock(InsecureRand256());
- BOOST_CHECK(stack[flushIndex]->Flush());
+ bool should_erase = InsecureRandRange(4) < 3;
+ BOOST_CHECK(should_erase ? stack[flushIndex]->Flush() : stack[flushIndex]->Sync());
+ flushed_without_erase |= !should_erase;
}
}
if (InsecureRandRange(100) == 0) {
@@ -224,19 +238,20 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
if (stack.size() > 0 && InsecureRandBool() == 0) {
//Remove the top cache
if (fake_best_block) stack.back()->SetBestBlock(InsecureRand256());
- BOOST_CHECK(stack.back()->Flush());
- delete stack.back();
+ bool should_erase = InsecureRandRange(4) < 3;
+ BOOST_CHECK(should_erase ? stack.back()->Flush() : stack.back()->Sync());
+ flushed_without_erase |= !should_erase;
stack.pop_back();
}
if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
//Add a new cache
CCoinsView* tip = base;
if (stack.size() > 0) {
- tip = stack.back();
+ tip = stack.back().get();
} else {
removed_all_caches = true;
}
- stack.push_back(new CCoinsViewCacheTest(tip));
+ stack.push_back(std::make_unique<CCoinsViewCacheTest>(tip));
if (stack.size() == 4) {
reached_4_caches = true;
}
@@ -244,12 +259,6 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
}
}
- // Clean up the stack.
- while (stack.size() > 0) {
- delete stack.back();
- stack.pop_back();
- }
-
// Verify coverage.
BOOST_CHECK(removed_all_caches);
BOOST_CHECK(reached_4_caches);
@@ -260,6 +269,7 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
BOOST_CHECK(found_an_entry);
BOOST_CHECK(missed_an_entry);
BOOST_CHECK(uncached_an_entry);
+ BOOST_CHECK(flushed_without_erase);
}
// Run the above simulation for multiple base types.
@@ -304,8 +314,8 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
// The cache stack.
CCoinsViewTest base; // A CCoinsViewTest at the bottom.
- std::vector<CCoinsViewCacheTest*> stack; // A stack of CCoinsViewCaches on top.
- stack.push_back(new CCoinsViewCacheTest(&base)); // Start with one cache.
+ std::vector<std::unique_ptr<CCoinsViewCacheTest>> stack; // A stack of CCoinsViewCaches on top.
+ stack.push_back(std::make_unique<CCoinsViewCacheTest>(&base)); // Start with one cache.
// Track the txids we've used in various sets
std::set<COutPoint> coinbase_coins;
@@ -470,25 +480,18 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
// Every 100 iterations, change the cache stack.
if (stack.size() > 0 && InsecureRandBool() == 0) {
BOOST_CHECK(stack.back()->Flush());
- delete stack.back();
stack.pop_back();
}
if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
CCoinsView* tip = &base;
if (stack.size() > 0) {
- tip = stack.back();
+ tip = stack.back().get();
}
- stack.push_back(new CCoinsViewCacheTest(tip));
+ stack.push_back(std::make_unique<CCoinsViewCacheTest>(tip));
}
}
}
- // Clean up the stack.
- while (stack.size() > 0) {
- delete stack.back();
- stack.pop_back();
- }
-
// Verify coverage.
BOOST_CHECK(spent_a_duplicate_coinbase);
@@ -498,7 +501,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
BOOST_AUTO_TEST_CASE(ccoins_serialization)
{
// Good example
- CDataStream ss1(ParseHex("97f23c835800816115944e077fe7c803cfa57f29b36bf87c1d35"), SER_DISK, CLIENT_VERSION);
+ DataStream ss1{ParseHex("97f23c835800816115944e077fe7c803cfa57f29b36bf87c1d35")};
Coin cc1;
ss1 >> cc1;
BOOST_CHECK_EQUAL(cc1.fCoinBase, false);
@@ -507,7 +510,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))))));
// Good example
- CDataStream ss2(ParseHex("8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4"), SER_DISK, CLIENT_VERSION);
+ DataStream ss2{ParseHex("8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4")};
Coin cc2;
ss2 >> cc2;
BOOST_CHECK_EQUAL(cc2.fCoinBase, true);
@@ -516,7 +519,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"))))));
// Smallest possible example
- CDataStream ss3(ParseHex("000006"), SER_DISK, CLIENT_VERSION);
+ DataStream ss3{ParseHex("000006")};
Coin cc3;
ss3 >> cc3;
BOOST_CHECK_EQUAL(cc3.fCoinBase, false);
@@ -525,7 +528,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
BOOST_CHECK_EQUAL(cc3.out.scriptPubKey.size(), 0U);
// scriptPubKey that ends beyond the end of the stream
- CDataStream ss4(ParseHex("000007"), SER_DISK, CLIENT_VERSION);
+ DataStream ss4{ParseHex("000007")};
try {
Coin cc4;
ss4 >> cc4;
@@ -534,11 +537,11 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
}
// Very large scriptPubKey (3*10^9 bytes) past the end of the stream
- CDataStream tmp(SER_DISK, CLIENT_VERSION);
+ DataStream tmp{};
uint64_t x = 3000000000ULL;
tmp << VARINT(x);
BOOST_CHECK_EQUAL(HexStr(tmp), "8a95c0bb00");
- CDataStream ss5(ParseHex("00008a95c0bb00"), SER_DISK, CLIENT_VERSION);
+ DataStream ss5{ParseHex("00008a95c0bb00")};
try {
Coin cc5;
ss5 >> cc5;
@@ -589,9 +592,9 @@ static size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags)
return inserted.first->second.coin.DynamicMemoryUsage();
}
-void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags)
+void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags, const COutPoint& outp = OUTPOINT)
{
- auto it = map.find(OUTPOINT);
+ auto it = map.find(outp);
if (it == map.end()) {
value = ABSENT;
flags = NO_ENTRY;
@@ -877,4 +880,199 @@ BOOST_AUTO_TEST_CASE(ccoins_write)
CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags);
}
+
+Coin MakeCoin()
+{
+ Coin coin;
+ coin.out.nValue = InsecureRand32();
+ coin.nHeight = InsecureRandRange(4096);
+ coin.fCoinBase = 0;
+ return coin;
+}
+
+
+//! For CCoinsViewCache instances backed by either another cache instance or
+//! leveldb, test cache behavior and flag state (DIRTY/FRESH) by
+//!
+//! 1. Adding a random coin to the child-most cache,
+//! 2. Flushing all caches (without erasing),
+//! 3. Ensure the entry still exists in the cache and has been written to parent,
+//! 4. (if `do_erasing_flush`) Flushing the caches again (with erasing),
+//! 5. (if `do_erasing_flush`) Ensure the entry has been written to the parent and is no longer in the cache,
+//! 6. Spend the coin, ensure it no longer exists in the parent.
+//!
+void TestFlushBehavior(
+ CCoinsViewCacheTest* view,
+ CCoinsViewDB& base,
+ std::vector<std::unique_ptr<CCoinsViewCacheTest>>& all_caches,
+ bool do_erasing_flush)
+{
+ CAmount value;
+ char flags;
+ size_t cache_usage;
+
+ auto flush_all = [&all_caches](bool erase) {
+ // Flush in reverse order to ensure that flushes happen from children up.
+ for (auto i = all_caches.rbegin(); i != all_caches.rend(); ++i) {
+ auto& cache = *i;
+ // hashBlock must be filled before flushing to disk; value is
+ // unimportant here. This is normally done during connect/disconnect block.
+ cache->SetBestBlock(InsecureRand256());
+ erase ? cache->Flush() : cache->Sync();
+ }
+ };
+
+ uint256 txid = InsecureRand256();
+ COutPoint outp = COutPoint(txid, 0);
+ Coin coin = MakeCoin();
+ // Ensure the coins views haven't seen this coin before.
+ BOOST_CHECK(!base.HaveCoin(outp));
+ BOOST_CHECK(!view->HaveCoin(outp));
+
+ // --- 1. Adding a random coin to the child cache
+ //
+ view->AddCoin(outp, Coin(coin), false);
+
+ cache_usage = view->DynamicMemoryUsage();
+ // `base` shouldn't have coin (no flush yet) but `view` should have cached it.
+ BOOST_CHECK(!base.HaveCoin(outp));
+ BOOST_CHECK(view->HaveCoin(outp));
+
+ GetCoinsMapEntry(view->map(), value, flags, outp);
+ BOOST_CHECK_EQUAL(value, coin.out.nValue);
+ BOOST_CHECK_EQUAL(flags, DIRTY|FRESH);
+
+ // --- 2. Flushing all caches (without erasing)
+ //
+ flush_all(/*erase=*/ false);
+
+ // CoinsMap usage should be unchanged since we didn't erase anything.
+ BOOST_CHECK_EQUAL(cache_usage, view->DynamicMemoryUsage());
+
+ // --- 3. Ensuring the entry still exists in the cache and has been written to parent
+ //
+ GetCoinsMapEntry(view->map(), value, flags, outp);
+ BOOST_CHECK_EQUAL(value, coin.out.nValue);
+ BOOST_CHECK_EQUAL(flags, 0); // Flags should have been wiped.
+
+ // Both views should now have the coin.
+ BOOST_CHECK(base.HaveCoin(outp));
+ BOOST_CHECK(view->HaveCoin(outp));
+
+ if (do_erasing_flush) {
+ // --- 4. Flushing the caches again (with erasing)
+ //
+ flush_all(/*erase=*/ true);
+
+ // Memory usage should have gone down.
+ BOOST_CHECK(view->DynamicMemoryUsage() < cache_usage);
+
+ // --- 5. Ensuring the entry is no longer in the cache
+ //
+ GetCoinsMapEntry(view->map(), value, flags, outp);
+ BOOST_CHECK_EQUAL(value, ABSENT);
+ BOOST_CHECK_EQUAL(flags, NO_ENTRY);
+
+ view->AccessCoin(outp);
+ GetCoinsMapEntry(view->map(), value, flags, outp);
+ BOOST_CHECK_EQUAL(value, coin.out.nValue);
+ BOOST_CHECK_EQUAL(flags, 0);
+ }
+
+ // Can't overwrite an entry without specifying that an overwrite is
+ // expected.
+ BOOST_CHECK_THROW(
+ view->AddCoin(outp, Coin(coin), /*possible_overwrite=*/ false),
+ std::logic_error);
+
+ // --- 6. Spend the coin.
+ //
+ BOOST_CHECK(view->SpendCoin(outp));
+
+ // The coin should be in the cache, but spent and marked dirty.
+ GetCoinsMapEntry(view->map(), value, flags, outp);
+ BOOST_CHECK_EQUAL(value, SPENT);
+ BOOST_CHECK_EQUAL(flags, DIRTY);
+ BOOST_CHECK(!view->HaveCoin(outp)); // Coin should be considered spent in `view`.
+ BOOST_CHECK(base.HaveCoin(outp)); // But coin should still be unspent in `base`.
+
+ flush_all(/*erase=*/ false);
+
+ // Coin should be considered spent in both views.
+ BOOST_CHECK(!view->HaveCoin(outp));
+ BOOST_CHECK(!base.HaveCoin(outp));
+
+ // Spent coin should not be spendable.
+ BOOST_CHECK(!view->SpendCoin(outp));
+
+ // --- Bonus check: ensure that a coin added to the base view via one cache
+ // can be spent by another cache which has never seen it.
+ //
+ txid = InsecureRand256();
+ outp = COutPoint(txid, 0);
+ coin = MakeCoin();
+ BOOST_CHECK(!base.HaveCoin(outp));
+ BOOST_CHECK(!all_caches[0]->HaveCoin(outp));
+ BOOST_CHECK(!all_caches[1]->HaveCoin(outp));
+
+ all_caches[0]->AddCoin(outp, std::move(coin), false);
+ all_caches[0]->Sync();
+ BOOST_CHECK(base.HaveCoin(outp));
+ BOOST_CHECK(all_caches[0]->HaveCoin(outp));
+ BOOST_CHECK(!all_caches[1]->HaveCoinInCache(outp));
+
+ BOOST_CHECK(all_caches[1]->SpendCoin(outp));
+ flush_all(/*erase=*/ false);
+ BOOST_CHECK(!base.HaveCoin(outp));
+ BOOST_CHECK(!all_caches[0]->HaveCoin(outp));
+ BOOST_CHECK(!all_caches[1]->HaveCoin(outp));
+
+ flush_all(/*erase=*/ true); // Erase all cache content.
+
+ // --- Bonus check 2: ensure that a FRESH, spent coin is deleted by Sync()
+ //
+ txid = InsecureRand256();
+ outp = COutPoint(txid, 0);
+ coin = MakeCoin();
+ CAmount coin_val = coin.out.nValue;
+ BOOST_CHECK(!base.HaveCoin(outp));
+ BOOST_CHECK(!all_caches[0]->HaveCoin(outp));
+ BOOST_CHECK(!all_caches[1]->HaveCoin(outp));
+
+ // Add and spend from same cache without flushing.
+ all_caches[0]->AddCoin(outp, std::move(coin), false);
+
+ // Coin should be FRESH in the cache.
+ GetCoinsMapEntry(all_caches[0]->map(), value, flags, outp);
+ BOOST_CHECK_EQUAL(value, coin_val);
+ BOOST_CHECK_EQUAL(flags, DIRTY|FRESH);
+
+ // Base shouldn't have seen coin.
+ BOOST_CHECK(!base.HaveCoin(outp));
+
+ BOOST_CHECK(all_caches[0]->SpendCoin(outp));
+ all_caches[0]->Sync();
+
+ // Ensure there is no sign of the coin after spend/flush.
+ GetCoinsMapEntry(all_caches[0]->map(), value, flags, outp);
+ BOOST_CHECK_EQUAL(value, ABSENT);
+ BOOST_CHECK_EQUAL(flags, NO_ENTRY);
+ BOOST_CHECK(!all_caches[0]->HaveCoinInCache(outp));
+ BOOST_CHECK(!base.HaveCoin(outp));
+}
+
+BOOST_AUTO_TEST_CASE(ccoins_flush_behavior)
+{
+ // Create two in-memory caches atop a leveldb view.
+ CCoinsViewDB base{"test", /*nCacheSize=*/ 1 << 23, /*fMemory=*/ true, /*fWipe=*/ false};
+ std::vector<std::unique_ptr<CCoinsViewCacheTest>> caches;
+ caches.push_back(std::make_unique<CCoinsViewCacheTest>(&base));
+ caches.push_back(std::make_unique<CCoinsViewCacheTest>(caches.back().get()));
+
+ for (const auto& view : caches) {
+ TestFlushBehavior(view.get(), base, caches, /*do_erasing_flush=*/false);
+ TestFlushBehavior(view.get(), base, caches, /*do_erasing_flush=*/true);
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/coinstatsindex_tests.cpp b/src/test/coinstatsindex_tests.cpp
index 8a2b0792fd..503a58076b 100644
--- a/src/test/coinstatsindex_tests.cpp
+++ b/src/test/coinstatsindex_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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 6148edf115..d3eef7beb7 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -723,14 +723,14 @@ BOOST_AUTO_TEST_CASE(countbits_tests)
// Check handling of zero.
BOOST_CHECK_EQUAL(CountBits(0), 0U);
} else if (i < 10) {
- for (uint64_t j = (uint64_t)1 << (i - 1); (j >> i) == 0; ++j) {
+ for (uint64_t j = uint64_t{1} << (i - 1); (j >> i) == 0; ++j) {
// Exhaustively test up to 10 bits
BOOST_CHECK_EQUAL(CountBits(j), i);
}
} else {
for (int k = 0; k < 1000; k++) {
// Randomly test 1000 samples of each length above 10 bits.
- uint64_t j = ((uint64_t)1) << (i - 1) | ctx.randbits(i - 1);
+ uint64_t j = (uint64_t{1}) << (i - 1) | ctx.randbits(i - 1);
BOOST_CHECK_EQUAL(CountBits(j), i);
}
}
@@ -925,7 +925,7 @@ BOOST_AUTO_TEST_CASE(muhash_tests)
// Test MuHash3072 serialization
MuHash3072 serchk = FromInt(1); serchk *= FromInt(2);
std::string ser_exp = "1fa093295ea30a6a3acdc7b3f770fa538eff537528e990e2910e40bbcfd7f6696b1256901929094694b56316de342f593303dd12ac43e06dce1be1ff8301c845beb15468fff0ef002dbf80c29f26e6452bccc91b5cb9437ad410d2a67ea847887fa3c6a6553309946880fe20db2c73fe0641adbd4e86edfee0d9f8cd0ee1230898873dc13ed8ddcaf045c80faa082774279007a2253f8922ee3ef361d378a6af3ddaf180b190ac97e556888c36b3d1fb1c85aab9ccd46e3deaeb7b7cf5db067a7e9ff86b658cf3acd6662bbcce37232daa753c48b794356c020090c831a8304416e2aa7ad633c0ddb2f11be1be316a81be7f7e472071c042cb68faef549c221ebff209273638b741aba5a81675c45a5fa92fea4ca821d7a324cb1e1a2ccd3b76c4228ec8066dad2a5df6e1bd0de45c7dd5de8070bdb46db6c554cf9aefc9b7b2bbf9f75b1864d9f95005314593905c0109b71f703d49944ae94477b51dac10a816bb6d1c700bafabc8bd86fac8df24be519a2f2836b16392e18036cb13e48c5c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
- CDataStream ss_chk(SER_DISK, PROTOCOL_VERSION);
+ DataStream ss_chk{};
ss_chk << serchk;
BOOST_CHECK_EQUAL(ser_exp, HexStr(ss_chk.str()));
@@ -938,7 +938,7 @@ BOOST_AUTO_TEST_CASE(muhash_tests)
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);
+ DataStream ss_max{ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")};
MuHash3072 overflowchk;
ss_max >> overflowchk;
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index ab4c587c46..7ad123754b 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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 <dbwrapper.h>
#include <test/util/setup_common.h>
#include <uint256.h>
+#include <util/string.h>
#include <memory>
@@ -324,12 +325,6 @@ struct StringContentsSerializer {
StringContentsSerializer() = default;
explicit StringContentsSerializer(const std::string& inp) : str(inp) {}
- StringContentsSerializer& operator+=(const std::string& s) {
- str += s;
- return *this;
- }
- StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; }
-
template<typename Stream>
void Serialize(Stream& s) const
{
@@ -343,44 +338,34 @@ struct StringContentsSerializer {
{
str.clear();
uint8_t c{0};
- while (true) {
- try {
- s >> c;
- str.push_back(c);
- } catch (const std::ios_base::failure&) {
- break;
- }
+ while (!s.eof()) {
+ s >> c;
+ str.push_back(c);
}
}
};
BOOST_AUTO_TEST_CASE(iterator_string_ordering)
{
- char buf[10];
-
fs::path ph = m_args.GetDataDirBase() / "iterator_string_ordering";
CDBWrapper dbw(ph, (1 << 20), true, false, false);
- for (int x=0x00; x<10; ++x) {
- for (int y = 0; y < 10; y++) {
- snprintf(buf, sizeof(buf), "%d", x);
- StringContentsSerializer key(buf);
- for (int z = 0; z < y; z++)
+ for (int x = 0; x < 10; ++x) {
+ for (int y = 0; y < 10; ++y) {
+ std::string key{ToString(x)};
+ for (int z = 0; z < y; ++z)
key += key;
uint32_t value = x*x;
- BOOST_CHECK(dbw.Write(key, value));
+ BOOST_CHECK(dbw.Write(StringContentsSerializer{key}, value));
}
}
std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
for (const int seek_start : {0, 5}) {
- snprintf(buf, sizeof(buf), "%d", seek_start);
- StringContentsSerializer seek_key(buf);
- it->Seek(seek_key);
- for (unsigned int x=seek_start; x<10; ++x) {
- for (int y = 0; y < 10; y++) {
- snprintf(buf, sizeof(buf), "%d", x);
- std::string exp_key(buf);
- for (int z = 0; z < y; z++)
+ it->Seek(StringContentsSerializer{ToString(seek_start)});
+ for (unsigned int x = seek_start; x < 10; ++x) {
+ for (int y = 0; y < 10; ++y) {
+ std::string exp_key{ToString(x)};
+ for (int z = 0; z < y; ++z)
exp_key += exp_key;
StringContentsSerializer key;
uint32_t value;
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index 7150698e64..aca2b8eff0 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index 6b2ef74e19..6e4f6cdbab 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/flatfile_tests.cpp b/src/test/flatfile_tests.cpp
index 605faa08e4..9931d19c2b 100644
--- a/src/test/flatfile_tests.cpp
+++ b/src/test/flatfile_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/fs_tests.cpp b/src/test/fs_tests.cpp
index d2554483d4..7e7d630daa 100644
--- a/src/test/fs_tests.cpp
+++ b/src/test/fs_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp
index 372c1a370e..7b84bfda20 100644
--- a/src/test/fuzz/addition_overflow.cpp
+++ b/src/test/fuzz/addition_overflow.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/addrman.cpp b/src/test/fuzz/addrman.cpp
index f3c29cd6b8..a59e41dbb5 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -117,7 +117,7 @@ void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
const std::chrono::seconds time_penalty{fast_random_context.randrange(100000001)};
addrman.Add({addr}, source, time_penalty);
- if (n > 0 && addrman.size() % n == 0) {
+ if (n > 0 && addrman.Size() % n == 0) {
addrman.Good(addr, Now<NodeSeconds>());
}
@@ -304,7 +304,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
/*max_pct=*/fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096),
/*network=*/std::nullopt);
(void)const_addr_man.Select(fuzzed_data_provider.ConsumeBool());
- (void)const_addr_man.size();
+ (void)const_addr_man.Size();
CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION);
data_stream << const_addr_man;
}
diff --git a/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp
index 1a8957d090..a7b41370a8 100644
--- a/src/test/fuzz/autofile.cpp
+++ b/src/test/fuzz/autofile.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/banman.cpp b/src/test/fuzz/banman.cpp
index d10f4586b4..273dcfd850 100644
--- a/src/test/fuzz/banman.cpp
+++ b/src/test/fuzz/banman.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/base_encode_decode.cpp b/src/test/fuzz/base_encode_decode.cpp
index 48356065b0..d322416d34 100644
--- a/src/test/fuzz/base_encode_decode.cpp
+++ b/src/test/fuzz/base_encode_decode.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,12 +14,7 @@
#include <string>
#include <vector>
-void initialize_base_encode_decode()
-{
- static const ECCVerifyHandle verify_handle;
-}
-
-FUZZ_TARGET_INIT(base_encode_decode, initialize_base_encode_decode)
+FUZZ_TARGET(base_encode_decode)
{
const std::string random_encoded_string(buffer.begin(), buffer.end());
diff --git a/src/test/fuzz/block.cpp b/src/test/fuzz/block.cpp
index b7ed2c6abd..c3e17724eb 100644
--- a/src/test/fuzz/block.cpp
+++ b/src/test/fuzz/block.cpp
@@ -19,7 +19,6 @@
void initialize_block()
{
- static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
diff --git a/src/test/fuzz/buffered_file.cpp b/src/test/fuzz/buffered_file.cpp
index a8c3318629..67cac8fa4e 100644
--- a/src/test/fuzz/buffered_file.cpp
+++ b/src/test/fuzz/buffered_file.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/chain.cpp b/src/test/fuzz/chain.cpp
index 01edb06138..49b9898228 100644
--- a/src/test/fuzz/chain.cpp
+++ b/src/test/fuzz/chain.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/checkqueue.cpp b/src/test/fuzz/checkqueue.cpp
index 7d107995aa..6256aefaa3 100644
--- a/src/test/fuzz/checkqueue.cpp
+++ b/src/test/fuzz/checkqueue.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index 6c96702f1e..e75dc3ce91 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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,6 +75,9 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
(void)coins_view_cache.Flush();
},
[&] {
+ (void)coins_view_cache.Sync();
+ },
+ [&] {
coins_view_cache.SetBestBlock(ConsumeUInt256(fuzzed_data_provider));
},
[&] {
diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp
index e8b10a0ad0..798c14030c 100644
--- a/src/test/fuzz/connman.cpp
+++ b/src/test/fuzz/connman.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp
index f5f86a574a..1f5601ca9f 100644
--- a/src/test/fuzz/descriptor_parse.cpp
+++ b/src/test/fuzz/descriptor_parse.cpp
@@ -9,7 +9,6 @@
void initialize_descriptor_parse()
{
- static const ECCVerifyHandle verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::MAIN);
}
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index 0a7d0c55bd..7cd78e0461 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -46,9 +46,6 @@ void initialize_deserialize()
{
static const auto testing_setup = MakeNoLogFileContext<>();
g_setup = testing_setup.get();
-
- // Fuzzers using pubkey must hold an ECCVerifyHandle.
- static const ECCVerifyHandle verify_handle;
}
#define FUZZ_TARGET_DESERIALIZE(name, code) \
diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp
index e7c49c2dbc..d762676c3c 100644
--- a/src/test/fuzz/eval_script.cpp
+++ b/src/test/fuzz/eval_script.cpp
@@ -9,12 +9,7 @@
#include <limits>
-void initialize_eval_script()
-{
- static const ECCVerifyHandle verify_handle;
-}
-
-FUZZ_TARGET_INIT(eval_script, initialize_eval_script)
+FUZZ_TARGET(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/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index 24ae34bd9e..9683f32d84 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/golomb_rice.cpp b/src/test/fuzz/golomb_rice.cpp
index b4bb4c6dc6..1a1225b635 100644
--- a/src/test/fuzz/golomb_rice.cpp
+++ b/src/test/fuzz/golomb_rice.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/hex.cpp b/src/test/fuzz/hex.cpp
index e637975b48..f67b820d11 100644
--- a/src/test/fuzz/hex.cpp
+++ b/src/test/fuzz/hex.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-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.
@@ -16,12 +16,7 @@
#include <string>
#include <vector>
-void initialize_hex()
-{
- static const ECCVerifyHandle verify_handle;
-}
-
-FUZZ_TARGET_INIT(hex, initialize_hex)
+FUZZ_TARGET(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 0fe18abaa9..66a1ff945f 100644
--- a/src/test/fuzz/http_request.cpp
+++ b/src/test/fuzz/http_request.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/i2p.cpp b/src/test/fuzz/i2p.cpp
index 72b7f9e334..6c2321cd68 100644
--- a/src/test/fuzz/i2p.cpp
+++ b/src/test/fuzz/i2p.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/integer.cpp b/src/test/fuzz/integer.cpp
index f05248ab47..c0aefe6067 100644
--- a/src/test/fuzz/integer.cpp
+++ b/src/test/fuzz/integer.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -152,7 +152,7 @@ FUZZ_TARGET_INIT(integer, initialize_integer)
const CScriptID script_id{u160};
{
- CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+ DataStream stream{};
uint256 deserialized_u256;
stream << u256;
@@ -217,7 +217,7 @@ FUZZ_TARGET_INIT(integer, initialize_integer)
}
{
- CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+ DataStream stream{};
ser_writedata64(stream, u64);
const uint64_t deserialized_u64 = ser_readdata64(stream);
@@ -245,7 +245,7 @@ FUZZ_TARGET_INIT(integer, initialize_integer)
}
{
- CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+ DataStream stream{};
WriteCompactSize(stream, u64);
try {
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index a76901e473..ea6883c08d 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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,7 +27,6 @@
void initialize_key()
{
- static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
@@ -112,7 +111,7 @@ FUZZ_TARGET_INIT(key, initialize_key)
}
{
- CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
+ DataStream data_stream{};
pubkey.Serialize(data_stream);
CPubKey pubkey_deserialized;
diff --git a/src/test/fuzz/key_io.cpp b/src/test/fuzz/key_io.cpp
index 32a81c2e17..29c6996365 100644
--- a/src/test/fuzz/key_io.cpp
+++ b/src/test/fuzz/key_io.cpp
@@ -13,7 +13,6 @@
void initialize_key_io()
{
- static const ECCVerifyHandle verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::MAIN);
}
diff --git a/src/test/fuzz/message.cpp b/src/test/fuzz/message.cpp
index 06cd0afe2a..63e24aacdd 100644
--- a/src/test/fuzz/message.cpp
+++ b/src/test/fuzz/message.cpp
@@ -18,7 +18,6 @@
void initialize_message()
{
- static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
diff --git a/src/test/fuzz/miniscript.cpp b/src/test/fuzz/miniscript.cpp
index 6be75322b4..d5667e0cf3 100644
--- a/src/test/fuzz/miniscript.cpp
+++ b/src/test/fuzz/miniscript.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -104,7 +104,7 @@ struct ScriptParserContext {
return key.data;
}
- const std::vector<unsigned char> ToPKHBytes(const Key& key) const
+ std::vector<unsigned char> ToPKHBytes(const Key& key) const
{
if (key.is_hash) return key.data;
const auto h = Hash160(key.data);
diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp
index 9f7c87dcd5..13b4638688 100644
--- a/src/test/fuzz/net.cpp
+++ b/src/test/fuzz/net.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/net_permissions.cpp b/src/test/fuzz/net_permissions.cpp
index 21a6640ef4..ae343602e9 100644
--- a/src/test/fuzz/net_permissions.cpp
+++ b/src/test/fuzz/net_permissions.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/netaddress.cpp b/src/test/fuzz/netaddress.cpp
index 2022f16a48..d61aef6d81 100644
--- a/src/test/fuzz/netaddress.cpp
+++ b/src/test/fuzz/netaddress.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/netbase_dns_lookup.cpp b/src/test/fuzz/netbase_dns_lookup.cpp
index 39d4935126..81e216b358 100644
--- a/src/test/fuzz/netbase_dns_lookup.cpp
+++ b/src/test/fuzz/netbase_dns_lookup.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/node_eviction.cpp b/src/test/fuzz/node_eviction.cpp
index 0f204babfa..e47432600c 100644
--- a/src/test/fuzz/node_eviction.cpp
+++ b/src/test/fuzz/node_eviction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/p2p_transport_serialization.cpp b/src/test/fuzz/p2p_transport_serialization.cpp
index 88c22ca305..96254aa222 100644
--- a/src/test/fuzz/p2p_transport_serialization.cpp
+++ b/src/test/fuzz/p2p_transport_serialization.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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,7 +24,7 @@ void initialize_p2p_transport_serialization()
FUZZ_TARGET_INIT(p2p_transport_serialization, initialize_p2p_transport_serialization)
{
// Construct deserializer, with a dummy NodeId
- V1TransportDeserializer deserializer{Params(), (NodeId)0, SER_NETWORK, INIT_PROTO_VERSION};
+ V1TransportDeserializer deserializer{Params(), NodeId{0}, SER_NETWORK, INIT_PROTO_VERSION};
V1TransportSerializer serializer{};
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp
index 0cc210f26f..16486f6b96 100644
--- a/src/test/fuzz/parse_univalue.cpp
+++ b/src/test/fuzz/parse_univalue.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,6 @@
void initialize_parse_univalue()
{
- static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
diff --git a/src/test/fuzz/partially_downloaded_block.cpp b/src/test/fuzz/partially_downloaded_block.cpp
new file mode 100644
index 0000000000..f8ba4f08d9
--- /dev/null
+++ b/src/test/fuzz/partially_downloaded_block.cpp
@@ -0,0 +1,142 @@
+#include <blockencodings.h>
+#include <consensus/merkle.h>
+#include <consensus/validation.h>
+#include <primitives/block.h>
+#include <primitives/transaction.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <test/fuzz/util/mempool.h>
+#include <test/util/setup_common.h>
+#include <test/util/txmempool.h>
+#include <txmempool.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <memory>
+#include <optional>
+#include <set>
+#include <vector>
+
+namespace {
+const TestingSetup* g_setup;
+} // namespace
+
+void initialize_pdb()
+{
+ static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
+ g_setup = testing_setup.get();
+}
+
+PartiallyDownloadedBlock::CheckBlockFn FuzzedCheckBlock(std::optional<BlockValidationResult> result)
+{
+ return [result](const CBlock&, BlockValidationState& state, const Consensus::Params&, bool, bool) {
+ if (result) {
+ return state.Invalid(*result);
+ }
+
+ return true;
+ };
+}
+
+FUZZ_TARGET_INIT(partially_downloaded_block, initialize_pdb)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+
+ auto block{ConsumeDeserializable<CBlock>(fuzzed_data_provider)};
+ if (!block || block->vtx.size() == 0 ||
+ block->vtx.size() >= std::numeric_limits<uint16_t>::max()) {
+ return;
+ }
+
+ CBlockHeaderAndShortTxIDs cmpctblock{*block};
+
+ CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node)};
+ PartiallyDownloadedBlock pdb{&pool};
+
+ // Set of available transactions (mempool or extra_txn)
+ std::set<uint16_t> available;
+ // The coinbase is always available
+ available.insert(0);
+
+ std::vector<std::pair<uint256, CTransactionRef>> extra_txn;
+ for (size_t i = 1; i < block->vtx.size(); ++i) {
+ auto tx{block->vtx[i]};
+
+ bool add_to_extra_txn{fuzzed_data_provider.ConsumeBool()};
+ bool add_to_mempool{fuzzed_data_provider.ConsumeBool()};
+
+ if (add_to_extra_txn) {
+ extra_txn.emplace_back(tx->GetWitnessHash(), tx);
+ available.insert(i);
+ }
+
+ if (add_to_mempool) {
+ LOCK2(cs_main, pool.cs);
+ pool.addUnchecked(ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
+ available.insert(i);
+ }
+ }
+
+ auto init_status{pdb.InitData(cmpctblock, extra_txn)};
+
+ std::vector<CTransactionRef> missing;
+ // Whether we skipped a transaction that should be included in `missing`.
+ // FillBlock should never return READ_STATUS_OK if that is the case.
+ bool skipped_missing{false};
+ for (size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
+ // If init_status == READ_STATUS_OK then a available transaction in the
+ // compact block (i.e. IsTxAvailable(i) == true) implies that we marked
+ // that transaction as available above (i.e. available.count(i) > 0).
+ // The reverse is not true, due to possible compact block short id
+ // collisions (i.e. available.count(i) > 0 does not imply
+ // IsTxAvailable(i) == true).
+ if (init_status == READ_STATUS_OK) {
+ assert(!pdb.IsTxAvailable(i) || available.count(i) > 0);
+ }
+
+ bool skip{fuzzed_data_provider.ConsumeBool()};
+ if (!pdb.IsTxAvailable(i) && !skip) {
+ missing.push_back(block->vtx[i]);
+ }
+
+ skipped_missing |= (!pdb.IsTxAvailable(i) && skip);
+ }
+
+ // Mock CheckBlock
+ bool fail_check_block{fuzzed_data_provider.ConsumeBool()};
+ auto validation_result =
+ fuzzed_data_provider.PickValueInArray(
+ {BlockValidationResult::BLOCK_RESULT_UNSET,
+ BlockValidationResult::BLOCK_CONSENSUS,
+ BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE,
+ BlockValidationResult::BLOCK_CACHED_INVALID,
+ BlockValidationResult::BLOCK_INVALID_HEADER,
+ BlockValidationResult::BLOCK_MUTATED,
+ BlockValidationResult::BLOCK_MISSING_PREV,
+ BlockValidationResult::BLOCK_INVALID_PREV,
+ BlockValidationResult::BLOCK_TIME_FUTURE,
+ BlockValidationResult::BLOCK_CHECKPOINT,
+ BlockValidationResult::BLOCK_HEADER_LOW_WORK});
+ pdb.m_check_block_mock = FuzzedCheckBlock(
+ fail_check_block ?
+ std::optional<BlockValidationResult>{validation_result} :
+ std::nullopt);
+
+ CBlock reconstructed_block;
+ auto fill_status{pdb.FillBlock(reconstructed_block, missing)};
+ switch (fill_status) {
+ case READ_STATUS_OK:
+ assert(!skipped_missing);
+ assert(!fail_check_block);
+ assert(block->GetHash() == reconstructed_block.GetHash());
+ break;
+ case READ_STATUS_CHECKBLOCK_FAILED: [[fallthrough]];
+ case READ_STATUS_FAILED:
+ assert(fail_check_block);
+ break;
+ case READ_STATUS_INVALID:
+ break;
+ }
+}
diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp
index 17c340695f..116fbd9015 100644
--- a/src/test/fuzz/policy_estimator.cpp
+++ b/src/test/fuzz/policy_estimator.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/policy_estimator_io.cpp b/src/test/fuzz/policy_estimator_io.cpp
index 436873c955..7c3289cd26 100644
--- a/src/test/fuzz/policy_estimator_io.cpp
+++ b/src/test/fuzz/policy_estimator_io.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/pow.cpp b/src/test/fuzz/pow.cpp
index 82fac8b9ee..e5a3a6e68a 100644
--- a/src/test/fuzz/pow.cpp
+++ b/src/test/fuzz/pow.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -26,7 +26,7 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const Consensus::Params& consensus_params = Params().GetConsensus();
- std::vector<CBlockIndex> blocks;
+ std::vector<std::unique_ptr<CBlockIndex>> blocks;
const uint32_t fixed_time = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
const uint32_t fixed_bits = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 10000) {
@@ -34,9 +34,10 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
if (!block_header) {
continue;
}
- CBlockIndex current_block{*block_header};
+ CBlockIndex& current_block{
+ *blocks.emplace_back(std::make_unique<CBlockIndex>(*block_header))};
{
- CBlockIndex* previous_block = blocks.empty() ? nullptr : &PickValue(fuzzed_data_provider, blocks);
+ CBlockIndex* previous_block = blocks.empty() ? nullptr : PickValue(fuzzed_data_provider, blocks).get();
const int current_height = (previous_block != nullptr && previous_block->nHeight != std::numeric_limits<int>::max()) ? previous_block->nHeight + 1 : 0;
if (fuzzed_data_provider.ConsumeBool()) {
current_block.pprev = previous_block;
@@ -58,7 +59,6 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
} else {
current_block.nChainWork = ConsumeArithUInt256(fuzzed_data_provider);
}
- blocks.push_back(current_block);
}
{
(void)GetBlockProof(current_block);
@@ -68,9 +68,9 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
}
}
{
- const CBlockIndex* to = &PickValue(fuzzed_data_provider, blocks);
- const CBlockIndex* from = &PickValue(fuzzed_data_provider, blocks);
- const CBlockIndex* tip = &PickValue(fuzzed_data_provider, blocks);
+ const auto& to = PickValue(fuzzed_data_provider, blocks);
+ const auto& from = PickValue(fuzzed_data_provider, blocks);
+ const auto& tip = PickValue(fuzzed_data_provider, blocks);
try {
(void)GetBlockProofEquivalentTime(*to, *from, *tip, consensus_params);
} catch (const uint_error&) {
diff --git a/src/test/fuzz/prevector.cpp b/src/test/fuzz/prevector.cpp
index e2d65a4796..9cea32e304 100644
--- a/src/test/fuzz/prevector.cpp
+++ b/src/test/fuzz/prevector.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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,8 +59,8 @@ public:
--pos;
assert(v == real_vector[pos]);
}
- CDataStream ss1(SER_DISK, 0);
- CDataStream ss2(SER_DISK, 0);
+ DataStream ss1{};
+ DataStream ss2{};
ss1 << real_vector;
ss2 << pre_vector;
assert(ss1.size() == ss2.size());
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index f6000535b3..0a7924f226 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -56,7 +56,9 @@ void initialize_process_message()
{
Assert(GetNumMsgTypes() == getAllNetMessageTypes().size()); // If this fails, add or remove the message type below
- static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
+ static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(
+ /*chain_name=*/CBaseChainParams::REGTEST,
+ /*extra_args=*/{"-txreconciliation"});
g_setup = testing_setup.get();
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
MineBlock(g_setup->m_node, CScript() << OP_TRUE);
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
index 41831fd176..96339743ba 100644
--- a/src/test/fuzz/process_messages.cpp
+++ b/src/test/fuzz/process_messages.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -23,7 +23,9 @@ const TestingSetup* g_setup;
void initialize_process_messages()
{
- static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
+ static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(
+ /*chain_name=*/CBaseChainParams::REGTEST,
+ /*extra_args=*/{"-txreconciliation"});
g_setup = testing_setup.get();
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
MineBlock(g_setup->m_node, CScript() << OP_TRUE);
diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp
index baa64bba0f..825ed67ec1 100644
--- a/src/test/fuzz/psbt.cpp
+++ b/src/test/fuzz/psbt.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -22,12 +22,7 @@ using node::AnalyzePSBT;
using node::PSBTAnalysis;
using node::PSBTInputAnalysis;
-void initialize_psbt()
-{
- static const ECCVerifyHandle verify_handle;
-}
-
-FUZZ_TARGET_INIT(psbt, initialize_psbt)
+FUZZ_TARGET(psbt)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
PartiallySignedTransaction psbt_mut;
diff --git a/src/test/fuzz/rbf.cpp b/src/test/fuzz/rbf.cpp
index 678fc7a5aa..57a9a15a85 100644
--- a/src/test/fuzz/rbf.cpp
+++ b/src/test/fuzz/rbf.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/rpc.cpp b/src/test/fuzz/rpc.cpp
index f32046e69f..2578137471 100644
--- a/src/test/fuzz/rpc.cpp
+++ b/src/test/fuzz/rpc.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -253,7 +253,7 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
if (!opt_block_header) {
return;
}
- CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
+ DataStream data_stream{};
data_stream << *opt_block_header;
r = HexStr(data_stream);
},
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index 00d7b7e29a..1037dd934a 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -32,9 +32,6 @@
void initialize_script()
{
- // Fuzzers using pubkey must hold an ECCVerifyHandle.
- static const ECCVerifyHandle verify_handle;
-
SelectParams(CBaseChainParams::REGTEST);
}
diff --git a/src/test/fuzz/script_assets_test_minimizer.cpp b/src/test/fuzz/script_assets_test_minimizer.cpp
index 35d7246ed8..206d219afe 100644
--- a/src/test/fuzz/script_assets_test_minimizer.cpp
+++ b/src/test/fuzz/script_assets_test_minimizer.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -184,10 +184,7 @@ void Test(const std::string& str)
}
}
-void test_init()
-{
- static ECCVerifyHandle handle;
-}
+void test_init() {}
FUZZ_TARGET_INIT_HIDDEN(script_assets_test_minimizer, test_init, /*hidden=*/true)
{
diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp
index 8dc99ee069..f8594fc233 100644
--- a/src/test/fuzz/script_flags.cpp
+++ b/src/test/fuzz/script_flags.cpp
@@ -11,12 +11,7 @@
#include <test/fuzz/fuzz.h>
-void initialize_script_flags()
-{
- static const ECCVerifyHandle verify_handle;
-}
-
-FUZZ_TARGET_INIT(script_flags, initialize_script_flags)
+FUZZ_TARGET(script_flags)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
diff --git a/src/test/fuzz/script_sigcache.cpp b/src/test/fuzz/script_sigcache.cpp
index f6af7947df..de895cc69c 100644
--- a/src/test/fuzz/script_sigcache.cpp
+++ b/src/test/fuzz/script_sigcache.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/script_sign.cpp b/src/test/fuzz/script_sign.cpp
index 3ddb30d870..3cef81c251 100644
--- a/src/test/fuzz/script_sign.cpp
+++ b/src/test/fuzz/script_sign.cpp
@@ -26,7 +26,6 @@
void initialize_script_sign()
{
- static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
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 f437d53b57..74ef6bfd4e 100644
--- a/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
+++ b/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
@@ -12,7 +12,7 @@
#include <vector>
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);
+int ecdsa_signature_parse_der_lax(secp256k1_ecdsa_signature* sig, const unsigned char* input, size_t inputlen);
FUZZ_TARGET(secp256k1_ecdsa_signature_parse_der_lax)
{
@@ -21,13 +21,11 @@ FUZZ_TARGET(secp256k1_ecdsa_signature_parse_der_lax)
if (signature_bytes.data() == nullptr) {
return;
}
- secp256k1_context* secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
secp256k1_ecdsa_signature sig_der_lax;
- const bool parsed_der_lax = ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig_der_lax, signature_bytes.data(), signature_bytes.size()) == 1;
+ const bool parsed_der_lax = ecdsa_signature_parse_der_lax(&sig_der_lax, signature_bytes.data(), signature_bytes.size()) == 1;
if (parsed_der_lax) {
ECC_Start();
(void)SigHasLowR(&sig_der_lax);
ECC_Stop();
}
- secp256k1_context_destroy(secp256k1_context_verify);
}
diff --git a/src/test/fuzz/signature_checker.cpp b/src/test/fuzz/signature_checker.cpp
index a585680de1..59f4792961 100644
--- a/src/test/fuzz/signature_checker.cpp
+++ b/src/test/fuzz/signature_checker.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,11 +14,6 @@
#include <string>
#include <vector>
-void initialize_signature_checker()
-{
- static const auto verify_handle = std::make_unique<ECCVerifyHandle>();
-}
-
namespace {
class FuzzedSignatureChecker : public BaseSignatureChecker
{
@@ -53,7 +48,7 @@ public:
};
} // namespace
-FUZZ_TARGET_INIT(signature_checker, initialize_signature_checker)
+FUZZ_TARGET(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/socks5.cpp b/src/test/fuzz/socks5.cpp
index 15f479b009..97f643db49 100644
--- a/src/test/fuzz/socks5.cpp
+++ b/src/test/fuzz/socks5.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/string.cpp b/src/test/fuzz/string.cpp
index f6373351d8..9890e4c0e5 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -196,7 +196,7 @@ FUZZ_TARGET(string)
}
{
- CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
+ DataStream data_stream{};
std::string s;
auto limited_string = LIMITED_STRING(s, 10);
data_stream << random_string_1;
@@ -212,7 +212,7 @@ FUZZ_TARGET(string)
}
}
{
- CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
+ DataStream data_stream{};
const auto limited_string = LIMITED_STRING(random_string_1, 10);
data_stream << limited_string;
std::string deserialized_string;
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index 7fa4523800..bacb178b44 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/tx_in.cpp b/src/test/fuzz/tx_in.cpp
index f8247c1fa4..fc16f80cde 100644
--- a/src/test/fuzz/tx_in.cpp
+++ b/src/test/fuzz/tx_in.cpp
@@ -14,12 +14,9 @@
FUZZ_TARGET(tx_in)
{
- CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ DataStream ds{buffer};
CTxIn tx_in;
try {
- int version;
- ds >> version;
- ds.SetVersion(version);
ds >> tx_in;
} catch (const std::ios_base::failure&) {
return;
diff --git a/src/test/fuzz/tx_out.cpp b/src/test/fuzz/tx_out.cpp
index a2421ff582..806216fbf5 100644
--- a/src/test/fuzz/tx_out.cpp
+++ b/src/test/fuzz/tx_out.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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,12 +13,9 @@
FUZZ_TARGET(tx_out)
{
- CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ DataStream ds{buffer};
CTxOut tx_out;
try {
- int version;
- ds >> version;
- ds.SetVersion(version);
ds >> tx_out;
} catch (const std::ios_base::failure&) {
return;
diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp
index 46ca8e47e9..0cabaf323b 100644
--- a/src/test/fuzz/tx_pool.cpp
+++ b/src/test/fuzz/tx_pool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -211,7 +211,7 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
for (int i = 0; i < num_out; ++i) {
tx_mut.vout.emplace_back(amount_out, P2WSH_OP_TRUE);
}
- const auto tx = MakeTransactionRef(tx_mut);
+ auto tx = MakeTransactionRef(tx_mut);
// Restore previously removed outpoints
for (const auto& in : tx->vin) {
Assert(outpoints_rbf.insert(in.prevout).second);
@@ -311,7 +311,7 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const auto& node = g_setup->m_node;
- auto& chainstate = node.chainman->ActiveChainstate();
+ auto& chainstate{static_cast<DummyChainState&>(node.chainman->ActiveChainstate())};
MockTime(fuzzed_data_provider, chainstate);
@@ -329,6 +329,8 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
+ chainstate.SetMempool(&tx_pool);
+
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300)
{
const auto mut_tx = ConsumeTransaction(fuzzed_data_provider, txids);
diff --git a/src/test/fuzz/txorphan.cpp b/src/test/fuzz/txorphan.cpp
index 02743051e8..ed55e3fad5 100644
--- a/src/test/fuzz/txorphan.cpp
+++ b/src/test/fuzz/txorphan.cpp
@@ -69,7 +69,7 @@ FUZZ_TARGET_INIT(txorphan, initialize_orphanage)
for (auto& in : tx_mut.vin) {
outpoints.push_back(in.prevout);
}
- const auto new_tx = MakeTransactionRef(tx_mut);
+ auto new_tx = MakeTransactionRef(tx_mut);
// add newly constructed transaction to outpoints
for (uint32_t i = 0; i < num_out; i++) {
outpoints.emplace_back(new_tx->GetHash(), i);
@@ -85,16 +85,12 @@ FUZZ_TARGET_INIT(txorphan, initialize_orphanage)
CallOneOf(
fuzzed_data_provider,
[&] {
- orphanage.AddChildrenToWorkSet(*tx, peer_id);
+ orphanage.AddChildrenToWorkSet(*tx);
},
[&] {
{
- NodeId originator;
- bool more = true;
- CTransactionRef ref = orphanage.GetTxToReconsider(peer_id, originator, more);
- if (!ref) {
- Assert(!more);
- } else {
+ CTransactionRef ref = orphanage.GetTxToReconsider(peer_id);
+ if (ref) {
bool have_tx = orphanage.HaveTx(GenTxid::Txid(ref->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(ref->GetHash()));
Assert(have_tx);
}
diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp
index 8babfadf4f..9da84fe90e 100644
--- a/src/test/fuzz/util.cpp
+++ b/src/test/fuzz/util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/util.h b/src/test/fuzz/util.h
index 09c57c7be3..c14f633029 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -47,7 +47,7 @@ size_t CallOneOf(FuzzedDataProvider& fuzzed_data_provider, Callables... callable
template <typename Collection>
auto& PickValue(FuzzedDataProvider& fuzzed_data_provider, Collection& col)
{
- const auto sz = col.size();
+ auto sz{col.size()};
assert(sz >= 1);
auto it = col.begin();
std::advance(it, fuzzed_data_provider.ConsumeIntegralInRange<decltype(sz)>(0, sz - 1));
diff --git a/src/test/fuzz/util/net.cpp b/src/test/fuzz/util/net.cpp
index c6c6e3ad16..65bc336297 100644
--- a/src/test/fuzz/util/net.cpp
+++ b/src/test/fuzz/util/net.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/util/net.h b/src/test/fuzz/util/net.h
index 74afbe1cd9..47e4a2fac0 100644
--- a/src/test/fuzz/util/net.h
+++ b/src/test/fuzz/util/net.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp
index 8abb943266..7119643b45 100644
--- a/src/test/fuzz/utxo_snapshot.cpp
+++ b/src/test/fuzz/utxo_snapshot.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/validation_load_mempool.cpp b/src/test/fuzz/validation_load_mempool.cpp
index 9a90de8911..817593cf6e 100644
--- a/src/test/fuzz/validation_load_mempool.cpp
+++ b/src/test/fuzz/validation_load_mempool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/versionbits.cpp b/src/test/fuzz/versionbits.cpp
index 95eb71099d..143027662f 100644
--- a/src/test/fuzz/versionbits.cpp
+++ b/src/test/fuzz/versionbits.cpp
@@ -55,7 +55,7 @@ public:
bool Condition(int32_t version) const
{
- uint32_t mask = ((uint32_t)1) << m_bit;
+ uint32_t mask = (uint32_t{1}) << m_bit;
return (((version & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (version & mask) != 0);
}
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index 3643b80d5f..9c2d8a4dad 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/i2p_tests.cpp b/src/test/i2p_tests.cpp
index 7b1bf11cfb..3e20b527b5 100644
--- a/src/test/i2p_tests.cpp
+++ b/src/test/i2p_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
index cb901b2259..d37fe35a11 100644
--- a/src/test/interfaces_tests.cpp
+++ b/src/test/interfaces_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/key_io_tests.cpp b/src/test/key_io_tests.cpp
index 1eac68de14..a400afee71 100644
--- a/src/test/key_io_tests.cpp
+++ b/src/test/key_io_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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,7 @@
#include <key.h>
#include <key_io.h>
#include <script/script.h>
+#include <test/util/json.h>
#include <test/util/setup_common.h>
#include <util/strencodings.h>
@@ -15,8 +16,6 @@
#include <univalue.h>
-UniValue read_json(const std::string& jsondata);
-
BOOST_FIXTURE_TEST_SUITE(key_io_tests, BasicTestingSetup)
// Goal: check that parsed keys match test payload
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 8cb0515a8a..edf28cfbfc 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -205,8 +205,7 @@ BOOST_AUTO_TEST_CASE(key_key_negation)
unsigned char rnd[8];
std::string str = "Bitcoin key verification\n";
GetRandBytes(rnd);
- uint256 hash;
- CHash256().Write(MakeUCharSpan(str)).Write(rnd).Finalize(hash);
+ uint256 hash{Hash(str, rnd)};
// import the static test key
CKey key = DecodeSecret(strSecret1C);
@@ -233,7 +232,7 @@ BOOST_AUTO_TEST_CASE(key_key_negation)
static CPubKey UnserializePubkey(const std::vector<uint8_t>& data)
{
- CDataStream stream{SER_NETWORK, INIT_PROTO_VERSION};
+ DataStream stream{};
stream << data;
CPubKey pubkey;
stream >> pubkey;
@@ -251,7 +250,7 @@ static unsigned int GetLen(unsigned char chHeader)
static void CmpSerializationPubkey(const CPubKey& pubkey)
{
- CDataStream stream{SER_NETWORK, INIT_PROTO_VERSION};
+ DataStream stream{};
stream << pubkey;
CPubKey pubkey2;
stream >> pubkey2;
diff --git a/src/test/logging_tests.cpp b/src/test/logging_tests.cpp
index a6f3a62c71..beb9398c74 100644
--- a/src/test/logging_tests.cpp
+++ b/src/test/logging_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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,20 +75,9 @@ struct LogSetup : public BasicTestingSetup {
BOOST_AUTO_TEST_CASE(logging_timer)
{
- SetMockTime(1);
auto micro_timer = BCLog::Timer<std::chrono::microseconds>("tests", "end_msg");
- SetMockTime(2);
- BOOST_CHECK_EQUAL(micro_timer.LogMsg("test micros"), "tests: test micros (1000000ÎĽs)");
-
- SetMockTime(1);
- auto ms_timer = BCLog::Timer<std::chrono::milliseconds>("tests", "end_msg");
- SetMockTime(2);
- BOOST_CHECK_EQUAL(ms_timer.LogMsg("test ms"), "tests: test ms (1000.00ms)");
-
- SetMockTime(1);
- auto sec_timer = BCLog::Timer<std::chrono::seconds>("tests", "end_msg");
- SetMockTime(2);
- BOOST_CHECK_EQUAL(sec_timer.LogMsg("test secs"), "tests: test secs (1.00s)");
+ const std::string_view result_prefix{"tests: msg ("};
+ BOOST_CHECK_EQUAL(micro_timer.LogMsg("msg").substr(0, result_prefix.size()), result_prefix);
}
BOOST_FIXTURE_TEST_CASE(logging_LogPrintf_, LogSetup)
diff --git a/src/test/main.cpp b/src/test/main.cpp
index 73bb331e21..0809f83c93 100644
--- a/src/test/main.cpp
+++ b/src/test/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/mempool_tests.cpp b/src/test/mempool_tests.cpp
index b12aac6299..94e553a304 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
CTxMemPool& testPool = *Assert(m_node.mempool);
- LOCK2(cs_main, testPool.cs);
+ LOCK2(::cs_main, testPool.cs);
// Nothing in pool, remove should do nothing:
unsigned int poolSize = testPool.size();
@@ -202,10 +202,9 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx7.vout[1].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx7.vout[1].nValue = 1 * COIN;
- CTxMemPool::setEntries setAncestorsCalculated;
- std::string dummy;
- BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(2'000'000LL).FromTx(tx7), setAncestorsCalculated, CTxMemPool::Limits::NoLimits(), dummy), true);
- BOOST_CHECK(setAncestorsCalculated == setAncestors);
+ auto ancestors_calculated{pool.CalculateMemPoolAncestors(entry.Fee(2000000LL).FromTx(tx7), CTxMemPool::Limits::NoLimits())};
+ BOOST_REQUIRE(ancestors_calculated.has_value());
+ BOOST_CHECK(*ancestors_calculated == setAncestors);
pool.addUnchecked(entry.FromTx(tx7), setAncestors);
BOOST_CHECK_EQUAL(pool.size(), 7U);
@@ -261,9 +260,9 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx10.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx10.vout[0].nValue = 10 * COIN;
- setAncestorsCalculated.clear();
- BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(200'000LL).Time(NodeSeconds{4s}).FromTx(tx10), setAncestorsCalculated, CTxMemPool::Limits::NoLimits(), dummy), true);
- BOOST_CHECK(setAncestorsCalculated == setAncestors);
+ ancestors_calculated = pool.CalculateMemPoolAncestors(entry.Fee(200000LL).Time(NodeSeconds{4s}).FromTx(tx10), CTxMemPool::Limits::NoLimits());
+ BOOST_REQUIRE(ancestors_calculated);
+ BOOST_CHECK(*ancestors_calculated == setAncestors);
pool.addUnchecked(entry.FromTx(tx10), setAncestors);
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 942d54ede8..74e01fc2a5 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -50,7 +50,7 @@ static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot
// For each of the lower bits in count that are 0, do 1 step. Each
// corresponds to an inner value that existed before processing the
// current leaf, and each needs a hash to combine it.
- for (level = 0; !(count & (((uint32_t)1) << level)); level++) {
+ for (level = 0; !(count & ((uint32_t{1}) << level)); level++) {
if (pbranch) {
if (matchh) {
pbranch->push_back(inner[level]);
@@ -60,7 +60,7 @@ static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot
}
}
mutated |= (inner[level] == h);
- CHash256().Write(inner[level]).Write(h).Finalize(h);
+ h = Hash(inner[level], h);
}
// Store the resulting hash at inner position level.
inner[level] = h;
@@ -74,25 +74,25 @@ static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot
int level = 0;
// As long as bit number level in count is zero, skip it. It means there
// is nothing left at this level.
- while (!(count & (((uint32_t)1) << level))) {
+ while (!(count & ((uint32_t{1}) << level))) {
level++;
}
uint256 h = inner[level];
bool matchh = matchlevel == level;
- while (count != (((uint32_t)1) << level)) {
+ while (count != ((uint32_t{1}) << level)) {
// If we reach this point, h is an inner value that is not the top.
// We combine it with itself (Bitcoin's special rule for odd levels in
// the tree) to produce a higher level one.
if (pbranch && matchh) {
pbranch->push_back(h);
}
- CHash256().Write(h).Write(h).Finalize(h);
+ h = Hash(h, h);
// Increment count to the value it would have if two entries at this
// level had existed.
- count += (((uint32_t)1) << level);
+ count += ((uint32_t{1}) << level);
level++;
// And propagate the result upwards accordingly.
- while (!(count & (((uint32_t)1) << level))) {
+ while (!(count & ((uint32_t{1}) << level))) {
if (pbranch) {
if (matchh) {
pbranch->push_back(inner[level]);
@@ -101,7 +101,7 @@ static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot
matchh = true;
}
}
- CHash256().Write(inner[level]).Write(h).Finalize(h);
+ h = Hash(inner[level], h);
level++;
}
}
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index ba43f1926b..e766a55673 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -87,11 +87,11 @@ constexpr static struct {
{0, 792342903}, {6, 678455063}, {6, 773251385}, {5, 186617471}, {6, 883189502}, {7, 396077336},
{8, 254702874}, {0, 455592851}};
-static CBlockIndex CreateBlockIndex(int nHeight, CBlockIndex* active_chain_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+static std::unique_ptr<CBlockIndex> CreateBlockIndex(int nHeight, CBlockIndex* active_chain_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- CBlockIndex index;
- index.nHeight = nHeight;
- index.pprev = active_chain_tip;
+ auto index{std::make_unique<CBlockIndex>()};
+ index->nHeight = nHeight;
+ index->pprev = active_chain_tip;
return index;
}
@@ -438,7 +438,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
{
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
- BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(active_chain_tip->nHeight + 2, active_chain_tip))); // Sequence locks pass on 2nd block
+ BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, *CreateBlockIndex(active_chain_tip->nHeight + 2, active_chain_tip))); // Sequence locks pass on 2nd block
}
// relative time locked
@@ -455,7 +455,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast
{
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
- BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip)));
+ BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, *CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip)));
}
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {
diff --git a/src/test/miniscript_tests.cpp b/src/test/miniscript_tests.cpp
index 9387c01e73..3181c9cf28 100644
--- a/src/test/miniscript_tests.cpp
+++ b/src/test/miniscript_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/minisketch_tests.cpp b/src/test/minisketch_tests.cpp
index 81f2aad623..59c0aab053 100644
--- a/src/test/minisketch_tests.cpp
+++ b/src/test/minisketch_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/multisig_tests.cpp b/src/test/multisig_tests.cpp
index ce23d6013d..1e1a9932ad 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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_peer_eviction_tests.cpp b/src/test/net_peer_eviction_tests.cpp
index d519a4442f..51d6c4384a 100644
--- a/src/test/net_peer_eviction_tests.cpp
+++ b/src/test/net_peer_eviction_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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 f24509dd97..5a97e9429a 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 0e1e9ae211..cef42b7dd8 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/pmt_tests.cpp b/src/test/pmt_tests.cpp
index 3cbbec92d6..21e0dd2fc5 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2020 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
CPartialMerkleTree pmt1(vTxid, vMatch);
// serialize
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ss{};
ss << pmt1;
// verify CPartialMerkleTree's size guarantees
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 76852d66f7..75ba9972f6 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/pow_tests.cpp b/src/test/pow_tests.cpp
index 3695ea9d16..7cd12ede0a 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/prevector_tests.cpp b/src/test/prevector_tests.cpp
index 3977a3d548..5f4d307048 100644
--- a/src/test/prevector_tests.cpp
+++ b/src/test/prevector_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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,8 +66,8 @@ class prevector_tester {
for (const T& v : reverse_iterate(const_pre_vector)) {
local_check(v == real_vector[--pos]);
}
- CDataStream ss1(SER_DISK, 0);
- CDataStream ss2(SER_DISK, 0);
+ DataStream ss1{};
+ DataStream ss2{};
ss1 << real_vector;
ss2 << pre_vector;
local_check_equal(ss1.size(), ss2.size());
diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp
index d4487cd941..ada61029ee 100644
--- a/src/test/raii_event_tests.cpp
+++ b/src/test/raii_event_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2020 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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/random_tests.cpp b/src/test/random_tests.cpp
index 96fb28dc9f..e5cf767614 100644
--- a/src/test/random_tests.cpp
+++ b/src/test/random_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -94,14 +94,14 @@ BOOST_AUTO_TEST_CASE(fastrandom_randbits)
for (int j = 0; j < 1000; ++j) {
uint64_t rangebits = ctx1.randbits(bits);
BOOST_CHECK_EQUAL(rangebits >> bits, 0U);
- uint64_t range = ((uint64_t)1) << bits | rangebits;
+ uint64_t range = (uint64_t{1}) << bits | rangebits;
uint64_t rand = ctx2.randrange(range);
BOOST_CHECK(rand < range);
}
}
}
-/** Does-it-compile test for compatibility with standard C++11 RNG interface. */
+/** Does-it-compile test for compatibility with standard library RNG interface. */
BOOST_AUTO_TEST_CASE(stdrandom_test)
{
FastRandomContext ctx;
diff --git a/src/test/rbf_tests.cpp b/src/test/rbf_tests.cpp
index d362c85560..0ec253747b 100644
--- a/src/test/rbf_tests.cpp
+++ b/src/test/rbf_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/rbf.h>
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 21ccbe9648..d807c7cda2 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -84,11 +84,15 @@ BOOST_FIXTURE_TEST_SUITE(rpc_tests, RPCTestingSetup)
BOOST_AUTO_TEST_CASE(rpc_namedparams)
{
- const std::vector<std::string> arg_names{{"arg1", "arg2", "arg3", "arg4", "arg5"}};
+ const std::vector<std::string> arg_names{"arg1", "arg2", "arg3", "arg4", "arg5"};
// Make sure named arguments are transformed into positional arguments in correct places separated by nulls
BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"arg2": 2, "arg4": 4})"), arg_names).write(), "[null,2,null,4]");
+ // Make sure named argument specified multiple times raises an exception
+ BOOST_CHECK_EXCEPTION(TransformParams(JSON(R"({"arg2": 2, "arg2": 4})"), arg_names), UniValue,
+ HasJSON(R"({"code":-8,"message":"Parameter arg2 specified multiple times"})"));
+
// Make sure named and positional arguments can be combined.
BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"arg5": 5, "args": [1, 2], "arg4": 4})"), arg_names).write(), "[1,2,null,4,5]");
@@ -100,7 +104,7 @@ BOOST_AUTO_TEST_CASE(rpc_namedparams)
BOOST_CHECK_EXCEPTION(TransformParams(JSON(R"({"args": [1,2,3], "arg4": 4, "arg2": 2})"), arg_names), UniValue,
HasJSON(R"({"code":-8,"message":"Parameter arg2 specified twice both as positional and named argument"})"));
- // Make sure extra positional arguments can be passed through to the method implemenation, as long as they don't overlap with named arguments.
+ // Make sure extra positional arguments can be passed through to the method implementation, as long as they don't overlap with named arguments.
BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"args": [1,2,3,4,5,6,7,8,9,10]})"), arg_names).write(), "[1,2,3,4,5,6,7,8,9,10]");
BOOST_CHECK_EQUAL(TransformParams(JSON(R"([1,2,3,4,5,6,7,8,9,10])"), arg_names).write(), "[1,2,3,4,5,6,7,8,9,10]");
}
diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp
index 907a3fd15b..451bc99d44 100644
--- a/src/test/sanity_tests.cpp
+++ b/src/test/sanity_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index 7b5dda8114..1301a1b219 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index a02d51eecc..e439ff3519 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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 25e47c0fb0..7bebadf224 100644
--- a/src/test/script_standard_tests.cpp
+++ b/src/test/script_standard_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -400,12 +400,11 @@ BOOST_AUTO_TEST_CASE(bip341_spk_test_vectors)
for (const auto& vec : vectors.getValues()) {
TaprootBuilder spktest;
- std::map<std::pair<CScript, int>, int> scriptposes;
+ std::map<std::pair<std::vector<unsigned char>, int>, int> scriptposes;
std::function<void (const UniValue&, int)> parse_tree = [&](const UniValue& node, int depth) {
if (node.isNull()) return;
if (node.isObject()) {
- auto script_bytes = ParseHex(node["script"].get_str());
- CScript script(script_bytes.begin(), script_bytes.end());
+ auto script = ParseHex(node["script"].get_str());
int idx = node["id"].getInt<int>();
int leaf_version = node["leafVersion"].getInt<int>();
scriptposes[{script, leaf_version}] = idx;
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 935194057c..22f6cfd164 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 @@
#include <script/sign.h>
#include <script/signingprovider.h>
#include <streams.h>
+#include <test/util/json.h>
#include <test/util/setup_common.h>
#include <test/util/transaction_utils.h>
#include <util/strencodings.h>
@@ -41,18 +42,6 @@ static const unsigned int gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
unsigned int ParseScriptFlags(std::string strFlags);
std::string FormatScriptFlags(unsigned int flags);
-UniValue read_json(const std::string& jsondata)
-{
- UniValue v;
-
- if (!v.read(jsondata) || !v.isArray())
- {
- BOOST_ERROR("Parse error.");
- return UniValue(UniValue::VARR);
- }
- return v.get_array();
-}
-
struct ScriptErrorDesc
{
ScriptError_t err;
@@ -1817,7 +1806,24 @@ BOOST_AUTO_TEST_CASE(bip341_keypath_test_vectors)
}
}
+}
+
+BOOST_AUTO_TEST_CASE(compute_tapbranch)
+{
+ uint256 hash1 = uint256S("8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7");
+ uint256 hash2 = uint256S("f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a");
+ uint256 result = uint256S("a64c5b7b943315f9b805d7a7296bedfcfd08919270a1f7a1466e98f8693d8cd9");
+ BOOST_CHECK_EQUAL(ComputeTapbranchHash(hash1, hash2), result);
+}
+
+BOOST_AUTO_TEST_CASE(compute_tapleaf)
+{
+ const uint8_t script[6] = {'f','o','o','b','a','r'};
+ uint256 tlc0 = uint256S("edbc10c272a1215dcdcc11d605b9027b5ad6ed97cd45521203f136767b5b9c06");
+ uint256 tlc2 = uint256S("8b5c4f90ae6bf76e259dbef5d8a59df06359c391b59263741b25eca76451b27a");
+ BOOST_CHECK_EQUAL(ComputeTapleafHash(0xc0, Span(script)), tlc0);
+ BOOST_CHECK_EQUAL(ComputeTapleafHash(0xc2, Span(script)), tlc2);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/serfloat_tests.cpp b/src/test/serfloat_tests.cpp
index ed1f081913..f6af32cf6c 100644
--- a/src/test/serfloat_tests.cpp
+++ b/src/test/serfloat_tests.cpp
@@ -111,7 +111,7 @@ Python code to generate the below hashes:
*/
BOOST_AUTO_TEST_CASE(doubles)
{
- CDataStream ss(SER_DISK, 0);
+ DataStream ss{};
// encode
for (int i = 0; i < 1000; i++) {
ss << EncodeDouble(i);
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 8c7c650cb1..09f77d2b61 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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,8 +90,8 @@ BOOST_AUTO_TEST_CASE(varints)
{
// encode
- CDataStream ss(SER_DISK, 0);
- CDataStream::size_type size = 0;
+ DataStream ss{};
+ DataStream::size_type size = 0;
for (int i = 0; i < 100000; i++) {
ss << VARINT_MODE(i, VarIntMode::NONNEGATIVE_SIGNED);
size += ::GetSerializeSize(VARINT_MODE(i, VarIntMode::NONNEGATIVE_SIGNED), 0);
@@ -120,20 +120,20 @@ BOOST_AUTO_TEST_CASE(varints)
BOOST_AUTO_TEST_CASE(varints_bitpatterns)
{
- CDataStream ss(SER_DISK, 0);
+ DataStream ss{};
ss << VARINT_MODE(0, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "00"); ss.clear();
ss << VARINT_MODE(0x7f, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
- ss << VARINT_MODE((int8_t)0x7f, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
+ ss << VARINT_MODE(int8_t{0x7f}, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
ss << VARINT_MODE(0x80, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
- ss << VARINT((uint8_t)0x80); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
+ ss << VARINT(uint8_t{0x80}); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
ss << VARINT_MODE(0x1234, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
- ss << VARINT_MODE((int16_t)0x1234, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
+ ss << VARINT_MODE(int16_t{0x1234}, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
ss << VARINT_MODE(0xffff, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
- ss << VARINT((uint16_t)0xffff); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
+ ss << VARINT(uint16_t{0xffff}); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
ss << VARINT_MODE(0x123456, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
- ss << VARINT_MODE((int32_t)0x123456, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
+ ss << VARINT_MODE(int32_t{0x123456}, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
ss << VARINT(0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
- ss << VARINT((uint32_t)0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
+ ss << VARINT(uint32_t{0x80123456U}); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
ss << VARINT(0xffffffff); BOOST_CHECK_EQUAL(HexStr(ss), "8efefefe7f"); ss.clear();
ss << VARINT_MODE(0x7fffffffffffffffLL, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "fefefefefefefefe7f"); ss.clear();
ss << VARINT(0xffffffffffffffffULL); BOOST_CHECK_EQUAL(HexStr(ss), "80fefefefefefefefe7f"); ss.clear();
@@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(varints_bitpatterns)
BOOST_AUTO_TEST_CASE(compactsize)
{
- CDataStream ss(SER_DISK, 0);
+ DataStream ss{};
std::vector<char>::size_type i, j;
for (i = 1; i <= MAX_SIZE; i *= 2)
@@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE(noncanonical)
{
// Write some non-canonical CompactSize encodings, and
// make sure an exception is thrown when read back.
- CDataStream ss(SER_DISK, 0);
+ DataStream ss{};
std::vector<char>::size_type n;
// zero encoded with three bytes:
@@ -237,7 +237,8 @@ BOOST_AUTO_TEST_CASE(class_methods)
BOOST_CHECK(methodtest2 == methodtest3);
BOOST_CHECK(methodtest3 == methodtest4);
- CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, charstrval, txval);
+ CDataStream ss2{SER_DISK, PROTOCOL_VERSION};
+ ss2 << intval << boolval << stringval << charstrval << txval;
ss2 >> methodtest3;
BOOST_CHECK(methodtest3 == methodtest4);
}
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 514798d8fa..368f9e6047 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2021 The Bitcoin Core developers
+// Copyright (c) 2013-2022 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,6 +10,7 @@
#include <serialize.h>
#include <streams.h>
#include <test/data/sighash.json.h>
+#include <test/util/json.h>
#include <test/util/setup_common.h>
#include <util/strencodings.h>
#include <util/system.h>
@@ -21,8 +22,6 @@
#include <univalue.h>
-UniValue read_json(const std::string& jsondata);
-
// Old script.cpp SignatureHash function
uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index d78f62972f..a17be54419 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index 9f5e3ab7ae..ae9021df58 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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/sock_tests.cpp b/src/test/sock_tests.cpp
index 5bea08c254..9e6f73745e 100644
--- a/src/test/sock_tests.cpp
+++ b/src/test/sock_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/streams_tests.cpp b/src/test/streams_tests.cpp
index b1b262eade..b7c1ce5066 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -128,9 +128,9 @@ BOOST_AUTO_TEST_CASE(streams_vector_reader_rvalue)
BOOST_AUTO_TEST_CASE(bitstream_reader_writer)
{
- CDataStream data(SER_NETWORK, INIT_PROTO_VERSION);
+ DataStream data{};
- BitStreamWriter<CDataStream> bit_writer(data);
+ BitStreamWriter bit_writer{data};
bit_writer.Write(0, 1);
bit_writer.Write(2, 2);
bit_writer.Write(6, 3);
@@ -141,15 +141,15 @@ BOOST_AUTO_TEST_CASE(bitstream_reader_writer)
bit_writer.Write(30497, 16);
bit_writer.Flush();
- CDataStream data_copy(data);
+ DataStream data_copy{data};
uint32_t serialized_int1;
data >> serialized_int1;
- BOOST_CHECK_EQUAL(serialized_int1, (uint32_t)0x7700C35A); // NOTE: Serialized as LE
+ BOOST_CHECK_EQUAL(serialized_int1, uint32_t{0x7700C35A}); // NOTE: Serialized as LE
uint16_t serialized_int2;
data >> serialized_int2;
- BOOST_CHECK_EQUAL(serialized_int2, (uint16_t)0x1072); // NOTE: Serialized as LE
+ BOOST_CHECK_EQUAL(serialized_int2, uint16_t{0x1072}); // NOTE: Serialized as LE
- BitStreamReader<CDataStream> bit_reader(data_copy);
+ BitStreamReader bit_reader{data_copy};
BOOST_CHECK_EQUAL(bit_reader.Read(1), 0U);
BOOST_CHECK_EQUAL(bit_reader.Read(2), 2U);
BOOST_CHECK_EQUAL(bit_reader.Read(3), 6U);
@@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
// Degenerate case
{
- CDataStream ds{in, 0, 0};
+ DataStream ds{in};
ds.Xor({0x00, 0x00});
BOOST_CHECK_EQUAL(""s, ds.str());
}
@@ -177,7 +177,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
// Single character key
{
- CDataStream ds{in, 0, 0};
+ DataStream ds{in};
ds.Xor({0xff});
BOOST_CHECK_EQUAL("\xf0\x0f"s, ds.str());
}
@@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
in.push_back(std::byte{0x0f});
{
- CDataStream ds{in, 0, 0};
+ DataStream ds{in};
ds.Xor({0xff, 0x0f});
BOOST_CHECK_EQUAL("\x0f\x00"s, ds.str());
}
@@ -500,4 +500,18 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file_rand)
fs::remove(streams_test_filename);
}
+BOOST_AUTO_TEST_CASE(streams_hashed)
+{
+ CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
+ HashedSourceWriter hash_writer{stream};
+ const std::string data{"bitcoin"};
+ hash_writer << data;
+
+ CHashVerifier hash_verifier{&stream};
+ std::string result;
+ hash_verifier >> result;
+ BOOST_CHECK_EQUAL(data, result);
+ BOOST_CHECK_EQUAL(hash_writer.GetHash(), hash_verifier.GetHash());
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp
index e1270a362b..0576bf1633 100644
--- a/src/test/sync_tests.cpp
+++ b/src/test/sync_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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/system_tests.cpp b/src/test/system_tests.cpp
index 472b58b4d5..f2dc6ee739 100644
--- a/src/test/system_tests.cpp
+++ b/src/test/system_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/timedata_tests.cpp b/src/test/timedata_tests.cpp
index 478d61d5e2..2814dbf4c0 100644
--- a/src/test/timedata_tests.cpp
+++ b/src/test/timedata_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-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.
//
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 952598f745..0180fa47e8 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -21,6 +21,7 @@
#include <script/signingprovider.h>
#include <script/standard.h>
#include <streams.h>
+#include <test/util/json.h>
#include <test/util/script.h>
#include <test/util/transaction_utils.h>
#include <util/strencodings.h>
@@ -37,9 +38,6 @@
typedef std::vector<unsigned char> valtype;
-// In script_tests.cpp
-UniValue read_json(const std::string& jsondata);
-
static CFeeRate g_dust{DUST_RELAY_TX_FEE};
static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
@@ -937,23 +935,58 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
CheckIsNotStandard(t, "bare-multisig");
g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;
+ // Check compressed P2PK outputs dust threshold (must have leading 02 or 03)
+ t.vout[0].scriptPubKey = CScript() << std::vector<unsigned char>(33, 0x02) << OP_CHECKSIG;
+ t.vout[0].nValue = 576;
+ CheckIsStandard(t);
+ t.vout[0].nValue = 575;
+ CheckIsNotStandard(t, "dust");
+
+ // Check uncompressed P2PK outputs dust threshold (must have leading 04/06/07)
+ t.vout[0].scriptPubKey = CScript() << std::vector<unsigned char>(65, 0x04) << OP_CHECKSIG;
+ t.vout[0].nValue = 672;
+ CheckIsStandard(t);
+ t.vout[0].nValue = 671;
+ CheckIsNotStandard(t, "dust");
+
+ // Check P2PKH outputs dust threshold
+ t.vout[0].scriptPubKey = CScript() << OP_DUP << OP_HASH160 << std::vector<unsigned char>(20, 0) << OP_EQUALVERIFY << OP_CHECKSIG;
+ t.vout[0].nValue = 546;
+ CheckIsStandard(t);
+ t.vout[0].nValue = 545;
+ CheckIsNotStandard(t, "dust");
+
+ // Check P2SH outputs dust threshold
+ t.vout[0].scriptPubKey = CScript() << OP_HASH160 << std::vector<unsigned char>(20, 0) << OP_EQUAL;
+ t.vout[0].nValue = 540;
+ CheckIsStandard(t);
+ t.vout[0].nValue = 539;
+ CheckIsNotStandard(t, "dust");
+
// Check P2WPKH outputs dust threshold
- t.vout[0].scriptPubKey = CScript() << OP_0 << ParseHex("ffffffffffffffffffffffffffffffffffffffff");
+ t.vout[0].scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(20, 0);
t.vout[0].nValue = 294;
CheckIsStandard(t);
t.vout[0].nValue = 293;
CheckIsNotStandard(t, "dust");
// Check P2WSH outputs dust threshold
- t.vout[0].scriptPubKey = CScript() << OP_0 << ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+ t.vout[0].scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(32, 0);
+ t.vout[0].nValue = 330;
+ CheckIsStandard(t);
+ t.vout[0].nValue = 329;
+ CheckIsNotStandard(t, "dust");
+
+ // Check P2TR outputs dust threshold (Invalid xonly key ok!)
+ t.vout[0].scriptPubKey = CScript() << OP_1 << std::vector<unsigned char>(32, 0);
t.vout[0].nValue = 330;
CheckIsStandard(t);
t.vout[0].nValue = 329;
CheckIsNotStandard(t, "dust");
- // Check future Witness Program versions dust threshold
- for (int op = OP_2; op <= OP_16; op += 1) {
- t.vout[0].scriptPubKey = CScript() << (opcodetype)op << ParseHex("ffff");
+ // Check future Witness Program versions dust threshold (non-32-byte pushes are undefined for version 1)
+ for (int op = OP_1; op <= OP_16; op += 1) {
+ t.vout[0].scriptPubKey = CScript() << (opcodetype)op << std::vector<unsigned char>(2, 0);
t.vout[0].nValue = 240;
CheckIsStandard(t);
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
index 643d9221fe..b9bfa65c0a 100644
--- a/src/test/txindex_tests.cpp
+++ b/src/test/txindex_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/txpackage_tests.cpp b/src/test/txpackage_tests.cpp
index 079b753304..e438867d15 100644
--- a/src/test/txpackage_tests.cpp
+++ b/src/test/txpackage_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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,17 +90,21 @@ BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup)
const auto result_parent_child = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {tx_parent, tx_child}, /*test_accept=*/true);
BOOST_CHECK_MESSAGE(result_parent_child.m_state.IsValid(),
"Package validation unexpectedly failed: " << result_parent_child.m_state.GetRejectReason());
+ BOOST_CHECK(result_parent_child.m_tx_results.size() == 2);
auto it_parent = result_parent_child.m_tx_results.find(tx_parent->GetWitnessHash());
auto it_child = result_parent_child.m_tx_results.find(tx_child->GetWitnessHash());
BOOST_CHECK(it_parent != result_parent_child.m_tx_results.end());
BOOST_CHECK_MESSAGE(it_parent->second.m_state.IsValid(),
"Package validation unexpectedly failed: " << it_parent->second.m_state.GetRejectReason());
+ BOOST_CHECK(it_parent->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_parent)) == COIN);
+ BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().size(), 1);
+ BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().front(), tx_parent->GetWitnessHash());
BOOST_CHECK(it_child != result_parent_child.m_tx_results.end());
BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(),
"Package validation unexpectedly failed: " << it_child->second.m_state.GetRejectReason());
- BOOST_CHECK(result_parent_child.m_package_feerate.has_value());
- BOOST_CHECK(result_parent_child.m_package_feerate.value() ==
- CFeeRate(2 * COIN, GetVirtualTransactionSize(*tx_parent) + GetVirtualTransactionSize(*tx_child)));
+ BOOST_CHECK(it_child->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child)) == COIN);
+ BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().size(), 1);
+ BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().front(), tx_child->GetWitnessHash());
// A single, giant transaction submitted through ProcessNewPackage fails on single tx policy.
CTransactionRef giant_ptx = create_placeholder_tx(999, 999);
@@ -109,10 +113,10 @@ BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup)
BOOST_CHECK(result_single_large.m_state.IsInvalid());
BOOST_CHECK_EQUAL(result_single_large.m_state.GetResult(), PackageValidationResult::PCKG_TX);
BOOST_CHECK_EQUAL(result_single_large.m_state.GetRejectReason(), "transaction failed");
+ BOOST_CHECK(result_single_large.m_tx_results.size() == 1);
auto it_giant_tx = result_single_large.m_tx_results.find(giant_ptx->GetWitnessHash());
BOOST_CHECK(it_giant_tx != result_single_large.m_tx_results.end());
BOOST_CHECK_EQUAL(it_giant_tx->second.m_state.GetRejectReason(), "tx-size");
- BOOST_CHECK(result_single_large.m_package_feerate == std::nullopt);
// Check that mempool size hasn't changed.
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize);
@@ -233,7 +237,6 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
BOOST_CHECK_EQUAL(result_unrelated_submit.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
BOOST_CHECK_EQUAL(result_unrelated_submit.m_state.GetRejectReason(), "package-not-child-with-parents");
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
- BOOST_CHECK(result_unrelated_submit.m_package_feerate == std::nullopt);
// Parent and Child (and Grandchild) Package
Package package_parent_child;
@@ -275,7 +278,30 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
BOOST_CHECK_EQUAL(result_3gen_submit.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
BOOST_CHECK_EQUAL(result_3gen_submit.m_state.GetRejectReason(), "package-not-child-with-parents");
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
- BOOST_CHECK(result_3gen_submit.m_package_feerate == std::nullopt);
+ }
+
+ // Parent and child package where transactions are invalid for reasons other than fee and
+ // missing inputs, so the package validation isn't expected to happen.
+ {
+ CScriptWitness bad_witness;
+ bad_witness.stack.push_back(std::vector<unsigned char>(1));
+ CMutableTransaction mtx_parent_invalid{mtx_parent};
+ mtx_parent_invalid.vin[0].scriptWitness = bad_witness;
+ CTransactionRef tx_parent_invalid = MakeTransactionRef(mtx_parent_invalid);
+ auto result_quit_early = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool,
+ {tx_parent_invalid, tx_child}, /*test_accept=*/ false);
+ BOOST_CHECK(result_quit_early.m_state.IsInvalid());
+ BOOST_CHECK_EQUAL(result_quit_early.m_state.GetResult(), PackageValidationResult::PCKG_TX);
+ BOOST_CHECK(!result_quit_early.m_tx_results.empty());
+ BOOST_CHECK_EQUAL(result_quit_early.m_tx_results.size(), 2);
+ auto it_parent = result_quit_early.m_tx_results.find(tx_parent_invalid->GetWitnessHash());
+ auto it_child = result_quit_early.m_tx_results.find(tx_child->GetWitnessHash());
+ BOOST_CHECK(it_parent != result_quit_early.m_tx_results.end());
+ BOOST_CHECK(it_child != result_quit_early.m_tx_results.end());
+ BOOST_CHECK_EQUAL(it_parent->second.m_state.GetResult(), TxValidationResult::TX_WITNESS_MUTATED);
+ BOOST_CHECK_EQUAL(it_parent->second.m_state.GetRejectReason(), "bad-witness-nonstandard");
+ BOOST_CHECK_EQUAL(it_child->second.m_state.GetResult(), TxValidationResult::TX_MISSING_INPUTS);
+ BOOST_CHECK_EQUAL(it_child->second.m_state.GetRejectReason(), "bad-txns-inputs-missingorspent");
}
// Child with missing parent.
@@ -290,8 +316,6 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
BOOST_CHECK_EQUAL(result_missing_parent.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
BOOST_CHECK_EQUAL(result_missing_parent.m_state.GetRejectReason(), "package-not-child-with-unconfirmed-parents");
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
-
- BOOST_CHECK(result_missing_parent.m_package_feerate == std::nullopt);
}
// Submit package with parent + child.
@@ -301,20 +325,23 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
expected_pool_size += 2;
BOOST_CHECK_MESSAGE(submit_parent_child.m_state.IsValid(),
"Package validation unexpectedly failed: " << submit_parent_child.m_state.GetRejectReason());
+ BOOST_CHECK_EQUAL(submit_parent_child.m_tx_results.size(), package_parent_child.size());
auto it_parent = submit_parent_child.m_tx_results.find(tx_parent->GetWitnessHash());
auto it_child = submit_parent_child.m_tx_results.find(tx_child->GetWitnessHash());
BOOST_CHECK(it_parent != submit_parent_child.m_tx_results.end());
BOOST_CHECK(it_parent->second.m_state.IsValid());
+ BOOST_CHECK(it_parent->second.m_effective_feerate == CFeeRate(1 * COIN, GetVirtualTransactionSize(*tx_parent)));
+ BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().size(), 1);
+ BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().front(), tx_parent->GetWitnessHash());
BOOST_CHECK(it_child != submit_parent_child.m_tx_results.end());
BOOST_CHECK(it_child->second.m_state.IsValid());
+ BOOST_CHECK(it_child->second.m_effective_feerate == CFeeRate(1 * COIN, GetVirtualTransactionSize(*tx_child)));
+ BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().size(), 1);
+ BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().front(), tx_child->GetWitnessHash());
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent->GetHash())));
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child->GetHash())));
-
- // Since both transactions have high feerates, they each passed validation individually.
- // Package validation was unnecessary, so there is no package feerate.
- BOOST_CHECK(submit_parent_child.m_package_feerate == std::nullopt);
}
// Already-in-mempool transactions should be detected and de-duplicated.
@@ -323,6 +350,7 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
package_parent_child, /*test_accept=*/false);
BOOST_CHECK_MESSAGE(submit_deduped.m_state.IsValid(),
"Package validation unexpectedly failed: " << submit_deduped.m_state.GetRejectReason());
+ BOOST_CHECK_EQUAL(submit_deduped.m_tx_results.size(), package_parent_child.size());
auto it_parent_deduped = submit_deduped.m_tx_results.find(tx_parent->GetWitnessHash());
auto it_child_deduped = submit_deduped.m_tx_results.find(tx_child->GetWitnessHash());
BOOST_CHECK(it_parent_deduped != submit_deduped.m_tx_results.end());
@@ -335,8 +363,6 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent->GetHash())));
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_child->GetHash())));
-
- BOOST_CHECK(submit_deduped.m_package_feerate == std::nullopt);
}
}
@@ -399,6 +425,7 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
{ptx_parent, ptx_child1}, /*test_accept=*/false);
BOOST_CHECK_MESSAGE(submit_witness1.m_state.IsValid(),
"Package validation unexpectedly failed: " << submit_witness1.m_state.GetRejectReason());
+ BOOST_CHECK_EQUAL(submit_witness1.m_tx_results.size(), 2);
auto it_parent1 = submit_witness1.m_tx_results.find(ptx_parent->GetWitnessHash());
auto it_child1 = submit_witness1.m_tx_results.find(ptx_child1->GetWitnessHash());
BOOST_CHECK(it_parent1 != submit_witness1.m_tx_results.end());
@@ -412,13 +439,11 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(ptx_child1->GetHash())));
// Child2 would have been validated individually.
- BOOST_CHECK(submit_witness1.m_package_feerate == std::nullopt);
-
const auto submit_witness2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool,
{ptx_parent, ptx_child2}, /*test_accept=*/false);
- BOOST_CHECK(submit_witness2.m_package_feerate == std::nullopt);
BOOST_CHECK_MESSAGE(submit_witness2.m_state.IsValid(),
"Package validation unexpectedly failed: " << submit_witness2.m_state.GetRejectReason());
+ BOOST_CHECK_EQUAL(submit_witness2.m_tx_results.size(), 2);
auto it_parent2_deduped = submit_witness2.m_tx_results.find(ptx_parent->GetWitnessHash());
auto it_child2 = submit_witness2.m_tx_results.find(ptx_child2->GetWitnessHash());
BOOST_CHECK(it_parent2_deduped != submit_witness2.m_tx_results.end());
@@ -436,11 +461,11 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
{ptx_parent, ptx_child1}, /*test_accept=*/false);
BOOST_CHECK_MESSAGE(submit_segwit_dedup.m_state.IsValid(),
"Package validation unexpectedly failed: " << submit_segwit_dedup.m_state.GetRejectReason());
+ BOOST_CHECK_EQUAL(submit_segwit_dedup.m_tx_results.size(), 2);
auto it_parent_dup = submit_segwit_dedup.m_tx_results.find(ptx_parent->GetWitnessHash());
auto it_child_dup = submit_segwit_dedup.m_tx_results.find(ptx_child1->GetWitnessHash());
BOOST_CHECK(it_parent_dup->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
BOOST_CHECK(it_child_dup->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY);
- BOOST_CHECK(submit_witness2.m_package_feerate == std::nullopt);
}
// Try submitting Package1{child2, grandchild} where child2 is same-txid-different-witness as
@@ -465,6 +490,7 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
{ptx_child2, ptx_grandchild}, /*test_accept=*/false);
BOOST_CHECK_MESSAGE(submit_spend_ignored.m_state.IsValid(),
"Package validation unexpectedly failed: " << submit_spend_ignored.m_state.GetRejectReason());
+ BOOST_CHECK_EQUAL(submit_spend_ignored.m_tx_results.size(), 2);
auto it_child2_ignored = submit_spend_ignored.m_tx_results.find(ptx_child2->GetWitnessHash());
auto it_grandchild = submit_spend_ignored.m_tx_results.find(ptx_grandchild->GetWitnessHash());
BOOST_CHECK(it_child2_ignored != submit_spend_ignored.m_tx_results.end());
@@ -475,9 +501,6 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(ptx_child2->GetHash())));
BOOST_CHECK(!m_node.mempool->exists(GenTxid::Wtxid(ptx_child2->GetWitnessHash())));
BOOST_CHECK(m_node.mempool->exists(GenTxid::Wtxid(ptx_grandchild->GetWitnessHash())));
-
- // Since child2 is ignored, grandchild would be validated individually.
- BOOST_CHECK(submit_spend_ignored.m_package_feerate == std::nullopt);
}
// A package Package{parent1, parent2, parent3, child} where the parents are a mixture of
@@ -568,6 +591,7 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
{
const auto mixed_result = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_mixed, false);
BOOST_CHECK_MESSAGE(mixed_result.m_state.IsValid(), mixed_result.m_state.GetRejectReason());
+ BOOST_CHECK_EQUAL(mixed_result.m_tx_results.size(), package_mixed.size());
auto it_parent1 = mixed_result.m_tx_results.find(ptx_parent1->GetWitnessHash());
auto it_parent2 = mixed_result.m_tx_results.find(ptx_parent2_v1->GetWitnessHash());
auto it_parent3 = mixed_result.m_tx_results.find(ptx_parent3->GetWitnessHash());
@@ -590,11 +614,12 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(ptx_mixed_child->GetHash())));
// package feerate should include parent3 and child. It should not include parent1 or parent2_v1.
- BOOST_CHECK(mixed_result.m_package_feerate.has_value());
const CFeeRate expected_feerate(1 * COIN, GetVirtualTransactionSize(*ptx_parent3) + GetVirtualTransactionSize(*ptx_mixed_child));
- BOOST_CHECK_MESSAGE(mixed_result.m_package_feerate.value() == expected_feerate,
- strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
- mixed_result.m_package_feerate.value().ToString()));
+ BOOST_CHECK(it_parent3->second.m_effective_feerate.value() == expected_feerate);
+ BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate);
+ std::vector<uint256> expected_wtxids({ptx_parent3->GetWitnessHash(), ptx_mixed_child->GetWitnessHash()});
+ BOOST_CHECK(it_parent3->second.m_wtxids_fee_calculations.value() == expected_wtxids);
+ BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids);
}
}
@@ -638,16 +663,12 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
const auto submit_cpfp_deprio = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool,
package_cpfp, /*test_accept=*/ false);
+ BOOST_CHECK_EQUAL(submit_cpfp_deprio.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
BOOST_CHECK_MESSAGE(submit_cpfp_deprio.m_state.IsInvalid(),
"Package validation unexpectedly succeeded: " << submit_cpfp_deprio.m_state.GetRejectReason());
BOOST_CHECK(submit_cpfp_deprio.m_tx_results.empty());
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
const CFeeRate expected_feerate(0, GetVirtualTransactionSize(*tx_parent) + GetVirtualTransactionSize(*tx_child));
- BOOST_CHECK(submit_cpfp_deprio.m_package_feerate.has_value());
- BOOST_CHECK(submit_cpfp_deprio.m_package_feerate.value() == CFeeRate{0});
- BOOST_CHECK_MESSAGE(submit_cpfp_deprio.m_package_feerate.value() == expected_feerate,
- strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
- submit_cpfp_deprio.m_package_feerate.value().ToString()));
}
// Clear the prioritisation of the parent transaction.
@@ -662,6 +683,7 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
expected_pool_size += 2;
BOOST_CHECK_MESSAGE(submit_cpfp.m_state.IsValid(),
"Package validation unexpectedly failed: " << submit_cpfp.m_state.GetRejectReason());
+ BOOST_CHECK_EQUAL(submit_cpfp.m_tx_results.size(), package_cpfp.size());
auto it_parent = submit_cpfp.m_tx_results.find(tx_parent->GetWitnessHash());
auto it_child = submit_cpfp.m_tx_results.find(tx_child->GetWitnessHash());
BOOST_CHECK(it_parent != submit_cpfp.m_tx_results.end());
@@ -677,11 +699,12 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
const CFeeRate expected_feerate(coinbase_value - child_value,
GetVirtualTransactionSize(*tx_parent) + GetVirtualTransactionSize(*tx_child));
+ BOOST_CHECK(it_parent->second.m_effective_feerate.value() == expected_feerate);
+ BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate);
+ std::vector<uint256> expected_wtxids({tx_parent->GetWitnessHash(), tx_child->GetWitnessHash()});
+ BOOST_CHECK(it_parent->second.m_wtxids_fee_calculations.value() == expected_wtxids);
+ BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids);
BOOST_CHECK(expected_feerate.GetFeePerK() > 1000);
- BOOST_CHECK(submit_cpfp.m_package_feerate.has_value());
- BOOST_CHECK_MESSAGE(submit_cpfp.m_package_feerate.value() == expected_feerate,
- strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
- submit_cpfp.m_package_feerate.value().ToString()));
}
// Just because we allow low-fee parents doesn't mean we allow low-feerate packages.
@@ -716,10 +739,6 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
const CFeeRate expected_feerate(200,
GetVirtualTransactionSize(*tx_parent_cheap) + GetVirtualTransactionSize(*tx_child_cheap));
BOOST_CHECK(expected_feerate.GetFeePerK() < 1000);
- BOOST_CHECK(submit_package_too_low.m_package_feerate.has_value());
- BOOST_CHECK_MESSAGE(submit_package_too_low.m_package_feerate.value() == expected_feerate,
- strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
- submit_package_too_low.m_package_feerate.value().ToString()));
}
// Package feerate includes the modified fees of the transactions.
@@ -734,10 +753,20 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
"Package validation unexpectedly failed" << submit_prioritised_package.m_state.GetRejectReason());
const CFeeRate expected_feerate(1 * COIN + 200,
GetVirtualTransactionSize(*tx_parent_cheap) + GetVirtualTransactionSize(*tx_child_cheap));
- BOOST_CHECK(submit_prioritised_package.m_package_feerate.has_value());
- BOOST_CHECK_MESSAGE(submit_prioritised_package.m_package_feerate.value() == expected_feerate,
- strprintf("Expected package feerate %s, got %s", expected_feerate.ToString(),
- submit_prioritised_package.m_package_feerate.value().ToString()));
+ BOOST_CHECK_EQUAL(submit_prioritised_package.m_tx_results.size(), package_still_too_low.size());
+ auto it_parent = submit_prioritised_package.m_tx_results.find(tx_parent_cheap->GetWitnessHash());
+ auto it_child = submit_prioritised_package.m_tx_results.find(tx_child_cheap->GetWitnessHash());
+ BOOST_CHECK(it_parent != submit_prioritised_package.m_tx_results.end());
+ BOOST_CHECK(it_parent->second.m_result_type == MempoolAcceptResult::ResultType::VALID);
+ BOOST_CHECK(it_parent->second.m_base_fees.value() == 0);
+ BOOST_CHECK(it_parent->second.m_effective_feerate.value() == expected_feerate);
+ BOOST_CHECK(it_child != submit_prioritised_package.m_tx_results.end());
+ BOOST_CHECK(it_child->second.m_result_type == MempoolAcceptResult::ResultType::VALID);
+ BOOST_CHECK(it_child->second.m_base_fees.value() == 200);
+ BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate);
+ std::vector<uint256> expected_wtxids({tx_parent_cheap->GetWitnessHash(), tx_child_cheap->GetWitnessHash()});
+ BOOST_CHECK(it_parent->second.m_wtxids_fee_calculations.value() == expected_wtxids);
+ BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids);
}
// Package feerate is calculated without topology in mind; it's just aggregating fees and sizes.
@@ -770,10 +799,6 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
BOOST_CHECK_MESSAGE(submit_rich_parent.m_state.IsInvalid(), "Package validation unexpectedly succeeded");
// The child would have been validated on its own and failed, then submitted as a "package" of 1.
- // The package feerate is just the child's feerate, which is 0sat/vb.
- BOOST_CHECK(submit_rich_parent.m_package_feerate.has_value());
- BOOST_CHECK_MESSAGE(submit_rich_parent.m_package_feerate.value() == CFeeRate(),
- "expected 0, got " << submit_rich_parent.m_package_feerate.value().ToString());
BOOST_CHECK_EQUAL(submit_rich_parent.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
BOOST_CHECK_EQUAL(submit_rich_parent.m_state.GetRejectReason(), "package-fee-too-low");
@@ -783,6 +808,7 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
BOOST_CHECK(it_parent->second.m_state.GetRejectReason() == "");
BOOST_CHECK_MESSAGE(it_parent->second.m_base_fees.value() == high_parent_fee,
strprintf("rich parent: expected fee %s, got %s", high_parent_fee, it_parent->second.m_base_fees.value()));
+ BOOST_CHECK(it_parent->second.m_effective_feerate == CFeeRate(high_parent_fee, GetVirtualTransactionSize(*tx_parent_rich)));
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent_rich->GetHash())));
diff --git a/src/test/txreconciliation_tests.cpp b/src/test/txreconciliation_tests.cpp
index b018629e76..e258e3353d 100644
--- a/src/test/txreconciliation_tests.cpp
+++ b/src/test/txreconciliation_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 633f75ff4f..8cdea3890e 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -77,7 +77,9 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
LOCK(cs_main);
BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash());
}
- m_node.mempool->clear();
+ BOOST_CHECK_EQUAL(m_node.mempool->size(), 1U);
+ WITH_LOCK(m_node.mempool->cs, m_node.mempool->removeRecursive(CTransaction{spends[0]}, MemPoolRemovalReason::CONFLICT));
+ BOOST_CHECK_EQUAL(m_node.mempool->size(), 0U);
// Test 3: ... and should be rejected if spend2 is in the memory pool
BOOST_CHECK(ToMemPool(spends[1]));
@@ -86,7 +88,9 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
LOCK(cs_main);
BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash());
}
- m_node.mempool->clear();
+ BOOST_CHECK_EQUAL(m_node.mempool->size(), 1U);
+ WITH_LOCK(m_node.mempool->cs, m_node.mempool->removeRecursive(CTransaction{spends[1]}, MemPoolRemovalReason::CONFLICT));
+ BOOST_CHECK_EQUAL(m_node.mempool->size(), 0U);
// Final sanity test: first spend in *m_node.mempool, second in block, that's OK:
std::vector<CMutableTransaction> oneSpend;
@@ -113,7 +117,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup)
// should fail.
// Capture this interaction with the upgraded_nop argument: set it when evaluating
// any script flag that is implemented as an upgraded NOP code.
-static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache, CCoinsViewCache& active_coins_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache, CCoinsViewCache& active_coins_tip) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
PrecomputedTransactionData txdata;
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
index bc206fc945..9caefe43e2 100644
--- a/src/test/uint256_tests.cpp
+++ b/src/test/uint256_tests.cpp
@@ -187,7 +187,7 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G
BOOST_CHECK(GetSerializeSize(R1L, PROTOCOL_VERSION) == 32);
BOOST_CHECK(GetSerializeSize(ZeroL, PROTOCOL_VERSION) == 32);
- CDataStream ss(0, PROTOCOL_VERSION);
+ DataStream ss{};
ss << R1L;
BOOST_CHECK(ss.str() == std::string(R1Array,R1Array+32));
ss >> TmpL;
diff --git a/src/test/util/chainstate.h b/src/test/util/chainstate.h
index 0ca63810f3..e664435e03 100644
--- a/src/test/util/chainstate.h
+++ b/src/test/util/chainstate.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/json.cpp b/src/test/util/json.cpp
new file mode 100644
index 0000000000..ad3c346c84
--- /dev/null
+++ b/src/test/util/json.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2023 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 <test/util/json.h>
+
+#include <string>
+#include <util/check.h>
+
+#include <univalue.h>
+
+UniValue read_json(const std::string& jsondata)
+{
+ UniValue v;
+ Assert(v.read(jsondata) && v.isArray());
+ return v.get_array();
+}
diff --git a/src/test/util/json.h b/src/test/util/json.h
new file mode 100644
index 0000000000..5b1026762e
--- /dev/null
+++ b/src/test/util/json.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2023 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_UTIL_JSON_H
+#define BITCOIN_TEST_UTIL_JSON_H
+
+#include <string>
+
+#include <univalue.h>
+
+UniValue read_json(const std::string& jsondata);
+
+#endif // BITCOIN_TEST_UTIL_JSON_H
diff --git a/src/test/util/logging.h b/src/test/util/logging.h
index f477088392..73ac23825f 100644
--- a/src/test/util/logging.h
+++ b/src/test/util/logging.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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 faa0b2878c..0df1db84c4 100644
--- a/src/test/util/mining.cpp
+++ b/src/test/util/mining.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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,6 @@
#include <consensus/merkle.h>
#include <key_io.h>
#include <node/context.h>
-#include <node/miner.h>
#include <pow.h>
#include <script/standard.h>
#include <test/util/script.h>
@@ -74,10 +73,11 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
return CTxIn{block->vtx[0]->GetHash(), 0};
}
-std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
+std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey,
+ const BlockAssembler::Options& assembler_options)
{
auto block = std::make_shared<CBlock>(
- BlockAssembler{Assert(node.chainman)->ActiveChainstate(), Assert(node.mempool.get())}
+ BlockAssembler{Assert(node.chainman)->ActiveChainstate(), Assert(node.mempool.get()), assembler_options}
.CreateNewBlock(coinbase_scriptPubKey)
->block);
@@ -87,3 +87,9 @@ std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coi
return block;
}
+std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
+{
+ BlockAssembler::Options assembler_options;
+ ApplyArgsManOptions(*node.args, assembler_options);
+ return PrepareBlock(node, coinbase_scriptPubKey, assembler_options);
+}
diff --git a/src/test/util/mining.h b/src/test/util/mining.h
index 09e712cd35..70b1f7b3fb 100644
--- a/src/test/util/mining.h
+++ b/src/test/util/mining.h
@@ -5,6 +5,8 @@
#ifndef BITCOIN_TEST_UTIL_MINING_H
#define BITCOIN_TEST_UTIL_MINING_H
+#include <node/miner.h>
+
#include <memory>
#include <string>
#include <vector>
@@ -25,6 +27,8 @@ CTxIn MineBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey);
/** Prepare a block to be mined */
std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey);
+std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext& node, const CScript& coinbase_scriptPubKey,
+ const node::BlockAssembler::Options& assembler_options);
/** RPC-like helper function, returns the generated coin */
CTxIn generatetoaddress(const node::NodeContext&, const std::string& address);
diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp
index 2e3e16e681..ac5dfe9e73 100644
--- a/src/test/util/net.cpp
+++ b/src/test/util/net.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -67,15 +67,14 @@ void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_by
assert(node.ReceiveMsgBytes(msg_bytes, complete));
if (complete) {
size_t nSizeAdded = 0;
- auto it(node.vRecvMsg.begin());
- for (; it != node.vRecvMsg.end(); ++it) {
+ for (const auto& msg : node.vRecvMsg) {
// vRecvMsg contains only completed CNetMessage
// the single possible partially deserialized message are held by TransportDeserializer
- nSizeAdded += it->m_raw_message_size;
+ nSizeAdded += msg.m_raw_message_size;
}
{
LOCK(node.cs_vProcessMsg);
- node.vProcessMsg.splice(node.vProcessMsg.end(), node.vRecvMsg, node.vRecvMsg.begin(), it);
+ node.vProcessMsg.splice(node.vProcessMsg.end(), node.vRecvMsg);
node.nProcessQueueSize += nSizeAdded;
node.fPauseRecv = node.nProcessQueueSize > nReceiveFloodSize;
}
diff --git a/src/test/util/net.h b/src/test/util/net.h
index 9ae7981980..e6506b0d08 100644
--- a/src/test/util/net.h
+++ b/src/test/util/net.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -103,7 +103,7 @@ constexpr auto ALL_NETWORKS = std::array{
class StaticContentsSock : public Sock
{
public:
- explicit StaticContentsSock(const std::string& contents) : m_contents{contents}, m_consumed{0}
+ explicit StaticContentsSock(const std::string& contents) : m_contents{contents}
{
// Just a dummy number that is not INVALID_SOCKET.
m_socket = INVALID_SOCKET - 1;
@@ -191,7 +191,7 @@ public:
private:
const std::string m_contents;
- mutable size_t m_consumed;
+ mutable size_t m_consumed{0};
};
std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext& random_context);
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index c97f400137..6e72f69968 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -208,23 +208,24 @@ ChainTestingSetup::~ChainTestingSetup()
void TestingSetup::LoadVerifyActivateChainstate()
{
+ auto& chainman{*Assert(m_node.chainman)};
node::ChainstateLoadOptions options;
options.mempool = Assert(m_node.mempool.get());
options.block_tree_db_in_memory = m_block_tree_db_in_memory;
options.coins_db_in_memory = m_coins_db_in_memory;
options.reindex = node::fReindex;
options.reindex_chainstate = m_args.GetBoolArg("-reindex-chainstate", false);
- options.prune = node::fPruneMode;
+ options.prune = chainman.m_blockman.IsPruneMode();
options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
- auto [status, error] = LoadChainstate(*Assert(m_node.chainman), m_cache_sizes, options);
+ auto [status, error] = LoadChainstate(chainman, m_cache_sizes, options);
assert(status == node::ChainstateLoadStatus::SUCCESS);
- std::tie(status, error) = VerifyLoadedChainstate(*Assert(m_node.chainman), options);
+ std::tie(status, error) = VerifyLoadedChainstate(chainman, options);
assert(status == node::ChainstateLoadStatus::SUCCESS);
BlockValidationState state;
- if (!m_node.chainman->ActiveChainstate().ActivateBestChain(state)) {
+ if (!chainman.ActiveChainstate().ActivateBestChain(state)) {
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
}
}
@@ -321,7 +322,7 @@ CBlock TestChain100Setup::CreateAndProcessBlock(
chainstate = &Assert(m_node.chainman)->ActiveChainstate();
}
- const CBlock block = this->CreateBlock(txns, scriptPubKey, *chainstate);
+ CBlock block = this->CreateBlock(txns, scriptPubKey, *chainstate);
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, true, nullptr);
@@ -397,15 +398,15 @@ std::vector<CTransactionRef> TestChain100Setup::PopulateMempool(FastRandomContex
unspent_prevouts.pop_front();
}
const size_t num_outputs = det_rand.randrange(24) + 1;
- // Approximately 1000sat "fee," equal output amounts.
- const CAmount amount_per_output = (total_in - 1000) / num_outputs;
+ const CAmount fee = 100 * det_rand.randrange(30);
+ const CAmount amount_per_output = (total_in - fee) / num_outputs;
for (size_t n{0}; n < num_outputs; ++n) {
CScript spk = CScript() << CScriptNum(num_transactions + n);
mtx.vout.push_back(CTxOut(amount_per_output, spk));
}
CTransactionRef ptx = MakeTransactionRef(mtx);
mempool_transactions.push_back(ptx);
- if (amount_per_output > 2000) {
+ if (amount_per_output > 3000) {
// If the value is high enough to fund another transaction + fees, keep track of it so
// it can be used to build a more complex transaction graph. Insert randomly into
// unspent_prevouts for extra randomness in the resulting structures.
@@ -415,9 +416,11 @@ std::vector<CTransactionRef> TestChain100Setup::PopulateMempool(FastRandomContex
}
}
if (submit) {
- LOCK2(m_node.mempool->cs, cs_main);
+ LOCK2(cs_main, m_node.mempool->cs);
LockPoints lp;
- m_node.mempool->addUnchecked(CTxMemPoolEntry(ptx, 1000, 0, 1, false, 4, lp));
+ m_node.mempool->addUnchecked(CTxMemPoolEntry(ptx, /*fee=*/(total_in - num_outputs * amount_per_output),
+ /*time=*/0, /*entry_height=*/1,
+ /*spends_coinbase=*/false, /*sigops_cost=*/4, lp));
}
--num_transactions;
}
diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h
index dfa36039a2..5f653d83ae 100644
--- a/src/test/util/setup_common.h
+++ b/src/test/util/setup_common.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/validation.cpp b/src/test/util/validation.cpp
index 49535855f9..c0d7a532dc 100644
--- a/src/test/util/validation.cpp
+++ b/src/test/util/validation.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/validation.h b/src/test/util/validation.h
index cbe7745b81..7a511a2b79 100644
--- a/src/test/util/validation.h
+++ b/src/test/util/validation.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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_tests.cpp b/src/test/util_tests.cpp
index 602c848c2a..6b6bb18523 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -810,8 +810,8 @@ BOOST_AUTO_TEST_CASE(test_ParseInt64)
BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
- BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == (int64_t)9223372036854775807);
- BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == (int64_t)-9223372036854775807-1);
+ BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == int64_t{9223372036854775807});
+ BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == int64_t{-9223372036854775807-1});
BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
// Invalid values
BOOST_CHECK(!ParseInt64("", &n));
@@ -907,8 +907,8 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt32)
BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234);
BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal
BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
- BOOST_CHECK(ParseUInt32("2147483648", &n) && n == (uint32_t)2147483648);
- BOOST_CHECK(ParseUInt32("4294967295", &n) && n == (uint32_t)4294967295);
+ BOOST_CHECK(ParseUInt32("2147483648", &n) && n == uint32_t{2147483648});
+ BOOST_CHECK(ParseUInt32("4294967295", &n) && n == uint32_t{4294967295});
BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234);
BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234);
BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0);
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index bb1ade153a..823c9877ac 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp
index f868c0d4e6..c40481a95c 100644
--- a/src/test/validation_chainstate_tests.cpp
+++ b/src/test/validation_chainstate_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
@@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
COutPoint outp{txid, 0};
newcoin.nHeight = 1;
newcoin.out.nValue = InsecureRand32();
- newcoin.out.scriptPubKey.assign((uint32_t)56, 1);
+ newcoin.out.scriptPubKey.assign(uint32_t{56}, 1);
coins_view.AddCoin(outp, std::move(newcoin), false);
return outp;
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
index 22b9af1201..56867a584b 100644
--- a/src/test/validation_chainstatemanager_tests.cpp
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
@@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
// Create a legacy (IBD) chainstate.
//
- Chainstate& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
+ Chainstate& c1 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(&mempool));
chainstates.push_back(&c1);
c1.InitCoinsDB(
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
diff --git a/src/test/validation_flush_tests.cpp b/src/test/validation_flush_tests.cpp
index c06e6c8d3b..f2ff570ca6 100644
--- a/src/test/validation_flush_tests.cpp
+++ b/src/test/validation_flush_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
@@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate)
COutPoint outp{txid, 0};
newcoin.nHeight = 1;
newcoin.out.nValue = InsecureRand32();
- newcoin.out.scriptPubKey.assign((uint32_t)56, 1);
+ newcoin.out.scriptPubKey.assign(uint32_t{56}, 1);
coins_view.AddCoin(outp, std::move(newcoin), false);
return outp;
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index e6203af4b4..91383ee4a5 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2021 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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 @@
/* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */
static int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; }
-static const std::string StateName(ThresholdState state)
+static std::string StateName(ThresholdState state)
{
switch (state) {
case ThresholdState::DEFINED: return "DEFINED";
diff --git a/src/timedata.cpp b/src/timedata.cpp
index fe9a5fbed7..a0646b4707 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2021 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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/timedata.h b/src/timedata.h
index 669a571f47..c6c36d9a39 100644
--- a/src/timedata.h
+++ b/src/timedata.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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/tinyformat.h b/src/tinyformat.h
index bedaa14007..3ec385bc95 100644
--- a/src/tinyformat.h
+++ b/src/tinyformat.h
@@ -508,9 +508,6 @@ class FormatArg
{
public:
FormatArg()
- : m_value(NULL),
- m_formatImpl(NULL),
- m_toIntImpl(NULL)
{ }
template<typename T>
@@ -549,10 +546,10 @@ class FormatArg
return convertToInt<T>::invoke(*static_cast<const T*>(value));
}
- const void* m_value;
+ const void* m_value{nullptr};
void (*m_formatImpl)(std::ostream& out, const char* fmtBegin,
- const char* fmtEnd, int ntrunc, const void* value);
- int (*m_toIntImpl)(const void* value);
+ const char* fmtEnd, int ntrunc, const void* value){nullptr};
+ int (*m_toIntImpl)(const void* value){nullptr};
};
@@ -1005,7 +1002,8 @@ class FormatListN : public FormatList
// Special 0-arg version - MSVC says zero-sized C array in struct is nonstandard
template<> class FormatListN<0> : public FormatList
{
- public: FormatListN() : FormatList(0, 0) {}
+public:
+ FormatListN() : FormatList(nullptr, 0) {}
};
} // namespace detail
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 3a21a79a34..ece77f9023 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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.
@@ -53,8 +53,8 @@ static const uint16_t DEFAULT_TOR_SOCKS_PORT = 9050;
/****** Low-level TorControlConnection ********/
-TorControlConnection::TorControlConnection(struct event_base *_base):
- base(_base), b_conn(nullptr)
+TorControlConnection::TorControlConnection(struct event_base* _base)
+ : base(_base)
{
}
diff --git a/src/torcontrol.h b/src/torcontrol.h
index 81475aee74..6563a2ef42 100644
--- a/src/torcontrol.h
+++ b/src/torcontrol.h
@@ -93,7 +93,7 @@ private:
/** Libevent event base */
struct event_base *base;
/** Connection to control socket */
- struct bufferevent *b_conn;
+ struct bufferevent* b_conn{nullptr};
/** Message being received */
TorControlReply message;
/** Response handlers */
diff --git a/src/txdb.cpp b/src/txdb.cpp
index bad3bb80a9..c12b540b9b 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -111,7 +111,7 @@ std::vector<uint256> CCoinsViewDB::GetHeadBlocks() const {
return vhashHeadBlocks;
}
-bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
+bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase) {
CDBBatch batch(*m_db);
size_t count = 0;
size_t changed = 0;
@@ -146,8 +146,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
changed++;
}
count++;
- CCoinsMap::iterator itOld = it++;
- mapCoins.erase(itOld);
+ it = erase ? mapCoins.erase(it) : std::next(it);
if (batch.SizeEstimate() > batch_size) {
LogPrint(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
m_db->WriteBatch(batch);
diff --git a/src/txdb.h b/src/txdb.h
index 8c41e26f6a..e3422846c0 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,7 @@
#include <coins.h>
#include <dbwrapper.h>
+#include <kernel/cs_main.h>
#include <sync.h>
#include <fs.h>
@@ -44,9 +45,6 @@ static const int64_t max_filter_index_cache = 1024;
//! Max memory allocated to coin DB specific cache (MiB)
static const int64_t nMaxCoinsDBCache = 8;
-// Actually declared in validation.cpp; can't include because of circular dependency.
-extern RecursiveMutex cs_main;
-
/** CCoinsView backed by the coin database (chainstate/) */
class CCoinsViewDB final : public CCoinsView
{
@@ -64,7 +62,7 @@ public:
bool HaveCoin(const COutPoint &outpoint) const override;
uint256 GetBestBlock() const override;
std::vector<uint256> GetHeadBlocks() const override;
- bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
+ bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, bool erase = true) override;
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
//! Whether an unsupported database format is used.
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 12e2d5f224..378123ce0f 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -17,12 +17,16 @@
#include <util/check.h>
#include <util/moneystr.h>
#include <util/overflow.h>
+#include <util/result.h>
#include <util/system.h>
#include <util/time.h>
+#include <util/translation.h>
#include <validationinterface.h>
#include <cmath>
#include <optional>
+#include <string_view>
+#include <utility>
bool TestLockPointValidity(CChain& active_chain, const LockPoints& lp)
{
@@ -147,32 +151,29 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256>& vHashes
}
}
-bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
- size_t entry_count,
- setEntries& setAncestors,
- CTxMemPoolEntry::Parents& staged_ancestors,
- const Limits& limits,
- std::string &errString) const
+util::Result<CTxMemPool::setEntries> CTxMemPool::CalculateAncestorsAndCheckLimits(
+ size_t entry_size,
+ size_t entry_count,
+ CTxMemPoolEntry::Parents& staged_ancestors,
+ const Limits& limits) const
{
size_t totalSizeWithAncestors = entry_size;
+ setEntries ancestors;
while (!staged_ancestors.empty()) {
const CTxMemPoolEntry& stage = staged_ancestors.begin()->get();
txiter stageit = mapTx.iterator_to(stage);
- setAncestors.insert(stageit);
+ ancestors.insert(stageit);
staged_ancestors.erase(stage);
totalSizeWithAncestors += stageit->GetTxSize();
if (stageit->GetSizeWithDescendants() + entry_size > static_cast<uint64_t>(limits.descendant_size_vbytes)) {
- errString = strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_size_vbytes);
- return false;
+ return util::Error{Untranslated(strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_size_vbytes))};
} else if (stageit->GetCountWithDescendants() + entry_count > static_cast<uint64_t>(limits.descendant_count)) {
- errString = strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_count);
- return false;
+ return util::Error{Untranslated(strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limits.descendant_count))};
} else if (totalSizeWithAncestors > static_cast<uint64_t>(limits.ancestor_size_vbytes)) {
- errString = strprintf("exceeds ancestor size limit [limit: %u]", limits.ancestor_size_vbytes);
- return false;
+ return util::Error{Untranslated(strprintf("exceeds ancestor size limit [limit: %u]", limits.ancestor_size_vbytes))};
}
const CTxMemPoolEntry::Parents& parents = stageit->GetMemPoolParentsConst();
@@ -180,17 +181,16 @@ bool CTxMemPool::CalculateAncestorsAndCheckLimits(size_t entry_size,
txiter parent_it = mapTx.iterator_to(parent);
// If this is a new ancestor, add it.
- if (setAncestors.count(parent_it) == 0) {
+ if (ancestors.count(parent_it) == 0) {
staged_ancestors.insert(parent);
}
- if (staged_ancestors.size() + setAncestors.size() + entry_count > static_cast<uint64_t>(limits.ancestor_count)) {
- errString = strprintf("too many unconfirmed ancestors [limit: %u]", limits.ancestor_count);
- return false;
+ if (staged_ancestors.size() + ancestors.size() + entry_count > static_cast<uint64_t>(limits.ancestor_count)) {
+ return util::Error{Untranslated(strprintf("too many unconfirmed ancestors [limit: %u]", limits.ancestor_count))};
}
}
}
- return true;
+ return ancestors;
}
bool CTxMemPool::CheckPackageLimits(const Package& package,
@@ -215,20 +215,17 @@ bool CTxMemPool::CheckPackageLimits(const Package& package,
// When multiple transactions are passed in, the ancestors and descendants of all transactions
// considered together must be within limits even if they are not interdependent. This may be
// stricter than the limits for each individual transaction.
- setEntries setAncestors;
- const auto ret = CalculateAncestorsAndCheckLimits(total_size, package.size(),
- setAncestors, staged_ancestors,
- limits, errString);
+ const auto ancestors{CalculateAncestorsAndCheckLimits(total_size, package.size(),
+ staged_ancestors, limits)};
// It's possible to overestimate the ancestor/descendant totals.
- if (!ret) errString.insert(0, "possibly ");
- return ret;
+ if (!ancestors.has_value()) errString = "possibly " + util::ErrorString(ancestors).original;
+ return ancestors.has_value();
}
-bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
- setEntries &setAncestors,
- const Limits& limits,
- std::string &errString,
- bool fSearchForParents /* = true */) const
+util::Result<CTxMemPool::setEntries> CTxMemPool::CalculateMemPoolAncestors(
+ const CTxMemPoolEntry &entry,
+ const Limits& limits,
+ bool fSearchForParents /* = true */) const
{
CTxMemPoolEntry::Parents staged_ancestors;
const CTransaction &tx = entry.GetTx();
@@ -242,8 +239,7 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
if (piter) {
staged_ancestors.insert(**piter);
if (staged_ancestors.size() + 1 > static_cast<uint64_t>(limits.ancestor_count)) {
- errString = strprintf("too many unconfirmed parents [limit: %u]", limits.ancestor_count);
- return false;
+ return util::Error{Untranslated(strprintf("too many unconfirmed parents [limit: %u]", limits.ancestor_count))};
}
}
}
@@ -254,9 +250,22 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry,
staged_ancestors = it->GetMemPoolParentsConst();
}
- return CalculateAncestorsAndCheckLimits(entry.GetTxSize(), /*entry_count=*/1,
- setAncestors, staged_ancestors,
- limits, errString);
+ return CalculateAncestorsAndCheckLimits(entry.GetTxSize(), /*entry_count=*/1, staged_ancestors,
+ limits);
+}
+
+CTxMemPool::setEntries CTxMemPool::AssumeCalculateMemPoolAncestors(
+ std::string_view calling_fn_name,
+ const CTxMemPoolEntry &entry,
+ const Limits& limits,
+ bool fSearchForParents /* = true */) const
+{
+ auto result{CalculateMemPoolAncestors(entry, limits, fSearchForParents)};
+ if (!Assume(result)) {
+ LogPrintLevel(BCLog::MEMPOOL, BCLog::Level::Error, "%s: CalculateMemPoolAncestors failed unexpectedly, continuing with empty ancestor set (%s)\n",
+ calling_fn_name, util::ErrorString(result).original);
+ }
+ return std::move(result).value_or(CTxMemPool::setEntries{});
}
void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors)
@@ -320,9 +329,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
}
}
for (txiter removeIt : entriesToRemove) {
- setEntries setAncestors;
const CTxMemPoolEntry &entry = *removeIt;
- std::string dummy;
// Since this is a tx that is already in the mempool, we can call CMPA
// with fSearchForParents = false. If the mempool is in a consistent
// state, then using true or false should both be correct, though false
@@ -342,10 +349,10 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
// mempool parents we'd calculate by searching, and it's important that
// we use the cached notion of ancestor transactions as the set of
// things to update for removal.
- CalculateMemPoolAncestors(entry, setAncestors, Limits::NoLimits(), dummy, false);
+ auto ancestors{AssumeCalculateMemPoolAncestors(__func__, entry, Limits::NoLimits(), /*fSearchForParents=*/false)};
// Note that UpdateAncestorsOf severs the child links that point to
// removeIt in the entries for the parents of removeIt.
- UpdateAncestorsOf(false, removeIt, setAncestors);
+ UpdateAncestorsOf(false, removeIt, ancestors);
}
// After updating all the ancestor sizes, we can now sever the link between each
// transaction being removed and any mempool children (ie, update CTxMemPoolEntry::m_parents
@@ -389,7 +396,6 @@ CTxMemPool::CTxMemPool(const Options& opts)
m_full_rbf{opts.full_rbf},
m_limits{opts.limits}
{
- _clear(); //lock free clear
}
bool CTxMemPool::isSpent(const COutPoint& outpoint) const
@@ -627,26 +633,6 @@ void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigne
blockSinceLastRollingFeeBump = true;
}
-void CTxMemPool::_clear()
-{
- vTxHashes.clear();
- mapTx.clear();
- mapNextTx.clear();
- totalTxSize = 0;
- m_total_fee = 0;
- cachedInnerUsage = 0;
- lastRollingFeeUpdate = GetTime();
- blockSinceLastRollingFeeBump = false;
- rollingMinimumFeeRate = 0;
- ++nTransactionsUpdated;
-}
-
-void CTxMemPool::clear()
-{
- LOCK(cs);
- _clear();
-}
-
void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendheight) const
{
if (m_check_ratio == 0) return;
@@ -695,15 +681,13 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
assert(setParentCheck.size() == it->GetMemPoolParentsConst().size());
assert(std::equal(setParentCheck.begin(), setParentCheck.end(), it->GetMemPoolParentsConst().begin(), comp));
// Verify ancestor state is correct.
- setEntries setAncestors;
- std::string dummy;
- CalculateMemPoolAncestors(*it, setAncestors, Limits::NoLimits(), dummy);
- uint64_t nCountCheck = setAncestors.size() + 1;
+ auto ancestors{AssumeCalculateMemPoolAncestors(__func__, *it, Limits::NoLimits())};
+ uint64_t nCountCheck = ancestors.size() + 1;
uint64_t nSizeCheck = it->GetTxSize();
CAmount nFeesCheck = it->GetModifiedFee();
int64_t nSigOpCheck = it->GetSigOpCost();
- for (txiter ancestorIt : setAncestors) {
+ for (txiter ancestorIt : ancestors) {
nSizeCheck += ancestorIt->GetTxSize();
nFeesCheck += ancestorIt->GetModifiedFee();
nSigOpCheck += ancestorIt->GetSigOpCost();
@@ -858,10 +842,8 @@ void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeD
if (it != mapTx.end()) {
mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(nFeeDelta); });
// Now update all ancestors' modified fees with descendants
- setEntries setAncestors;
- std::string dummy;
- CalculateMemPoolAncestors(*it, setAncestors, Limits::NoLimits(), dummy, false);
- for (txiter ancestorIt : setAncestors) {
+ auto ancestors{AssumeCalculateMemPoolAncestors(__func__, *it, Limits::NoLimits(), /*fSearchForParents=*/false)};
+ for (txiter ancestorIt : ancestors) {
mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e){ e.UpdateDescendantState(0, nFeeDelta, 0);});
}
// Now update all descendants' modified fees with ancestors
@@ -998,10 +980,8 @@ int CTxMemPool::Expire(std::chrono::seconds time)
void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, bool validFeeEstimate)
{
- setEntries setAncestors;
- std::string dummy;
- CalculateMemPoolAncestors(entry, setAncestors, Limits::NoLimits(), dummy);
- return addUnchecked(entry, setAncestors, validFeeEstimate);
+ auto ancestors{AssumeCalculateMemPoolAncestors(__func__, entry, Limits::NoLimits())};
+ return addUnchecked(entry, ancestors, validFeeEstimate);
}
void CTxMemPool::UpdateChild(txiter entry, txiter child, bool add)
@@ -1148,7 +1128,7 @@ void CTxMemPool::SetLoadTried(bool load_tried)
}
-const std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept
+std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept
{
switch (r) {
case MemPoolRemovalReason::EXPIRY: return "expiry";
diff --git a/src/txmempool.h b/src/txmempool.h
index dd28a84c23..2c3cb7e9db 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,6 +11,7 @@
#include <optional>
#include <set>
#include <string>
+#include <string_view>
#include <utility>
#include <vector>
@@ -20,6 +21,7 @@
#include <coins.h>
#include <consensus/amount.h>
#include <indirectmap.h>
+#include <kernel/cs_main.h>
#include <kernel/mempool_entry.h>
#include <policy/feerate.h>
#include <policy/packages.h>
@@ -28,6 +30,7 @@
#include <sync.h>
#include <util/epochguard.h>
#include <util/hasher.h>
+#include <util/result.h>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
@@ -37,7 +40,6 @@
class CBlockIndex;
class CChain;
class Chainstate;
-extern RecursiveMutex cs_main;
/** Fake height value used in Coin to signify they are only in the memory pool (since 0.8) */
static const uint32_t MEMPOOL_HEIGHT = 0x7FFFFFFF;
@@ -235,7 +237,7 @@ enum class MemPoolRemovalReason {
REPLACED, //!< Removed for replacement
};
-const std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept;
+std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept;
/**
* CTxMemPool stores valid-according-to-the-current-best-chain transactions
@@ -317,14 +319,14 @@ protected:
std::atomic<unsigned int> nTransactionsUpdated{0}; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
CBlockPolicyEstimator* const minerPolicyEstimator;
- uint64_t totalTxSize GUARDED_BY(cs); //!< sum of all mempool tx's virtual sizes. Differs from serialized tx size since witness data is discounted. Defined in BIP 141.
- CAmount m_total_fee GUARDED_BY(cs); //!< sum of all mempool tx's fees (NOT modified fee)
- uint64_t cachedInnerUsage GUARDED_BY(cs); //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves)
+ uint64_t totalTxSize GUARDED_BY(cs){0}; //!< sum of all mempool tx's virtual sizes. Differs from serialized tx size since witness data is discounted. Defined in BIP 141.
+ CAmount m_total_fee GUARDED_BY(cs){0}; //!< sum of all mempool tx's fees (NOT modified fee)
+ uint64_t cachedInnerUsage GUARDED_BY(cs){0}; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves)
- mutable int64_t lastRollingFeeUpdate GUARDED_BY(cs);
- mutable bool blockSinceLastRollingFeeBump GUARDED_BY(cs);
- mutable double rollingMinimumFeeRate GUARDED_BY(cs); //!< minimum fee to get into the pool, decreases exponentially
- mutable Epoch m_epoch GUARDED_BY(cs);
+ mutable int64_t lastRollingFeeUpdate GUARDED_BY(cs){GetTime()};
+ mutable bool blockSinceLastRollingFeeBump GUARDED_BY(cs){false};
+ mutable double rollingMinimumFeeRate GUARDED_BY(cs){0}; //!< minimum fee to get into the pool, decreases exponentially
+ mutable Epoch m_epoch GUARDED_BY(cs){};
// In-memory counter for external mempool tracking purposes.
// This number is incremented once every time a transaction
@@ -428,24 +430,20 @@ private:
/**
* Helper function to calculate all in-mempool ancestors of staged_ancestors and apply ancestor
- * and descendant limits (including staged_ancestors thsemselves, entry_size and entry_count).
+ * and descendant limits (including staged_ancestors themselves, entry_size and entry_count).
*
* @param[in] entry_size Virtual size to include in the limits.
* @param[in] entry_count How many entries to include in the limits.
- * @param[out] setAncestors Will be populated with all mempool ancestors.
* @param[in] staged_ancestors Should contain entries in the mempool.
* @param[in] limits Maximum number and size of ancestors and descendants
- * @param[out] errString Populated with error reason if any limits are hit
*
- * @return true if no limits were hit and all in-mempool ancestors were calculated, false
- * otherwise
+ * @return all in-mempool ancestors, or an error if any ancestor or descendant limits were hit
*/
- bool CalculateAncestorsAndCheckLimits(size_t entry_size,
- size_t entry_count,
- setEntries& setAncestors,
- CTxMemPoolEntry::Parents &staged_ancestors,
- const Limits& limits,
- std::string &errString) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+ util::Result<setEntries> CalculateAncestorsAndCheckLimits(size_t entry_size,
+ size_t entry_count,
+ CTxMemPoolEntry::Parents &staged_ancestors,
+ const Limits& limits
+ ) const EXCLUSIVE_LOCKS_REQUIRED(cs);
public:
indirectmap<COutPoint, const CTransaction*> mapNextTx GUARDED_BY(cs);
@@ -502,8 +500,6 @@ public:
void removeConflicts(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs);
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs);
- void clear();
- void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs); //lock free
bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb, bool wtxid=false);
void queryHashes(std::vector<uint256>& vtxid) const;
bool isSpent(const COutPoint& outpoint) const;
@@ -558,22 +554,37 @@ public:
* (these are all calculated including the tx itself)
*
* @param[in] entry CTxMemPoolEntry of which all in-mempool ancestors are calculated
- * @param[out] setAncestors Will be populated with all mempool ancestors.
* @param[in] limits Maximum number and size of ancestors and descendants
- * @param[out] errString Populated with error reason if any limits are hit
* @param[in] fSearchForParents Whether to search a tx's vin for in-mempool parents, or look
* up parents from mapLinks. Must be true for entries not in
* the mempool
*
- * @return true if no limits were hit and all in-mempool ancestors were calculated, false
- * otherwise
+ * @return all in-mempool ancestors, or an error if any ancestor or descendant limits were hit
*/
- bool CalculateMemPoolAncestors(const CTxMemPoolEntry& entry,
- setEntries& setAncestors,
+ util::Result<setEntries> CalculateMemPoolAncestors(const CTxMemPoolEntry& entry,
const Limits& limits,
- std::string& errString,
bool fSearchForParents = true) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+ /**
+ * Same as CalculateMemPoolAncestors, but always returns a (non-optional) setEntries.
+ * Should only be used when it is assumed CalculateMemPoolAncestors would not fail. If
+ * CalculateMemPoolAncestors does unexpectedly fail, an empty setEntries is returned and the
+ * error is logged to BCLog::MEMPOOL with level BCLog::Level::Error. In debug builds, failure
+ * of CalculateMemPoolAncestors will lead to shutdown due to assertion failure.
+ *
+ * @param[in] calling_fn_name Name of calling function so we can properly log the call site
+ *
+ * @return a setEntries corresponding to the result of CalculateMemPoolAncestors or an empty
+ * setEntries if it failed
+ *
+ * @see CTXMemPool::CalculateMemPoolAncestors()
+ */
+ setEntries AssumeCalculateMemPoolAncestors(
+ std::string_view calling_fn_name,
+ const CTxMemPoolEntry &entry,
+ const Limits& limits,
+ bool fSearchForParents = true) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+
/** Calculate all in-mempool ancestors of a set of transactions not already in the mempool and
* check ancestor and descendant limits. Heuristics are used to estimate the ancestor and
* descendant count of all entries if the package were to be added to the mempool. The limits
diff --git a/src/txorphanage.cpp b/src/txorphanage.cpp
index b0b71e135c..19f9fae998 100644
--- a/src/txorphanage.cpp
+++ b/src/txorphanage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -145,17 +145,19 @@ void TxOrphanage::LimitOrphans(unsigned int max_orphans)
if (nEvicted > 0) LogPrint(BCLog::MEMPOOL, "orphanage overflow, removed %u tx\n", nEvicted);
}
-void TxOrphanage::AddChildrenToWorkSet(const CTransaction& tx, NodeId peer)
+void TxOrphanage::AddChildrenToWorkSet(const CTransaction& tx)
{
LOCK(m_mutex);
- // Get this peer's work set, emplacing an empty set it didn't exist
- std::set<uint256>& orphan_work_set = m_peer_work_set.try_emplace(peer).first->second;
for (unsigned int i = 0; i < tx.vout.size(); i++) {
const auto it_by_prev = m_outpoint_to_orphan_it.find(COutPoint(tx.GetHash(), i));
if (it_by_prev != m_outpoint_to_orphan_it.end()) {
for (const auto& elem : it_by_prev->second) {
+ // Get this source peer's work set, emplacing an empty set if it didn't exist
+ // (note: if this peer wasn't still connected, we would have removed the orphan tx already)
+ std::set<uint256>& orphan_work_set = m_peer_work_set.try_emplace(elem->second.fromPeer).first->second;
+ // Add this tx to the work set
orphan_work_set.insert(elem->first);
}
}
@@ -172,7 +174,7 @@ bool TxOrphanage::HaveTx(const GenTxid& gtxid) const
}
}
-CTransactionRef TxOrphanage::GetTxToReconsider(NodeId peer, NodeId& originator, bool& more)
+CTransactionRef TxOrphanage::GetTxToReconsider(NodeId peer)
{
LOCK(m_mutex);
@@ -185,16 +187,25 @@ CTransactionRef TxOrphanage::GetTxToReconsider(NodeId peer, NodeId& originator,
const auto orphan_it = m_orphans.find(txid);
if (orphan_it != m_orphans.end()) {
- more = !work_set.empty();
- originator = orphan_it->second.fromPeer;
return orphan_it->second.tx;
}
}
}
- more = false;
return nullptr;
}
+bool TxOrphanage::HaveTxToReconsider(NodeId peer)
+{
+ LOCK(m_mutex);
+
+ auto work_set_it = m_peer_work_set.find(peer);
+ if (work_set_it != m_peer_work_set.end()) {
+ auto& work_set = work_set_it->second;
+ return !work_set.empty();
+ }
+ return false;
+}
+
void TxOrphanage::EraseForBlock(const CBlock& block)
{
LOCK(m_mutex);
diff --git a/src/txorphanage.h b/src/txorphanage.h
index 551502d325..45276c6c98 100644
--- a/src/txorphanage.h
+++ b/src/txorphanage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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,13 +27,11 @@ public:
bool HaveTx(const GenTxid& gtxid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
/** Extract a transaction from a peer's work set
- * Returns nullptr and sets more to false if there are no transactions
- * to work on. Otherwise returns the transaction reference, removes
- * the transaction from the work set, and populates its arguments with
- * the originating peer, and whether there are more orphans for this peer
- * to work on after this tx.
+ * Returns nullptr if there are no transactions to work on.
+ * Otherwise returns the transaction reference, and removes
+ * it from the work set.
*/
- CTransactionRef GetTxToReconsider(NodeId peer, NodeId& originator, bool& more) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
+ CTransactionRef GetTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
/** Erase an orphan by txid */
int EraseTx(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
@@ -47,8 +45,11 @@ public:
/** Limit the orphanage to the given maximum */
void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
- /** Add any orphans that list a particular tx as a parent into a peer's work set */
- void AddChildrenToWorkSet(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
+ /** Add any orphans that list a particular tx as a parent into the from peer's work set */
+ void AddChildrenToWorkSet(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);;
+
+ /** Does this peer have any work to do? */
+ bool HaveTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);;
/** Return how many entries exist in the orphange */
size_t Size() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
@@ -72,7 +73,7 @@ protected:
* -maxorphantx/DEFAULT_MAX_ORPHAN_TRANSACTIONS */
std::map<uint256, OrphanTx> m_orphans GUARDED_BY(m_mutex);
- /** Which peer provided a parent tx of orphans that need to be reconsidered */
+ /** Which peer provided the orphans that need to be reconsidered */
std::map<NodeId, std::set<uint256>> m_peer_work_set GUARDED_BY(m_mutex);
using OrphanMap = decltype(m_orphans);
diff --git a/src/uint256.h b/src/uint256.h
index 782fec8e51..1cc3721487 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/univalue/include/univalue_utffilter.h b/src/univalue/include/univalue_utffilter.h
index f688eaaa30..41d8e6bb05 100644
--- a/src/univalue/include/univalue_utffilter.h
+++ b/src/univalue/include/univalue_utffilter.h
@@ -13,8 +13,8 @@
class JSONUTF8StringFilter
{
public:
- explicit JSONUTF8StringFilter(std::string &s):
- str(s), is_valid(true), codepoint(0), state(0), surpair(0)
+ explicit JSONUTF8StringFilter(std::string& s)
+ : str(s)
{
}
// Write single 8-bit char (may be part of UTF-8 sequence)
@@ -79,10 +79,10 @@ public:
}
private:
std::string &str;
- bool is_valid;
+ bool is_valid{true};
// Current UTF-8 decoding state
- unsigned int codepoint;
- int state; // Top bit to be filled in for next UTF-8 byte, or 0
+ unsigned int codepoint{0};
+ int state{0}; // Top bit to be filled in for next UTF-8 byte, or 0
// Keep track of the following state to handle the following section of
// RFC4627:
@@ -94,7 +94,7 @@ private:
// "\uD834\uDD1E".
//
// Two subsequent \u.... may have to be replaced with one actual codepoint.
- unsigned int surpair; // First half of open UTF-16 surrogate pair, or 0
+ unsigned int surpair{0}; // First half of open UTF-16 surrogate pair, or 0
void append_codepoint(unsigned int codepoint_)
{
diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp
index eeaadae3e2..5ddf300393 100644
--- a/src/univalue/test/object.cpp
+++ b/src/univalue/test/object.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2014 BitPay Inc.
-// Copyright (c) 2014-2016 The Bitcoin Core developers
+// Copyright (c) 2014-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://opensource.org/licenses/mit-license.php.
diff --git a/src/util/asmap.cpp b/src/util/asmap.cpp
index 33258d9962..4b548c5a4d 100644
--- a/src/util/asmap.cpp
+++ b/src/util/asmap.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/bip32.cpp b/src/util/bip32.cpp
index 796af4a544..c4b7120394 100644
--- a/src/util/bip32.cpp
+++ b/src/util/bip32.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/bip32.h b/src/util/bip32.h
index 0872bc88de..b720cb5638 100644
--- a/src/util/bip32.h
+++ b/src/util/bip32.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/bytevectorhash.cpp b/src/util/bytevectorhash.cpp
index 6d777613e6..29be138eeb 100644
--- a/src/util/bytevectorhash.cpp
+++ b/src/util/bytevectorhash.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/bytevectorhash.h b/src/util/bytevectorhash.h
index c2322b8daf..079385678c 100644
--- a/src/util/bytevectorhash.h
+++ b/src/util/bytevectorhash.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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.cpp b/src/util/check.cpp
index 34b9d376a7..795dce7124 100644
--- a/src/util/check.cpp
+++ b/src/util/check.cpp
@@ -14,8 +14,9 @@
#include <cstdio>
#include <cstdlib>
#include <string>
+#include <string_view>
-std::string StrFormatInternalBug(const char* msg, const char* file, int line, const char* func)
+std::string StrFormatInternalBug(std::string_view msg, std::string_view file, int line, std::string_view func)
{
return strprintf("Internal bug detected: \"%s\"\n%s:%d (%s)\n"
"%s %s\n"
@@ -23,12 +24,12 @@ std::string StrFormatInternalBug(const char* msg, const char* file, int line, co
msg, file, line, func, PACKAGE_NAME, FormatFullVersion(), PACKAGE_BUGREPORT);
}
-NonFatalCheckError::NonFatalCheckError(const char* msg, const char* file, int line, const char* func)
+NonFatalCheckError::NonFatalCheckError(std::string_view msg, std::string_view file, int line, std::string_view func)
: std::runtime_error{StrFormatInternalBug(msg, file, line, func)}
{
}
-void assertion_fail(const char* file, int line, const char* func, const char* assertion)
+void assertion_fail(std::string_view file, int line, std::string_view func, std::string_view assertion)
{
auto str = strprintf("%s:%s %s: Assertion `%s' failed.\n", file, line, func, assertion);
fwrite(str.data(), 1, str.size(), stderr);
diff --git a/src/util/check.h b/src/util/check.h
index b791944502..7ddcebf506 100644
--- a/src/util/check.h
+++ b/src/util/check.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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,14 +8,16 @@
#include <attributes.h>
#include <stdexcept>
+#include <string>
+#include <string_view>
#include <utility>
-std::string StrFormatInternalBug(const char* msg, const char* file, int line, const char* func);
+std::string StrFormatInternalBug(std::string_view msg, std::string_view file, int line, std::string_view func);
class NonFatalCheckError : public std::runtime_error
{
public:
- NonFatalCheckError(const char* msg, const char* file, int line, const char* func);
+ NonFatalCheckError(std::string_view msg, std::string_view file, int line, std::string_view func);
};
#define STR_INTERNAL_BUG(msg) StrFormatInternalBug((msg), __FILE__, __LINE__, __func__)
@@ -49,7 +51,7 @@ T&& inline_check_non_fatal(LIFETIMEBOUND T&& val, const char* file, int line, co
#endif
/** Helper for Assert() */
-void assertion_fail(const char* file, int line, const char* func, const char* assertion);
+void assertion_fail(std::string_view file, int line, std::string_view func, std::string_view assertion);
/** Helper for Assert()/Assume() */
template <bool IS_ASSERT, typename T>
diff --git a/src/util/epochguard.h b/src/util/epochguard.h
index 7f6477fb3b..145f4dc132 100644
--- a/src/util/epochguard.h
+++ b/src/util/epochguard.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.cpp b/src/util/error.cpp
index 390cb6c11b..193265c842 100644
--- a/src/util/error.cpp
+++ b/src/util/error.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2010-2021 The Bitcoin Core developers
+// Copyright (c) 2010-2022 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 27916501f0..649200c98e 100644
--- a/src/util/error.h
+++ b/src/util/error.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010-2020 The Bitcoin Core developers
+// Copyright (c) 2010-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.
diff --git a/src/util/fastrange.h b/src/util/fastrange.h
index 77cb883ce0..87a2415976 100644
--- a/src/util/fastrange.h
+++ b/src/util/fastrange.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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 cbefe18dbb..8ada02ce54 100644
--- a/src/util/fees.cpp
+++ b/src/util/fees.cpp
@@ -49,7 +49,7 @@ std::string FeeModes(const std::string& delimiter)
return Join(FeeModeMap(), delimiter, [&](const std::pair<std::string, FeeEstimateMode>& i) { return i.first; });
}
-const std::string InvalidEstimateModeErrorMessage()
+std::string InvalidEstimateModeErrorMessage()
{
return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\"";
}
diff --git a/src/util/fees.h b/src/util/fees.h
index 9ef2389d3e..10ba1e4f85 100644
--- a/src/util/fees.h
+++ b/src/util/fees.h
@@ -13,6 +13,6 @@ enum class FeeReason;
bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode);
std::string StringForFeeReason(FeeReason reason);
std::string FeeModes(const std::string& delimiter);
-const std::string InvalidEstimateModeErrorMessage();
+std::string InvalidEstimateModeErrorMessage();
#endif // BITCOIN_UTIL_FEES_H
diff --git a/src/util/getuniquepath.cpp b/src/util/getuniquepath.cpp
index 1d8e511c83..42c5dee0ed 100644
--- a/src/util/getuniquepath.cpp
+++ b/src/util/getuniquepath.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/golombrice.h b/src/util/golombrice.h
index 4ff4f6d7e5..63402c5e4d 100644
--- a/src/util/golombrice.h
+++ b/src/util/golombrice.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2020 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/hasher.cpp b/src/util/hasher.cpp
index a80f20c894..a3a3f7a429 100644
--- a/src/util/hasher.cpp
+++ b/src/util/hasher.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/hasher.h b/src/util/hasher.h
index 426b8990e6..82d278b086 100644
--- a/src/util/hasher.h
+++ b/src/util/hasher.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/macros.h b/src/util/macros.h
index bf6ba665dc..11aa683152 100644
--- a/src/util/macros.h
+++ b/src/util/macros.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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 7d6f3403f4..f8ea8247d5 100644
--- a/src/util/message.cpp
+++ b/src/util/message.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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.h b/src/util/message.h
index 1b7febe60a..d0e2422574 100644
--- a/src/util/message.h
+++ b/src/util/message.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/moneystr.cpp b/src/util/moneystr.cpp
index d9e6cef600..9181329afc 100644
--- a/src/util/moneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -34,7 +34,7 @@ std::string FormatMoney(const CAmount n)
str.erase(str.size()-nTrim, nTrim);
if (n < 0)
- str.insert((unsigned int)0, 1, '-');
+ str.insert(uint32_t{0}, 1, '-');
return str;
}
diff --git a/src/util/moneystr.h b/src/util/moneystr.h
index 3d33bd7f99..dba0ce676a 100644
--- a/src/util/moneystr.h
+++ b/src/util/moneystr.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/overflow.h b/src/util/overflow.h
index 6b7dd1e8fd..7e0cce6c27 100644
--- a/src/util/overflow.h
+++ b/src/util/overflow.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/readwritefile.cpp b/src/util/readwritefile.cpp
index 3ec08119e7..c22e6815e3 100644
--- a/src/util/readwritefile.cpp
+++ b/src/util/readwritefile.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/util/serfloat.h b/src/util/serfloat.h
index 343ccb9d3a..0dbba6ee03 100644
--- a/src/util/serfloat.h
+++ b/src/util/serfloat.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/settings.cpp b/src/util/settings.cpp
index 924a9cfab2..2b25b7f0e1 100644
--- a/src/util/settings.cpp
+++ b/src/util/settings.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/settings.h b/src/util/settings.h
index e97158dc09..b0d8acb711 100644
--- a/src/util/settings.h
+++ b/src/util/settings.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2020 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/sock.cpp b/src/util/sock.cpp
index e3d30c24b3..53d20bdf19 100644
--- a/src/util/sock.cpp
+++ b/src/util/sock.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/sock.h b/src/util/sock.h
index a7347df8ee..6bac2dfd34 100644
--- a/src/util/sock.h
+++ b/src/util/sock.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -181,9 +181,9 @@ public:
* Auxiliary requested/occurred events to wait for in `WaitMany()`.
*/
struct Events {
- explicit Events(Event req) : requested{req}, occurred{0} {}
+ explicit Events(Event req) : requested{req} {}
Event requested;
- Event occurred;
+ Event occurred{0};
};
struct HashSharedPtrSock {
diff --git a/src/util/spanparsing.cpp b/src/util/spanparsing.cpp
index 565c867e18..c464fc2b87 100644
--- a/src/util/spanparsing.cpp
+++ b/src/util/spanparsing.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/spanparsing.h b/src/util/spanparsing.h
index 51795271de..765fe13aca 100644
--- a/src/util/spanparsing.h
+++ b/src/util/spanparsing.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/strencodings.cpp b/src/util/strencodings.cpp
index e28ca8e73a..45a01429e1 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/strencodings.h b/src/util/strencodings.h
index 94bc6cc2f3..626e48f499 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/string.cpp b/src/util/string.cpp
index e994c85f1c..3d31849745 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/string.h b/src/util/string.h
index 9b4c9a7e28..fb93d2a80e 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/syscall_sandbox.cpp b/src/util/syscall_sandbox.cpp
index a69f815ce4..b1579bdb9c 100644
--- a/src/util/syscall_sandbox.cpp
+++ b/src/util/syscall_sandbox.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/syscall_sandbox.h b/src/util/syscall_sandbox.h
index dc02ce29e9..3e56ebe937 100644
--- a/src/util/syscall_sandbox.h
+++ b/src/util/syscall_sandbox.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/system.cpp b/src/util/system.cpp
index d7a0793ea8..0cea283ece 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -242,7 +242,7 @@ static std::optional<util::SettingsValue> InterpretValue(const KeyInfo& key, con
ArgsManager::ArgsManager() = default;
ArgsManager::~ArgsManager() = default;
-const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
+std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
{
std::set<std::string> unsuitables;
@@ -262,7 +262,7 @@ const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
return unsuitables;
}
-const std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const
+std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const
{
// Section names to be recognized in the config file.
static const std::set<std::string> available_sections{
diff --git a/src/util/system.h b/src/util/system.h
index 29629e547e..c053adf8c3 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -250,12 +250,12 @@ protected:
* on the command line or in a network-specific section in the
* config file.
*/
- const std::set<std::string> GetUnsuitableSectionOnlyArgs() const;
+ std::set<std::string> GetUnsuitableSectionOnlyArgs() const;
/**
* Log warnings for unrecognized section names in the config file.
*/
- const std::list<SectionInfo> GetUnrecognizedSections() const;
+ std::list<SectionInfo> GetUnrecognizedSections() const;
struct Command {
/** The command (if one has been registered with AddCommand), or empty */
diff --git a/src/util/thread.cpp b/src/util/thread.cpp
index ae98abdb3d..e9f611bc50 100644
--- a/src/util/thread.cpp
+++ b/src/util/thread.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/thread.h b/src/util/thread.h
index b80bf046a0..8a2de84a7f 100644
--- a/src/util/thread.h
+++ b/src/util/thread.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/threadinterrupt.cpp b/src/util/threadinterrupt.cpp
index 70731d6f31..3ea406d4a8 100644
--- a/src/util/threadinterrupt.cpp
+++ b/src/util/threadinterrupt.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/threadinterrupt.h b/src/util/threadinterrupt.h
index d95cbb9aba..ccc053f576 100644
--- a/src/util/threadinterrupt.h
+++ b/src/util/threadinterrupt.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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/threadnames.cpp b/src/util/threadnames.cpp
index a5a86d2598..91883fe4ff 100644
--- a/src/util/threadnames.cpp
+++ b/src/util/threadnames.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/time.cpp b/src/util/time.cpp
index 0b20849079..58200c83fc 100644
--- a/src/util/time.cpp
+++ b/src/util/time.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/time.h b/src/util/time.h
index 10a581a44c..d45baaa378 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/tokenpipe.cpp b/src/util/tokenpipe.cpp
index 49456814e2..3c27d5e523 100644
--- a/src/util/tokenpipe.cpp
+++ b/src/util/tokenpipe.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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 <util/tokenpipe.h>
diff --git a/src/util/translation.h b/src/util/translation.h
index 07b7f43c8a..05e7da0b5a 100644
--- a/src/util/translation.h
+++ b/src/util/translation.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/vector.h b/src/util/vector.h
index ed745affe5..9b9218e54f 100644
--- a/src/util/vector.h
+++ b/src/util/vector.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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 d7017248fc..f0ffb748dd 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -64,6 +64,7 @@
#include <numeric>
#include <optional>
#include <string>
+#include <utility>
using kernel::CCoinsStats;
using kernel::CoinStatsHashType;
@@ -75,8 +76,6 @@ using node::BlockManager;
using node::BlockMap;
using node::CBlockIndexHeightOnlyComparator;
using node::CBlockIndexWorkComparator;
-using node::fImporting;
-using node::fPruneMode;
using node::fReindex;
using node::ReadBlockFromDisk;
using node::SnapshotMetadata;
@@ -106,18 +105,6 @@ const std::vector<std::string> CHECKLEVEL_DOC {
* */
static constexpr int PRUNE_LOCK_BUFFER{10};
-/**
- * Mutex to guard access to validation specific variables, such as reading
- * or changing the chainstate.
- *
- * This may also need to be locked when updating the transaction pool, e.g. on
- * AcceptToMemoryPool. See CTxMemPool::cs comment for details.
- *
- * The transaction pool has a separate lock to allow reading from it and the
- * chainstate at the same time.
- */
-RecursiveMutex cs_main;
-
GlobalMutex g_best_block_mutex;
std::condition_variable g_best_block_cv;
uint256 g_best_block;
@@ -582,6 +569,11 @@ private:
/** Total virtual size of all transactions being replaced. */
size_t m_conflicting_size{0};
+ /** If we're doing package validation (i.e. m_package_feerates=true), the "effective"
+ * package feerate of this transaction is the total fees divided by the total size of
+ * transactions (which may include its ancestors and/or descendants). */
+ CFeeRate m_package_feerate{0};
+
const CTransactionRef& m_ptx;
/** Txid. */
const uint256& m_hash;
@@ -690,10 +682,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
}
- // Do not work on transactions that are too small.
- // A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes.
- // Transactions smaller than this are not relayed to mitigate CVE-2017-12842 by not relaying
- // 64-byte transactions.
+ // Transactions smaller than 65 non-witness bytes are not relayed to mitigate CVE-2017-12842.
if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) < MIN_STANDARD_TX_NONWITNESS_SIZE)
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "tx-size-small");
@@ -870,11 +859,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
m_limits.descendant_size_vbytes += conflict->GetSizeWithDescendants();
}
- std::string errString;
- if (!m_pool.CalculateMemPoolAncestors(*entry, ws.m_ancestors, m_limits, errString)) {
- ws.m_ancestors.clear();
+ auto ancestors{m_pool.CalculateMemPoolAncestors(*entry, m_limits)};
+ if (!ancestors) {
// If CalculateMemPoolAncestors fails second time, we want the original error string.
- std::string dummy_err_string;
// Contracting/payment channels CPFP carve-out:
// If the new transaction is relatively small (up to 40k weight)
// and has at most one ancestor (ie ancestor limit of 2, including
@@ -892,14 +879,16 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
.descendant_count = m_limits.descendant_count + 1,
.descendant_size_vbytes = m_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
};
- if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT ||
- !m_pool.CalculateMemPoolAncestors(*entry, ws.m_ancestors,
- cpfp_carve_out_limits,
- dummy_err_string)) {
- return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", errString);
+ const auto error_message{util::ErrorString(ancestors).original};
+ if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT) {
+ return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
}
+ ancestors = m_pool.CalculateMemPoolAncestors(*entry, cpfp_carve_out_limits);
+ if (!ancestors) return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
}
+ ws.m_ancestors = *ancestors;
+
// A transaction that spends outputs that would be replaced by it is invalid. Now
// that we have the set of all ancestors we can detect this
// pathological case by making sure ws.m_conflicts and ws.m_ancestors don't
@@ -1114,15 +1103,18 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
// Re-calculate mempool ancestors to call addUnchecked(). They may have changed since the
// last calculation done in PreChecks, since package ancestors have already been submitted.
- std::string unused_err_string;
- if(!m_pool.CalculateMemPoolAncestors(*ws.m_entry, ws.m_ancestors, m_limits, unused_err_string)) {
- results.emplace(ws.m_ptx->GetWitnessHash(), MempoolAcceptResult::Failure(ws.m_state));
- // Since PreChecks() and PackageMempoolChecks() both enforce limits, this should never fail.
- Assume(false);
- all_submitted = false;
- package_state.Invalid(PackageValidationResult::PCKG_MEMPOOL_ERROR,
- strprintf("BUG! Mempool ancestors or descendants were underestimated: %s",
- ws.m_ptx->GetHash().ToString()));
+ {
+ auto ancestors{m_pool.CalculateMemPoolAncestors(*ws.m_entry, m_limits)};
+ if(!ancestors) {
+ results.emplace(ws.m_ptx->GetWitnessHash(), MempoolAcceptResult::Failure(ws.m_state));
+ // Since PreChecks() and PackageMempoolChecks() both enforce limits, this should never fail.
+ Assume(false);
+ all_submitted = false;
+ package_state.Invalid(PackageValidationResult::PCKG_MEMPOOL_ERROR,
+ strprintf("BUG! Mempool ancestors or descendants were underestimated: %s",
+ ws.m_ptx->GetHash().ToString()));
+ }
+ ws.m_ancestors = std::move(ancestors).value_or(ws.m_ancestors);
}
// If we call LimitMempoolSize() for each individual Finalize(), the mempool will not take
// the transaction's descendant feerate into account because it hasn't seen them yet. Also,
@@ -1143,12 +1135,21 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
// make sure we haven't exceeded max mempool size.
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
+ std::vector<uint256> all_package_wtxids;
+ all_package_wtxids.reserve(workspaces.size());
+ std::transform(workspaces.cbegin(), workspaces.cend(), std::back_inserter(all_package_wtxids),
+ [](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
// Find the wtxids of the transactions that made it into the mempool. Allow partial submission,
// but don't report success unless they all made it into the mempool.
for (Workspace& ws : workspaces) {
+ const auto effective_feerate = args.m_package_feerates ? ws.m_package_feerate :
+ CFeeRate{ws.m_modified_fees, static_cast<uint32_t>(ws.m_vsize)};
+ const auto effective_feerate_wtxids = args.m_package_feerates ? all_package_wtxids :
+ std::vector<uint256>({ws.m_ptx->GetWitnessHash()});
if (m_pool.exists(GenTxid::Wtxid(ws.m_ptx->GetWitnessHash()))) {
results.emplace(ws.m_ptx->GetWitnessHash(),
- MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees));
+ MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize,
+ ws.m_base_fees, effective_feerate, effective_feerate_wtxids));
GetMainSignals().TransactionAddedToMempool(ws.m_ptx, m_pool.GetAndIncrementSequence());
} else {
all_submitted = false;
@@ -1176,16 +1177,20 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
if (!ConsensusScriptChecks(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
+ const CFeeRate effective_feerate{ws.m_modified_fees, static_cast<uint32_t>(ws.m_vsize)};
+ const std::vector<uint256> single_wtxid{ws.m_ptx->GetWitnessHash()};
// Tx was accepted, but not added
if (args.m_test_accept) {
- return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees);
+ return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize,
+ ws.m_base_fees, effective_feerate, single_wtxid);
}
if (!Finalize(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence());
- return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees);
+ return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees,
+ effective_feerate, single_wtxid);
}
PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::vector<CTransactionRef>& txns, ATMPArgs& args)
@@ -1232,7 +1237,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
if (args.m_package_feerates &&
!CheckFeeRate(m_total_vsize, m_total_modified_fees, placeholder_state)) {
package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-fee-too-low");
- return PackageMempoolAcceptResult(package_state, package_feerate, {});
+ return PackageMempoolAcceptResult(package_state, {});
}
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
@@ -1240,51 +1245,60 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
// transactions, but this exemption is not extended to packages in CheckPackageLimits().
std::string err_string;
if (txns.size() > 1 && !PackageMempoolChecks(txns, package_state)) {
- return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
+ return PackageMempoolAcceptResult(package_state, std::move(results));
}
+ std::vector<uint256> all_package_wtxids;
+ all_package_wtxids.reserve(workspaces.size());
+ std::transform(workspaces.cbegin(), workspaces.cend(), std::back_inserter(all_package_wtxids),
+ [](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
for (Workspace& ws : workspaces) {
+ ws.m_package_feerate = package_feerate;
if (!PolicyScriptChecks(args, ws)) {
// Exit early to avoid doing pointless work. Update the failed tx result; the rest are unfinished.
package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
results.emplace(ws.m_ptx->GetWitnessHash(), MempoolAcceptResult::Failure(ws.m_state));
- return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
+ return PackageMempoolAcceptResult(package_state, std::move(results));
}
if (args.m_test_accept) {
- // When test_accept=true, transactions that pass PolicyScriptChecks are valid because there are
- // no further mempool checks (passing PolicyScriptChecks implies passing ConsensusScriptChecks).
+ const auto effective_feerate = args.m_package_feerates ? ws.m_package_feerate :
+ CFeeRate{ws.m_modified_fees, static_cast<uint32_t>(ws.m_vsize)};
+ const auto effective_feerate_wtxids = args.m_package_feerates ? all_package_wtxids :
+ std::vector<uint256>{ws.m_ptx->GetWitnessHash()};
results.emplace(ws.m_ptx->GetWitnessHash(),
MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions),
- ws.m_vsize, ws.m_base_fees));
+ ws.m_vsize, ws.m_base_fees, effective_feerate,
+ effective_feerate_wtxids));
}
}
- if (args.m_test_accept) return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
+ if (args.m_test_accept) return PackageMempoolAcceptResult(package_state, std::move(results));
if (!SubmitPackage(args, workspaces, package_state, results)) {
// PackageValidationState filled in by SubmitPackage().
- return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
+ return PackageMempoolAcceptResult(package_state, std::move(results));
}
- return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
+ return PackageMempoolAcceptResult(package_state, std::move(results));
}
PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package, ATMPArgs& args)
{
AssertLockHeld(cs_main);
- PackageValidationState package_state;
+ // Used if returning a PackageMempoolAcceptResult directly from this function.
+ PackageValidationState package_state_quit_early;
// Check that the package is well-formed. If it isn't, we won't try to validate any of the
// transactions and thus won't return any MempoolAcceptResults, just a package-wide error.
// Context-free package checks.
- if (!CheckPackage(package, package_state)) return PackageMempoolAcceptResult(package_state, {});
+ if (!CheckPackage(package, package_state_quit_early)) return PackageMempoolAcceptResult(package_state_quit_early, {});
// All transactions in the package must be a parent of the last transaction. This is just an
// opportunity for us to fail fast on a context-free check without taking the mempool lock.
if (!IsChildWithParents(package)) {
- package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-not-child-with-parents");
- return PackageMempoolAcceptResult(package_state, {});
+ package_state_quit_early.Invalid(PackageValidationResult::PCKG_POLICY, "package-not-child-with-parents");
+ return PackageMempoolAcceptResult(package_state_quit_early, {});
}
// IsChildWithParents() guarantees the package is > 1 transactions.
@@ -1316,15 +1330,16 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
return unconfirmed_parent_txids.count(input.prevout.hash) > 0 || m_view.HaveCoin(input.prevout);
};
if (!std::all_of(child->vin.cbegin(), child->vin.cend(), package_or_confirmed)) {
- package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-not-child-with-unconfirmed-parents");
- return PackageMempoolAcceptResult(package_state, {});
+ package_state_quit_early.Invalid(PackageValidationResult::PCKG_POLICY, "package-not-child-with-unconfirmed-parents");
+ return PackageMempoolAcceptResult(package_state_quit_early, {});
}
// Protect against bugs where we pull more inputs from disk that miss being added to
// coins_to_uncache. The backend will be connected again when needed in PreChecks.
m_view.SetBackend(m_dummy);
LOCK(m_pool.cs);
- std::map<const uint256, const MempoolAcceptResult> results;
+ // Stores final results that won't change
+ std::map<const uint256, const MempoolAcceptResult> results_final;
// Node operators are free to set their mempool policies however they please, nodes may receive
// transactions in different orders, and malicious counterparties may try to take advantage of
// policy differences to pin or delay propagation of transactions. As such, it's possible for
@@ -1334,8 +1349,13 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
// the new transactions. This ensures we don't double-count transaction counts and sizes when
// checking ancestor/descendant limits, or double-count transaction fees for fee-related policy.
ATMPArgs single_args = ATMPArgs::SingleInPackageAccept(args);
+ // Results from individual validation. "Nonfinal" because if a transaction fails by itself but
+ // succeeds later (i.e. when evaluated with a fee-bumping child), the result changes (though not
+ // reflected in this map). If a transaction fails more than once, we want to return the first
+ // result, when it was considered on its own. So changes will only be from invalid -> valid.
+ std::map<uint256, MempoolAcceptResult> individual_results_nonfinal;
bool quit_early{false};
- std::vector<CTransactionRef> txns_new;
+ std::vector<CTransactionRef> txns_package_eval;
for (const auto& tx : package) {
const auto& wtxid = tx->GetWitnessHash();
const auto& txid = tx->GetHash();
@@ -1346,7 +1366,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
// Exact transaction already exists in the mempool.
auto iter = m_pool.GetIter(txid);
assert(iter != std::nullopt);
- results.emplace(wtxid, MempoolAcceptResult::MempoolTx(iter.value()->GetTxSize(), iter.value()->GetFee()));
+ results_final.emplace(wtxid, MempoolAcceptResult::MempoolTx(iter.value()->GetTxSize(), iter.value()->GetFee()));
} else if (m_pool.exists(GenTxid::Txid(txid))) {
// Transaction with the same non-witness data but different witness (same txid,
// different wtxid) already exists in the mempool.
@@ -1358,7 +1378,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
auto iter = m_pool.GetIter(txid);
assert(iter != std::nullopt);
// Provide the wtxid of the mempool tx so that the caller can look it up in the mempool.
- results.emplace(wtxid, MempoolAcceptResult::MempoolTxDifferentWitness(iter.value()->GetTx().GetWitnessHash()));
+ results_final.emplace(wtxid, MempoolAcceptResult::MempoolTxDifferentWitness(iter.value()->GetTx().GetWitnessHash()));
} else {
// Transaction does not already exist in the mempool.
// Try submitting the transaction on its own.
@@ -1367,7 +1387,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
// The transaction succeeded on its own and is now in the mempool. Don't include it
// in package validation, because its fees should only be "used" once.
assert(m_pool.exists(GenTxid::Wtxid(wtxid)));
- results.emplace(wtxid, single_res);
+ results_final.emplace(wtxid, single_res);
} else if (single_res.m_state.GetResult() != TxValidationResult::TX_MEMPOOL_POLICY &&
single_res.m_state.GetResult() != TxValidationResult::TX_MISSING_INPUTS) {
// Package validation policy only differs from individual policy in its evaluation
@@ -1380,24 +1400,40 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
// future. Continue individually validating the rest of the transactions, because
// some of them may still be valid.
quit_early = true;
+ package_state_quit_early.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
+ individual_results_nonfinal.emplace(wtxid, single_res);
} else {
- txns_new.push_back(tx);
+ individual_results_nonfinal.emplace(wtxid, single_res);
+ txns_package_eval.push_back(tx);
}
}
}
- // Nothing to do if the entire package has already been submitted.
- if (quit_early || txns_new.empty()) {
- // No package feerate when no package validation was done.
- return PackageMempoolAcceptResult(package_state, std::move(results));
+ // Quit early because package validation won't change the result or the entire package has
+ // already been submitted.
+ if (quit_early || txns_package_eval.empty()) {
+ for (const auto& [wtxid, mempoolaccept_res] : individual_results_nonfinal) {
+ Assume(results_final.emplace(wtxid, mempoolaccept_res).second);
+ Assume(mempoolaccept_res.m_result_type == MempoolAcceptResult::ResultType::INVALID);
+ }
+ return PackageMempoolAcceptResult(package_state_quit_early, std::move(results_final));
}
- // Validate the (deduplicated) transactions as a package.
- auto submission_result = AcceptMultipleTransactions(txns_new, args);
+ // Validate the (deduplicated) transactions as a package. Note that submission_result has its
+ // own PackageValidationState; package_state_quit_early is unused past this point.
+ auto submission_result = AcceptMultipleTransactions(txns_package_eval, args);
// Include already-in-mempool transaction results in the final result.
- for (const auto& [wtxid, mempoolaccept_res] : results) {
- submission_result.m_tx_results.emplace(wtxid, mempoolaccept_res);
+ for (const auto& [wtxid, mempoolaccept_res] : results_final) {
+ Assume(submission_result.m_tx_results.emplace(wtxid, mempoolaccept_res).second);
+ Assume(mempoolaccept_res.m_result_type != MempoolAcceptResult::ResultType::INVALID);
+ }
+ if (submission_result.m_state.GetResult() == PackageValidationResult::PCKG_TX) {
+ // Package validation failed because one or more transactions failed. Provide a result for
+ // each transaction; if AcceptMultipleTransactions() didn't return a result for a tx,
+ // include the previous individual failure reason.
+ submission_result.m_tx_results.insert(individual_results_nonfinal.cbegin(),
+ individual_results_nonfinal.cend());
+ Assume(submission_result.m_tx_results.size() == package.size());
}
- if (submission_result.m_state.IsValid()) assert(submission_result.m_package_feerate.has_value());
return submission_result;
}
@@ -1414,7 +1450,7 @@ MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTra
std::vector<COutPoint> coins_to_uncache;
auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, bypass_limits, coins_to_uncache, test_accept);
- const MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
+ MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
// Remove coins that were not present in the coins cache before calling
// AcceptSingleTransaction(); this is to prevent memory DoS in case we receive a large
@@ -1439,7 +1475,7 @@ PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxM
std::vector<COutPoint> coins_to_uncache;
const CChainParams& chainparams = active_chainstate.m_chainman.GetParams();
- const auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
+ auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
AssertLockHeld(cs_main);
if (test_accept) {
auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams, GetTime(), coins_to_uncache);
@@ -1535,14 +1571,15 @@ bool Chainstate::IsInitialBlockDownload() const
LOCK(cs_main);
if (m_cached_finished_ibd.load(std::memory_order_relaxed))
return false;
- if (fImporting || fReindex)
+ if (m_chainman.m_blockman.LoadingBlocks()) {
return true;
+ }
if (m_chain.Tip() == nullptr)
return true;
if (m_chain.Tip()->nChainWork < m_chainman.MinimumChainWork()) {
return true;
}
- if (m_chain.Tip()->Time() < NodeClock::now() - m_chainman.m_options.max_tip_age) {
+ if (m_chain.Tip()->Time() < Now<NodeSeconds>() - m_chainman.m_options.max_tip_age) {
return true;
}
LogPrintf("Leaving InitialBlockDownload (latching to false)\n");
@@ -2373,7 +2410,7 @@ bool Chainstate::FlushStateToDisk(
CoinsCacheSizeState cache_state = GetCoinsCacheSizeState();
LOCK(m_blockman.cs_LastBlockFile);
- if (fPruneMode && (m_blockman.m_check_for_pruning || nManualPruneHeight > 0) && !fReindex) {
+ if (m_blockman.IsPruneMode() && (m_blockman.m_check_for_pruning || nManualPruneHeight > 0) && !fReindex) {
// make sure we don't prune above any of the prune locks bestblocks
// pruning is height-based
int last_prune{m_chain.Height()}; // last height we can prune
@@ -4044,7 +4081,8 @@ bool CVerifyDB::VerifyDB(
int nGoodTransactions = 0;
BlockValidationState state;
int reportDone = 0;
- LogPrintf("[0%%]..."); /* Continued */
+ bool skipped_l3_checks{false};
+ LogPrintf("Verification progress: 0%%\n");
const bool is_snapshot_cs{!chainstate.m_from_snapshot_blockhash};
@@ -4052,14 +4090,14 @@ bool CVerifyDB::VerifyDB(
const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
if (reportDone < percentageDone / 10) {
// report every 10% step
- LogPrintf("[%d%%]...", percentageDone); /* Continued */
+ LogPrintf("Verification progress: %d%%\n", percentageDone);
reportDone = percentageDone / 10;
}
uiInterface.ShowProgress(_("Verifying blocks…").translated, percentageDone, false);
if (pindex->nHeight <= chainstate.m_chain.Height() - nCheckDepth) {
break;
}
- if ((fPruneMode || is_snapshot_cs) && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
+ if ((chainstate.m_blockman.IsPruneMode() || is_snapshot_cs) && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
// If pruning or running under an assumeutxo snapshot, only go
// back as far as we have data.
LogPrintf("VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->nHeight);
@@ -4087,17 +4125,21 @@ bool CVerifyDB::VerifyDB(
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
size_t curr_coins_usage = coins.DynamicMemoryUsage() + chainstate.CoinsTip().DynamicMemoryUsage();
- if (nCheckLevel >= 3 && curr_coins_usage <= chainstate.m_coinstip_cache_size_bytes) {
- assert(coins.GetBestBlock() == pindex->GetBlockHash());
- DisconnectResult res = chainstate.DisconnectBlock(block, pindex, coins);
- if (res == DISCONNECT_FAILED) {
- return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
- }
- if (res == DISCONNECT_UNCLEAN) {
- nGoodTransactions = 0;
- pindexFailure = pindex;
+ if (nCheckLevel >= 3) {
+ if (curr_coins_usage <= chainstate.m_coinstip_cache_size_bytes) {
+ assert(coins.GetBestBlock() == pindex->GetBlockHash());
+ DisconnectResult res = chainstate.DisconnectBlock(block, pindex, coins);
+ if (res == DISCONNECT_FAILED) {
+ return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
+ }
+ if (res == DISCONNECT_UNCLEAN) {
+ nGoodTransactions = 0;
+ pindexFailure = pindex;
+ } else {
+ nGoodTransactions += block.vtx.size();
+ }
} else {
- nGoodTransactions += block.vtx.size();
+ skipped_l3_checks = true;
}
}
if (ShutdownRequested()) return true;
@@ -4105,17 +4147,19 @@ bool CVerifyDB::VerifyDB(
if (pindexFailure) {
return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainstate.m_chain.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
}
-
+ if (skipped_l3_checks) {
+ LogPrintf("Skipped verification of level >=3 (insufficient database cache size). Consider increasing -dbcache.\n");
+ }
// store block count as we move pindex at check level >= 4
int block_count = chainstate.m_chain.Height() - pindex->nHeight;
// check level 4: try reconnecting blocks
- if (nCheckLevel >= 4) {
+ if (nCheckLevel >= 4 && !skipped_l3_checks) {
while (pindex != chainstate.m_chain.Tip()) {
const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)));
if (reportDone < percentageDone / 10) {
// report every 10% step
- LogPrintf("[%d%%]...", percentageDone); /* Continued */
+ LogPrintf("Verification progress: %d%%\n", percentageDone);
reportDone = percentageDone / 10;
}
uiInterface.ShowProgress(_("Verifying blocks…").translated, percentageDone, false);
@@ -4130,8 +4174,7 @@ bool CVerifyDB::VerifyDB(
}
}
- LogPrintf("[DONE].\n");
- LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
+ LogPrintf("Verification: No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
return true;
}
diff --git a/src/validation.h b/src/validation.h
index 00f7265793..7170467b00 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 @@
#include <consensus/amount.h>
#include <deploymentstatus.h>
#include <fs.h>
+#include <kernel/cs_main.h> // IWYU pragma: export
#include <node/blockstorage.h>
#include <policy/feerate.h>
#include <policy/packages.h>
@@ -86,7 +87,6 @@ enum class SynchronizationState {
POST_INIT
};
-extern RecursiveMutex cs_main;
extern GlobalMutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
/** Used to notify getblocktemplate RPC of new tips. */
@@ -134,6 +134,19 @@ struct MempoolAcceptResult {
const std::optional<int64_t> m_vsize;
/** Raw base fees in satoshis. */
const std::optional<CAmount> m_base_fees;
+ /** The feerate at which this transaction was considered. This includes any fee delta added
+ * using prioritisetransaction (i.e. modified fees). If this transaction was submitted as a
+ * package, this is the package feerate, which may also include its descendants and/or
+ * ancestors (see m_wtxids_fee_calculations below).
+ * Only present when m_result_type = ResultType::VALID.
+ */
+ const std::optional<CFeeRate> m_effective_feerate;
+ /** Contains the wtxids of the transactions used for fee-related checks. Includes this
+ * transaction's wtxid and may include others if this transaction was validated as part of a
+ * package. This is not necessarily equivalent to the list of transactions passed to
+ * ProcessNewPackage().
+ * Only present when m_result_type = ResultType::VALID. */
+ const std::optional<std::vector<uint256>> m_wtxids_fee_calculations;
// The following field is only present when m_result_type = ResultType::DIFFERENT_WITNESS
/** The wtxid of the transaction in the mempool which has the same txid but different witness. */
@@ -143,8 +156,13 @@ struct MempoolAcceptResult {
return MempoolAcceptResult(state);
}
- static MempoolAcceptResult Success(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees) {
- return MempoolAcceptResult(std::move(replaced_txns), vsize, fees);
+ static MempoolAcceptResult Success(std::list<CTransactionRef>&& replaced_txns,
+ int64_t vsize,
+ CAmount fees,
+ CFeeRate effective_feerate,
+ const std::vector<uint256>& wtxids_fee_calculations) {
+ return MempoolAcceptResult(std::move(replaced_txns), vsize, fees,
+ effective_feerate, wtxids_fee_calculations);
}
static MempoolAcceptResult MempoolTx(int64_t vsize, CAmount fees) {
@@ -164,9 +182,17 @@ private:
}
/** Constructor for success case */
- explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees)
+ explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns,
+ int64_t vsize,
+ CAmount fees,
+ CFeeRate effective_feerate,
+ const std::vector<uint256>& wtxids_fee_calculations)
: m_result_type(ResultType::VALID),
- m_replaced_transactions(std::move(replaced_txns)), m_vsize{vsize}, m_base_fees(fees) {}
+ m_replaced_transactions(std::move(replaced_txns)),
+ m_vsize{vsize},
+ m_base_fees(fees),
+ m_effective_feerate(effective_feerate),
+ m_wtxids_fee_calculations(wtxids_fee_calculations) {}
/** Constructor for already-in-mempool case. It wouldn't replace any transactions. */
explicit MempoolAcceptResult(int64_t vsize, CAmount fees)
@@ -190,10 +216,6 @@ struct PackageMempoolAcceptResult
* was a package-wide error (see result in m_state), m_tx_results will be empty.
*/
std::map<const uint256, const MempoolAcceptResult> m_tx_results;
- /** Package feerate, defined as the aggregated modified fees divided by the total virtual size
- * of all transactions in the package. May be unavailable if some inputs were not available or
- * a transaction failure caused validation to terminate early. */
- std::optional<CFeeRate> m_package_feerate;
explicit PackageMempoolAcceptResult(PackageValidationState state,
std::map<const uint256, const MempoolAcceptResult>&& results)
@@ -201,7 +223,7 @@ struct PackageMempoolAcceptResult
explicit PackageMempoolAcceptResult(PackageValidationState state, CFeeRate feerate,
std::map<const uint256, const MempoolAcceptResult>&& results)
- : m_state{state}, m_tx_results(std::move(results)), m_package_feerate{feerate} {}
+ : m_state{state}, m_tx_results(std::move(results)) {}
/** Constructor to create a PackageMempoolAcceptResult from a single MempoolAcceptResult */
explicit PackageMempoolAcceptResult(const uint256& wtxid, const MempoolAcceptResult& result)
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 740c39d99d..d344c8bfbd 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -17,7 +17,7 @@
#include <unordered_map>
#include <utility>
-const std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept;
+std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept;
/**
* MainSignalsImpl manages a list of shared_ptr<CValidationInterface> callbacks.
diff --git a/src/validationinterface.h b/src/validationinterface.h
index a929a3d56b..8c20cc8ffb 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -1,18 +1,18 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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_VALIDATIONINTERFACE_H
#define BITCOIN_VALIDATIONINTERFACE_H
+#include <kernel/cs_main.h>
#include <primitives/transaction.h> // CTransaction(Ref)
#include <sync.h>
#include <functional>
#include <memory>
-extern RecursiveMutex cs_main;
class BlockValidationState;
class CBlock;
class CBlockIndex;
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
index dc85655028..fa9d1fe9c9 100644
--- a/src/versionbits.cpp
+++ b/src/versionbits.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -195,7 +195,7 @@ protected:
public:
explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
- uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
+ uint32_t Mask(const Consensus::Params& params) const { return (uint32_t{1}) << params.vDeployments[id].bit; }
};
} // namespace
diff --git a/src/versionbits.h b/src/versionbits.h
index 9f7ee1b48e..09313d2054 100644
--- a/src/versionbits.h
+++ b/src/versionbits.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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 3a9d277f65..653115aa81 100644
--- a/src/wallet/bdb.cpp
+++ b/src/wallet/bdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,7 @@
#include <wallet/bdb.h>
#include <wallet/db.h>
+#include <util/check.h>
#include <util/strencodings.h>
#include <util/translation.h>
@@ -100,7 +101,7 @@ void BerkeleyEnvironment::Close()
if (ret != 0)
LogPrintf("BerkeleyEnvironment::Close: Error %d closing database environment: %s\n", ret, DbEnv::strerror(ret));
if (!fMockDb)
- DbEnv((uint32_t)0).remove(strPath.c_str(), 0);
+ DbEnv(uint32_t{0}).remove(strPath.c_str(), 0);
if (error_file) fclose(error_file);
@@ -220,17 +221,17 @@ BerkeleyEnvironment::BerkeleyEnvironment() : m_use_shared_memory(false)
fMockDb = true;
}
-BerkeleyBatch::SafeDbt::SafeDbt()
+SafeDbt::SafeDbt()
{
m_dbt.set_flags(DB_DBT_MALLOC);
}
-BerkeleyBatch::SafeDbt::SafeDbt(void* data, size_t size)
+SafeDbt::SafeDbt(void* data, size_t size)
: m_dbt(data, size)
{
}
-BerkeleyBatch::SafeDbt::~SafeDbt()
+SafeDbt::~SafeDbt()
{
if (m_dbt.get_data() != nullptr) {
// Clear memory, e.g. in case it was a private key
@@ -244,17 +245,17 @@ BerkeleyBatch::SafeDbt::~SafeDbt()
}
}
-const void* BerkeleyBatch::SafeDbt::get_data() const
+const void* SafeDbt::get_data() const
{
return m_dbt.get_data();
}
-uint32_t BerkeleyBatch::SafeDbt::get_size() const
+uint32_t SafeDbt::get_size() const
{
return m_dbt.get_size();
}
-BerkeleyBatch::SafeDbt::operator Dbt*()
+SafeDbt::operator Dbt*()
{
return &m_dbt;
}
@@ -307,7 +308,7 @@ BerkeleyDatabase::~BerkeleyDatabase()
}
}
-BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const bool read_only, bool fFlushOnCloseIn) : pdb(nullptr), activeTxn(nullptr), m_cursor(nullptr), m_database(database)
+BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const bool read_only, bool fFlushOnCloseIn) : m_database(database)
{
database.AddRef();
database.Open();
@@ -398,7 +399,6 @@ void BerkeleyBatch::Close()
activeTxn->abort();
activeTxn = nullptr;
pdb = nullptr;
- CloseCursor();
if (fFlushOnClose)
Flush();
@@ -476,15 +476,15 @@ bool BerkeleyDatabase::Rewrite(const char* pszSkip)
fSuccess = false;
}
- if (db.StartCursor()) {
+ std::unique_ptr<DatabaseCursor> cursor = db.GetNewCursor();
+ if (cursor) {
while (fSuccess) {
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- CDataStream ssValue(SER_DISK, CLIENT_VERSION);
- bool complete;
- bool ret1 = db.ReadAtCursor(ssKey, ssValue, complete);
- if (complete) {
+ DataStream ssKey{};
+ DataStream ssValue{};
+ DatabaseCursor::Status ret1 = cursor->Next(ssKey, ssValue);
+ if (ret1 == DatabaseCursor::Status::DONE) {
break;
- } else if (!ret1) {
+ } else if (ret1 == DatabaseCursor::Status::FAIL) {
fSuccess = false;
break;
}
@@ -502,7 +502,7 @@ bool BerkeleyDatabase::Rewrite(const char* pszSkip)
if (ret2 > 0)
fSuccess = false;
}
- db.CloseCursor();
+ cursor.reset();
}
if (fSuccess) {
db.Close();
@@ -656,48 +656,52 @@ void BerkeleyDatabase::ReloadDbEnv()
env->ReloadDbEnv();
}
-bool BerkeleyBatch::StartCursor()
+BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database)
{
- assert(!m_cursor);
- if (!pdb)
- return false;
- int ret = pdb->cursor(nullptr, &m_cursor, 0);
- return ret == 0;
+ if (!database.m_db.get()) {
+ throw std::runtime_error(STR_INTERNAL_BUG("BerkeleyDatabase does not exist"));
+ }
+ int ret = database.m_db->cursor(nullptr, &m_cursor, 0);
+ if (ret != 0) {
+ throw std::runtime_error(STR_INTERNAL_BUG(strprintf("BDB Cursor could not be created. Returned %d", ret)));
+ }
}
-bool BerkeleyBatch::ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete)
+DatabaseCursor::Status BerkeleyCursor::Next(DataStream& ssKey, DataStream& ssValue)
{
- complete = false;
- if (m_cursor == nullptr) return false;
+ if (m_cursor == nullptr) return Status::FAIL;
// Read at cursor
SafeDbt datKey;
SafeDbt datValue;
int ret = m_cursor->get(datKey, datValue, DB_NEXT);
if (ret == DB_NOTFOUND) {
- complete = true;
+ return Status::DONE;
+ }
+ if (ret != 0 || datKey.get_data() == nullptr || datValue.get_data() == nullptr) {
+ return Status::FAIL;
}
- if (ret != 0)
- return false;
- else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
- return false;
// Convert to streams
- ssKey.SetType(SER_DISK);
ssKey.clear();
ssKey.write({AsBytePtr(datKey.get_data()), datKey.get_size()});
- ssValue.SetType(SER_DISK);
ssValue.clear();
ssValue.write({AsBytePtr(datValue.get_data()), datValue.get_size()});
- return true;
+ return Status::MORE;
}
-void BerkeleyBatch::CloseCursor()
+BerkeleyCursor::~BerkeleyCursor()
{
if (!m_cursor) return;
m_cursor->close();
m_cursor = nullptr;
}
+std::unique_ptr<DatabaseCursor> BerkeleyBatch::GetNewCursor()
+{
+ if (!pdb) return nullptr;
+ return std::make_unique<BerkeleyCursor>(m_database);
+}
+
bool BerkeleyBatch::TxnBegin()
{
if (!pdb || activeTxn)
@@ -749,7 +753,7 @@ std::string BerkeleyDatabaseVersion()
return DbEnv::version(nullptr, nullptr, nullptr);
}
-bool BerkeleyBatch::ReadKey(CDataStream&& key, CDataStream& value)
+bool BerkeleyBatch::ReadKey(DataStream&& key, DataStream& value)
{
if (!pdb)
return false;
@@ -765,7 +769,7 @@ bool BerkeleyBatch::ReadKey(CDataStream&& key, CDataStream& value)
return false;
}
-bool BerkeleyBatch::WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite)
+bool BerkeleyBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite)
{
if (!pdb)
return false;
@@ -780,7 +784,7 @@ bool BerkeleyBatch::WriteKey(CDataStream&& key, CDataStream&& value, bool overwr
return (ret == 0);
}
-bool BerkeleyBatch::EraseKey(CDataStream&& key)
+bool BerkeleyBatch::EraseKey(DataStream&& key)
{
if (!pdb)
return false;
@@ -793,7 +797,7 @@ bool BerkeleyBatch::EraseKey(CDataStream&& key)
return (ret == 0 || ret == DB_NOTFOUND);
}
-bool BerkeleyBatch::HasKey(CDataStream&& key)
+bool BerkeleyBatch::HasKey(DataStream&& key)
{
if (!pdb)
return false;
diff --git a/src/wallet/bdb.h b/src/wallet/bdb.h
index ddab85521b..06c98972b0 100644
--- a/src/wallet/bdb.h
+++ b/src/wallet/bdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -165,40 +165,51 @@ public:
std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override;
};
-/** RAII class that provides access to a Berkeley database */
-class BerkeleyBatch : public DatabaseBatch
+/** RAII class that automatically cleanses its data on destruction */
+class SafeDbt final
{
- /** RAII class that automatically cleanses its data on destruction */
- class SafeDbt final
- {
- Dbt m_dbt;
+ Dbt m_dbt;
- public:
- // construct Dbt with internally-managed data
- SafeDbt();
- // construct Dbt with provided data
- SafeDbt(void* data, size_t size);
- ~SafeDbt();
+public:
+ // construct Dbt with internally-managed data
+ SafeDbt();
+ // construct Dbt with provided data
+ SafeDbt(void* data, size_t size);
+ ~SafeDbt();
+
+ // delegate to Dbt
+ const void* get_data() const;
+ uint32_t get_size() const;
+
+ // conversion operator to access the underlying Dbt
+ operator Dbt*();
+};
- // delegate to Dbt
- const void* get_data() const;
- uint32_t get_size() const;
+class BerkeleyCursor : public DatabaseCursor
+{
+private:
+ Dbc* m_cursor;
- // conversion operator to access the underlying Dbt
- operator Dbt*();
- };
+public:
+ explicit BerkeleyCursor(BerkeleyDatabase& database);
+ ~BerkeleyCursor() override;
+
+ Status Next(DataStream& key, DataStream& value) override;
+};
+/** RAII class that provides access to a Berkeley database */
+class BerkeleyBatch : public DatabaseBatch
+{
private:
- bool ReadKey(CDataStream&& key, CDataStream& value) override;
- bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite = true) override;
- bool EraseKey(CDataStream&& key) override;
- bool HasKey(CDataStream&& key) override;
+ bool ReadKey(DataStream&& key, DataStream& value) override;
+ bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override;
+ bool EraseKey(DataStream&& key) override;
+ bool HasKey(DataStream&& key) override;
protected:
- Db* pdb;
+ Db* pdb{nullptr};
std::string strFile;
- DbTxn* activeTxn;
- Dbc* m_cursor;
+ DbTxn* activeTxn{nullptr};
bool fReadOnly;
bool fFlushOnClose;
BerkeleyEnvironment *env;
@@ -214,9 +225,7 @@ public:
void Flush() override;
void Close() override;
- bool StartCursor() override;
- bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override;
- void CloseCursor() override;
+ std::unique_ptr<DatabaseCursor> GetNewCursor() override;
bool TxnBegin() override;
bool TxnCommit() override;
bool TxnAbort() override;
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index b56a6d3aee..cb6f0a1635 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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.cpp b/src/wallet/coinselection.cpp
index ba1d60fe44..e6ba89627c 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -88,13 +88,15 @@ std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_poo
std::vector<size_t> best_selection;
CAmount best_waste = MAX_MONEY;
+ bool is_feerate_high = utxo_pool.at(0).fee > utxo_pool.at(0).long_term_fee;
+
// Depth First search loop for choosing the UTXOs
for (size_t curr_try = 0, utxo_pool_index = 0; curr_try < TOTAL_TRIES; ++curr_try, ++utxo_pool_index) {
// Conditions for starting a backtrack
bool backtrack = false;
if (curr_value + curr_available_value < selection_target || // Cannot possibly reach target with the amount remaining in the curr_available_value.
curr_value > selection_target + cost_of_change || // Selected value is out of range, go back and try other branch
- (curr_waste > best_waste && (utxo_pool.at(0).fee - utxo_pool.at(0).long_term_fee) > 0)) { // Don't select things which we know will be more wasteful if the waste is increasing
+ (curr_waste > best_waste && is_feerate_high)) { // Don't select things which we know will be more wasteful if the waste is increasing
backtrack = true;
} else if (curr_value >= selection_target) { // Selected value is within range
curr_waste += (curr_value - selection_target); // This is the excess value which is added to the waste for the below comparison
@@ -446,7 +448,8 @@ void SelectionResult::Clear()
void SelectionResult::AddInput(const OutputGroup& group)
{
- util::insert(m_selected_inputs, group.m_outputs);
+ // As it can fail, combine inputs first
+ InsertInputs(group.m_outputs);
m_use_effective = !group.m_subtract_fee_outputs;
m_weight += group.m_weight;
@@ -454,7 +457,8 @@ void SelectionResult::AddInput(const OutputGroup& group)
void SelectionResult::AddInputs(const std::set<COutput>& inputs, bool subtract_fee_outputs)
{
- util::insert(m_selected_inputs, inputs);
+ // As it can fail, combine inputs first
+ InsertInputs(inputs);
m_use_effective = !subtract_fee_outputs;
m_weight += std::accumulate(inputs.cbegin(), inputs.cend(), 0, [](int sum, const auto& coin) {
@@ -464,16 +468,14 @@ void SelectionResult::AddInputs(const std::set<COutput>& inputs, bool subtract_f
void SelectionResult::Merge(const SelectionResult& other)
{
- // Obtain the expected selected inputs count after the merge (for now, duplicates are not allowed)
- const size_t expected_count = m_selected_inputs.size() + other.m_selected_inputs.size();
+ // As it can fail, combine inputs first
+ InsertInputs(other.m_selected_inputs);
m_target += other.m_target;
m_use_effective |= other.m_use_effective;
if (m_algo == SelectionAlgorithm::MANUAL) {
m_algo = other.m_algo;
}
- util::insert(m_selected_inputs, other.m_selected_inputs);
- assert(m_selected_inputs.size() == expected_count);
m_weight += other.m_weight;
}
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index ecfc5bfd6b..9ff2011ce3 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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,6 +10,8 @@
#include <policy/feerate.h>
#include <primitives/transaction.h>
#include <random.h>
+#include <util/system.h>
+#include <util/check.h>
#include <optional>
@@ -186,6 +188,7 @@ struct CoinEligibilityFilter
/** When avoid_reuse=true and there are full groups (OUTPUT_GROUP_MAX_ENTRIES), whether or not to use any partial groups.*/
const bool m_include_partial_groups{false};
+ CoinEligibilityFilter() = delete;
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_ancestors) {}
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors, uint64_t max_descendants) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_descendants) {}
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors, uint64_t max_descendants, bool include_partial) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_descendants), m_include_partial_groups(include_partial) {}
@@ -301,6 +304,17 @@ private:
/** Total weight of the selected inputs */
int m_weight{0};
+ template<typename T>
+ void InsertInputs(const T& inputs)
+ {
+ // Store sum of combined input sets to check that the results have no shared UTXOs
+ const size_t expected_count = m_selected_inputs.size() + inputs.size();
+ util::insert(m_selected_inputs, inputs);
+ if (m_selected_inputs.size() != expected_count) {
+ throw std::runtime_error(STR_INTERNAL_BUG("Shared UTXOs among selection results"));
+ }
+ }
+
public:
explicit SelectionResult(const CAmount target, SelectionAlgorithm algo)
: m_target(target), m_algo(algo) {}
diff --git a/src/wallet/context.cpp b/src/wallet/context.cpp
index 3d4bf9d703..39c3b54bf1 100644
--- a/src/wallet/context.cpp
+++ b/src/wallet/context.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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 4d325c7557..b776a9c497 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-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.
diff --git a/src/wallet/db.h b/src/wallet/db.h
index f09844c37e..d4c590fac7 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -22,14 +22,33 @@ struct bilingual_str;
namespace wallet {
void SplitWalletPath(const fs::path& wallet_path, fs::path& env_directory, std::string& database_filename);
+class DatabaseCursor
+{
+public:
+ explicit DatabaseCursor() {}
+ virtual ~DatabaseCursor() {}
+
+ DatabaseCursor(const DatabaseCursor&) = delete;
+ DatabaseCursor& operator=(const DatabaseCursor&) = delete;
+
+ enum class Status
+ {
+ FAIL,
+ MORE,
+ DONE,
+ };
+
+ virtual Status Next(DataStream& key, DataStream& value) { return Status::FAIL; }
+};
+
/** RAII class that provides access to a WalletDatabase */
class DatabaseBatch
{
private:
- virtual bool ReadKey(CDataStream&& key, CDataStream& value) = 0;
- virtual bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) = 0;
- virtual bool EraseKey(CDataStream&& key) = 0;
- virtual bool HasKey(CDataStream&& key) = 0;
+ virtual bool ReadKey(DataStream&& key, DataStream& value) = 0;
+ virtual bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) = 0;
+ virtual bool EraseKey(DataStream&& key) = 0;
+ virtual bool HasKey(DataStream&& key) = 0;
public:
explicit DatabaseBatch() {}
@@ -44,7 +63,7 @@ public:
template <typename K, typename T>
bool Read(const K& key, T& value)
{
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{};
ssKey.reserve(1000);
ssKey << key;
@@ -61,7 +80,7 @@ public:
template <typename K, typename T>
bool Write(const K& key, const T& value, bool fOverwrite = true)
{
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{};
ssKey.reserve(1000);
ssKey << key;
@@ -75,7 +94,7 @@ public:
template <typename K>
bool Erase(const K& key)
{
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{};
ssKey.reserve(1000);
ssKey << key;
@@ -85,16 +104,14 @@ public:
template <typename K>
bool Exists(const K& key)
{
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{};
ssKey.reserve(1000);
ssKey << key;
return HasKey(std::move(ssKey));
}
- virtual bool StartCursor() = 0;
- virtual bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) = 0;
- virtual void CloseCursor() = 0;
+ virtual std::unique_ptr<DatabaseCursor> GetNewCursor() = 0;
virtual bool TxnBegin() = 0;
virtual bool TxnCommit() = 0;
virtual bool TxnAbort() = 0;
@@ -106,7 +123,7 @@ class WalletDatabase
{
public:
/** Create dummy DB handle */
- WalletDatabase() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0) {}
+ WalletDatabase() : nUpdateCounter(0) {}
virtual ~WalletDatabase() {};
/** Open the database if it is not already opened. */
@@ -148,30 +165,33 @@ public:
virtual std::string Format() = 0;
std::atomic<unsigned int> nUpdateCounter;
- unsigned int nLastSeen;
- unsigned int nLastFlushed;
- int64_t nLastWalletUpdate;
+ unsigned int nLastSeen{0};
+ unsigned int nLastFlushed{0};
+ int64_t nLastWalletUpdate{0};
/** Make a DatabaseBatch connected to this database */
virtual std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) = 0;
};
+class DummyCursor : public DatabaseCursor
+{
+ Status Next(DataStream& key, DataStream& value) override { return Status::FAIL; }
+};
+
/** RAII class that provides access to a DummyDatabase. Never fails. */
class DummyBatch : public DatabaseBatch
{
private:
- bool ReadKey(CDataStream&& key, CDataStream& value) override { return true; }
- bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return true; }
- bool EraseKey(CDataStream&& key) override { return true; }
- bool HasKey(CDataStream&& key) override { return true; }
+ bool ReadKey(DataStream&& key, DataStream& value) override { return true; }
+ bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override { return true; }
+ bool EraseKey(DataStream&& key) override { return true; }
+ bool HasKey(DataStream&& key) override { return true; }
public:
void Flush() override {}
void Close() override {}
- bool StartCursor() override { return true; }
- bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return true; }
- void CloseCursor() override {}
+ std::unique_ptr<DatabaseCursor> GetNewCursor() override { return std::make_unique<DummyCursor>(); }
bool TxnBegin() override { return true; }
bool TxnCommit() override { return true; }
bool TxnAbort() override { return true; }
diff --git a/src/wallet/dump.cpp b/src/wallet/dump.cpp
index 2e46cf5454..403ec711ff 100644
--- a/src/wallet/dump.cpp
+++ b/src/wallet/dump.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -47,7 +47,8 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error)
std::unique_ptr<DatabaseBatch> batch = db.MakeBatch();
bool ret = true;
- if (!batch->StartCursor()) {
+ std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
+ if (!cursor) {
error = _("Error: Couldn't create cursor into database");
ret = false;
}
@@ -66,15 +67,15 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error)
// 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) {
+ DataStream ss_key{};
+ DataStream ss_value{};
+ DatabaseCursor::Status status = cursor->Next(ss_key, ss_value);
+ if (status == DatabaseCursor::Status::DONE) {
ret = true;
break;
- } else if (!ret) {
+ } else if (status == DatabaseCursor::Status::FAIL) {
error = _("Error reading next record from wallet database");
+ ret = false;
break;
}
std::string key_str = HexStr(ss_key);
@@ -85,7 +86,7 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error)
}
}
- batch->CloseCursor();
+ cursor.reset();
batch.reset();
// Close the wallet after we're done with it. The caller won't be doing this
@@ -254,8 +255,8 @@ bool CreateFromDump(const ArgsManager& args, const std::string& name, const fs::
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);
+ DataStream ss_key{k};
+ DataStream ss_value{v};
if (!batch->Write(ss_key, ss_value)) {
error = strprintf(_("Error: Unable to write record to new wallet"));
diff --git a/src/wallet/dump.h b/src/wallet/dump.h
index bf683e9843..ff0d94e4b2 100644
--- a/src/wallet/dump.h
+++ b/src/wallet/dump.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-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.
diff --git a/src/wallet/external_signer_scriptpubkeyman.cpp b/src/wallet/external_signer_scriptpubkeyman.cpp
index 76de51ac3e..cb861d835e 100644
--- a/src/wallet/external_signer_scriptpubkeyman.cpp
+++ b/src/wallet/external_signer_scriptpubkeyman.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 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/feebumper.cpp b/src/wallet/feebumper.cpp
index 6d7bb299cc..bd158b5985 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -293,7 +293,22 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx) {
LOCK(wallet.cs_wallet);
- return wallet.SignTransaction(mtx);
+
+ if (wallet.IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
+ // Make a blank psbt
+ PartiallySignedTransaction psbtx(mtx);
+
+ // First fill transaction with our data without signing,
+ // so external signers are not asked to sign more than once.
+ bool complete;
+ wallet.FillPSBT(psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */);
+ const TransactionError err = wallet.FillPSBT(psbtx, complete, SIGHASH_ALL, true /* sign */, false /* bip32derivs */);
+ if (err != TransactionError::OK) return false;
+ complete = FinalizeAndExtractPSBT(psbtx, mtx);
+ return complete;
+ } else {
+ return wallet.SignTransaction(mtx);
+ }
}
Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<bilingual_str>& errors, uint256& bumped_txid)
diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
index 760ab58e5c..a96871b26f 100644
--- a/src/wallet/feebumper.h
+++ b/src/wallet/feebumper.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.
diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp
index 3e442a3f5f..eda6d319ec 100644
--- a/src/wallet/fees.cpp
+++ b/src/wallet/fees.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/init.cpp b/src/wallet/init.cpp
index 174c68744c..773f094274 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/interfaces.cpp b/src/wallet/interfaces.cpp
index 21726a1185..68dd3da9b5 100644
--- a/src/wallet/interfaces.cpp
+++ b/src/wallet/interfaces.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/load.cpp b/src/wallet/load.cpp
index 6eb0ef5e7a..8c60a2da72 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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/load.h b/src/wallet/load.h
index 5c2bbdabe4..0882f7f8ad 100644
--- a/src/wallet/load.h
+++ b/src/wallet/load.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-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.
diff --git a/src/wallet/receive.cpp b/src/wallet/receive.cpp
index 7fbf2ff8cf..0a75bb6d92 100644
--- a/src/wallet/receive.cpp
+++ b/src/wallet/receive.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/receive.h b/src/wallet/receive.h
index 9125b1e9aa..87be0fc2ae 100644
--- a/src/wallet/receive.h
+++ b/src/wallet/receive.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/rpc/addresses.cpp b/src/wallet/rpc/addresses.cpp
index 903a569cb9..da63d45d11 100644
--- a/src/wallet/rpc/addresses.cpp
+++ b/src/wallet/rpc/addresses.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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,9 +43,7 @@ RPCHelpMan getnewaddress()
}
// Parse the label first so we don't generate a key if there's an error
- std::string label;
- if (!request.params[0].isNull())
- label = LabelFromValue(request.params[0]);
+ const std::string label{LabelFromValue(request.params[0])};
OutputType output_type = pwallet->m_default_address_type;
if (!request.params[1].isNull()) {
@@ -140,7 +138,7 @@ RPCHelpMan setlabel()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
}
- std::string label = LabelFromValue(request.params[1]);
+ const std::string label{LabelFromValue(request.params[1])};
if (pwallet->IsMine(dest)) {
pwallet->SetAddressBook(dest, label, "receive");
@@ -228,7 +226,7 @@ RPCHelpMan addmultisigaddress()
{"key", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address or hex-encoded public key"},
},
},
- {"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A label to assign the addresses to."},
+ {"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A label to assign the addresses to."},
{"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
},
RPCResult{
@@ -258,9 +256,7 @@ RPCHelpMan addmultisigaddress()
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
- std::string label;
- if (!request.params[2].isNull())
- label = LabelFromValue(request.params[2]);
+ const std::string label{LabelFromValue(request.params[2])};
int required = request.params[0].getInt<int>();
@@ -662,7 +658,7 @@ RPCHelpMan getaddressesbylabel()
LOCK(pwallet->cs_wallet);
- std::string label = LabelFromValue(request.params[0]);
+ const std::string label{LabelFromValue(request.params[0])};
// Find all addresses that have the given label
UniValue ret(UniValue::VOBJ);
@@ -700,7 +696,7 @@ RPCHelpMan listlabels()
return RPCHelpMan{"listlabels",
"\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n",
{
- {"purpose", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument."},
+ {"purpose", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument."},
},
RPCResult{
RPCResult::Type::ARR, "", "",
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
index ddf10cae15..93a6bbde20 100644
--- a/src/wallet/rpc/backup.cpp
+++ b/src/wallet/rpc/backup.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,6 +6,7 @@
#include <clientversion.h>
#include <core_io.h>
#include <fs.h>
+#include <hash.h>
#include <interfaces/chain.h>
#include <key_io.h>
#include <merkleblock.h>
@@ -14,6 +15,7 @@
#include <script/script.h>
#include <script/standard.h>
#include <sync.h>
+#include <uint256.h>
#include <util/bip32.h>
#include <util/system.h>
#include <util/time.h>
@@ -93,6 +95,22 @@ static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver,
}
}
+static void EnsureBlockDataFromTime(const CWallet& wallet, int64_t timestamp)
+{
+ auto& chain{wallet.chain()};
+ if (!chain.havePruned()) {
+ return;
+ }
+
+ int height{0};
+ const bool found{chain.findFirstBlockWithTimeAndHeight(timestamp - TIMESTAMP_WINDOW, 0, FoundBlock().height(height))};
+
+ uint256 tip_hash{WITH_LOCK(wallet.cs_wallet, return wallet.GetLastBlockHash())};
+ if (found && !chain.hasBlocks(tip_hash, height)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Pruned blocks from height %d required to import keys. Use RPC call getblockchaininfo to determine your pruned height.", height));
+ }
+}
+
RPCHelpMan importprivkey()
{
return RPCHelpMan{"importprivkey",
@@ -140,9 +158,7 @@ RPCHelpMan importprivkey()
EnsureWalletIsUnlocked(*pwallet);
std::string strSecret = request.params[0].get_str();
- std::string strLabel;
- if (!request.params[1].isNull())
- strLabel = request.params[1].get_str();
+ const std::string strLabel{LabelFromValue(request.params[1])};
// Whether to perform rescan after import
if (!request.params[2].isNull())
@@ -233,9 +249,7 @@ RPCHelpMan importaddress()
EnsureLegacyScriptPubKeyMan(*pwallet, true);
- std::string strLabel;
- if (!request.params[1].isNull())
- strLabel = request.params[1].get_str();
+ const std::string strLabel{LabelFromValue(request.params[1])};
// Whether to perform rescan after import
bool fRescan = true;
@@ -322,7 +336,7 @@ RPCHelpMan importprunedfunds()
}
uint256 hashTx = tx.GetHash();
- CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
+ DataStream ssMB{ParseHexV(request.params[1], "proof")};
CMerkleBlock merkleBlock;
ssMB >> merkleBlock;
@@ -426,9 +440,7 @@ RPCHelpMan importpubkey()
EnsureLegacyScriptPubKeyMan(*pwallet, true);
- std::string strLabel;
- if (!request.params[1].isNull())
- strLabel = request.params[1].get_str();
+ const std::string strLabel{LabelFromValue(request.params[1])};
// Whether to perform rescan after import
bool fRescan = true;
@@ -504,13 +516,6 @@ RPCHelpMan importwallet()
EnsureLegacyScriptPubKeyMan(*pwallet, true);
- if (pwallet->chain().havePruned()) {
- // Exit early and print an error.
- // If a block is pruned after this check, we will import the key(s),
- // but fail the rescan with a generic error.
- throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled when blocks are pruned");
- }
-
WalletRescanReserver reserver(*pwallet);
if (!reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
@@ -565,15 +570,18 @@ RPCHelpMan importwallet()
fLabel = true;
}
}
+ nTimeBegin = std::min(nTimeBegin, nTime);
keys.push_back(std::make_tuple(key, nTime, fLabel, strLabel));
} else if(IsHex(vstr[0])) {
std::vector<unsigned char> vData(ParseHex(vstr[0]));
CScript script = CScript(vData.begin(), vData.end());
int64_t birth_time = ParseISO8601DateTime(vstr[1]);
+ if (birth_time > 0) nTimeBegin = std::min(nTimeBegin, birth_time);
scripts.push_back(std::pair<CScript, int64_t>(script, birth_time));
}
}
file.close();
+ EnsureBlockDataFromTime(*pwallet, nTimeBegin);
// We now know whether we are importing private keys, so we can error if private keys are disabled
if (keys.size() > 0 && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI
@@ -602,8 +610,6 @@ RPCHelpMan importwallet()
if (has_label)
pwallet->SetAddressBook(PKHash(keyid), label, "receive");
-
- nTimeBegin = std::min(nTimeBegin, time);
progress++;
}
for (const auto& script_pair : scripts) {
@@ -616,9 +622,6 @@ RPCHelpMan importwallet()
fGood = false;
continue;
}
- if (time > 0) {
- nTimeBegin = std::min(nTimeBegin, time);
- }
progress++;
}
@@ -885,9 +888,7 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
}
case TxoutType::WITNESS_V0_SCRIPTHASH: {
if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2WSH inside another P2WSH");
- uint256 fullid(solverdata[0]);
- CScriptID id;
- CRIPEMD160().Write(fullid.begin(), fullid.size()).Finalize(id.begin());
+ CScriptID id{RIPEMD160(solverdata[0])};
auto subscript = std::move(import_data.witnessscript); // Remove redeemscript from import_data to check for superfluous script later.
if (!subscript) return "missing witnessscript";
if (CScriptID(*subscript) != id) return "witnessScript does not match the scriptPubKey or redeemScript";
@@ -1163,7 +1164,7 @@ static UniValue ProcessImport(CWallet& wallet, const UniValue& data, const int64
if (internal && data.exists("label")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal addresses should not have a label");
}
- const std::string& label = data.exists("label") ? data["label"].get_str() : "";
+ const std::string label{LabelFromValue(data["label"])};
const bool add_keypool = data.exists("keypool") ? data["keypool"].get_bool() : false;
// Add to keypool only works with privkeys disabled
@@ -1291,7 +1292,7 @@ RPCHelpMan importmulti()
},
},
RPCArgOptions{.oneline_description="\"requests\""}},
- {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
{"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Scan the chain and mempool for wallet transactions after all imports."},
},
@@ -1329,8 +1330,6 @@ RPCHelpMan importmulti()
// the user could have gotten from another RPC command prior to now
wallet.BlockUntilSyncedToCurrentChain();
- RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
-
EnsureLegacyScriptPubKeyMan(*pwallet, true);
const UniValue& requests = mainRequest.params[0];
@@ -1457,7 +1456,7 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
const std::string& descriptor = data["desc"].get_str();
const bool active = data.exists("active") ? data["active"].get_bool() : false;
const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
- const std::string& label = data.exists("label") ? data["label"].get_str() : "";
+ const std::string label{LabelFromValue(data["label"])};
// Parse descriptor string
FlatSigningProvider keys;
@@ -1651,8 +1650,6 @@ RPCHelpMan importdescriptors()
throw JSONRPCError(RPC_WALLET_ERROR, "importdescriptors is not available for non-descriptor wallets");
}
- RPCTypeCheck(main_request.params, {UniValue::VARR, UniValue::VOBJ});
-
WalletRescanReserver reserver(*pwallet);
if (!reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
@@ -1894,7 +1891,7 @@ RPCHelpMan restorewallet()
{
{"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO, "The name that will be applied to the restored wallet"},
{"backup_file", RPCArg::Type::STR, RPCArg::Optional::NO, "The backup file that will be used to restore the wallet."},
- {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED_NAMED_ARG, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
+ {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
diff --git a/src/wallet/rpc/coins.cpp b/src/wallet/rpc/coins.cpp
index 6021e4bf4f..4c386789f1 100644
--- a/src/wallet/rpc/coins.cpp
+++ b/src/wallet/rpc/coins.cpp
@@ -1,8 +1,9 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 <core_io.h>
+#include <hash.h>
#include <key_io.h>
#include <rpc/util.h>
#include <util/moneystr.h>
@@ -165,7 +166,7 @@ RPCHelpMan getbalance()
"The available balance is what the wallet considers currently spendable, and is\n"
"thus affected by options which limit spendability such as -spendzeroconfchange.\n",
{
- {"dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Remains for backward compatibility. Must be excluded or set to \"*\"."},
+ {"dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Remains for backward compatibility. Must be excluded or set to \"*\"."},
{"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "Only include transactions confirmed at least this many times."},
{"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also include balance in watch-only addresses (see 'importaddress')"},
{"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{true}, "(only available if avoid_reuse wallet flag is set) Do not include balance in dirty outputs; addresses are considered dirty if they have previously been used in a transaction."},
@@ -509,7 +510,7 @@ RPCHelpMan listunspent()
},
{"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include outputs that are not safe to spend\n"
"See description of \"safe\" attribute below."},
- {"query_options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "JSON with query options",
+ {"query_options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "JSON with query options",
{
{"minimumAmount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(0)}, "Minimum value of each UTXO in " + CURRENCY_UNIT + ""},
{"maximumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Maximum value of each UTXO in " + CURRENCY_UNIT + ""},
@@ -679,8 +680,7 @@ RPCHelpMan listunspent()
CHECK_NONFATAL(extracted);
// Also return the witness script
const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(witness_destination);
- CScriptID id;
- CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
+ CScriptID id{RIPEMD160(whash)};
CScript witnessScript;
if (provider->GetCScript(id, witnessScript)) {
entry.pushKV("witnessScript", HexStr(witnessScript));
@@ -689,8 +689,7 @@ RPCHelpMan listunspent()
}
} else if (scriptPubKey.IsPayToWitnessScriptHash()) {
const WitnessV0ScriptHash& whash = std::get<WitnessV0ScriptHash>(address);
- CScriptID id;
- CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
+ CScriptID id{RIPEMD160(whash)};
CScript witnessScript;
if (provider->GetCScript(id, witnessScript)) {
entry.pushKV("witnessScript", HexStr(witnessScript));
diff --git a/src/wallet/rpc/encrypt.cpp b/src/wallet/rpc/encrypt.cpp
index a68f52a718..fcf25e01d6 100644
--- a/src/wallet/rpc/encrypt.cpp
+++ b/src/wallet/rpc/encrypt.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/rpc/signmessage.cpp b/src/wallet/rpc/signmessage.cpp
index ae4bd4fbc5..c9fb693482 100644
--- a/src/wallet/rpc/signmessage.cpp
+++ b/src/wallet/rpc/signmessage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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/rpc/spend.cpp b/src/wallet/rpc/spend.cpp
index fb5e9a425e..cab797bbce 100644
--- a/src/wallet/rpc/spend.cpp
+++ b/src/wallet/rpc/spend.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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,10 +82,10 @@ static UniValue FinishTransaction(const std::shared_ptr<CWallet> pwallet, const
PartiallySignedTransaction psbtx(rawTx);
// First fill transaction with our data without signing,
- // so external signers are not asked sign more than once.
+ // so external signers are not asked to sign more than once.
bool complete;
- pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, false, true);
- const TransactionError err{pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, true, false)};
+ pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/false, /*bip32derivs=*/true);
+ const TransactionError err{pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/true, /*bip32derivs=*/false)};
if (err != TransactionError::OK) {
throw JSONRPCTransactionError(err);
}
@@ -217,9 +217,9 @@ RPCHelpMan sendtoaddress()
{
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to send to."},
{"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The amount in " + CURRENCY_UNIT + " to send. eg 0.1"},
- {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment used to store what the transaction is for.\n"
+ {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment used to store what the transaction is for.\n"
"This is not part of the transaction, just kept in your wallet."},
- {"comment_to", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment to store the name of the person or organization\n"
+ {"comment_to", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment to store the name of the person or organization\n"
"to which you're sending the transaction. This is not part of the \n"
"transaction, just kept in your wallet."},
{"subtractfeefromamount", RPCArg::Type::BOOL, RPCArg::Default{false}, "The fee will be deducted from the amount being sent.\n"
@@ -314,18 +314,21 @@ RPCHelpMan sendtoaddress()
RPCHelpMan sendmany()
{
return RPCHelpMan{"sendmany",
- "\nSend multiple times. Amounts are double-precision floating point numbers." +
+ "Send multiple times. Amounts are double-precision floating point numbers." +
HELP_REQUIRING_PASSPHRASE,
{
- {"dummy", RPCArg::Type::STR, RPCArg::Optional::NO, "Must be set to \"\" for backwards compatibility.", RPCArgOptions{.oneline_description="\"\""}},
+ {"dummy", RPCArg::Type::STR, RPCArg::Default{"\"\""}, "Must be set to \"\" for backwards compatibility.",
+ RPCArgOptions{
+ .oneline_description = "\"\"",
+ }},
{"amounts", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::NO, "The addresses and amounts",
{
{"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"},
},
},
- {"minconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "Ignored dummy value"},
- {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "A comment"},
- {"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The addresses.\n"
+ {"minconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Ignored dummy value"},
+ {"comment", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A comment"},
+ {"subtractfeefrom", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The addresses.\n"
"The fee will be equally deducted from the amount of each selected address.\n"
"Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
"If no addresses are specified here, the sender pays the fee.",
@@ -459,7 +462,7 @@ static std::vector<RPCArg> FundTxDoc(bool solving_data = true)
},
};
if (solving_data) {
- args.push_back({"solving_data", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "Keys and scripts needed for producing a final transaction with a dummy signature.\n"
+ args.push_back({"solving_data", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "Keys and scripts needed for producing a final transaction with a dummy signature.\n"
"Used for fee estimation during coin selection.",
{
{
@@ -528,6 +531,8 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
{"replaceable", UniValueType(UniValue::VBOOL)},
{"conf_target", UniValueType(UniValue::VNUM)},
{"estimate_mode", UniValueType(UniValue::VSTR)},
+ {"minconf", UniValueType(UniValue::VNUM)},
+ {"maxconf", UniValueType(UniValue::VNUM)},
{"input_weights", UniValueType(UniValue::VARR)},
},
true, true);
@@ -593,6 +598,22 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
if (options.exists("replaceable")) {
coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool();
}
+
+ if (options.exists("minconf")) {
+ coinControl.m_min_depth = options["minconf"].getInt<int>();
+
+ if (coinControl.m_min_depth < 0) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative minconf");
+ }
+ }
+
+ if (options.exists("maxconf")) {
+ coinControl.m_max_depth = options["maxconf"].getInt<int>();
+
+ if (coinControl.m_max_depth < coinControl.m_min_depth) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("maxconf can't be lower than minconf: %d < %d", coinControl.m_max_depth, coinControl.m_min_depth));
+ }
+ }
SetFeeEstimateMode(wallet, coinControl, options["conf_target"], options["estimate_mode"], options["fee_rate"], override_min_fee);
}
} else {
@@ -737,13 +758,15 @@ RPCHelpMan fundrawtransaction()
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n",
{
{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
- {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}",
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}",
Cat<std::vector<RPCArg>>(
{
{"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{true}, "For a transaction with existing inputs, automatically include more if they are not enough."},
{"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"
"Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"
"If that happens, you will need to fund the transaction with different inputs and republish it."},
+ {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "If add_inputs is specified, require inputs with at least this many confirmations."},
+ {"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},
{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
@@ -761,20 +784,27 @@ RPCHelpMan fundrawtransaction()
{"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
},
},
- {"input_weights", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "Inputs and their corresponding weights",
+ {"input_weights", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Inputs and their corresponding weights",
{
- {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
- {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output index"},
- {"weight", RPCArg::Type::NUM, RPCArg::Optional::NO, "The maximum weight for this input, "
- "including the weight of the outpoint and sequence number. "
- "Note that serialized signature sizes are not guaranteed to be consistent, "
- "so the maximum DER signatures size of 73 bytes should be used when considering ECDSA signatures."
- "Remember to convert serialized sizes to weight units when necessary."},
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
+ {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output index"},
+ {"weight", RPCArg::Type::NUM, RPCArg::Optional::NO, "The maximum weight for this input, "
+ "including the weight of the outpoint and sequence number. "
+ "Note that serialized signature sizes are not guaranteed to be consistent, "
+ "so the maximum DER signatures size of 73 bytes should be used when considering ECDSA signatures."
+ "Remember to convert serialized sizes to weight units when necessary."},
+ },
+ },
},
},
},
FundTxDoc()),
- RPCArgOptions{.oneline_description="options"}},
+ RPCArgOptions{
+ .skip_type_check = true,
+ .oneline_description = "options",
+ }},
{"iswitness", RPCArg::Type::BOOL, RPCArg::DefaultHint{"depends on heuristic tests"}, "Whether the transaction hex is a serialized witness transaction.\n"
"If iswitness is not present, heuristic tests will be used in decoding.\n"
"If true, only witness deserialization will be tried.\n"
@@ -806,8 +836,6 @@ RPCHelpMan fundrawtransaction()
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!pwallet) return UniValue::VNULL;
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType(), UniValue::VBOOL});
-
// parse hex string from parameter
CMutableTransaction tx;
bool try_witness = request.params[2].isNull() ? true : request.params[2].get_bool();
@@ -842,7 +870,7 @@ RPCHelpMan signrawtransactionwithwallet()
HELP_REQUIRING_PASSPHRASE,
{
{"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
- {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The previous dependent transaction outputs",
+ {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The previous dependent transaction outputs",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -896,8 +924,6 @@ RPCHelpMan signrawtransactionwithwallet()
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
if (!pwallet) return UniValue::VNULL;
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true);
-
CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_str())) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
@@ -951,7 +977,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
"* WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB. *\n",
{
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"},
- {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks\n"},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"},
@@ -993,11 +1019,10 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!pwallet) return UniValue::VNULL;
- if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !want_psbt) {
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER) && !want_psbt) {
throw JSONRPCError(RPC_WALLET_ERROR, "bumpfee is not available with wallets that have private keys disabled. Use psbtbumpfee instead.");
}
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
uint256 hash(ParseHashV(request.params[0], "txid"));
CCoinControl coin_control;
@@ -1071,6 +1096,9 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
// For psbtbumpfee, return the base64-encoded unsigned PSBT of the new transaction.
if (!want_psbt) {
if (!feebumper::SignTransaction(*pwallet, mtx)) {
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Transaction incomplete. Try psbtbumpfee instead.");
+ }
throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
}
@@ -1128,18 +1156,20 @@ RPCHelpMan send()
},
},
},
- },
+ RPCArgOptions{.skip_type_check = true}},
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
"\"" + FeeModes("\"\n\"") + "\""},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
- {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
Cat<std::vector<RPCArg>>(
{
{"add_inputs", RPCArg::Type::BOOL, RPCArg::DefaultHint{"false when \"inputs\" are specified, true otherwise"},"Automatically include coins from the wallet to cover the target amount.\n"},
{"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"
"Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"
"If that happens, you will need to fund the transaction with different inputs and republish it."},
+ {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "If add_inputs is specified, require inputs with at least this many confirmations."},
+ {"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},
{"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "When false, returns a serialized transaction which will not be added to the wallet or broadcast"},
{"change_address", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"change_position", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
@@ -1198,15 +1228,6 @@ RPCHelpMan send()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {
- UniValueType(), // outputs (ARR or OBJ, checked later)
- UniValue::VNUM, // conf_target
- UniValue::VSTR, // estimate_mode
- UniValueType(), // fee_rate, will be checked by AmountFromValue() in SetFeeEstimateMode()
- UniValue::VOBJ, // options
- }, true
- );
-
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!pwallet) return UniValue::VNULL;
@@ -1255,7 +1276,7 @@ RPCHelpMan sendall()
"\"" + FeeModes("\"\n\"") + "\""},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{
- "options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ "options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
Cat<std::vector<RPCArg>>(
{
{"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "When false, returns the serialized transaction without broadcasting or adding it to the wallet"},
@@ -1263,7 +1284,7 @@ RPCHelpMan sendall()
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch-only.\n"
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
"e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
- {"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Use exactly the specified inputs to build the transaction. Specifying inputs is incompatible with send_max.",
+ {"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Use exactly the specified inputs to build the transaction. Specifying inputs is incompatible with the send_max, minconf, and maxconf options.",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -1278,6 +1299,8 @@ RPCHelpMan sendall()
{"lock_unspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
{"psbt", RPCArg::Type::BOOL, RPCArg::DefaultHint{"automatic"}, "Always return a PSBT, implies add_to_wallet=false."},
{"send_max", RPCArg::Type::BOOL, RPCArg::Default{false}, "When true, only use UTXOs that can pay for their own fees to maximize the output amount. When 'false' (default), no UTXO is left behind. send_max is incompatible with providing specific inputs."},
+ {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "Require inputs with at least this many confirmations."},
+ {"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Require inputs with at most this many confirmations."},
},
FundTxDoc()
),
@@ -1307,15 +1330,6 @@ RPCHelpMan sendall()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- RPCTypeCheck(request.params, {
- UniValue::VARR, // recipients
- UniValue::VNUM, // conf_target
- UniValue::VSTR, // estimate_mode
- UniValueType(), // fee_rate, will be checked by AmountFromValue() in SetFeeEstimateMode()
- UniValue::VOBJ, // options
- }, true
- );
-
std::shared_ptr<CWallet> const pwallet{GetWalletForJSONRPCRequest(request)};
if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
@@ -1352,6 +1366,23 @@ RPCHelpMan sendall()
coin_control.fAllowWatchOnly = ParseIncludeWatchonly(options["include_watching"], *pwallet);
+ if (options.exists("minconf")) {
+ if (options["minconf"].getInt<int>() < 0)
+ {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid minconf (minconf cannot be negative): %s", options["minconf"].getInt<int>()));
+ }
+
+ coin_control.m_min_depth = options["minconf"].getInt<int>();
+ }
+
+ if (options.exists("maxconf")) {
+ coin_control.m_max_depth = options["maxconf"].getInt<int>();
+
+ if (coin_control.m_max_depth < coin_control.m_min_depth) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("maxconf can't be lower than minconf: %d < %d", coin_control.m_max_depth, coin_control.m_min_depth));
+ }
+ }
+
const bool rbf{options.exists("replaceable") ? options["replaceable"].get_bool() : pwallet->m_signal_rbf};
FeeCalculation fee_calc_out;
@@ -1373,6 +1404,8 @@ RPCHelpMan sendall()
bool send_max{options.exists("send_max") ? options["send_max"].get_bool() : false};
if (options.exists("inputs") && options.exists("send_max")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot combine send_max with specific inputs.");
+ } else if (options.exists("inputs") && (options.exists("minconf") || options.exists("maxconf"))) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot combine minconf or maxconf with specific inputs.");
} else if (options.exists("inputs")) {
for (const CTxIn& input : rawTx.vin) {
if (pwallet->IsSpent(input.prevout)) {
@@ -1511,8 +1544,6 @@ RPCHelpMan walletprocesspsbt()
// the user could have gotten from another RPC command prior to now
wallet.BlockUntilSyncedToCurrentChain();
- RPCTypeCheck(request.params, {UniValue::VSTR});
-
// Unserialize the transaction
PartiallySignedTransaction psbtx;
std::string error;
@@ -1555,7 +1586,7 @@ RPCHelpMan walletcreatefundedpsbt()
"All existing inputs must either have their previous output transaction be in the wallet\n"
"or be in the UTXO set. Solving data must be provided for non-wallet inputs.\n",
{
- {"inputs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "Leave empty to add inputs automatically. See add_inputs option.",
+ {"inputs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Leave empty to add inputs automatically. See add_inputs option.",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -1587,15 +1618,17 @@ RPCHelpMan walletcreatefundedpsbt()
},
},
},
- },
+ RPCArgOptions{.skip_type_check = true}},
{"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
- {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
Cat<std::vector<RPCArg>>(
{
{"add_inputs", RPCArg::Type::BOOL, RPCArg::DefaultHint{"false when \"inputs\" are specified, true otherwise"}, "Automatically include coins from the wallet to cover the target amount.\n"},
{"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"
"Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"
"If that happens, you will need to fund the transaction with different inputs and republish it."},
+ {"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "If add_inputs is specified, require inputs with at least this many confirmations."},
+ {"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},
{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
@@ -1638,15 +1671,6 @@ RPCHelpMan walletcreatefundedpsbt()
// the user could have gotten from another RPC command prior to now
wallet.BlockUntilSyncedToCurrentChain();
- RPCTypeCheck(request.params, {
- UniValue::VARR,
- UniValueType(), // ARR or OBJ, checked later
- UniValue::VNUM,
- UniValue::VOBJ,
- UniValue::VBOOL
- }, true
- );
-
UniValue options{request.params[3].isNull() ? UniValue::VOBJ : request.params[3]};
CAmount fee;
@@ -1667,7 +1691,7 @@ RPCHelpMan walletcreatefundedpsbt()
// Fill transaction with out data but don't sign
bool bip32derivs = request.params[4].isNull() ? true : request.params[4].get_bool();
bool complete = true;
- const TransactionError err{wallet.FillPSBT(psbtx, complete, 1, false, bip32derivs)};
+ const TransactionError err{wallet.FillPSBT(psbtx, complete, 1, /*sign=*/false, /*bip32derivs=*/bip32derivs)};
if (err != TransactionError::OK) {
throw JSONRPCTransactionError(err);
}
diff --git a/src/wallet/rpc/transactions.cpp b/src/wallet/rpc/transactions.cpp
index 02a1ac5ea1..e590aa1f08 100644
--- a/src/wallet/rpc/transactions.cpp
+++ b/src/wallet/rpc/transactions.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -206,7 +206,7 @@ RPCHelpMan listreceivedbyaddress()
{"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "The minimum number of confirmations before payments are included."},
{"include_empty", RPCArg::Type::BOOL, RPCArg::Default{false}, "Whether to include addresses that haven't received any payments."},
{"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see 'importaddress')"},
- {"address_filter", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If present and non-empty, only return information on this address."},
+ {"address_filter", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "If present and non-empty, only return information on this address."},
{"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase transactions."},
},
RPCResult{
@@ -397,7 +397,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM
}
-static const std::vector<RPCResult> TransactionDescriptionString()
+static std::vector<RPCResult> TransactionDescriptionString()
{
return{{RPCResult::Type::NUM, "confirmations", "The number of confirmations for the transaction. Negative confirmations means the\n"
"transaction conflicted that many blocks ago."},
@@ -416,7 +416,6 @@ static const std::vector<RPCResult> TransactionDescriptionString()
}},
{RPCResult::Type::STR_HEX, "replaced_by_txid", /*optional=*/true, "The txid if this tx was replaced."},
{RPCResult::Type::STR_HEX, "replaces_txid", /*optional=*/true, "The txid if the tx replaces one."},
- {RPCResult::Type::STR, "comment", /*optional=*/true, ""},
{RPCResult::Type::STR, "to", /*optional=*/true, "If a comment to is associated with the transaction."},
{RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},
{RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."},
@@ -435,7 +434,7 @@ RPCHelpMan listtransactions()
"\nIf a label name is provided, this will return only incoming transactions paying to addresses with the specified label.\n"
"\nReturns up to 'count' most recent transactions skipping the first 'from' transactions.\n",
{
- {"label|dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
+ {"label|dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "If set, should be a valid label name to return only incoming transactions\n"
"with the specified label, or \"*\" to disable filtering and return all transactions."},
{"count", RPCArg::Type::NUM, RPCArg::Default{10}, "The number of transactions to return"},
{"skip", RPCArg::Type::NUM, RPCArg::Default{0}, "The number of transactions to skip"},
@@ -487,7 +486,7 @@ RPCHelpMan listtransactions()
std::optional<std::string> filter_label;
if (!request.params[0].isNull() && request.params[0].get_str() != "*") {
- filter_label = request.params[0].get_str();
+ filter_label.emplace(LabelFromValue(request.params[0]));
if (filter_label.value().empty()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Label argument must be a valid label name or \"*\".");
}
@@ -546,13 +545,13 @@ RPCHelpMan listsinceblock()
"If \"blockhash\" is no longer a part of the main chain, transactions from the fork point onward are included.\n"
"Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \"removed\" array.\n",
{
- {"blockhash", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, the block hash to list transactions since, otherwise list all transactions."},
+ {"blockhash", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "If set, the block hash to list transactions since, otherwise list all transactions."},
{"target_confirmations", RPCArg::Type::NUM, RPCArg::Default{1}, "Return the nth block hash from the main chain. e.g. 1 would mean the best block hash. Note: this is not used as a filter, but only affects [lastblock] in the return value"},
{"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Include transactions to watch-only addresses (see 'importaddress')"},
{"include_removed", RPCArg::Type::BOOL, RPCArg::Default{true}, "Show transactions that were removed due to a reorg in the \"removed\" array\n"
"(not guaranteed to work on pruned nodes)"},
{"include_change", RPCArg::Type::BOOL, RPCArg::Default{false}, "Also add entries for change outputs.\n"},
- {"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Return only incoming transactions paying to addresses with the specified label.\n"},
+ {"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Return only incoming transactions paying to addresses with the specified label.\n"},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -635,10 +634,9 @@ RPCHelpMan listsinceblock()
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
bool include_change = (!request.params[4].isNull() && request.params[4].get_bool());
+ // Only set it if 'label' was provided.
std::optional<std::string> filter_label;
- if (!request.params[5].isNull()) {
- filter_label = request.params[5].get_str();
- }
+ if (!request.params[5].isNull()) filter_label.emplace(LabelFromValue(request.params[5]));
int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
@@ -850,7 +848,7 @@ RPCHelpMan rescanblockchain()
"and block filters are available (using startup option \"-blockfilterindex=1\").\n",
{
{"start_height", RPCArg::Type::NUM, RPCArg::Default{0}, "block height where the rescan should start"},
- {"stop_height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "the last block height that should be scanned. If none is provided it will rescan up to the tip at return time of this call."},
+ {"stop_height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "the last block height that should be scanned. If none is provided it will rescan up to the tip at return time of this call."},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
diff --git a/src/wallet/rpc/util.cpp b/src/wallet/rpc/util.cpp
index 26270f23ed..31435a69ba 100644
--- a/src/wallet/rpc/util.cpp
+++ b/src/wallet/rpc/util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2021 The Bitcoin Core developers
+// Copyright (c) 2011-2022 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 @@ std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& reques
std::string wallet_name;
if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
- const std::shared_ptr<CWallet> pwallet = GetWallet(context, wallet_name);
+ std::shared_ptr<CWallet> pwallet = GetWallet(context, wallet_name);
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
return pwallet;
}
@@ -132,7 +132,10 @@ const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wal
std::string LabelFromValue(const UniValue& value)
{
- std::string label = value.get_str();
+ static const std::string empty_string;
+ if (value.isNull()) return empty_string;
+
+ const std::string& label{value.get_str()};
if (label == "*")
throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
return label;
diff --git a/src/wallet/rpc/util.h b/src/wallet/rpc/util.h
index 87d34f7c11..d5d6ac0dfa 100644
--- a/src/wallet/rpc/util.h
+++ b/src/wallet/rpc/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 971814e9cd..23a88cd51b 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -201,7 +201,7 @@ static RPCHelpMan loadwallet()
"\napplied to the new wallet.\n",
{
{"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet directory or .dat file."},
- {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED_NAMED_ARG, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
+ {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -226,6 +226,14 @@ static RPCHelpMan loadwallet()
bilingual_str error;
std::vector<bilingual_str> warnings;
std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
+
+ {
+ LOCK(context.wallets_mutex);
+ if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
+ throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
+ }
+ }
+
std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
HandleWalletError(wallet, status, error);
@@ -315,12 +323,12 @@ static RPCHelpMan createwallet()
{"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO, "The name for the new wallet. If this is a path, the wallet will be created at the path location."},
{"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
{"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."},
- {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Encrypt the wallet with this passphrase."},
+ {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
{"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{false}, "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
{"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation."
" Setting to \"false\" will create a legacy wallet; however, the legacy wallet type is being deprecated and"
" support for creating and opening legacy wallets will be removed in the future."},
- {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED_NAMED_ARG, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
+ {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
{"external_signer", RPCArg::Type::BOOL, RPCArg::Default{false}, "Use an external signer such as a hardware wallet. Requires -signer to be configured. Wallet creation will fail if keys cannot be fetched. Requires disable_private_keys and descriptors set to true."},
},
RPCResult{
@@ -411,7 +419,7 @@ static RPCHelpMan unloadwallet()
"Specifying the wallet name on a wallet endpoint is invalid.",
{
{"wallet_name", RPCArg::Type::STR, RPCArg::DefaultHint{"the wallet name from the RPC endpoint"}, "The name of the wallet to unload. If provided both here and in the RPC endpoint, the two must be identical."},
- {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED_NAMED_ARG, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
+ {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
},
RPCResult{RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::STR, "warning", "Warning message if wallet was not unloaded cleanly."},
@@ -437,13 +445,20 @@ static RPCHelpMan unloadwallet()
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
}
- // Release the "main" shared pointer and prevent further notifications.
- // Note that any attempt to load the same wallet would fail until the wallet
- // is destroyed (see CheckUniqueFileid).
std::vector<bilingual_str> warnings;
- std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
- if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
- throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
+ {
+ WalletRescanReserver reserver(*wallet);
+ if (!reserver.reserve()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
+ }
+
+ // Release the "main" shared pointer and prevent further notifications.
+ // Note that any attempt to load the same wallet would fail until the wallet
+ // is destroyed (see CheckUniqueFileid).
+ std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
+ if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
+ }
}
UnloadWallet(std::move(wallet));
@@ -553,8 +568,6 @@ static RPCHelpMan upgradewallet()
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!pwallet) return UniValue::VNULL;
- RPCTypeCheck(request.params, {UniValue::VNUM}, true);
-
EnsureWalletIsUnlocked(*pwallet);
int version = 0;
@@ -595,12 +608,12 @@ RPCHelpMan simulaterawtransaction()
return RPCHelpMan{"simulaterawtransaction",
"\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
{
- {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "An array of hex strings of raw transactions.\n",
+ {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
{
{"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
},
},
- {"options", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::OMITTED_NAMED_ARG, "Options",
+ {"options", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::OMITTED, "Options",
{
{"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
},
@@ -622,8 +635,6 @@ RPCHelpMan simulaterawtransaction()
if (!rpc_wallet) return UniValue::VNULL;
const CWallet& wallet = *rpc_wallet;
- RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ}, true);
-
LOCK(wallet.cs_wallet);
UniValue include_watchonly(UniValue::VNULL);
diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp
index 9ba3c7fd2c..84f33e50b3 100644
--- a/src/wallet/salvage.cpp
+++ b/src/wallet/salvage.cpp
@@ -139,7 +139,7 @@ bool RecoverDatabaseFile(const ArgsManager& args, const fs::path& file_path, bil
for (KeyValPair& row : salvagedData)
{
/* Filter for only private key type KV pairs to be added to the salvaged wallet */
- CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{row.first};
CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
std::string strType, strErr;
bool fReadOK;
diff --git a/src/wallet/salvage.h b/src/wallet/salvage.h
index e4822c3c75..ce918aec2d 100644
--- a/src/wallet/salvage.h
+++ b/src/wallet/salvage.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-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.
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 896ade77dd..59cf87355b 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -1,7 +1,8 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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 <hash.h>
#include <key_io.h>
#include <logging.h>
#include <outputtype.h>
@@ -166,9 +167,7 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
break;
}
- uint160 hash;
- CRIPEMD160().Write(vSolutions[0].data(), vSolutions[0].size()).Finalize(hash.begin());
- CScriptID scriptID = CScriptID(hash);
+ CScriptID scriptID{RIPEMD160(vSolutions[0])};
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
ret = std::max(ret, recurse_scripthash ? IsMineInner(keystore, subscript, IsMineSigVersion::WITNESS_V0) : IsMineResult::SPENDABLE);
@@ -1665,7 +1664,7 @@ std::set<CKeyID> LegacyScriptPubKeyMan::GetKeys() const
return set_address;
}
-const std::unordered_set<CScript, SaltedSipHasher> LegacyScriptPubKeyMan::GetScriptPubKeys() const
+std::unordered_set<CScript, SaltedSipHasher> LegacyScriptPubKeyMan::GetScriptPubKeys() const
{
LOCK(cs_KeyStore);
std::unordered_set<CScript, SaltedSipHasher> spks;
@@ -2123,7 +2122,7 @@ bool DescriptorScriptPubKeyMan::TopUp(unsigned int size)
if (size > 0) {
target_size = size;
} else {
- target_size = std::max(gArgs.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 1);
+ target_size = std::max(gArgs.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), int64_t{1});
}
// Calculate the new range_end
@@ -2651,17 +2650,17 @@ void DescriptorScriptPubKeyMan::WriteDescriptor()
}
}
-const WalletDescriptor DescriptorScriptPubKeyMan::GetWalletDescriptor() const
+WalletDescriptor DescriptorScriptPubKeyMan::GetWalletDescriptor() const
{
return m_wallet_descriptor;
}
-const std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys() const
+std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys() const
{
return GetScriptPubKeys(0);
}
-const std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys(int32_t minimum_index) const
+std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys(int32_t minimum_index) const
{
LOCK(cs_desc_man);
std::unordered_set<CScript, SaltedSipHasher> script_pub_keys;
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
index eb77015956..4399ac2087 100644
--- a/src/wallet/scriptpubkeyman.h
+++ b/src/wallet/scriptpubkeyman.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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,7 +36,7 @@ class WalletStorage
{
public:
virtual ~WalletStorage() = default;
- virtual const std::string GetDisplayName() const = 0;
+ virtual std::string GetDisplayName() const = 0;
virtual WalletDatabase& GetDatabase() const = 0;
virtual bool IsWalletFlagSet(uint64_t) const = 0;
virtual void UnsetBlankWalletFlag(WalletBatch&) = 0;
@@ -243,7 +243,7 @@ public:
virtual uint256 GetID() const { return uint256(); }
/** Returns a set of all the scriptPubKeys that this ScriptPubKeyMan watches */
- virtual const std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const { return {}; };
+ virtual std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const { return {}; };
/** Prepends the wallet name in logging output to ease debugging in multi-wallet use cases */
template<typename... Params>
@@ -512,7 +512,7 @@ public:
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
std::set<CKeyID> GetKeys() const override;
- const std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
+ std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
/** Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this LegacyScriptPubKeyMan.
* Does not modify this ScriptPubKeyMan. */
@@ -641,9 +641,9 @@ public:
void AddDescriptorKey(const CKey& key, const CPubKey &pubkey);
void WriteDescriptor();
- const WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
- const std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
- const std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys(int32_t minimum_index) const;
+ WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
+ std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
+ std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys(int32_t minimum_index) const;
int32_t GetEndRange() const;
bool GetDescriptorString(std::string& out, const bool priv) const;
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 3ced3ebeb5..e66ff8c97c 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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,7 @@
#include <interfaces/chain.h>
#include <numeric>
#include <policy/policy.h>
+#include <primitives/transaction.h>
#include <script/signingprovider.h>
#include <util/check.h>
#include <util/fees.h>
@@ -286,7 +287,7 @@ CoinsResult AvailableCoins(const CWallet& wallet,
if (coinControl && coinControl->HasSelected() && coinControl->IsSelected(outpoint))
continue;
- if (wallet.IsLockedCoin(outpoint))
+ if (wallet.IsLockedCoin(outpoint) && params.skip_locked)
continue;
if (wallet.IsSpent(outpoint))
@@ -361,67 +362,45 @@ CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinContr
return AvailableCoins(wallet, coinControl).GetTotalAmount();
}
-const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const CTransaction& tx, int output)
+const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint& outpoint)
{
AssertLockHeld(wallet.cs_wallet);
- const CTransaction* ptx = &tx;
- int n = output;
+ const CWalletTx* wtx{Assert(wallet.GetWalletTx(outpoint.hash))};
+
+ const CTransaction* ptx = wtx->tx.get();
+ int n = outpoint.n;
while (OutputIsChange(wallet, ptx->vout[n]) && ptx->vin.size() > 0) {
const COutPoint& prevout = ptx->vin[0].prevout;
- auto it = wallet.mapWallet.find(prevout.hash);
- if (it == wallet.mapWallet.end() || it->second.tx->vout.size() <= prevout.n ||
- !wallet.IsMine(it->second.tx->vout[prevout.n])) {
+ const CWalletTx* it = wallet.GetWalletTx(prevout.hash);
+ if (!it || it->tx->vout.size() <= prevout.n ||
+ !wallet.IsMine(it->tx->vout[prevout.n])) {
break;
}
- ptx = it->second.tx.get();
+ ptx = it->tx.get();
n = prevout.n;
}
return ptx->vout[n];
}
-const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint& outpoint)
-{
- AssertLockHeld(wallet.cs_wallet);
- return FindNonChangeParentOutput(wallet, *wallet.GetWalletTx(outpoint.hash)->tx, outpoint.n);
-}
-
std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet)
{
AssertLockHeld(wallet.cs_wallet);
std::map<CTxDestination, std::vector<COutput>> result;
- for (COutput& coin : AvailableCoinsListUnspent(wallet).All()) {
+ CCoinControl coin_control;
+ // Include watch-only for LegacyScriptPubKeyMan wallets without private keys
+ coin_control.fAllowWatchOnly = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
+ CoinFilterParams coins_params;
+ coins_params.only_spendable = false;
+ coins_params.skip_locked = false;
+ for (const COutput& coin : AvailableCoins(wallet, &coin_control, /*feerate=*/std::nullopt, coins_params).All()) {
CTxDestination address;
if ((coin.spendable || (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && coin.solvable)) &&
ExtractDestination(FindNonChangeParentOutput(wallet, coin.outpoint).scriptPubKey, address)) {
- result[address].emplace_back(std::move(coin));
- }
- }
-
- std::vector<COutPoint> lockedCoins;
- wallet.ListLockedCoins(lockedCoins);
- // Include watch-only for LegacyScriptPubKeyMan wallets without private keys
- const bool include_watch_only = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
- const isminetype is_mine_filter = include_watch_only ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
- for (const COutPoint& output : lockedCoins) {
- auto it = wallet.mapWallet.find(output.hash);
- if (it != wallet.mapWallet.end()) {
- const auto& wtx = it->second;
- int depth = wallet.GetTxDepthInMainChain(wtx);
- if (depth >= 0 && output.n < wtx.tx->vout.size() &&
- wallet.IsMine(wtx.tx->vout[output.n]) == is_mine_filter
- ) {
- CTxDestination address;
- if (ExtractDestination(FindNonChangeParentOutput(wallet, *wtx.tx, output.n).scriptPubKey, address)) {
- const auto out = wtx.tx->vout.at(output.n);
- result[address].emplace_back(
- COutPoint(wtx.GetHash(), output.n), out, depth, CalculateMaximumSignedInputSize(out, &wallet, /*coin_control=*/nullptr), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ false, wtx.GetTxTime(), CachedTxIsFromMe(wallet, wtx, ISMINE_ALL));
- }
- }
+ result[address].emplace_back(coin);
}
}
-
return result;
}
@@ -509,33 +488,37 @@ std::vector<OutputGroup> GroupOutputs(const CWallet& wallet, const std::vector<C
return groups_out;
}
-std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const CoinsResult& available_coins,
+// Returns true if the result contains an error and the message is not empty
+static bool HasErrorMsg(const util::Result<SelectionResult>& res) { return !util::ErrorString(res).empty(); }
+
+util::Result<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const CoinsResult& available_coins,
const CoinSelectionParams& coin_selection_params, bool allow_mixed_output_types)
{
// Run coin selection on each OutputType and compute the Waste Metric
std::vector<SelectionResult> results;
for (const auto& it : available_coins.coins) {
- if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, it.second, coin_selection_params)}) {
- results.push_back(*result);
- }
+ auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, it.second, coin_selection_params)};
+ // If any specific error message appears here, then something particularly wrong happened.
+ if (HasErrorMsg(result)) return result; // So let's return the specific error.
+ // Append the favorable result.
+ if (result) results.push_back(*result);
}
// If we have at least one solution for funding the transaction without mixing, choose the minimum one according to waste metric
// and return the result
if (results.size() > 0) return *std::min_element(results.begin(), results.end());
// If we can't fund the transaction from any individual OutputType, run coin selection one last time
- // over all available coins, which would allow mixing
- if (allow_mixed_output_types) {
- if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.All(), coin_selection_params)}) {
- return result;
- }
+ // over all available coins, which would allow mixing.
+ // If TypesCount() <= 1, there is nothing to mix.
+ if (allow_mixed_output_types && available_coins.TypesCount() > 1) {
+ return ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.All(), coin_selection_params);
}
// Either mixing is not allowed and we couldn't find a solution from any single OutputType, or mixing was allowed and we still couldn't
// find a solution using all available coins
- return std::nullopt;
+ return util::Error();
};
-std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const std::vector<COutput>& available_coins, const CoinSelectionParams& coin_selection_params)
+util::Result<SelectionResult> ChooseSelectionResult(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const std::vector<COutput>& available_coins, const CoinSelectionParams& coin_selection_params)
{
// Vector of results. We will choose the best one based on waste.
std::vector<SelectionResult> results;
@@ -559,7 +542,7 @@ std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, cons
if (results.empty()) {
// No solution found
- return std::nullopt;
+ return util::Error();
}
std::vector<SelectionResult> eligible_results;
@@ -569,7 +552,8 @@ std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, cons
});
if (eligible_results.empty()) {
- return std::nullopt;
+ return util::Error{_("The inputs size exceeds the maximum weight. "
+ "Please try sending a smaller amount or manually consolidating your wallet's UTXOs")};
}
// Choose the result with the least waste
@@ -578,15 +562,18 @@ std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, cons
return best_result;
}
-std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const PreSelectedInputs& pre_set_inputs,
- const CAmount& nTargetValue, const CCoinControl& coin_control,
- const CoinSelectionParams& coin_selection_params)
+util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const PreSelectedInputs& pre_set_inputs,
+ const CAmount& nTargetValue, const CCoinControl& coin_control,
+ const CoinSelectionParams& coin_selection_params)
{
// Deduct preset inputs amount from the search target
CAmount selection_target = nTargetValue - pre_set_inputs.total_amount;
// Return if automatic coin selection is disabled, and we don't cover the selection target
- if (!coin_control.m_allow_other_inputs && selection_target > 0) return std::nullopt;
+ if (!coin_control.m_allow_other_inputs && selection_target > 0) {
+ return util::Error{_("The preselected coins total amount does not cover the transaction target. "
+ "Please allow other inputs to be automatically selected or include more coins manually")};
+ }
// Return if we can cover the target only with the preset inputs
if (selection_target <= 0) {
@@ -601,7 +588,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
CAmount available_coins_total_amount = coin_selection_params.m_subtract_fee_outputs ? available_coins.GetTotalAmount() :
(available_coins.GetEffectiveTotalAmount().has_value() ? *available_coins.GetEffectiveTotalAmount() : 0);
if (selection_target > available_coins_total_amount) {
- return std::nullopt; // Insufficient funds
+ return util::Error(); // Insufficient funds
}
// Start wallet Coin Selection procedure
@@ -620,7 +607,12 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
return op_selection_result;
}
-std::optional<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& value_to_select, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
+struct SelectionFilter {
+ CoinEligibilityFilter filter;
+ bool allow_mixed_output_types{true};
+};
+
+util::Result<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& value_to_select, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
{
unsigned int limit_ancestor_count = 0;
unsigned int limit_descendant_count = 0;
@@ -641,54 +633,56 @@ std::optional<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, Coi
// Coin Selection attempts to select inputs from a pool of eligible UTXOs to fund the
// transaction at a target feerate. If an attempt fails, more attempts may be made using a more
// permissive CoinEligibilityFilter.
- std::optional<SelectionResult> res = [&] {
- // If possible, fund the transaction with confirmed UTXOs only. Prefer at least six
- // confirmations on outputs received from other wallets and only spend confirmed change.
- if (auto r1{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 6, 0), available_coins, coin_selection_params, /*allow_mixed_output_types=*/false)}) return r1;
- // Allow mixing only if no solution from any single output type can be found
- if (auto r2{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 1, 0), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) return r2;
-
+ util::Result<SelectionResult> res = [&] {
+ // Place coins eligibility filters on a scope increasing order.
+ std::vector<SelectionFilter> ordered_filters{
+ // If possible, fund the transaction with confirmed UTXOs only. Prefer at least six
+ // confirmations on outputs received from other wallets and only spend confirmed change.
+ {CoinEligibilityFilter(1, 6, 0), /*allow_mixed_output_types=*/false},
+ {CoinEligibilityFilter(1, 1, 0)},
+ };
// Fall back to using zero confirmation change (but with as few ancestors in the mempool as
// possible) if we cannot fund the transaction otherwise.
if (wallet.m_spend_zero_conf_change) {
- if (auto r3{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, 2), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) return r3;
- if (auto r4{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)),
- available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
- return r4;
- }
- if (auto r5{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2),
- available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
- return r5;
- }
+ ordered_filters.push_back({CoinEligibilityFilter(0, 1, 2)});
+ ordered_filters.push_back({CoinEligibilityFilter(0, 1, std::min(size_t{4}, max_ancestors/3), std::min(size_t{4}, max_descendants/3))});
+ ordered_filters.push_back({CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2)});
// If partial groups are allowed, relax the requirement of spending OutputGroups (groups
// of UTXOs sent to the same address, which are obviously controlled by a single wallet)
// in their entirety.
- if (auto r6{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, /*include_partial=*/true),
- available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
- return r6;
- }
+ ordered_filters.push_back({CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, /*include_partial=*/true)});
// Try with unsafe inputs if they are allowed. This may spend unconfirmed outputs
// received from other wallets.
if (coin_control.m_include_unsafe_inputs) {
- if (auto r7{AttemptSelection(wallet, value_to_select,
- CoinEligibilityFilter(/*conf_mine=*/0, /*conf_theirs=*/0, max_ancestors-1, max_descendants-1, /*include_partial=*/true),
- available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
- return r7;
- }
+ ordered_filters.push_back({CoinEligibilityFilter(/*conf_mine=*/0, /*conf_theirs*/0, max_ancestors-1, max_descendants-1, /*include_partial=*/true)});
}
// Try with unlimited ancestors/descendants. The transaction will still need to meet
// mempool ancestor/descendant policy to be accepted to mempool and broadcasted, but
// OutputGroups use heuristics that may overestimate ancestor/descendant counts.
if (!fRejectLongChains) {
- if (auto r8{AttemptSelection(wallet, value_to_select,
- CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), /*include_partial=*/true),
- available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
- return r8;
- }
+ ordered_filters.push_back({CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(),
+ std::numeric_limits<uint64_t>::max(),
+ /*include_partial=*/true)});
+ }
+ }
+
+ // Walk-through the filters until the solution gets found.
+ // If no solution is found, return the first detailed error (if any).
+ // future: add "error level" so the worst one can be picked instead.
+ std::vector<util::Result<SelectionResult>> res_detailed_errors;
+ for (const auto& select_filter : ordered_filters) {
+ if (auto res{AttemptSelection(wallet, value_to_select, select_filter.filter, available_coins,
+ coin_selection_params, select_filter.allow_mixed_output_types)}) {
+ return res; // result found
+ } else {
+ // If any specific error message appears here, then something particularly wrong might have happened.
+ // Save the error and continue the selection process. So if no solutions gets found, we can return
+ // the detailed error to the upper layers.
+ if (HasErrorMsg(res)) res_detailed_errors.emplace_back(res);
}
}
// Coin Selection failed.
- return std::optional<SelectionResult>();
+ return res_detailed_errors.empty() ? util::Result<SelectionResult>(util::Error()) : res_detailed_errors.front();
}();
return res;
@@ -778,7 +772,6 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
AssertLockHeld(wallet.cs_wallet);
// out variables, to be packed into returned result structure
- CAmount nFeeRet;
int nChangePosInOut = change_pos;
FastRandomContext rng_fast;
@@ -916,13 +909,16 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
}
// Choose coins to use
- std::optional<SelectionResult> result = SelectCoins(wallet, available_coins, preset_inputs, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
- if (!result) {
- return util::Error{_("Insufficient funds")};
+ auto select_coins_res = SelectCoins(wallet, available_coins, preset_inputs, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
+ if (!select_coins_res) {
+ // 'SelectCoins' either returns a specific error message or, if empty, means a general "Insufficient funds".
+ const bilingual_str& err = util::ErrorString(select_coins_res);
+ return util::Error{err.empty() ?_("Insufficient funds") : err};
}
- TRACE5(coin_selection, selected_coins, wallet.GetName().c_str(), GetAlgorithmName(result->GetAlgo()).c_str(), result->GetTarget(), result->GetWaste(), result->GetSelectedValue());
+ const SelectionResult& result = *select_coins_res;
+ TRACE5(coin_selection, selected_coins, wallet.GetName().c_str(), GetAlgorithmName(result.GetAlgo()).c_str(), result.GetTarget(), result.GetWaste(), result.GetSelectedValue());
- const CAmount change_amount = result->GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
+ const CAmount change_amount = result.GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
if (change_amount > 0) {
CTxOut newTxOut(change_amount, scriptChange);
if (nChangePosInOut == -1) {
@@ -937,7 +933,7 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
}
// Shuffle selected coins and fill in final vin
- std::vector<COutput> selected_coins = result->GetShuffledInputVector();
+ std::vector<COutput> selected_coins = result.GetShuffledInputVector();
// The sequence number is set to non-maxint so that DiscourageFeeSniping
// works.
@@ -960,24 +956,28 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
return util::Error{_("Missing solving data for estimating transaction size")};
}
CAmount fee_needed = coin_selection_params.m_effective_feerate.GetFee(nBytes);
- nFeeRet = result->GetSelectedValue() - recipients_sum - change_amount;
+ const CAmount output_value = CalculateOutputValue(txNew);
+ Assume(recipients_sum + change_amount == output_value);
+ CAmount current_fee = result.GetSelectedValue() - output_value;
- // The only time that fee_needed should be less than the amount available for fees is when
- // we are subtracting the fee from the outputs. If this occurs at any other time, it is a bug.
- if (!coin_selection_params.m_subtract_fee_outputs && fee_needed > nFeeRet) {
- return util::Error{Untranslated(STR_INTERNAL_BUG("Fee needed > fee paid"))};
+ // Sanity check that the fee cannot be negative as that means we have more output value than input value
+ if (current_fee < 0) {
+ return util::Error{Untranslated(STR_INTERNAL_BUG("Fee paid < 0"))};
}
// If there is a change output and we overpay the fees then increase the change to match the fee needed
- if (nChangePosInOut != -1 && fee_needed < nFeeRet) {
+ if (nChangePosInOut != -1 && fee_needed < current_fee) {
auto& change = txNew.vout.at(nChangePosInOut);
- change.nValue += nFeeRet - fee_needed;
- nFeeRet = fee_needed;
+ change.nValue += current_fee - fee_needed;
+ current_fee = result.GetSelectedValue() - CalculateOutputValue(txNew);
+ if (fee_needed != current_fee) {
+ return util::Error{Untranslated(STR_INTERNAL_BUG("Change adjustment: Fee needed != fee paid"))};
+ }
}
// Reduce output values for subtractFeeFromAmount
if (coin_selection_params.m_subtract_fee_outputs) {
- CAmount to_reduce = fee_needed - nFeeRet;
+ CAmount to_reduce = fee_needed - current_fee;
int i = 0;
bool fFirst = true;
for (const auto& recipient : vecSend)
@@ -1008,7 +1008,16 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
}
++i;
}
- nFeeRet = fee_needed;
+ current_fee = result.GetSelectedValue() - CalculateOutputValue(txNew);
+ if (fee_needed != current_fee) {
+ return util::Error{Untranslated(STR_INTERNAL_BUG("SFFO: Fee needed != fee paid"))};
+ }
+ }
+
+ // fee_needed should now always be less than or equal to the current fees that we pay.
+ // If it is not, it is a bug.
+ if (fee_needed > current_fee) {
+ return util::Error{Untranslated(STR_INTERNAL_BUG("Fee needed > fee paid"))};
}
// Give up if change keypool ran out and change is required
@@ -1030,7 +1039,7 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
return util::Error{_("Transaction too large")};
}
- if (nFeeRet > wallet.m_default_max_tx_fee) {
+ if (current_fee > wallet.m_default_max_tx_fee) {
return util::Error{TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED)};
}
@@ -1046,14 +1055,14 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
reservedest.KeepDestination();
wallet.WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
- nFeeRet, nBytes, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
+ current_fee, nBytes, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
feeCalc.est.pass.start, feeCalc.est.pass.end,
(feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) > 0.0 ? 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) : 0.0,
feeCalc.est.pass.withinTarget, feeCalc.est.pass.totalConfirmed, feeCalc.est.pass.inMempool, feeCalc.est.pass.leftMempool,
feeCalc.est.fail.start, feeCalc.est.fail.end,
(feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) > 0.0 ? 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) : 0.0,
feeCalc.est.fail.withinTarget, feeCalc.est.fail.totalConfirmed, feeCalc.est.fail.inMempool, feeCalc.est.fail.leftMempool);
- return CreatedTransactionResult(tx, nFeeRet, nChangePosInOut, feeCalc);
+ return CreatedTransactionResult(tx, current_fee, nChangePosInOut, feeCalc);
}
util::Result<CreatedTransactionResult> CreateTransaction(
diff --git a/src/wallet/spend.h b/src/wallet/spend.h
index 2b861c2361..d8da556d29 100644
--- a/src/wallet/spend.h
+++ b/src/wallet/spend.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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,6 +46,8 @@ struct CoinsResult {
/** The following methods are provided so that CoinsResult can mimic a vector,
* i.e., methods can work with individual OutputType vectors or on the entire object */
size_t Size() const;
+ /** Return how many different output types this struct stores */
+ size_t TypesCount() const { return coins.size(); }
void Clear();
void Erase(const std::unordered_set<COutPoint, SaltedOutpointHasher>& coins_to_remove);
void Shuffle(FastRandomContext& rng_fast);
@@ -74,6 +76,8 @@ struct CoinFilterParams {
bool only_spendable{true};
// By default, do not include immature coinbase outputs
bool include_immature_coinbase{false};
+ // By default, skip locked UTXOs
+ bool skip_locked{true};
};
/**
@@ -95,7 +99,6 @@ CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinContr
/**
* Find non-change parent output.
*/
-const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const CTransaction& tx, int output) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint& outpoint) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
/**
@@ -117,9 +120,11 @@ std::vector<OutputGroup> GroupOutputs(const CWallet& wallet, const std::vector<C
* param@[in] coin_selection_params Parameters for the coin selection
* param@[in] allow_mixed_output_types Relax restriction that SelectionResults must be of the same OutputType
* returns If successful, a SelectionResult containing the input set
- * If failed, a nullopt
+ * If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds")
+ * or (2) an specific error message if there was something particularly wrong (e.g. a selection
+ * result that surpassed the tx max weight size).
*/
-std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const CoinsResult& available_coins,
+util::Result<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const CoinsResult& available_coins,
const CoinSelectionParams& coin_selection_params, bool allow_mixed_output_types);
/**
@@ -133,9 +138,11 @@ std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAm
* param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
* param@[in] coin_selection_params Parameters for the coin selection
* returns If successful, a SelectionResult containing the input set
- * If failed, a nullopt
+ * If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds")
+ * or (2) an specific error message if there was something particularly wrong (e.g. a selection
+ * result that surpassed the tx max weight size).
*/
-std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const std::vector<COutput>& available_coins,
+util::Result<SelectionResult> ChooseSelectionResult(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const std::vector<COutput>& available_coins,
const CoinSelectionParams& coin_selection_params);
// User manually selected inputs that must be part of the transaction
@@ -173,18 +180,20 @@ util::Result<PreSelectedInputs> FetchSelectedInputs(const CWallet& wallet, const
* param@[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends,
* and whether to subtract the fee from the outputs.
* returns If successful, a SelectionResult containing the selected coins
- * If failed, a nullopt.
+ * If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds")
+ * or (2) an specific error message if there was something particularly wrong (e.g. a selection
+ * result that surpassed the tx max weight size).
*/
-std::optional<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CCoinControl& coin_control,
+util::Result<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CCoinControl& coin_control,
const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
/**
* Select all coins from coin_control, and if coin_control 'm_allow_other_inputs=true', call 'AutomaticCoinSelection' to
* select a set of coins such that nTargetValue - pre_set_inputs.total_amount is met.
*/
-std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const PreSelectedInputs& pre_set_inputs,
- const CAmount& nTargetValue, const CCoinControl& coin_control,
- const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
+util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const PreSelectedInputs& pre_set_inputs,
+ const CAmount& nTargetValue, const CCoinControl& coin_control,
+ const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
struct CreatedTransactionResult
{
diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp
index 053fb8f983..4af49db609 100644
--- a/src/wallet/sqlite.cpp
+++ b/src/wallet/sqlite.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
+// Copyright (c) 2020-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -125,7 +125,6 @@ void SQLiteBatch::SetupSQLStatements()
{&m_insert_stmt, "INSERT INTO main VALUES(?, ?)"},
{&m_overwrite_stmt, "INSERT or REPLACE into main values(?, ?)"},
{&m_delete_stmt, "DELETE FROM main WHERE key = ?"},
- {&m_cursor_stmt, "SELECT key, value FROM main"},
};
for (const auto& [stmt_prepared, stmt_text] : statements) {
@@ -374,7 +373,6 @@ void SQLiteBatch::Close()
{&m_insert_stmt, "insert"},
{&m_overwrite_stmt, "overwrite"},
{&m_delete_stmt, "delete"},
- {&m_cursor_stmt, "cursor"},
};
for (const auto& [stmt_prepared, stmt_description] : statements) {
@@ -387,7 +385,7 @@ void SQLiteBatch::Close()
}
}
-bool SQLiteBatch::ReadKey(CDataStream&& key, CDataStream& value)
+bool SQLiteBatch::ReadKey(DataStream&& key, DataStream& value)
{
if (!m_database.m_db) return false;
assert(m_read_stmt);
@@ -414,7 +412,7 @@ bool SQLiteBatch::ReadKey(CDataStream&& key, CDataStream& value)
return true;
}
-bool SQLiteBatch::WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite)
+bool SQLiteBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite)
{
if (!m_database.m_db) return false;
assert(m_insert_stmt && m_overwrite_stmt);
@@ -441,7 +439,7 @@ bool SQLiteBatch::WriteKey(CDataStream&& key, CDataStream&& value, bool overwrit
return res == SQLITE_DONE;
}
-bool SQLiteBatch::EraseKey(CDataStream&& key)
+bool SQLiteBatch::EraseKey(DataStream&& key)
{
if (!m_database.m_db) return false;
assert(m_delete_stmt);
@@ -459,7 +457,7 @@ bool SQLiteBatch::EraseKey(CDataStream&& key)
return res == SQLITE_DONE;
}
-bool SQLiteBatch::HasKey(CDataStream&& key)
+bool SQLiteBatch::HasKey(DataStream&& key)
{
if (!m_database.m_db) return false;
assert(m_read_stmt);
@@ -472,28 +470,15 @@ bool SQLiteBatch::HasKey(CDataStream&& key)
return res == SQLITE_ROW;
}
-bool SQLiteBatch::StartCursor()
+DatabaseCursor::Status SQLiteCursor::Next(DataStream& key, DataStream& value)
{
- assert(!m_cursor_init);
- if (!m_database.m_db) return false;
- m_cursor_init = true;
- return true;
-}
-
-bool SQLiteBatch::ReadAtCursor(CDataStream& key, CDataStream& value, bool& complete)
-{
- complete = false;
-
- if (!m_cursor_init) return false;
-
int res = sqlite3_step(m_cursor_stmt);
if (res == SQLITE_DONE) {
- complete = true;
- return true;
+ return Status::DONE;
}
if (res != SQLITE_ROW) {
- LogPrintf("SQLiteBatch::ReadAtCursor: Unable to execute cursor step: %s\n", sqlite3_errstr(res));
- return false;
+ LogPrintf("%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res));
+ return Status::FAIL;
}
// Leftmost column in result is index 0
@@ -503,13 +488,32 @@ bool SQLiteBatch::ReadAtCursor(CDataStream& key, CDataStream& value, bool& compl
const std::byte* value_data{AsBytePtr(sqlite3_column_blob(m_cursor_stmt, 1))};
size_t value_data_size(sqlite3_column_bytes(m_cursor_stmt, 1));
value.write({value_data, value_data_size});
- return true;
+ return Status::MORE;
}
-void SQLiteBatch::CloseCursor()
+SQLiteCursor::~SQLiteCursor()
{
sqlite3_reset(m_cursor_stmt);
- m_cursor_init = false;
+ int res = sqlite3_finalize(m_cursor_stmt);
+ if (res != SQLITE_OK) {
+ LogPrintf("%s: cursor closed but could not finalize cursor statement: %s\n",
+ __func__, sqlite3_errstr(res));
+ }
+}
+
+std::unique_ptr<DatabaseCursor> SQLiteBatch::GetNewCursor()
+{
+ if (!m_database.m_db) return nullptr;
+ auto cursor = std::make_unique<SQLiteCursor>();
+
+ const char* stmt_text = "SELECT key, value FROM main";
+ int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, &cursor->m_cursor_stmt, nullptr);
+ if (res != SQLITE_OK) {
+ throw std::runtime_error(strprintf(
+ "%s: Failed to setup cursor SQL statement: %s\n", __func__, sqlite3_errstr(res)));
+ }
+
+ return cursor;
}
bool SQLiteBatch::TxnBegin()
diff --git a/src/wallet/sqlite.h b/src/wallet/sqlite.h
index 47b7ebb0ec..c6745d7a7e 100644
--- a/src/wallet/sqlite.h
+++ b/src/wallet/sqlite.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Bitcoin Core developers
+// Copyright (c) 2020-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.
@@ -14,26 +14,34 @@ struct bilingual_str;
namespace wallet {
class SQLiteDatabase;
+class SQLiteCursor : public DatabaseCursor
+{
+public:
+ sqlite3_stmt* m_cursor_stmt{nullptr};
+
+ explicit SQLiteCursor() {}
+ ~SQLiteCursor() override;
+
+ Status Next(DataStream& key, DataStream& value) override;
+};
+
/** RAII class that provides access to a WalletDatabase */
class SQLiteBatch : public DatabaseBatch
{
private:
SQLiteDatabase& m_database;
- bool m_cursor_init = false;
-
sqlite3_stmt* m_read_stmt{nullptr};
sqlite3_stmt* m_insert_stmt{nullptr};
sqlite3_stmt* m_overwrite_stmt{nullptr};
sqlite3_stmt* m_delete_stmt{nullptr};
- sqlite3_stmt* m_cursor_stmt{nullptr};
void SetupSQLStatements();
- bool ReadKey(CDataStream&& key, CDataStream& value) override;
- bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite = true) override;
- bool EraseKey(CDataStream&& key) override;
- bool HasKey(CDataStream&& key) override;
+ bool ReadKey(DataStream&& key, DataStream& value) override;
+ bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override;
+ bool EraseKey(DataStream&& key) override;
+ bool HasKey(DataStream&& key) override;
public:
explicit SQLiteBatch(SQLiteDatabase& database);
@@ -44,9 +52,7 @@ public:
void Close() override;
- bool StartCursor() override;
- bool ReadAtCursor(CDataStream& key, CDataStream& value, bool& complete) override;
- void CloseCursor() override;
+ std::unique_ptr<DatabaseCursor> GetNewCursor() override;
bool TxnBegin() override;
bool TxnCommit() override;
bool TxnAbort() override;
diff --git a/src/wallet/test/availablecoins_tests.cpp b/src/wallet/test/availablecoins_tests.cpp
deleted file mode 100644
index 2427a343d5..0000000000
--- a/src/wallet/test/availablecoins_tests.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or https://www.opensource.org/licenses/mit-license.php.
-
-#include <validation.h>
-#include <wallet/coincontrol.h>
-#include <wallet/spend.h>
-#include <wallet/test/util.h>
-#include <wallet/test/wallet_test_fixture.h>
-
-#include <boost/test/unit_test.hpp>
-
-namespace wallet {
-BOOST_FIXTURE_TEST_SUITE(availablecoins_tests, WalletTestingSetup)
-class AvailableCoinsTestingSetup : public TestChain100Setup
-{
-public:
- AvailableCoinsTestingSetup()
- {
- CreateAndProcessBlock({}, {});
- wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey);
- }
-
- ~AvailableCoinsTestingSetup()
- {
- wallet.reset();
- }
- CWalletTx& AddTx(CRecipient recipient)
- {
- CTransactionRef tx;
- CCoinControl dummy;
- {
- constexpr int RANDOM_CHANGE_POSITION = -1;
- auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, dummy);
- BOOST_CHECK(res);
- tx = res->tx;
- }
- wallet->CommitTransaction(tx, {}, {});
- CMutableTransaction blocktx;
- {
- LOCK(wallet->cs_wallet);
- blocktx = CMutableTransaction(*wallet->mapWallet.at(tx->GetHash()).tx);
- }
- CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
-
- LOCK(wallet->cs_wallet);
- LOCK(m_node.chainman->GetMutex());
- wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
- auto it = wallet->mapWallet.find(tx->GetHash());
- BOOST_CHECK(it != wallet->mapWallet.end());
- it->second.m_state = TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/1};
- return it->second;
- }
-
- std::unique_ptr<CWallet> wallet;
-};
-
-BOOST_FIXTURE_TEST_CASE(BasicOutputTypesTest, AvailableCoinsTestingSetup)
-{
- CoinsResult available_coins;
- util::Result<CTxDestination> dest{util::Error{}};
- LOCK(wallet->cs_wallet);
-
- // Verify our wallet has one usable coinbase UTXO before starting
- // This UTXO is a P2PK, so it should show up in the Other bucket
- available_coins = AvailableCoins(*wallet);
- BOOST_CHECK_EQUAL(available_coins.Size(), 1U);
- BOOST_CHECK_EQUAL(available_coins.coins[OutputType::UNKNOWN].size(), 1U);
-
- // We will create a self transfer for each of the OutputTypes and
- // verify it is put in the correct bucket after running GetAvailablecoins
- //
- // For each OutputType, We expect 2 UTXOs in our wallet following the self transfer:
- // 1. One UTXO as the recipient
- // 2. One UTXO from the change, due to payment address matching logic
-
- // Bech32m
- dest = wallet->GetNewDestination(OutputType::BECH32M, "");
- BOOST_ASSERT(dest);
- AddTx(CRecipient{{GetScriptForDestination(*dest)}, 1 * COIN, /*fSubtractFeeFromAmount=*/true});
- available_coins = AvailableCoins(*wallet);
- BOOST_CHECK_EQUAL(available_coins.coins[OutputType::BECH32M].size(), 2U);
-
- // Bech32
- dest = wallet->GetNewDestination(OutputType::BECH32, "");
- BOOST_ASSERT(dest);
- AddTx(CRecipient{{GetScriptForDestination(*dest)}, 2 * COIN, /*fSubtractFeeFromAmount=*/true});
- available_coins = AvailableCoins(*wallet);
- BOOST_CHECK_EQUAL(available_coins.coins[OutputType::BECH32].size(), 2U);
-
- // P2SH-SEGWIT
- dest = wallet->GetNewDestination(OutputType::P2SH_SEGWIT, "");
- BOOST_ASSERT(dest);
- AddTx(CRecipient{{GetScriptForDestination(*dest)}, 3 * COIN, /*fSubtractFeeFromAmount=*/true});
- available_coins = AvailableCoins(*wallet);
- BOOST_CHECK_EQUAL(available_coins.coins[OutputType::P2SH_SEGWIT].size(), 2U);
-
- // Legacy (P2PKH)
- dest = wallet->GetNewDestination(OutputType::LEGACY, "");
- BOOST_ASSERT(dest);
- AddTx(CRecipient{{GetScriptForDestination(*dest)}, 4 * COIN, /*fSubtractFeeFromAmount=*/true});
- available_coins = AvailableCoins(*wallet);
- BOOST_CHECK_EQUAL(available_coins.coins[OutputType::LEGACY].size(), 2U);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-} // namespace wallet
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index ce875d5442..5281d0589a 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -121,9 +121,9 @@ static CAmount make_hard_case(int utxos, std::vector<COutput>& utxo_pool)
utxo_pool.clear();
CAmount target = 0;
for (int i = 0; i < utxos; ++i) {
- target += (CAmount)1 << (utxos+i);
- add_coin((CAmount)1 << (utxos+i), 2*i, utxo_pool);
- add_coin(((CAmount)1 << (utxos+i)) + ((CAmount)1 << (utxos-1-i)), 2*i + 1, utxo_pool);
+ target += CAmount{1} << (utxos+i);
+ add_coin(CAmount{1} << (utxos+i), 2*i, utxo_pool);
+ add_coin((CAmount{1} << (utxos+i)) + (CAmount{1} << (utxos-1-i)), 2*i + 1, utxo_pool);
}
return target;
}
@@ -232,17 +232,6 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
BOOST_CHECK_EQUAL(result5->GetSelectedValue(), 10 * CENT);
expected_result.Clear();
- // Negative effective value
- // Select 10 Cent but have 1 Cent not be possible because too small
- add_coin(5 * CENT, 5, expected_result);
- add_coin(3 * CENT, 3, expected_result);
- add_coin(2 * CENT, 2, expected_result);
- const auto result6 = SelectCoinsBnB(GroupCoins(utxo_pool), 10 * CENT, 5000);
- BOOST_CHECK(result6);
- BOOST_CHECK_EQUAL(result6->GetSelectedValue(), 10 * CENT);
- // FIXME: this test is redundant with the above, because 1 Cent is selected, not "too small"
- // BOOST_CHECK(EquivalentResult(expected_result, *result));
-
// Select 0.25 Cent, not possible
BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), 0.25 * CENT, 0.5 * CENT));
expected_result.Clear();
@@ -302,6 +291,8 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
coin_selection_params_bnb.m_change_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_output_size);
coin_selection_params_bnb.m_cost_of_change = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_spend_size) + coin_selection_params_bnb.m_change_fee;
coin_selection_params_bnb.min_viable_change = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_spend_size);
+ coin_selection_params_bnb.m_subtract_fee_outputs = true;
+
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
wallet->LoadWallet();
@@ -319,7 +310,6 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
available_coins.Clear();
add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate);
available_coins.All().at(0).input_bytes = 40;
- coin_selection_params_bnb.m_subtract_fee_outputs = true;
const auto result9 = SelectCoinsBnB(GroupCoins(available_coins.All()), 1 * CENT, coin_selection_params_bnb.m_cost_of_change);
BOOST_CHECK(result9);
BOOST_CHECK_EQUAL(result9->GetSelectedValue(), 1 * CENT);
@@ -931,7 +921,7 @@ BOOST_AUTO_TEST_CASE(effective_value_test)
BOOST_CHECK_EQUAL(output5.GetEffectiveValue(), nValue); // The effective value should be equal to the absolute value if input_bytes is -1
}
-static std::optional<SelectionResult> select_coins(const CAmount& target, const CoinSelectionParams& cs_params, const CCoinControl& cc, std::function<CoinsResult(CWallet&)> coin_setup, interfaces::Chain* chain, const ArgsManager& args)
+static util::Result<SelectionResult> select_coins(const CAmount& target, const CoinSelectionParams& cs_params, const CCoinControl& cc, std::function<CoinsResult(CWallet&)> coin_setup, interfaces::Chain* chain, const ArgsManager& args)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(chain, "", args, CreateMockWalletDatabase());
wallet->LoadWallet();
@@ -941,7 +931,7 @@ static std::optional<SelectionResult> select_coins(const CAmount& target, const
auto available_coins = coin_setup(*wallet);
- const auto result = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/ {}, target, cc, cs_params);
+ auto result = SelectCoins(*wallet, available_coins, /*pre_set_inputs=*/ {}, target, cc, cs_params);
if (result) {
const auto signedTxSize = 10 + 34 + 68 * result->GetInputSet().size(); // static header size + output size + inputs size (P2WPKH)
BOOST_CHECK_LE(signedTxSize * WITNESS_SCALE_FACTOR, MAX_STANDARD_TX_WEIGHT);
diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp
index f61808c549..7e26656b86 100644
--- a/src/wallet/test/db_tests.cpp
+++ b/src/wallet/test/db_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/fuzz/notifications.cpp b/src/wallet/test/fuzz/notifications.cpp
index 5e9cd4001b..de381a5ec9 100644
--- a/src/wallet/test/fuzz/notifications.cpp
+++ b/src/wallet/test/fuzz/notifications.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/fuzz/parse_iso8601.cpp b/src/wallet/test/fuzz/parse_iso8601.cpp
index 5be248c2fb..c1bafc1073 100644
--- a/src/wallet/test/fuzz/parse_iso8601.cpp
+++ b/src/wallet/test/fuzz/parse_iso8601.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
+// Copyright (c) 2019-2022 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/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp
index 8eb7689c94..60b1bab8ac 100644
--- a/src/wallet/test/init_test_fixture.cpp
+++ b/src/wallet/test/init_test_fixture.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/init_tests.cpp b/src/wallet/test/init_tests.cpp
index fb0a07e181..3dbc91fc68 100644
--- a/src/wallet/test/init_tests.cpp
+++ b/src/wallet/test/init_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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 2c83d25c20..151b09d2a6 100644
--- a/src/wallet/test/ismine_tests.cpp
+++ b/src/wallet/test/ismine_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
index 62053ae8d2..9510f28282 100644
--- a/src/wallet/test/psbt_wallet_tests.cpp
+++ b/src/wallet/test/psbt_wallet_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/spend_tests.cpp b/src/wallet/test/spend_tests.cpp
index 40756fedfb..364cc5c20b 100644
--- a/src/wallet/test/spend_tests.cpp
+++ b/src/wallet/test/spend_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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/util.cpp b/src/wallet/test/util.cpp
index f6c7ecb598..225871fd91 100644
--- a/src/wallet/test/util.cpp
+++ b/src/wallet/test/util.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -50,18 +50,18 @@ std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database,
// Get a cursor to the original database
auto batch = database.MakeBatch();
- batch->StartCursor();
+ std::unique_ptr<wallet::DatabaseCursor> cursor = batch->GetNewCursor();
// Get a batch for the new database
auto new_batch = new_database->MakeBatch();
// Read all records from the original database and write them to the new one
while (true) {
- CDataStream key(SER_DISK, CLIENT_VERSION);
- CDataStream value(SER_DISK, CLIENT_VERSION);
- bool complete;
- batch->ReadAtCursor(key, value, complete);
- if (complete) break;
+ DataStream key{};
+ DataStream value{};
+ DatabaseCursor::Status status = cursor->Next(key, value);
+ assert(status != DatabaseCursor::Status::FAIL);
+ if (status == DatabaseCursor::Status::DONE) break;
new_batch->Write(key, value);
}
diff --git a/src/wallet/test/util.h b/src/wallet/test/util.h
index a2e361ddca..635a5152ec 100644
--- a/src/wallet/test/util.h
+++ b/src/wallet/test/util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 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_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp
index 327c28412a..6b8542f378 100644
--- a/src/wallet/test/wallet_crypto_tests.cpp
+++ b/src/wallet/test/wallet_crypto_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2020 The Bitcoin Core developers
+// Copyright (c) 2014-2022 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 38d23b6f91..c47e56c093 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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.h b/src/wallet/test/wallet_test_fixture.h
index e0b38a40e7..f1ef15a282 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 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_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 0f703b7d00..f056c54734 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2021 The Bitcoin Core developers
+// Copyright (c) 2012-2022 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,7 +43,7 @@ static_assert(WALLET_INCREMENTAL_RELAY_FEE >= DEFAULT_INCREMENTAL_RELAY_FEE, "wa
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
-static const std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
+static std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
{
DatabaseOptions options;
options.create_flags = WALLET_FLAG_DESCRIPTORS;
@@ -622,6 +622,46 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup)
BOOST_CHECK_EQUAL(list.begin()->second.size(), 2U);
}
+void TestCoinsResult(ListCoinsTest& context, OutputType out_type, CAmount amount,
+ std::map<OutputType, size_t>& expected_coins_sizes)
+{
+ LOCK(context.wallet->cs_wallet);
+ util::Result<CTxDestination> dest = Assert(context.wallet->GetNewDestination(out_type, ""));
+ CWalletTx& wtx = context.AddTx(CRecipient{{GetScriptForDestination(*dest)}, amount, /*fSubtractFeeFromAmount=*/true});
+ CoinFilterParams filter;
+ filter.skip_locked = false;
+ CoinsResult available_coins = AvailableCoins(*context.wallet, nullptr, std::nullopt, filter);
+ // Lock outputs so they are not spent in follow-up transactions
+ for (uint32_t i = 0; i < wtx.tx->vout.size(); i++) context.wallet->LockCoin({wtx.GetHash(), i});
+ for (const auto& [type, size] : expected_coins_sizes) BOOST_CHECK_EQUAL(size, available_coins.coins[type].size());
+}
+
+BOOST_FIXTURE_TEST_CASE(BasicOutputTypesTest, ListCoinsTest)
+{
+ std::map<OutputType, size_t> expected_coins_sizes;
+ for (const auto& out_type : OUTPUT_TYPES) { expected_coins_sizes[out_type] = 0U; }
+
+ // Verify our wallet has one usable coinbase UTXO before starting
+ // This UTXO is a P2PK, so it should show up in the Other bucket
+ expected_coins_sizes[OutputType::UNKNOWN] = 1U;
+ CoinsResult available_coins = WITH_LOCK(wallet->cs_wallet, return AvailableCoins(*wallet));
+ BOOST_CHECK_EQUAL(available_coins.Size(), expected_coins_sizes[OutputType::UNKNOWN]);
+ BOOST_CHECK_EQUAL(available_coins.coins[OutputType::UNKNOWN].size(), expected_coins_sizes[OutputType::UNKNOWN]);
+
+ // We will create a self transfer for each of the OutputTypes and
+ // verify it is put in the correct bucket after running GetAvailablecoins
+ //
+ // For each OutputType, We expect 2 UTXOs in our wallet following the self transfer:
+ // 1. One UTXO as the recipient
+ // 2. One UTXO from the change, due to payment address matching logic
+
+ for (const auto& out_type : OUTPUT_TYPES) {
+ if (out_type == OutputType::UNKNOWN) continue;
+ expected_coins_sizes[out_type] = 2U;
+ TestCoinsResult(*this, out_type, 1 * COIN, expected_coins_sizes);
+ }
+}
+
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
{
{
@@ -696,10 +736,10 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
std::vector<unsigned char> malformed_record;
CVectorWriter vw(0, 0, malformed_record, 0);
vw << std::string("notadescriptor");
- vw << (uint64_t)0;
- vw << (int32_t)0;
- vw << (int32_t)0;
- vw << (int32_t)1;
+ vw << uint64_t{0};
+ vw << int32_t{0};
+ vw << int32_t{0};
+ vw << int32_t{1};
SpanReader vr{0, 0, malformed_record};
WalletDescriptor w_desc;
@@ -867,24 +907,28 @@ BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
TestUnloadWallet(std::move(wallet));
}
+class FailCursor : public DatabaseCursor
+{
+public:
+ Status Next(DataStream& key, DataStream& value) override { return Status::FAIL; }
+};
+
/** RAII class that provides access to a FailDatabase. Which fails if needed. */
class FailBatch : public DatabaseBatch
{
private:
bool m_pass{true};
- bool ReadKey(CDataStream&& key, CDataStream& value) override { return m_pass; }
- bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return m_pass; }
- bool EraseKey(CDataStream&& key) override { return m_pass; }
- bool HasKey(CDataStream&& key) override { return m_pass; }
+ bool ReadKey(DataStream&& key, DataStream& value) override { return m_pass; }
+ bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override { return m_pass; }
+ bool EraseKey(DataStream&& key) override { return m_pass; }
+ bool HasKey(DataStream&& key) override { return m_pass; }
public:
explicit FailBatch(bool pass) : m_pass(pass) {}
void Flush() override {}
void Close() override {}
- bool StartCursor() override { return true; }
- bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return false; }
- void CloseCursor() override {}
+ std::unique_ptr<DatabaseCursor> GetNewCursor() override { return std::make_unique<FailCursor>(); }
bool TxnBegin() override { return false; }
bool TxnCommit() override { return false; }
bool TxnAbort() override { return false; }
@@ -946,7 +990,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
mtx.vin.clear();
mtx.vin.push_back(CTxIn(tx_id_to_spend, 0));
- wallet.transactionAddedToMempool(MakeTransactionRef(mtx), 0);
+ wallet.transactionAddedToMempool(MakeTransactionRef(mtx));
const uint256& good_tx_id = mtx.GetHash();
{
@@ -967,7 +1011,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
static_cast<FailDatabase&>(wallet.GetDatabase()).m_pass = false;
mtx.vin.clear();
mtx.vin.push_back(CTxIn(good_tx_id, 0));
- BOOST_CHECK_EXCEPTION(wallet.transactionAddedToMempool(MakeTransactionRef(mtx), 0),
+ BOOST_CHECK_EXCEPTION(wallet.transactionAddedToMempool(MakeTransactionRef(mtx)),
std::runtime_error,
HasReason("DB error adding transaction to wallet, write failed"));
}
diff --git a/src/wallet/test/walletdb_tests.cpp b/src/wallet/test/walletdb_tests.cpp
index e251a3a0e4..21842fe780 100644
--- a/src/wallet/test/walletdb_tests.cpp
+++ b/src/wallet/test/walletdb_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2020 The Bitcoin Core developers
+// Copyright (c) 2012-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.
diff --git a/src/wallet/test/walletload_tests.cpp b/src/wallet/test/walletload_tests.cpp
index 24d21c2f22..f1feb28e7d 100644
--- a/src/wallet/test/walletload_tests.cpp
+++ b/src/wallet/test/walletload_tests.cpp
@@ -54,13 +54,15 @@ BOOST_FIXTURE_TEST_CASE(wallet_load_unknown_descriptor, TestingSetup)
bool HasAnyRecordOfType(WalletDatabase& db, const std::string& key)
{
std::unique_ptr<DatabaseBatch> batch = db.MakeBatch(false);
- BOOST_CHECK(batch->StartCursor());
+ BOOST_CHECK(batch);
+ std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
+ BOOST_CHECK(cursor);
while (true) {
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- CDataStream ssValue(SER_DISK, CLIENT_VERSION);
- bool complete;
- BOOST_CHECK(batch->ReadAtCursor(ssKey, ssValue, complete));
- if (complete) break;
+ DataStream ssKey{};
+ DataStream ssValue{};
+ DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
+ assert(status != DatabaseCursor::Status::FAIL);
+ if (status == DatabaseCursor::Status::DONE) break;
std::string type;
ssKey >> type;
if (type == key) return true;
diff --git a/src/wallet/transaction.h b/src/wallet/transaction.h
index 27983e356d..290ef4eaa9 100644
--- a/src/wallet/transaction.h
+++ b/src/wallet/transaction.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 The Bitcoin Core developers
+// Copyright (c) 2021-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -293,6 +293,7 @@ public:
bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; }
bool isConflicted() const { return state<TxStateConflicted>(); }
+ bool isInactive() const { return state<TxStateInactive>(); }
bool isUnconfirmed() const { return !isAbandoned() && !isConflicted() && !isConfirmed(); }
bool isConfirmed() const { return state<TxStateConfirmed>(); }
const uint256& GetHash() const { return tx->GetHash(); }
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 2c0ce89929..5a92dbe428 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -241,7 +241,7 @@ std::shared_ptr<CWallet> LoadWalletInternal(WalletContext& context, const std::s
}
context.chain->initMessage(_("Loading wallet…").translated);
- const std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), options.create_flags, error, warnings);
+ std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), options.create_flags, error, warnings);
if (!wallet) {
error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
status = DatabaseStatus::FAILED_LOAD;
@@ -381,7 +381,7 @@ std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string&
// Make the wallet
context.chain->initMessage(_("Loading wallet…").translated);
- const std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), wallet_creation_flags, error, warnings);
+ std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), wallet_creation_flags, error, warnings);
if (!wallet) {
error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
status = DatabaseStatus::FAILED_CREATE;
@@ -472,8 +472,7 @@ std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& b
error += strprintf(Untranslated("Unexpected exception: %s"), e.what());
}
if (!wallet) {
- fs::remove(wallet_file);
- fs::remove(wallet_path);
+ fs::remove_all(wallet_path);
}
return wallet;
@@ -648,8 +647,7 @@ bool CWallet::HasWalletSpend(const CTransactionRef& tx) const
AssertLockHeld(cs_wallet);
const uint256& txid = tx->GetHash();
for (unsigned int i = 0; i < tx->vout.size(); ++i) {
- auto iter = mapTxSpends.find(COutPoint(txid, i));
- if (iter != mapTxSpends.end()) {
+ if (IsSpent(COutPoint(txid, i))) {
return true;
}
}
@@ -1067,6 +1065,33 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const TxState& state, const
}
}
+ // Mark inactive coinbase transactions and their descendants as abandoned
+ if (wtx.IsCoinBase() && wtx.isInactive()) {
+ std::vector<CWalletTx*> txs{&wtx};
+
+ TxStateInactive inactive_state = TxStateInactive{/*abandoned=*/true};
+
+ while (!txs.empty()) {
+ CWalletTx* desc_tx = txs.back();
+ txs.pop_back();
+ desc_tx->m_state = inactive_state;
+ // Break caches since we have changed the state
+ desc_tx->MarkDirty();
+ batch.WriteTx(*desc_tx);
+ MarkInputsDirty(desc_tx->tx);
+ for (unsigned int i = 0; i < desc_tx->tx->vout.size(); ++i) {
+ COutPoint outpoint(desc_tx->GetHash(), i);
+ std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(outpoint);
+ for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
+ const auto wit = mapWallet.find(it->second);
+ if (wit != mapWallet.end()) {
+ txs.push_back(&wit->second);
+ }
+ }
+ }
+ }
+ }
+
//// debug print
WalletLogPrintf("AddToWallet %s %s%s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
@@ -1276,7 +1301,11 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
wtx.MarkDirty();
batch.WriteTx(wtx);
NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
- // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
+ // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too.
+ // States are not permanent, so these transactions can become unabandoned if they are re-added to the
+ // mempool, or confirmed in a block, or conflicted.
+ // Note: If the reorged coinbase is re-added to the main chain, the descendants that have not had their
+ // states change will remain abandoned and will require manual broadcast if the user wants them.
for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
@@ -1355,7 +1384,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const SyncTxState& sta
MarkInputsDirty(ptx);
}
-void CWallet::transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) {
+void CWallet::transactionAddedToMempool(const CTransactionRef& tx) {
LOCK(cs_wallet);
SyncTransaction(tx, TxStateInMempool{});
@@ -1365,7 +1394,7 @@ void CWallet::transactionAddedToMempool(const CTransactionRef& tx, uint64_t memp
}
}
-void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {
+void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason) {
LOCK(cs_wallet);
auto it = mapWallet.find(tx->GetHash());
if (it != mapWallet.end()) {
@@ -1411,7 +1440,7 @@ void CWallet::blockConnected(const interfaces::BlockInfo& block)
m_last_block_processed = block.hash;
for (size_t index = 0; index < block.data->vtx.size(); index++) {
SyncTransaction(block.data->vtx[index], TxStateConfirmed{block.hash, block.height, static_cast<int>(index)});
- transactionRemovedFromMempool(block.data->vtx[index], MemPoolRemovalReason::BLOCK, /*mempool_sequence=*/0);
+ transactionRemovedFromMempool(block.data->vtx[index], MemPoolRemovalReason::BLOCK);
}
}
@@ -2884,7 +2913,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
const auto start{SteadyClock::now()};
// TODO: Can't use std::make_shared because we need a custom deleter but
// should be possible to use std::allocate_shared.
- const std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, args, std::move(database)), ReleaseWallet);
+ std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, args, std::move(database)), ReleaseWallet);
bool rescan_required = false;
DBErrors nLoadWalletRet = walletInstance->LoadWallet();
if (nLoadWalletRet != DBErrors::LOAD_OK) {
@@ -2997,7 +3026,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
if (args.IsArgSet("-mintxfee")) {
std::optional<CAmount> min_tx_fee = ParseMoney(args.GetArg("-mintxfee", ""));
- if (!min_tx_fee || min_tx_fee.value() == 0) {
+ if (!min_tx_fee) {
error = AmountErrMsg("mintxfee", args.GetArg("-mintxfee", ""));
return nullptr;
} else if (min_tx_fee.value() > HIGH_TX_FEE_PER_KB) {
@@ -3184,6 +3213,24 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
if (tip_height && *tip_height != rescan_height)
{
+ // No need to read and scan block if block was created before
+ // our wallet birthday (as adjusted for block time variability)
+ std::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) {
+ FoundBlock found = FoundBlock().height(rescan_height);
+ chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, found);
+ if (!found.found) {
+ // We were unable to find a block that had a time more recent than our earliest timestamp
+ // or a height higher than the wallet was synced to, indicating that the wallet is newer than the
+ // current chain tip. Skip rescanning in this case.
+ rescan_height = *tip_height;
+ }
+ }
+
// Technically we could execute the code below in any case, but performing the
// `while` loop below can make startup very slow, so only check blocks on disk
// if necessary.
@@ -3218,17 +3265,6 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
chain.initMessage(_("Rescanning…").translated);
walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
- // No need to read and scan block if block was created before
- // our wallet birthday (as adjusted for block time variability)
- std::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) {
- chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, FoundBlock().height(rescan_height));
- }
-
{
WalletRescanReserver reserver(*walletInstance);
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/true).status)) {
@@ -3770,26 +3806,27 @@ bool CWallet::MigrateToSQLite(bilingual_str& error)
// Get all of the records for DB type migration
std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch();
+ std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
std::vector<std::pair<SerializeData, SerializeData>> records;
- if (!batch->StartCursor()) {
+ if (!cursor) {
error = _("Error: Unable to begin reading all records in the database");
return false;
}
- bool complete = false;
+ DatabaseCursor::Status status = DatabaseCursor::Status::FAIL;
while (true) {
- CDataStream ss_key(SER_DISK, CLIENT_VERSION);
- CDataStream ss_value(SER_DISK, CLIENT_VERSION);
- bool ret = batch->ReadAtCursor(ss_key, ss_value, complete);
- if (!ret) {
+ DataStream ss_key{};
+ DataStream ss_value{};
+ status = cursor->Next(ss_key, ss_value);
+ if (status != DatabaseCursor::Status::MORE) {
break;
}
SerializeData key(ss_key.begin(), ss_key.end());
SerializeData value(ss_value.begin(), ss_value.end());
records.emplace_back(key, value);
}
- batch->CloseCursor();
+ cursor.reset();
batch.reset();
- if (!complete) {
+ if (status != DatabaseCursor::Status::DONE) {
error = _("Error: Unable to read all records in the database");
return false;
}
@@ -3815,8 +3852,8 @@ bool CWallet::MigrateToSQLite(bilingual_str& error)
bool began = batch->TxnBegin();
assert(began); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
for (const auto& [key, value] : records) {
- CDataStream ss_key(key, SER_DISK, CLIENT_VERSION);
- CDataStream ss_value(value, SER_DISK, CLIENT_VERSION);
+ DataStream ss_key{key};
+ DataStream ss_value{value};
if (!batch->Write(ss_key, ss_value)) {
batch->TxnAbort();
m_database->Close();
@@ -3834,10 +3871,7 @@ std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& err
AssertLockHeld(cs_wallet);
LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
- if (!legacy_spkm) {
- error = _("Error: This wallet is already a descriptor wallet");
- return std::nullopt;
- }
+ assert(legacy_spkm);
std::optional<MigrationData> res = legacy_spkm->MigrateToDescriptor();
if (res == std::nullopt) {
@@ -4002,6 +4036,23 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
}
}
}
+
+ // Persist added address book entries (labels, purpose) for watchonly and solvable wallets
+ auto persist_address_book = [](const CWallet& wallet) {
+ LOCK(wallet.cs_wallet);
+ WalletBatch batch{wallet.GetDatabase()};
+ for (const auto& [destination, addr_book_data] : wallet.m_address_book) {
+ auto address{EncodeDestination(destination)};
+ auto purpose{addr_book_data.purpose};
+ auto label{addr_book_data.GetLabel()};
+ // don't bother writing default values (unknown purpose, empty label)
+ if (purpose != "unknown") batch.WritePurpose(address, purpose);
+ if (!label.empty()) batch.WriteName(address, label);
+ }
+ };
+ if (data.watchonly_wallet) persist_address_book(*data.watchonly_wallet);
+ if (data.solvable_wallet) persist_address_book(*data.solvable_wallet);
+
// Remove the things to delete
if (dests_to_delete.size() > 0) {
for (const auto& dest : dests_to_delete) {
@@ -4116,6 +4167,11 @@ bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error,
util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>&& wallet, WalletContext& context)
{
+ // Before anything else, check if there is something to migrate.
+ if (!wallet->GetLegacyScriptPubKeyMan()) {
+ return util::Error{_("Error: This wallet is already a descriptor wallet")};
+ }
+
MigrationResult res;
bilingual_str error;
std::vector<bilingual_str> warnings;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 137320acda..f104a15f98 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -516,7 +516,7 @@ public:
*/
CWalletTx* AddToWallet(CTransactionRef tx, const TxState& state, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block = false);
bool LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override;
+ void transactionAddedToMempool(const CTransactionRef& tx) override;
void blockConnected(const interfaces::BlockInfo& block) override;
void blockDisconnected(const interfaces::BlockInfo& block) override;
void updatedBlockTip() override;
@@ -538,7 +538,7 @@ public:
uint256 last_failed_block;
};
ScanResult ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate, const bool save_progress);
- void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override;
+ void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason) override;
/** Set the next time this wallet should resend transactions to 12-36 hours from now, ~1 day on average. */
void SetNextResend() { m_next_resend = GetDefaultNextResend(); }
/** Return true if all conditions for periodically resending transactions are met. */
@@ -821,7 +821,8 @@ public:
bool IsLegacy() const;
/** Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet has no name */
- const std::string GetDisplayName() const override {
+ std::string GetDisplayName() const override
+ {
std::string wallet_name = GetName().length() == 0 ? "default wallet" : GetName();
return strprintf("[%s]", wallet_name);
};
@@ -954,10 +955,10 @@ private:
using Clock = std::chrono::steady_clock;
using NowFn = std::function<Clock::time_point()>;
CWallet& m_wallet;
- bool m_could_reserve;
+ bool m_could_reserve{false};
NowFn m_now;
public:
- explicit WalletRescanReserver(CWallet& w) : m_wallet(w), m_could_reserve(false) {}
+ explicit WalletRescanReserver(CWallet& w) : m_wallet(w) {}
bool reserve()
{
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 826cecfb6f..2cd35ae40e 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -321,7 +321,7 @@ public:
};
static bool
-ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
+ReadKeyValue(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue,
CWalletScanState &wss, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
try {
@@ -759,7 +759,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
return true;
}
-bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn)
+bool ReadKeyValue(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn)
{
CWalletScanState dummy_wss;
LOCK(pwallet->cs_wallet);
@@ -812,7 +812,8 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
#endif
// Get cursor
- if (!m_batch->StartCursor())
+ std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
+ if (!cursor)
{
pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
return DBErrors::CORRUPT;
@@ -821,16 +822,13 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
while (true)
{
// Read next record
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ DataStream ssKey{};
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
- bool complete;
- bool ret = m_batch->ReadAtCursor(ssKey, ssValue, complete);
- if (complete) {
+ DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
+ if (status == DatabaseCursor::Status::DONE) {
break;
- }
- else if (!ret)
- {
- m_batch->CloseCursor();
+ } else if (status == DatabaseCursor::Status::FAIL) {
+ cursor.reset();
pwallet->WalletLogPrintf("Error reading next record from wallet database\n");
return DBErrors::CORRUPT;
}
@@ -878,7 +876,6 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
} catch (...) {
result = DBErrors::CORRUPT;
}
- m_batch->CloseCursor();
// Set the active ScriptPubKeyMans
for (auto spk_man_pair : wss.m_active_external_spks) {
@@ -974,7 +971,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
return result;
}
-DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWalletTx>& vWtx)
+DBErrors WalletBatch::FindWalletTxHashes(std::vector<uint256>& tx_hashes)
{
DBErrors result = DBErrors::LOAD_OK;
@@ -986,7 +983,8 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
}
// Get cursor
- if (!m_batch->StartCursor())
+ std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
+ if (!cursor)
{
LogPrintf("Error getting wallet database cursor\n");
return DBErrors::CORRUPT;
@@ -995,14 +993,12 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
while (true)
{
// Read next record
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- CDataStream ssValue(SER_DISK, CLIENT_VERSION);
- bool complete;
- bool ret = m_batch->ReadAtCursor(ssKey, ssValue, complete);
- if (complete) {
+ DataStream ssKey{};
+ DataStream ssValue{};
+ DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
+ if (status == DatabaseCursor::Status::DONE) {
break;
- } else if (!ret) {
- m_batch->CloseCursor();
+ } else if (status == DatabaseCursor::Status::FAIL) {
LogPrintf("Error reading next record from wallet database\n");
return DBErrors::CORRUPT;
}
@@ -1012,25 +1008,21 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
if (strType == DBKeys::TX) {
uint256 hash;
ssKey >> hash;
- vTxHash.push_back(hash);
- vWtx.emplace_back(/*tx=*/nullptr, TxStateInactive{});
- ssValue >> vWtx.back();
+ tx_hashes.push_back(hash);
}
}
} catch (...) {
result = DBErrors::CORRUPT;
}
- m_batch->CloseCursor();
return result;
}
DBErrors WalletBatch::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<uint256>& vTxHashOut)
{
- // build list of wallet TXs and hashes
+ // build list of wallet TX hashes
std::vector<uint256> vTxHash;
- std::list<CWalletTx> vWtx;
- DBErrors err = FindWalletTx(vTxHash, vWtx);
+ DBErrors err = FindWalletTxHashes(vTxHash);
if (err != DBErrors::LOAD_OK) {
return err;
}
@@ -1114,7 +1106,8 @@ bool WalletBatch::WriteWalletFlags(const uint64_t flags)
bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
{
// Get cursor
- if (!m_batch->StartCursor())
+ std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
+ if (!cursor)
{
return false;
}
@@ -1123,16 +1116,12 @@ bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
while (true)
{
// Read next record
- CDataStream key(SER_DISK, CLIENT_VERSION);
- CDataStream value(SER_DISK, CLIENT_VERSION);
- bool complete;
- bool ret = m_batch->ReadAtCursor(key, value, complete);
- if (complete) {
+ DataStream key{};
+ DataStream value{};
+ DatabaseCursor::Status status = cursor->Next(key, value);
+ if (status == DatabaseCursor::Status::DONE) {
break;
- }
- else if (!ret)
- {
- m_batch->CloseCursor();
+ } else if (status == DatabaseCursor::Status::FAIL) {
return false;
}
@@ -1146,7 +1135,6 @@ bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
m_batch->Erase(key_data);
}
}
- m_batch->CloseCursor();
return true;
}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 27b5dbdd96..c97356a71f 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2021 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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,7 +273,7 @@ public:
bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal);
DBErrors LoadWallet(CWallet* pwallet);
- DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWalletTx>& vWtx);
+ DBErrors FindWalletTxHashes(std::vector<uint256>& tx_hashes);
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
/* Function to determine if a certain KV/key-type is a key (cryptographical key) type */
static bool IsKeyType(const std::string& strType);
@@ -303,7 +303,7 @@ void MaybeCompactWalletDB(WalletContext& context);
using KeyFilterFn = std::function<bool(const std::string&)>;
//! Unserialize a given Key-Value pair and load it into the wallet
-bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr);
+bool ReadKeyValue(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr);
/** Return object for accessing dummy database with no read/write capabilities. */
std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase();
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
index 9ed2a7c18b..96537b9873 100644
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2021 The Bitcoin Core developers
+// Copyright (c) 2016-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -47,7 +47,7 @@ static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flag
wallet_instance->TopUpKeyPool();
}
-static const std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, const ArgsManager& args, DatabaseOptions options)
+static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, const ArgsManager& args, DatabaseOptions options)
{
DatabaseStatus status;
bilingual_str error;
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index df1b10a634..299c74d01c 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021 The Bitcoin Core developers
+// Copyright (c) 2017-2022 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/walletinitinterface.h b/src/walletinitinterface.h
index 7624c2b16d..ce8b6cfd6e 100644
--- a/src/walletinitinterface.h
+++ b/src/walletinitinterface.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.
diff --git a/src/warnings.cpp b/src/warnings.cpp
index dabb194ce1..d0de706953 100644
--- a/src/warnings.cpp
+++ b/src/warnings.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Copyright (c) 2009-2022 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 97c2599366..cf0ee48f47 100644
--- a/src/zmq/zmqabstractnotifier.h
+++ b/src/zmq/zmqabstractnotifier.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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,7 @@ class CZMQAbstractNotifier
public:
static const int DEFAULT_ZMQ_SNDHWM {1000};
- CZMQAbstractNotifier() : psocket(nullptr), outbound_message_high_water_mark(DEFAULT_ZMQ_SNDHWM) { }
+ CZMQAbstractNotifier() : outbound_message_high_water_mark(DEFAULT_ZMQ_SNDHWM) {}
virtual ~CZMQAbstractNotifier();
template <typename T>
@@ -57,7 +57,7 @@ public:
virtual bool NotifyTransaction(const CTransaction &transaction);
protected:
- void *psocket;
+ void* psocket{nullptr};
std::string type;
std::string address;
int outbound_message_high_water_mark; // aka SNDHWM
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 6ee134f392..df129c0830 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -21,7 +21,7 @@
#include <utility>
#include <vector>
-CZMQNotificationInterface::CZMQNotificationInterface() : pcontext(nullptr)
+CZMQNotificationInterface::CZMQNotificationInterface()
{
}
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index 585e900ca6..a43f9bfef3 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -39,7 +39,7 @@ protected:
private:
CZMQNotificationInterface();
- void *pcontext;
+ void* pcontext{nullptr};
std::list<std::unique_ptr<CZMQAbstractNotifier>> notifiers;
};
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index c785a929d3..6418455d19 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2021 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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,6 +7,7 @@
#include <chain.h>
#include <chainparams.h>
#include <crypto/common.h>
+#include <kernel/cs_main.h>
#include <logging.h>
#include <netaddress.h>
#include <netbase.h>
diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h
index fcedd1aabe..18336a5eb0 100644
--- a/src/zmq/zmqpublishnotifier.h
+++ b/src/zmq/zmqpublishnotifier.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2020 The Bitcoin Core developers
+// Copyright (c) 2015-2022 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/zmqrpc.cpp b/src/zmq/zmqrpc.cpp
index 047e6bf9b7..fcc2608262 100644
--- a/src/zmq/zmqrpc.cpp
+++ b/src/zmq/zmqrpc.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018-2021 The Bitcoin Core developers
+// Copyright (c) 2018-2022 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/zmqutil.cpp b/src/zmq/zmqutil.cpp
index cf3a0b2d71..3c6d1b9ab5 100644
--- a/src/zmq/zmqutil.cpp
+++ b/src/zmq/zmqutil.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2021 The Bitcoin Core developers
+// Copyright (c) 2014-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.