aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am165
-rw-r--r--src/Makefile.bench.include19
-rw-r--r--src/Makefile.leveldb.include2
-rw-r--r--src/Makefile.qt.include50
-rw-r--r--src/Makefile.qttest.include21
-rw-r--r--src/Makefile.test.include259
-rw-r--r--src/addrdb.cpp11
-rw-r--r--src/addrdb.h11
-rw-r--r--src/addrman.cpp51
-rw-r--r--src/addrman.h95
-rw-r--r--src/amount.h3
-rw-r--r--src/arith_uint256.cpp6
-rw-r--r--src/arith_uint256.h5
-rw-r--r--src/attributes.h22
-rw-r--r--src/banman.cpp220
-rw-r--r--src/banman.h70
-rw-r--r--src/base58.cpp9
-rw-r--r--src/base58.h12
-rw-r--r--src/bech32.cpp4
-rw-r--r--src/bench/base58.cpp4
-rw-r--r--src/bench/bech32.cpp2
-rw-r--r--src/bench/bench.cpp20
-rw-r--r--src/bench/bench.h2
-rw-r--r--src/bench/bench_bitcoin.cpp37
-rw-r--r--src/bench/block_assemble.cpp73
-rw-r--r--src/bench/ccoins_caching.cpp31
-rw-r--r--src/bench/chacha20.cpp46
-rw-r--r--src/bench/checkblock.cpp15
-rw-r--r--src/bench/checkqueue.cpp4
-rw-r--r--src/bench/coin_selection.cpp40
-rw-r--r--src/bench/crypto_hash.cpp11
-rw-r--r--src/bench/duplicate_inputs.cpp70
-rw-r--r--src/bench/examples.cpp4
-rw-r--r--src/bench/gcs_filter.cpp43
-rw-r--r--src/bench/lockedpool.cpp2
-rw-r--r--src/bench/mempool_eviction.cpp10
-rw-r--r--src/bench/merkle_root.cpp2
-rw-r--r--src/bench/poly1305.cpp41
-rw-r--r--src/bench/prevector.cpp12
-rw-r--r--src/bench/rollingbloom.cpp5
-rw-r--r--src/bench/rpc_mempool.cpp43
-rw-r--r--src/bench/verify_script.cpp4
-rw-r--r--src/bench/wallet_balance.cpp53
-rw-r--r--src/bitcoin-cli.cpp58
-rw-r--r--src/bitcoin-tx.cpp56
-rw-r--r--src/bitcoin-wallet-res.rc35
-rw-r--r--src/bitcoin-wallet.cpp117
-rw-r--r--src/bitcoind.cpp29
-rw-r--r--src/blockencodings.cpp11
-rw-r--r--src/blockencodings.h11
-rw-r--r--src/blockfilter.cpp338
-rw-r--r--src/blockfilter.h170
-rw-r--r--src/bloom.cpp19
-rw-r--r--src/bloom.h6
-rw-r--r--src/chain.cpp9
-rw-r--r--src/chain.h76
-rw-r--r--src/chainparams.cpp109
-rw-r--r--src/chainparams.h16
-rw-r--r--src/chainparamsbase.cpp7
-rw-r--r--src/chainparamsbase.h2
-rw-r--r--src/chainparamsseeds.h2193
-rw-r--r--src/checkpoints.cpp32
-rw-r--r--src/checkpoints.h27
-rw-r--r--src/checkqueue.h2
-rw-r--r--src/clientversion.cpp2
-rw-r--r--src/clientversion.h2
-rw-r--r--src/coins.cpp5
-rw-r--r--src/coins.h24
-rw-r--r--src/compat.h25
-rw-r--r--src/compat/assumptions.h65
-rw-r--r--src/compat/byteswap.h2
-rw-r--r--src/compat/endian.h2
-rw-r--r--src/compat/glibc_compat.cpp4
-rw-r--r--src/compat/glibc_sanity.cpp2
-rw-r--r--src/compat/glibcxx_sanity.cpp2
-rw-r--r--src/compat/strnlen.cpp2
-rw-r--r--src/compressor.cpp2
-rw-r--r--src/compressor.h2
-rw-r--r--src/consensus/consensus.h2
-rw-r--r--src/consensus/merkle.cpp4
-rw-r--r--src/consensus/merkle.h2
-rw-r--r--src/consensus/params.h2
-rw-r--r--src/consensus/tx_check.cpp57
-rw-r--r--src/consensus/tx_check.h20
-rw-r--r--src/consensus/tx_verify.cpp64
-rw-r--r--src/consensus/tx_verify.h5
-rw-r--r--src/consensus/validation.h114
-rw-r--r--src/core_io.h22
-rw-r--r--src/core_memusage.h2
-rw-r--r--src/core_read.cpp44
-rw-r--r--src/core_write.cpp13
-rw-r--r--src/crypto/aes.cpp64
-rw-r--r--src/crypto/aes.h53
-rw-r--r--src/crypto/chacha20.cpp132
-rw-r--r--src/crypto/chacha20.h18
-rw-r--r--src/crypto/common.h2
-rw-r--r--src/crypto/hkdf_sha256_32.cpp21
-rw-r--r--src/crypto/hkdf_sha256_32.h25
-rw-r--r--src/crypto/hmac_sha256.cpp2
-rw-r--r--src/crypto/hmac_sha256.h2
-rw-r--r--src/crypto/hmac_sha512.cpp2
-rw-r--r--src/crypto/hmac_sha512.h2
-rw-r--r--src/crypto/poly1305.cpp141
-rw-r--r--src/crypto/poly1305.h17
-rw-r--r--src/crypto/ripemd160.cpp4
-rw-r--r--src/crypto/sha1.cpp4
-rw-r--r--src/crypto/sha256.cpp2
-rw-r--r--src/crypto/sha256.h2
-rw-r--r--src/crypto/sha512.cpp4
-rw-r--r--src/crypto/sha512.h2
-rw-r--r--src/crypto/siphash.cpp173
-rw-r--r--src/crypto/siphash.h47
-rw-r--r--src/cuckoocache.h6
-rw-r--r--src/dbwrapper.cpp6
-rw-r--r--src/dbwrapper.h6
-rw-r--r--src/dummywallet.cpp86
-rw-r--r--src/flatfile.cpp98
-rw-r--r--src/flatfile.h96
-rw-r--r--src/fs.cpp212
-rw-r--r--src/fs.h78
-rw-r--r--src/hash.cpp170
-rw-r--r--src/hash.h47
-rw-r--r--src/httprpc.cpp29
-rw-r--r--src/httprpc.h4
-rw-r--r--src/httpserver.cpp121
-rw-r--r--src/httpserver.h16
-rw-r--r--src/index/base.cpp85
-rw-r--r--src/index/base.h21
-rw-r--r--src/index/blockfilterindex.cpp467
-rw-r--r--src/index/blockfilterindex.h94
-rw-r--r--src/index/txindex.cpp17
-rw-r--r--src/init.cpp549
-rw-r--r--src/init.h20
-rw-r--r--src/interfaces/README.md4
-rw-r--r--src/interfaces/chain.cpp385
-rw-r--r--src/interfaces/chain.h313
-rw-r--r--src/interfaces/handler.cpp4
-rw-r--r--src/interfaces/node.cpp104
-rw-r--r--src/interfaces/node.h26
-rw-r--r--src/interfaces/wallet.cpp355
-rw-r--r--src/interfaces/wallet.h26
-rw-r--r--src/key.cpp38
-rw-r--r--src/key.h13
-rw-r--r--src/key_io.cpp18
-rw-r--r--src/key_io.h2
-rw-r--r--src/keystore.cpp13
-rw-r--r--src/keystore.h2
-rw-r--r--src/leveldb/db/c.cc2
-rw-r--r--src/leveldb/port/port_win.h7
-rw-r--r--src/leveldb/util/env_posix.cc4
-rw-r--r--src/leveldb/util/env_win.cc25
-rw-r--r--src/limitedmap.h2
-rw-r--r--src/logging.cpp48
-rw-r--r--src/logging.h61
-rw-r--r--src/memusage.h2
-rw-r--r--src/merkleblock.cpp8
-rw-r--r--src/merkleblock.h2
-rw-r--r--src/miner.cpp42
-rw-r--r--src/miner.h11
-rw-r--r--src/net.cpp1039
-rw-r--r--src/net.h276
-rw-r--r--src/net_processing.cpp894
-rw-r--r--src/net_processing.h17
-rw-r--r--src/netaddress.cpp152
-rw-r--r--src/netaddress.h13
-rw-r--r--src/netbase.cpp73
-rw-r--r--src/netbase.h2
-rw-r--r--src/netmessagemaker.h2
-rw-r--r--src/node/README.md22
-rw-r--r--src/node/coin.cpp22
-rw-r--r--src/node/coin.h22
-rw-r--r--src/node/psbt.cpp134
-rw-r--r--src/node/psbt.h43
-rw-r--r--src/node/transaction.cpp78
-rw-r--r--src/node/transaction.h24
-rw-r--r--src/noui.cpp19
-rw-r--r--src/noui.h14
-rw-r--r--src/optional.h26
-rw-r--r--src/outputtype.cpp20
-rw-r--r--src/outputtype.h5
-rw-r--r--src/policy/feerate.cpp2
-rw-r--r--src/policy/feerate.h2
-rw-r--r--src/policy/fees.cpp57
-rw-r--r--src/policy/fees.h142
-rw-r--r--src/policy/policy.cpp55
-rw-r--r--src/policy/policy.h26
-rw-r--r--src/policy/rbf.cpp15
-rw-r--r--src/policy/rbf.h10
-rw-r--r--src/policy/settings.cpp14
-rw-r--r--src/policy/settings.h35
-rw-r--r--src/pow.cpp2
-rw-r--r--src/pow.h2
-rw-r--r--src/prevector.h40
-rw-r--r--src/primitives/block.cpp4
-rw-r--r--src/primitives/block.h2
-rw-r--r--src/primitives/transaction.cpp6
-rw-r--r--src/primitives/transaction.h20
-rw-r--r--src/protocol.cpp6
-rw-r--r--src/protocol.h3
-rw-r--r--src/psbt.cpp370
-rw-r--r--src/psbt.h599
-rw-r--r--src/pubkey.cpp2
-rw-r--r--src/pubkey.h2
-rw-r--r--src/qt/README.md4
-rw-r--r--src/qt/addressbookpage.cpp28
-rw-r--r--src/qt/addressbookpage.h4
-rw-r--r--src/qt/addresstablemodel.cpp10
-rw-r--r--src/qt/addresstablemodel.h4
-rw-r--r--src/qt/askpassphrasedialog.cpp34
-rw-r--r--src/qt/askpassphrasedialog.h2
-rw-r--r--src/qt/bantablemodel.cpp15
-rw-r--r--src/qt/bantablemodel.h4
-rw-r--r--src/qt/bitcoin.cpp331
-rw-r--r--src/qt/bitcoin.h124
-rw-r--r--src/qt/bitcoinaddressvalidator.cpp2
-rw-r--r--src/qt/bitcoinamountfield.cpp83
-rw-r--r--src/qt/bitcoinamountfield.h15
-rw-r--r--src/qt/bitcoingui.cpp514
-rw-r--r--src/qt/bitcoingui.h80
-rw-r--r--src/qt/bitcoinstrings.cpp19
-rw-r--r--src/qt/bitcoinunits.cpp2
-rw-r--r--src/qt/bitcoinunits.h2
-rw-r--r--src/qt/callback.h30
-rw-r--r--src/qt/clientmodel.cpp36
-rw-r--r--src/qt/clientmodel.h5
-rw-r--r--src/qt/coincontroldialog.cpp73
-rw-r--r--src/qt/coincontroldialog.h13
-rw-r--r--src/qt/coincontroltreewidget.cpp2
-rw-r--r--src/qt/coincontroltreewidget.h2
-rw-r--r--src/qt/csvmodelwriter.cpp4
-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/forms/coincontroldialog.ui2
-rw-r--r--src/qt/forms/debugwindow.ui1218
-rw-r--r--src/qt/forms/optionsdialog.ui4
-rw-r--r--src/qt/forms/receivecoinsdialog.ui10
-rw-r--r--src/qt/forms/receiverequestdialog.ui2
-rw-r--r--src/qt/forms/sendcoinsdialog.ui41
-rw-r--r--src/qt/guiconstants.h12
-rw-r--r--src/qt/guiutil.cpp161
-rw-r--r--src/qt/guiutil.h29
-rw-r--r--src/qt/intro.cpp59
-rw-r--r--src/qt/intro.h13
-rw-r--r--src/qt/locale/bitcoin_af.ts336
-rw-r--r--src/qt/locale/bitcoin_af_ZA.ts386
-rw-r--r--src/qt/locale/bitcoin_am.ts451
-rw-r--r--src/qt/locale/bitcoin_ar.ts1211
-rw-r--r--src/qt/locale/bitcoin_be_BY.ts86
-rw-r--r--src/qt/locale/bitcoin_bg.ts178
-rw-r--r--src/qt/locale/bitcoin_bg_BG.ts8
-rw-r--r--src/qt/locale/bitcoin_ca.ts754
-rw-r--r--src/qt/locale/bitcoin_ca@valencia.ts356
-rw-r--r--src/qt/locale/bitcoin_ca_ES.ts386
-rw-r--r--src/qt/locale/bitcoin_cs.ts840
-rw-r--r--src/qt/locale/bitcoin_cy.ts12
-rw-r--r--src/qt/locale/bitcoin_da.ts747
-rw-r--r--src/qt/locale/bitcoin_de.ts785
-rw-r--r--src/qt/locale/bitcoin_el.ts8
-rw-r--r--src/qt/locale/bitcoin_el_GR.ts585
-rw-r--r--src/qt/locale/bitcoin_en.ts548
-rw-r--r--src/qt/locale/bitcoin_en_GB.ts764
-rw-r--r--src/qt/locale/bitcoin_eo.ts134
-rw-r--r--src/qt/locale/bitcoin_es.ts864
-rw-r--r--src/qt/locale/bitcoin_es_CL.ts2455
-rw-r--r--src/qt/locale/bitcoin_es_CO.ts72
-rw-r--r--src/qt/locale/bitcoin_es_DO.ts249
-rw-r--r--src/qt/locale/bitcoin_es_ES.ts527
-rw-r--r--src/qt/locale/bitcoin_es_MX.ts46
-rw-r--r--src/qt/locale/bitcoin_es_UY.ts12
-rw-r--r--src/qt/locale/bitcoin_es_VE.ts182
-rw-r--r--src/qt/locale/bitcoin_et.ts134
-rw-r--r--src/qt/locale/bitcoin_et_EE.ts18
-rw-r--r--src/qt/locale/bitcoin_eu_ES.ts52
-rw-r--r--src/qt/locale/bitcoin_fa.ts356
-rw-r--r--src/qt/locale/bitcoin_fa_IR.ts1358
-rw-r--r--src/qt/locale/bitcoin_fi.ts688
-rw-r--r--src/qt/locale/bitcoin_fr.ts784
-rw-r--r--src/qt/locale/bitcoin_fr_FR.ts208
-rw-r--r--src/qt/locale/bitcoin_gl.ts102
-rw-r--r--src/qt/locale/bitcoin_he.ts592
-rw-r--r--src/qt/locale/bitcoin_hi_IN.ts146
-rw-r--r--src/qt/locale/bitcoin_hr.ts2173
-rw-r--r--src/qt/locale/bitcoin_hu.ts322
-rw-r--r--src/qt/locale/bitcoin_id.ts969
-rw-r--r--src/qt/locale/bitcoin_id_ID.ts450
-rw-r--r--src/qt/locale/bitcoin_is.ts997
-rw-r--r--src/qt/locale/bitcoin_it.ts754
-rw-r--r--src/qt/locale/bitcoin_it_IT.ts94
-rw-r--r--src/qt/locale/bitcoin_ja.ts856
-rw-r--r--src/qt/locale/bitcoin_ka.ts164
-rw-r--r--src/qt/locale/bitcoin_kk_KZ.ts4
-rw-r--r--src/qt/locale/bitcoin_ko.ts471
-rw-r--r--src/qt/locale/bitcoin_ko_KR.ts746
-rw-r--r--src/qt/locale/bitcoin_ku_IQ.ts4
-rw-r--r--src/qt/locale/bitcoin_ky.ts8
-rw-r--r--src/qt/locale/bitcoin_la.ts86
-rw-r--r--src/qt/locale/bitcoin_lt.ts436
-rw-r--r--src/qt/locale/bitcoin_lv_LV.ts98
-rw-r--r--src/qt/locale/bitcoin_mk_MK.ts8
-rw-r--r--src/qt/locale/bitcoin_ml.ts336
-rw-r--r--src/qt/locale/bitcoin_mn.ts20
-rw-r--r--src/qt/locale/bitcoin_ms_MY.ts43
-rw-r--r--src/qt/locale/bitcoin_nb.ts646
-rw-r--r--src/qt/locale/bitcoin_ne.ts88
-rw-r--r--src/qt/locale/bitcoin_nl.ts868
-rw-r--r--src/qt/locale/bitcoin_pam.ts74
-rw-r--r--src/qt/locale/bitcoin_pl.ts782
-rw-r--r--src/qt/locale/bitcoin_pt_BR.ts1072
-rw-r--r--src/qt/locale/bitcoin_pt_PT.ts797
-rw-r--r--src/qt/locale/bitcoin_ro.ts196
-rw-r--r--src/qt/locale/bitcoin_ro_RO.ts794
-rw-r--r--src/qt/locale/bitcoin_ru.ts3760
-rw-r--r--src/qt/locale/bitcoin_ru_RU.ts1534
-rw-r--r--src/qt/locale/bitcoin_sk.ts780
-rw-r--r--src/qt/locale/bitcoin_sl_SI.ts368
-rw-r--r--src/qt/locale/bitcoin_sn.ts367
-rw-r--r--src/qt/locale/bitcoin_sq.ts52
-rw-r--r--src/qt/locale/bitcoin_sr.ts875
-rw-r--r--src/qt/locale/bitcoin_sr@latin.ts8
-rw-r--r--src/qt/locale/bitcoin_sv.ts1012
-rw-r--r--src/qt/locale/bitcoin_szl.ts2123
-rw-r--r--src/qt/locale/bitcoin_ta.ts12
-rw-r--r--src/qt/locale/bitcoin_th_TH.ts44
-rw-r--r--src/qt/locale/bitcoin_tr.ts658
-rw-r--r--src/qt/locale/bitcoin_tr_TR.ts1023
-rw-r--r--src/qt/locale/bitcoin_uk.ts1060
-rw-r--r--src/qt/locale/bitcoin_ur_PK.ts60
-rw-r--r--src/qt/locale/bitcoin_uz@Cyrl.ts50
-rw-r--r--src/qt/locale/bitcoin_vi.ts604
-rw-r--r--src/qt/locale/bitcoin_vi_VN.ts56
-rw-r--r--src/qt/locale/bitcoin_zh.ts28
-rw-r--r--src/qt/locale/bitcoin_zh_CN.ts907
-rw-r--r--src/qt/locale/bitcoin_zh_HK.ts4
-rw-r--r--src/qt/locale/bitcoin_zh_TW.ts943
-rw-r--r--src/qt/macdockiconhandler.h21
-rw-r--r--src/qt/macdockiconhandler.mm100
-rw-r--r--src/qt/macnotificationhandler.h4
-rw-r--r--src/qt/macnotificationhandler.mm23
-rw-r--r--src/qt/macos_appnap.h24
-rw-r--r--src/qt/macos_appnap.mm71
-rw-r--r--src/qt/main.cpp17
-rw-r--r--src/qt/modaloverlay.cpp12
-rw-r--r--src/qt/modaloverlay.h3
-rw-r--r--src/qt/networkstyle.cpp6
-rw-r--r--src/qt/notificator.cpp22
-rw-r--r--src/qt/notificator.h8
-rw-r--r--src/qt/openuridialog.cpp2
-rw-r--r--src/qt/optionsdialog.cpp95
-rw-r--r--src/qt/optionsdialog.h8
-rw-r--r--src/qt/optionsmodel.cpp16
-rw-r--r--src/qt/optionsmodel.h4
-rw-r--r--src/qt/overviewpage.cpp50
-rw-r--r--src/qt/overviewpage.h4
-rw-r--r--src/qt/paymentrequestplus.cpp5
-rw-r--r--src/qt/paymentrequestplus.h2
-rw-r--r--src/qt/paymentserver.cpp328
-rw-r--r--src/qt/paymentserver.h46
-rw-r--r--src/qt/peertablemodel.cpp19
-rw-r--r--src/qt/peertablemodel.h4
-rw-r--r--src/qt/platformstyle.cpp4
-rw-r--r--src/qt/qrimagewidget.cpp141
-rw-r--r--src/qt/qrimagewidget.h45
-rw-r--r--src/qt/qvalidatedlineedit.cpp6
-rw-r--r--src/qt/qvalidatedlineedit.h2
-rw-r--r--src/qt/qvaluecombobox.cpp4
-rw-r--r--src/qt/qvaluecombobox.h2
-rw-r--r--src/qt/receivecoinsdialog.cpp39
-rw-r--r--src/qt/receivecoinsdialog.h4
-rw-r--r--src/qt/receiverequestdialog.cpp128
-rw-r--r--src/qt/receiverequestdialog.h34
-rw-r--r--src/qt/recentrequeststablemodel.cpp6
-rw-r--r--src/qt/recentrequeststablemodel.h4
-rwxr-xr-xsrc/qt/res/movies/makespinner.sh2
-rw-r--r--src/qt/rpcconsole.cpp176
-rw-r--r--src/qt/rpcconsole.h21
-rw-r--r--src/qt/sendcoinsdialog.cpp119
-rw-r--r--src/qt/sendcoinsdialog.h8
-rw-r--r--src/qt/sendcoinsentry.cpp30
-rw-r--r--src/qt/sendcoinsentry.h4
-rw-r--r--src/qt/signverifymessagedialog.cpp16
-rw-r--r--src/qt/splashscreen.cpp23
-rw-r--r--src/qt/splashscreen.h9
-rw-r--r--src/qt/test/addressbooktests.cpp22
-rw-r--r--src/qt/test/apptests.cpp115
-rw-r--r--src/qt/test/apptests.h50
-rw-r--r--src/qt/test/compattests.cpp8
-rw-r--r--src/qt/test/paymentrequestdata.h2
-rw-r--r--src/qt/test/paymentservertests.cpp20
-rw-r--r--src/qt/test/paymentservertests.h2
-rw-r--r--src/qt/test/rpcnestedtests.cpp10
-rw-r--r--src/qt/test/rpcnestedtests.h2
-rw-r--r--src/qt/test/test_main.cpp22
-rw-r--r--src/qt/test/uritests.cpp2
-rw-r--r--src/qt/test/util.cpp11
-rw-r--r--src/qt/test/util.h4
-rw-r--r--src/qt/test/wallettests.cpp38
-rw-r--r--src/qt/trafficgraphwidget.cpp12
-rw-r--r--src/qt/trafficgraphwidget.h2
-rw-r--r--src/qt/transactiondesc.cpp21
-rw-r--r--src/qt/transactiondesc.h4
-rw-r--r--src/qt/transactiondescdialog.cpp2
-rw-r--r--src/qt/transactiondescdialog.h2
-rw-r--r--src/qt/transactionfilterproxy.cpp2
-rw-r--r--src/qt/transactionfilterproxy.h4
-rw-r--r--src/qt/transactionrecord.cpp17
-rw-r--r--src/qt/transactionrecord.h4
-rw-r--r--src/qt/transactiontablemodel.cpp23
-rw-r--r--src/qt/transactiontablemodel.h4
-rw-r--r--src/qt/transactionview.cpp82
-rw-r--r--src/qt/transactionview.h6
-rw-r--r--src/qt/utilitydialog.cpp18
-rw-r--r--src/qt/utilitydialog.h4
-rw-r--r--src/qt/walletcontroller.cpp169
-rw-r--r--src/qt/walletcontroller.h90
-rw-r--r--src/qt/walletframe.cpp59
-rw-r--r--src/qt/walletframe.h15
-rw-r--r--src/qt/walletmodel.cpp76
-rw-r--r--src/qt/walletmodel.h30
-rw-r--r--src/qt/walletmodeltransaction.cpp10
-rw-r--r--src/qt/walletmodeltransaction.h3
-rw-r--r--src/qt/walletview.cpp72
-rw-r--r--src/qt/walletview.h2
-rw-r--r--src/qt/winshutdownmonitor.cpp4
-rw-r--r--src/qt/winshutdownmonitor.h2
-rw-r--r--src/random.cpp584
-rw-r--r--src/random.h143
-rw-r--r--src/rest.cpp136
-rw-r--r--src/rpc/blockchain.cpp1109
-rw-r--r--src/rpc/blockchain.h27
-rw-r--r--src/rpc/client.cpp34
-rw-r--r--src/rpc/client.h2
-rw-r--r--src/rpc/mining.cpp418
-rw-r--r--src/rpc/mining.h18
-rw-r--r--src/rpc/misc.cpp392
-rw-r--r--src/rpc/net.cpp344
-rw-r--r--src/rpc/protocol.cpp20
-rw-r--r--src/rpc/protocol.h2
-rw-r--r--src/rpc/rawtransaction.cpp1491
-rw-r--r--src/rpc/rawtransaction.h18
-rw-r--r--src/rpc/rawtransaction_util.cpp283
-rw-r--r--src/rpc/rawtransaction_util.h32
-rw-r--r--src/rpc/register.h2
-rw-r--r--src/rpc/server.cpp326
-rw-r--r--src/rpc/server.h79
-rw-r--r--src/rpc/util.cpp569
-rw-r--r--src/rpc/util.h227
-rw-r--r--src/scheduler.cpp13
-rw-r--r--src/scheduler.h20
-rw-r--r--src/script/bitcoinconsensus.cpp4
-rw-r--r--src/script/bitcoinconsensus.h2
-rw-r--r--src/script/descriptor.cpp733
-rw-r--r--src/script/descriptor.h95
-rw-r--r--src/script/interpreter.cpp2
-rw-r--r--src/script/interpreter.h2
-rw-r--r--src/script/ismine.cpp21
-rw-r--r--src/script/ismine.h31
-rw-r--r--src/script/script.cpp4
-rw-r--r--src/script/script.h17
-rw-r--r--src/script/script_error.cpp2
-rw-r--r--src/script/script_error.h2
-rw-r--r--src/script/sigcache.cpp4
-rw-r--r--src/script/sigcache.h2
-rw-r--r--src/script/sign.cpp271
-rw-r--r--src/script/sign.h583
-rw-r--r--src/script/standard.cpp79
-rw-r--r--src/script/standard.h32
-rw-r--r--src/serialize.h33
-rw-r--r--src/streams.h208
-rw-r--r--src/support/allocators/secure.h8
-rw-r--r--src/support/allocators/zeroafterfree.h2
-rw-r--r--src/support/cleanse.cpp2
-rw-r--r--src/support/cleanse.h2
-rw-r--r--src/support/events.h2
-rw-r--r--src/support/lockedpool.cpp13
-rw-r--r--src/support/lockedpool.h4
-rw-r--r--src/sync.cpp53
-rw-r--r--src/sync.h127
-rw-r--r--src/test/README.md2
-rw-r--r--src/test/addrman_tests.cpp84
-rw-r--r--src/test/allocator_tests.cpp16
-rw-r--r--src/test/amount_tests.cpp61
-rw-r--r--src/test/arith_uint256_tests.cpp4
-rw-r--r--src/test/base32_tests.cpp6
-rw-r--r--src/test/base58_tests.cpp6
-rw-r--r--src/test/base64_tests.cpp6
-rw-r--r--src/test/bech32_tests.cpp2
-rw-r--r--src/test/bip32_tests.cpp8
-rw-r--r--src/test/blockchain_tests.cpp9
-rw-r--r--src/test/blockencodings_tests.cpp62
-rw-r--r--src/test/blockfilter_index_tests.cpp307
-rw-r--r--src/test/blockfilter_tests.cpp194
-rw-r--r--src/test/bloom_tests.cpp26
-rw-r--r--src/test/bswap_tests.cpp4
-rw-r--r--src/test/checkqueue_tests.cpp30
-rw-r--r--src/test/coins_tests.cpp53
-rw-r--r--src/test/compress_tests.cpp6
-rw-r--r--src/test/crypto_tests.cpp269
-rw-r--r--src/test/cuckoocache_tests.cpp57
-rw-r--r--src/test/data/blockfilters.json13
-rw-r--r--src/test/data/tx_invalid.json2
-rw-r--r--src/test/dbwrapper_tests.cpp26
-rw-r--r--src/test/denialofservice_tests.cpp121
-rw-r--r--src/test/descriptor_tests.cpp130
-rw-r--r--src/test/flatfile_tests.cpp123
-rw-r--r--src/test/fs_tests.cpp56
-rw-r--r--src/test/fuzz/deserialize.cpp167
-rw-r--r--src/test/fuzz/fuzz.cpp77
-rw-r--r--src/test/fuzz/fuzz.h15
-rw-r--r--src/test/fuzz/script_flags.cpp72
-rw-r--r--src/test/gen/crypto_gen.cpp19
-rw-r--r--src/test/gen/crypto_gen.h63
-rw-r--r--src/test/getarg_tests.cpp13
-rw-r--r--src/test/hash_tests.cpp7
-rw-r--r--src/test/key_io_tests.cpp10
-rw-r--r--src/test/key_properties.cpp53
-rw-r--r--src/test/key_tests.cpp84
-rw-r--r--src/test/limitedmap_tests.cpp4
-rw-r--r--src/test/main.cpp7
-rw-r--r--src/test/mempool_tests.cpp124
-rw-r--r--src/test/merkle_tests.cpp8
-rw-r--r--src/test/merkleblock_tests.cpp4
-rw-r--r--src/test/miner_tests.cpp162
-rw-r--r--src/test/multisig_tests.cpp18
-rw-r--r--src/test/net_tests.cpp152
-rw-r--r--src/test/netbase_tests.cpp24
-rw-r--r--src/test/pmt_tests.cpp4
-rw-r--r--src/test/policyestimator_tests.cpp16
-rw-r--r--src/test/pow_tests.cpp8
-rw-r--r--src/test/prevector_tests.cpp8
-rw-r--r--src/test/raii_event_tests.cpp4
-rw-r--r--src/test/random_tests.cpp65
-rw-r--r--src/test/reverselock_tests.cpp4
-rw-r--r--src/test/rpc_tests.cpp99
-rw-r--r--src/test/sanity_tests.cpp4
-rw-r--r--src/test/scheduler_tests.cpp29
-rw-r--r--src/test/script_p2sh_tests.cpp115
-rw-r--r--src/test/script_standard_tests.cpp213
-rw-r--r--src/test/script_tests.cpp103
-rw-r--r--src/test/scriptnum10.h2
-rw-r--r--src/test/scriptnum_tests.cpp4
-rw-r--r--src/test/serialize_tests.cpp10
-rw-r--r--src/test/setup_common.cpp (renamed from src/test/test_bitcoin.cpp)132
-rw-r--r--src/test/setup_common.h (renamed from src/test/test_bitcoin.h)62
-rw-r--r--src/test/sighash_tests.cpp14
-rw-r--r--src/test/sigopcount_tests.cpp28
-rw-r--r--src/test/skiplist_tests.cpp55
-rw-r--r--src/test/streams_tests.cpp84
-rw-r--r--src/test/sync_tests.cpp52
-rw-r--r--src/test/test_bitcoin_fuzzy.cpp329
-rw-r--r--src/test/test_bitcoin_main.cpp28
-rw-r--r--src/test/timedata_tests.cpp4
-rw-r--r--src/test/torcontrol_tests.cpp5
-rw-r--r--src/test/transaction_tests.cpp133
-rw-r--r--src/test/txindex_tests.cpp25
-rw-r--r--src/test/txvalidation_tests.cpp11
-rw-r--r--src/test/txvalidationcache_tests.cpp71
-rw-r--r--src/test/uint256_tests.cpp12
-rw-r--r--src/test/util.cpp92
-rw-r--r--src/test/util.h70
-rw-r--r--src/test/util_tests.cpp453
-rw-r--r--src/test/util_threadnames_tests.cpp73
-rw-r--r--src/test/validation_block_tests.cpp30
-rw-r--r--src/test/validation_tests.cpp (renamed from src/test/main_tests.cpp)8
-rw-r--r--src/test/versionbits_tests.cpp4
-rw-r--r--src/threadinterrupt.cpp8
-rw-r--r--src/threadinterrupt.h6
-rw-r--r--src/threadsafety.h15
-rw-r--r--src/timedata.cpp10
-rw-r--r--src/timedata.h2
-rw-r--r--src/torcontrol.cpp31
-rw-r--r--src/torcontrol.h2
-rw-r--r--src/txdb.cpp2
-rw-r--r--src/txdb.h4
-rw-r--r--src/txmempool.cpp93
-rw-r--r--src/txmempool.h109
-rw-r--r--src/ui_interface.cpp62
-rw-r--r--src/ui_interface.h47
-rw-r--r--src/uint256.cpp8
-rw-r--r--src/uint256.h13
-rw-r--r--src/undo.h6
-rw-r--r--src/univalue/gen/gen.cpp2
-rw-r--r--src/univalue/include/univalue.h68
-rw-r--r--src/univalue/lib/univalue.cpp16
-rw-r--r--src/univalue/lib/univalue_read.cpp12
-rw-r--r--src/univalue/lib/univalue_write.cpp18
-rw-r--r--src/univalue/test/unitester.cpp15
-rw-r--r--src/util/bip32.cpp66
-rw-r--r--src/util/bip32.h19
-rw-r--r--src/util/bytevectorhash.cpp18
-rw-r--r--src/util/bytevectorhash.h26
-rw-r--r--src/util/error.cpp43
-rw-r--r--src/util/error.h38
-rw-r--r--src/util/fees.cpp42
-rw-r--r--src/util/fees.h16
-rw-r--r--src/util/memory.h (renamed from src/utilmemory.h)4
-rw-r--r--src/util/moneystr.cpp (renamed from src/utilmoneystr.cpp)20
-rw-r--r--src/util/moneystr.h (renamed from src/utilmoneystr.h)19
-rw-r--r--src/util/rbf.cpp17
-rw-r--r--src/util/rbf.h18
-rw-r--r--src/util/strencodings.cpp (renamed from src/utilstrencodings.cpp)41
-rw-r--r--src/util/strencodings.h (renamed from src/utilstrencodings.h)108
-rw-r--r--src/util/system.cpp (renamed from src/util.cpp)309
-rw-r--r--src/util/system.h (renamed from src/util.h)106
-rw-r--r--src/util/threadnames.cpp62
-rw-r--r--src/util/threadnames.h21
-rw-r--r--src/util/time.cpp (renamed from src/utiltime.cpp)15
-rw-r--r--src/util/time.h (renamed from src/utiltime.h)9
-rw-r--r--src/util/url.cpp21
-rw-r--r--src/util/url.h12
-rw-r--r--src/util/validation.cpp20
-rw-r--r--src/util/validation.h18
-rw-r--r--src/validation.cpp1196
-rw-r--r--src/validation.h96
-rw-r--r--src/validationinterface.cpp75
-rw-r--r--src/validationinterface.h10
-rw-r--r--src/version.h2
-rw-r--r--src/versionbits.cpp17
-rw-r--r--src/versionbits.h11
-rw-r--r--src/versionbitsinfo.cpp22
-rw-r--r--src/versionbitsinfo.h17
-rw-r--r--src/wallet/coincontrol.cpp2
-rw-r--r--src/wallet/coincontrol.h4
-rw-r--r--src/wallet/coinselection.cpp23
-rw-r--r--src/wallet/coinselection.h4
-rw-r--r--src/wallet/crypter.cpp14
-rw-r--r--src/wallet/crypter.h4
-rw-r--r--src/wallet/db.cpp236
-rw-r--r--src/wallet/db.h149
-rw-r--r--src/wallet/feebumper.cpp210
-rw-r--r--src/wallet/feebumper.h15
-rw-r--r--src/wallet/fees.cpp30
-rw-r--r--src/wallet/fees.h10
-rw-r--r--src/wallet/init.cpp166
-rw-r--r--src/wallet/load.cpp112
-rw-r--r--src/wallet/load.h38
-rw-r--r--src/wallet/psbtwallet.cpp60
-rw-r--r--src/wallet/psbtwallet.h34
-rw-r--r--src/wallet/rpcdump.cpp1143
-rw-r--r--src/wallet/rpcwallet.cpp3345
-rw-r--r--src/wallet/rpcwallet.h18
-rw-r--r--src/wallet/test/accounting_tests.cpp136
-rw-r--r--src/wallet/test/coinselector_tests.cpp86
-rw-r--r--src/wallet/test/db_tests.cpp72
-rw-r--r--src/wallet/test/init_test_fixture.cpp44
-rw-r--r--src/wallet/test/init_test_fixture.h24
-rw-r--r--src/wallet/test/init_tests.cpp78
-rw-r--r--src/wallet/test/psbt_wallet_tests.cpp19
-rw-r--r--src/wallet/test/wallet_crypto_tests.cpp6
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp17
-rw-r--r--src/wallet/test/wallet_test_fixture.h9
-rw-r--r--src/wallet/test/wallet_tests.cpp223
-rw-r--r--src/wallet/wallet.cpp1938
-rw-r--r--src/wallet/wallet.h670
-rw-r--r--src/wallet/walletdb.cpp179
-rw-r--r--src/wallet/walletdb.h30
-rw-r--r--src/wallet/wallettool.cpp135
-rw-r--r--src/wallet/wallettool.h20
-rw-r--r--src/wallet/walletutil.cpp79
-rw-r--r--src/wallet/walletutil.h30
-rw-r--r--src/walletinitinterface.h23
-rw-r--r--src/warnings.cpp4
-rw-r--r--src/warnings.h10
-rw-r--r--src/zmq/zmqabstractnotifier.cpp5
-rw-r--r--src/zmq/zmqabstractnotifier.h13
-rw-r--r--src/zmq/zmqconfig.h2
-rw-r--r--src/zmq/zmqnotificationinterface.cpp17
-rw-r--r--src/zmq/zmqpublishnotifier.cpp21
-rw-r--r--src/zmq/zmqpublishnotifier.h4
-rw-r--r--src/zmq/zmqrpc.cpp20
670 files changed, 54603 insertions, 39951 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index d1693fa85c..ec3d81b76f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,7 @@ LIBBITCOINCONSENSUS=libbitcoinconsensus.la
endif
if ENABLE_WALLET
LIBBITCOIN_WALLET=libbitcoin_wallet.a
+LIBBITCOIN_WALLET_TOOL=libbitcoin_wallet_tool.a
endif
LIBBITCOIN_CRYPTO= $(LIBBITCOIN_CRYPTO_BASE)
@@ -70,6 +71,7 @@ EXTRA_LIBRARIES += \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_CLI) \
$(LIBBITCOIN_WALLET) \
+ $(LIBBITCOIN_WALLET_TOOL) \
$(LIBBITCOIN_ZMQ)
lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS)
@@ -83,8 +85,16 @@ if BUILD_BITCOIND
bin_PROGRAMS += bitcoind
endif
-if BUILD_BITCOIN_UTILS
- bin_PROGRAMS += bitcoin-cli bitcoin-tx
+if BUILD_BITCOIN_CLI
+ bin_PROGRAMS += bitcoin-cli
+endif
+if BUILD_BITCOIN_TX
+ bin_PROGRAMS += bitcoin-tx
+endif
+if ENABLE_WALLET
+if BUILD_BITCOIN_WALLET
+ bin_PROGRAMS += bitcoin-wallet
+endif
endif
.PHONY: FORCE check-symbols check-security
@@ -92,35 +102,42 @@ endif
BITCOIN_CORE_H = \
addrdb.h \
addrman.h \
+ attributes.h \
+ banman.h \
base58.h \
bech32.h \
bloom.h \
blockencodings.h \
+ blockfilter.h \
chain.h \
chainparams.h \
chainparamsbase.h \
chainparamsseeds.h \
- checkpoints.h \
checkqueue.h \
clientversion.h \
coins.h \
compat.h \
+ compat/assumptions.h \
compat/byteswap.h \
compat/endian.h \
compat/sanity.h \
compressor.h \
consensus/consensus.h \
+ consensus/tx_check.h \
consensus/tx_verify.h \
core_io.h \
core_memusage.h \
cuckoocache.h \
+ flatfile.h \
fs.h \
httprpc.h \
httpserver.h \
index/base.h \
+ index/blockfilterindex.h \
index/txindex.h \
indirectmap.h \
init.h \
+ interfaces/chain.h \
interfaces/handler.h \
interfaces/node.h \
interfaces/wallet.h \
@@ -138,23 +155,28 @@ BITCOIN_CORE_H = \
netaddress.h \
netbase.h \
netmessagemaker.h \
+ node/coin.h \
+ node/psbt.h \
+ node/transaction.h \
noui.h \
+ optional.h \
outputtype.h \
policy/feerate.h \
policy/fees.h \
policy/policy.h \
policy/rbf.h \
+ policy/settings.h \
pow.h \
protocol.h \
+ psbt.h \
random.h \
reverse_iterator.h \
reverselock.h \
rpc/blockchain.h \
rpc/client.h \
- rpc/mining.h \
rpc/protocol.h \
rpc/server.h \
- rpc/rawtransaction.h \
+ rpc/rawtransaction_util.h \
rpc/register.h \
rpc/util.h \
scheduler.h \
@@ -179,22 +201,34 @@ BITCOIN_CORE_H = \
txmempool.h \
ui_interface.h \
undo.h \
- util.h \
- utilmemory.h \
- utilmoneystr.h \
- utiltime.h \
+ util/bip32.h \
+ util/bytevectorhash.h \
+ util/error.h \
+ util/fees.h \
+ util/system.h \
+ util/memory.h \
+ util/moneystr.h \
+ util/rbf.h \
+ util/threadnames.h \
+ util/time.h \
+ util/url.h \
+ util/validation.h \
validation.h \
validationinterface.h \
versionbits.h \
+ versionbitsinfo.h \
walletinitinterface.h \
wallet/coincontrol.h \
wallet/crypter.h \
wallet/db.h \
wallet/feebumper.h \
wallet/fees.h \
+ wallet/load.h \
+ wallet/psbtwallet.h \
wallet/rpcwallet.h \
wallet/wallet.h \
wallet/walletdb.h \
+ wallet/wallettool.h \
wallet/walletutil.h \
wallet/coinselection.h \
warnings.h \
@@ -212,31 +246,39 @@ obj/build.h: FORCE
libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
# server: shared between bitcoind and bitcoin-qt
+# Contains code accessing mempool and chain state that is meant to be separated
+# from wallet and gui code (see node/README.md). Shared code should go in
+# libbitcoin_common or libbitcoin_util libraries, instead.
libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_server_a_SOURCES = \
addrdb.cpp \
addrman.cpp \
- bloom.cpp \
+ banman.cpp \
blockencodings.cpp \
+ blockfilter.cpp \
chain.cpp \
- checkpoints.cpp \
consensus/tx_verify.cpp \
+ flatfile.cpp \
httprpc.cpp \
httpserver.cpp \
index/base.cpp \
+ index/blockfilterindex.cpp \
index/txindex.cpp \
+ interfaces/chain.cpp \
+ interfaces/node.cpp \
init.cpp \
dbwrapper.cpp \
- merkleblock.cpp \
miner.cpp \
net.cpp \
net_processing.cpp \
+ node/coin.cpp \
+ node/psbt.cpp \
+ node/transaction.cpp \
noui.cpp \
- outputtype.cpp \
policy/fees.cpp \
- policy/policy.cpp \
policy/rbf.cpp \
+ policy/settings.cpp \
pow.cpp \
rest.cpp \
rpc/blockchain.cpp \
@@ -245,7 +287,6 @@ libbitcoin_server_a_SOURCES = \
rpc/net.cpp \
rpc/rawtransaction.cpp \
rpc/server.cpp \
- rpc/util.cpp \
script/sigcache.cpp \
shutdown.cpp \
timedata.cpp \
@@ -258,6 +299,13 @@ libbitcoin_server_a_SOURCES = \
versionbits.cpp \
$(BITCOIN_CORE_H)
+if ENABLE_WALLET
+libbitcoin_server_a_SOURCES += wallet/init.cpp
+endif
+if !ENABLE_WALLET
+libbitcoin_server_a_SOURCES += dummywallet.cpp
+endif
+
if ENABLE_ZMQ
libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS)
libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -280,7 +328,8 @@ libbitcoin_wallet_a_SOURCES = \
wallet/db.cpp \
wallet/feebumper.cpp \
wallet/fees.cpp \
- wallet/init.cpp \
+ wallet/load.cpp \
+ wallet/psbtwallet.cpp \
wallet/rpcdump.cpp \
wallet/rpcwallet.cpp \
wallet/wallet.cpp \
@@ -289,6 +338,12 @@ libbitcoin_wallet_a_SOURCES = \
wallet/coinselection.cpp \
$(BITCOIN_CORE_H)
+libbitcoin_wallet_tool_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+libbitcoin_wallet_tool_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+libbitcoin_wallet_tool_a_SOURCES = \
+ wallet/wallettool.cpp \
+ $(BITCOIN_CORE_H)
+
# crypto primitives library
crypto_libbitcoin_crypto_base_a_CPPFLAGS = $(AM_CPPFLAGS)
crypto_libbitcoin_crypto_base_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -298,10 +353,14 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \
crypto/chacha20.h \
crypto/chacha20.cpp \
crypto/common.h \
+ crypto/hkdf_sha256_32.cpp \
+ crypto/hkdf_sha256_32.h \
crypto/hmac_sha256.cpp \
crypto/hmac_sha256.h \
crypto/hmac_sha512.cpp \
crypto/hmac_sha512.h \
+ crypto/poly1305.h \
+ crypto/poly1305.cpp \
crypto/ripemd160.cpp \
crypto/ripemd160.h \
crypto/sha1.cpp \
@@ -309,7 +368,9 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \
crypto/sha256.cpp \
crypto/sha256.h \
crypto/sha512.cpp \
- crypto/sha512.h
+ crypto/sha512.h \
+ crypto/siphash.cpp \
+ crypto/siphash.h
if USE_ASM
crypto_libbitcoin_crypto_base_a_SOURCES += crypto/sha256_sse4.cpp
@@ -343,6 +404,7 @@ libbitcoin_consensus_a_SOURCES = \
consensus/merkle.cpp \
consensus/merkle.h \
consensus/params.h \
+ consensus/tx_check.cpp \
consensus/validation.h \
hash.cpp \
hash.h \
@@ -365,8 +427,8 @@ libbitcoin_consensus_a_SOURCES = \
tinyformat.h \
uint256.cpp \
uint256.h \
- utilstrencodings.cpp \
- utilstrencodings.h \
+ util/strencodings.cpp \
+ util/strencodings.h \
version.h
# common: shared between bitcoind, and bitcoin-qt and non-server tools
@@ -375,6 +437,7 @@ libbitcoin_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_common_a_SOURCES = \
base58.cpp \
bech32.cpp \
+ bloom.cpp \
chainparams.cpp \
coins.cpp \
compressor.cpp \
@@ -383,15 +446,22 @@ libbitcoin_common_a_SOURCES = \
key.cpp \
key_io.cpp \
keystore.cpp \
+ merkleblock.cpp \
netaddress.cpp \
netbase.cpp \
+ outputtype.cpp \
policy/feerate.cpp \
+ policy/policy.cpp \
protocol.cpp \
+ psbt.cpp \
+ rpc/rawtransaction_util.cpp \
+ rpc/util.cpp \
scheduler.cpp \
script/descriptor.cpp \
script/ismine.cpp \
script/sign.cpp \
script/standard.cpp \
+ versionbitsinfo.cpp \
warnings.cpp \
$(BITCOIN_CORE_H)
@@ -409,17 +479,24 @@ libbitcoin_util_a_SOURCES = \
compat/strnlen.cpp \
fs.cpp \
interfaces/handler.cpp \
- interfaces/node.cpp \
logging.cpp \
random.cpp \
rpc/protocol.cpp \
support/cleanse.cpp \
sync.cpp \
threadinterrupt.cpp \
- util.cpp \
- utilmoneystr.cpp \
- utilstrencodings.cpp \
- utiltime.cpp \
+ util/bip32.cpp \
+ util/bytevectorhash.cpp \
+ util/error.cpp \
+ util/fees.cpp \
+ util/system.cpp \
+ util/moneystr.cpp \
+ util/rbf.cpp \
+ util/threadnames.cpp \
+ util/strencodings.cpp \
+ util/time.cpp \
+ util/url.cpp \
+ util/validation.cpp \
$(BITCOIN_CORE_H)
if GLIBC_BACK_COMPAT
@@ -447,9 +524,12 @@ if TARGET_WINDOWS
bitcoind_SOURCES += bitcoind-res.rc
endif
+# Libraries below may be listed more than once to resolve circular dependencies (see
+# https://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking#circular-dependency)
bitcoind_LDADD = \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_WALLET) \
+ $(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBUNIVALUE) \
$(LIBBITCOIN_UTIL) \
@@ -461,7 +541,7 @@ bitcoind_LDADD = \
$(LIBMEMENV) \
$(LIBSECP256K1)
-bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
+bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
# bitcoin-cli binary #
bitcoin_cli_SOURCES = bitcoin-cli.cpp
@@ -479,7 +559,7 @@ bitcoin_cli_LDADD = \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CRYPTO)
-bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
+bitcoin_cli_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
#
# bitcoin-tx binary #
@@ -503,6 +583,33 @@ bitcoin_tx_LDADD = \
bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
#
+# bitcoin-wallet binary #
+bitcoin_wallet_SOURCES = bitcoin-wallet.cpp
+bitcoin_wallet_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+bitcoin_wallet_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+bitcoin_wallet_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+
+if TARGET_WINDOWS
+bitcoin_wallet_SOURCES += bitcoin-wallet-res.rc
+endif
+
+bitcoin_wallet_LDADD = \
+ $(LIBBITCOIN_WALLET_TOOL) \
+ $(LIBBITCOIN_WALLET) \
+ $(LIBBITCOIN_COMMON) \
+ $(LIBBITCOIN_CONSENSUS) \
+ $(LIBBITCOIN_UTIL) \
+ $(LIBBITCOIN_CRYPTO) \
+ $(LIBBITCOIN_ZMQ) \
+ $(LIBLEVELDB) \
+ $(LIBLEVELDB_SSE42) \
+ $(LIBMEMENV) \
+ $(LIBSECP256K1) \
+ $(LIBUNIVALUE)
+
+bitcoin_wallet_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(ZMQ_LIBS)
+#
+
# bitcoinconsensus library #
if BUILD_BITCOIN_LIBS
include_HEADERS = script/bitcoinconsensus.h
@@ -567,18 +674,20 @@ clean-local:
check-symbols: $(bin_PROGRAMS)
if GLIBC_BACK_COMPAT
@echo "Checking glibc back compat..."
- $(AM_V_at) READELF=$(READELF) CPPFILT=$(CPPFILT) $(top_srcdir)/contrib/devtools/symbol-check.py < $(bin_PROGRAMS)
+ $(AM_V_at) READELF=$(READELF) CPPFILT=$(CPPFILT) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py < $(bin_PROGRAMS)
endif
check-security: $(bin_PROGRAMS)
if HARDEN
@echo "Checking binary security..."
- $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS)
+ $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS)
endif
+if ENABLE_BIP70
%.pb.cc %.pb.h: %.proto
@test -f $(PROTOC)
$(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $<
+endif
if EMBEDDED_LEVELDB
include Makefile.leveldb.include
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index f5293585a0..ef8a207841 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -18,23 +18,33 @@ bench_bench_bitcoin_SOURCES = \
bench/block_assemble.cpp \
bench/checkblock.cpp \
bench/checkqueue.cpp \
+ bench/duplicate_inputs.cpp \
bench/examples.cpp \
bench/rollingbloom.cpp \
+ bench/chacha20.cpp \
bench/crypto_hash.cpp \
bench/ccoins_caching.cpp \
+ bench/gcs_filter.cpp \
bench/merkle_root.cpp \
bench/mempool_eviction.cpp \
+ bench/rpc_mempool.cpp \
bench/verify_script.cpp \
bench/base58.cpp \
bench/bech32.cpp \
bench/lockedpool.cpp \
- bench/prevector.cpp
+ bench/poly1305.cpp \
+ bench/prevector.cpp \
+ test/setup_common.h \
+ test/setup_common.cpp \
+ test/util.h \
+ test/util.cpp
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
bench_bench_bitcoin_LDADD = \
+ $(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_WALLET) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
@@ -45,7 +55,9 @@ bench_bench_bitcoin_LDADD = \
$(LIBLEVELDB_SSE42) \
$(LIBMEMENV) \
$(LIBSECP256K1) \
- $(LIBUNIVALUE)
+ $(LIBUNIVALUE) \
+ $(EVENT_PTHREADS_LIBS) \
+ $(EVENT_LIBS)
if ENABLE_ZMQ
bench_bench_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
@@ -53,9 +65,10 @@ endif
if ENABLE_WALLET
bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
+bench_bench_bitcoin_SOURCES += bench/wallet_balance.cpp
endif
-bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
+bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS)
bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES)
diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include
index 833f3d2a10..bd08bcb4ed 100644
--- a/src/Makefile.leveldb.include
+++ b/src/Makefile.leveldb.include
@@ -24,7 +24,7 @@ LEVELDB_CPPFLAGS_INT += -DLEVELDB_ATOMIC_PRESENT
LEVELDB_CPPFLAGS_INT += -D__STDC_LIMIT_MACROS
if TARGET_WINDOWS
-LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1
+LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_WINDOWS -D__USE_MINGW_ANSI_STDIO=1
else
LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_POSIX
endif
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index c7a1963135..c4c08487f3 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -120,9 +120,9 @@ QT_MOC_CPP = \
qt/moc_bantablemodel.cpp \
qt/moc_bitcoinaddressvalidator.cpp \
qt/moc_bitcoinamountfield.cpp \
+ qt/moc_bitcoin.cpp \
qt/moc_bitcoingui.cpp \
qt/moc_bitcoinunits.cpp \
- qt/moc_callback.cpp \
qt/moc_clientmodel.cpp \
qt/moc_coincontroldialog.cpp \
qt/moc_coincontroltreewidget.cpp \
@@ -140,6 +140,7 @@ QT_MOC_CPP = \
qt/moc_overviewpage.cpp \
qt/moc_peertablemodel.cpp \
qt/moc_paymentserver.cpp \
+ qt/moc_qrimagewidget.cpp \
qt/moc_qvalidatedlineedit.cpp \
qt/moc_qvaluecombobox.cpp \
qt/moc_receivecoinsdialog.cpp \
@@ -157,18 +158,18 @@ QT_MOC_CPP = \
qt/moc_transactiontablemodel.cpp \
qt/moc_transactionview.cpp \
qt/moc_utilitydialog.cpp \
+ qt/moc_walletcontroller.cpp \
qt/moc_walletframe.cpp \
qt/moc_walletmodel.cpp \
qt/moc_walletview.cpp
BITCOIN_MM = \
qt/macdockiconhandler.mm \
- qt/macnotificationhandler.mm
+ qt/macnotificationhandler.mm \
+ qt/macos_appnap.mm
QT_MOC = \
- qt/bitcoin.moc \
qt/bitcoinamountfield.moc \
- qt/callback.moc \
qt/intro.moc \
qt/overviewpage.moc \
qt/rpcconsole.moc
@@ -178,9 +179,15 @@ QT_QRC = qt/bitcoin.qrc
QT_QRC_LOCALE_CPP = qt/qrc_bitcoin_locale.cpp
QT_QRC_LOCALE = qt/bitcoin_locale.qrc
+if ENABLE_BIP70
PROTOBUF_CC = qt/paymentrequest.pb.cc
PROTOBUF_H = qt/paymentrequest.pb.h
PROTOBUF_PROTO = qt/paymentrequest.proto
+else
+PROTOBUF_CC =
+PROTOBUF_H =
+PROTOBUF_PROTO =
+endif
BITCOIN_QT_H = \
qt/addressbookpage.h \
@@ -189,9 +196,9 @@ BITCOIN_QT_H = \
qt/bantablemodel.h \
qt/bitcoinaddressvalidator.h \
qt/bitcoinamountfield.h \
+ qt/bitcoin.h \
qt/bitcoingui.h \
qt/bitcoinunits.h \
- qt/callback.h \
qt/clientmodel.h \
qt/coincontroldialog.h \
qt/coincontroltreewidget.h \
@@ -202,6 +209,7 @@ BITCOIN_QT_H = \
qt/intro.h \
qt/macdockiconhandler.h \
qt/macnotificationhandler.h \
+ qt/macos_appnap.h \
qt/modaloverlay.h \
qt/networkstyle.h \
qt/notificator.h \
@@ -213,6 +221,7 @@ BITCOIN_QT_H = \
qt/paymentserver.h \
qt/peertablemodel.h \
qt/platformstyle.h \
+ qt/qrimagewidget.h \
qt/qvalidatedlineedit.h \
qt/qvaluecombobox.h \
qt/receivecoinsdialog.h \
@@ -231,6 +240,7 @@ BITCOIN_QT_H = \
qt/transactiontablemodel.h \
qt/transactionview.h \
qt/utilitydialog.h \
+ qt/walletcontroller.h \
qt/walletframe.h \
qt/walletmodel.h \
qt/walletmodeltransaction.h \
@@ -297,6 +307,7 @@ RES_ICONS = \
BITCOIN_QT_BASE_CPP = \
qt/bantablemodel.cpp \
+ qt/bitcoin.cpp \
qt/bitcoinaddressvalidator.cpp \
qt/bitcoinamountfield.cpp \
qt/bitcoingui.cpp \
@@ -330,8 +341,8 @@ BITCOIN_QT_WALLET_CPP = \
qt/editaddressdialog.cpp \
qt/openuridialog.cpp \
qt/overviewpage.cpp \
- qt/paymentrequestplus.cpp \
qt/paymentserver.cpp \
+ qt/qrimagewidget.cpp \
qt/receivecoinsdialog.cpp \
qt/receiverequestdialog.cpp \
qt/recentrequeststablemodel.cpp \
@@ -344,18 +355,25 @@ BITCOIN_QT_WALLET_CPP = \
qt/transactionrecord.cpp \
qt/transactiontablemodel.cpp \
qt/transactionview.cpp \
+ qt/walletcontroller.cpp \
qt/walletframe.cpp \
qt/walletmodel.cpp \
qt/walletmodeltransaction.cpp \
qt/walletview.cpp
+BITCOIN_QT_WALLET_BIP70_CPP = \
+ qt/paymentrequestplus.cpp
+
BITCOIN_QT_CPP = $(BITCOIN_QT_BASE_CPP)
if TARGET_WINDOWS
BITCOIN_QT_CPP += $(BITCOIN_QT_WINDOWS_CPP)
endif
if ENABLE_WALLET
BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP)
-endif
+if ENABLE_BIP70
+BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_BIP70_CPP)
+endif # ENABLE_BIP70
+endif # ENABLE_WALLET
RES_IMAGES =
@@ -372,6 +390,9 @@ qt_libbitcoinqt_a_OBJCXXFLAGS = $(AM_OBJCXXFLAGS) $(QT_PIE_FLAGS)
qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \
$(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
+if TARGET_DARWIN
+ qt_libbitcoinqt_a_SOURCES += $(BITCOIN_MM)
+endif
nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \
$(PROTOBUF_H) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP)
@@ -394,10 +415,7 @@ qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDE
$(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
qt_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
-qt_bitcoin_qt_SOURCES = qt/bitcoin.cpp
-if TARGET_DARWIN
- qt_bitcoin_qt_SOURCES += $(BITCOIN_MM)
-endif
+qt_bitcoin_qt_SOURCES = qt/main.cpp
if TARGET_WINDOWS
qt_bitcoin_qt_SOURCES += $(BITCOIN_RC)
endif
@@ -409,8 +427,16 @@ if ENABLE_ZMQ
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
- $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
+ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
+if ENABLE_BIP70
+qt_bitcoin_qt_LDADD += $(SSL_LIBS)
+else
+if TARGET_WINDOWS
+qt_bitcoin_qt_LDADD += $(SSL_LIBS)
+endif
+endif
+qt_bitcoin_qt_LDADD += $(CRYPTO_LIBS)
qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 4b14212b2e..4acfff809e 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -6,6 +6,7 @@ bin_PROGRAMS += qt/test/test_bitcoin-qt
TESTS += qt/test/test_bitcoin-qt
TEST_QT_MOC_CPP = \
+ qt/test/moc_apptests.cpp \
qt/test/moc_compattests.cpp \
qt/test/moc_rpcnestedtests.cpp \
qt/test/moc_uritests.cpp
@@ -13,12 +14,16 @@ TEST_QT_MOC_CPP = \
if ENABLE_WALLET
TEST_QT_MOC_CPP += \
qt/test/moc_addressbooktests.cpp \
- qt/test/moc_paymentservertests.cpp \
qt/test/moc_wallettests.cpp
-endif
+if ENABLE_BIP70
+TEST_QT_MOC_CPP += \
+ qt/test/moc_paymentservertests.cpp
+endif # ENABLE_BIP70
+endif # ENABLE_WALLET
TEST_QT_H = \
qt/test/addressbooktests.h \
+ qt/test/apptests.h \
qt/test/compattests.h \
qt/test/rpcnestedtests.h \
qt/test/uritests.h \
@@ -28,15 +33,16 @@ TEST_QT_H = \
qt/test/wallettests.h
TEST_BITCOIN_CPP = \
- test/test_bitcoin.cpp
+ test/setup_common.cpp
TEST_BITCOIN_H = \
- test/test_bitcoin.h
+ test/setup_common.h
qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
$(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS)
qt_test_test_bitcoin_qt_SOURCES = \
+ qt/test/apptests.cpp \
qt/test/compattests.cpp \
qt/test/rpcnestedtests.cpp \
qt/test/test_main.cpp \
@@ -48,10 +54,13 @@ qt_test_test_bitcoin_qt_SOURCES = \
if ENABLE_WALLET
qt_test_test_bitcoin_qt_SOURCES += \
qt/test/addressbooktests.cpp \
- qt/test/paymentservertests.cpp \
qt/test/wallettests.cpp \
wallet/test/wallet_test_fixture.cpp
-endif
+if ENABLE_BIP70
+qt_test_test_bitcoin_qt_SOURCES += \
+ qt/test/paymentservertests.cpp
+endif # ENABLE_BIP70
+endif # ENABLE_WALLET
nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 6f401636f5..1144ca8a78 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -2,13 +2,43 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+FUZZ_TARGETS = \
+ test/fuzz/address_deserialize \
+ test/fuzz/addrman_deserialize \
+ test/fuzz/banentry_deserialize \
+ test/fuzz/block_deserialize \
+ test/fuzz/blockheader_deserialize \
+ test/fuzz/blocklocator_deserialize \
+ test/fuzz/blockmerkleroot \
+ test/fuzz/blocktransactions_deserialize \
+ test/fuzz/blocktransactionsrequest_deserialize \
+ test/fuzz/blockundo_deserialize \
+ test/fuzz/bloomfilter_deserialize \
+ test/fuzz/coins_deserialize \
+ test/fuzz/diskblockindex_deserialize \
+ test/fuzz/inv_deserialize \
+ test/fuzz/messageheader_deserialize \
+ test/fuzz/netaddr_deserialize \
+ test/fuzz/script_flags \
+ test/fuzz/service_deserialize \
+ test/fuzz/transaction_deserialize \
+ test/fuzz/txoutcompressor_deserialize \
+ test/fuzz/txundo_deserialize
+
+if ENABLE_FUZZ
+noinst_PROGRAMS += $(FUZZ_TARGETS:=)
+else
bin_PROGRAMS += test/test_bitcoin
-noinst_PROGRAMS += test/test_bitcoin_fuzzy
+endif
+
TEST_SRCDIR = test
TEST_BINARY=test/test_bitcoin$(EXEEXT)
JSON_TEST_FILES = \
+ test/data/script_tests.json \
test/data/base58_encode_decode.json \
+ test/data/blockfilters.json \
test/data/key_io_valid.json \
test/data/key_io_invalid.json \
test/data/script_tests.json \
@@ -21,9 +51,31 @@ RAW_TEST_FILES =
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
BITCOIN_TEST_SUITE = \
- test/test_bitcoin_main.cpp \
- test/test_bitcoin.h \
- test/test_bitcoin.cpp
+ test/main.cpp \
+ test/setup_common.h \
+ test/setup_common.cpp
+
+FUZZ_SUITE = \
+ test/setup_common.h \
+ test/setup_common.cpp \
+ test/fuzz/fuzz.cpp \
+ test/fuzz/fuzz.h
+
+FUZZ_SUITE_LD_COMMON = \
+ $(LIBBITCOIN_SERVER) \
+ $(LIBBITCOIN_COMMON) \
+ $(LIBBITCOIN_UTIL) \
+ $(LIBBITCOIN_CONSENSUS) \
+ $(LIBBITCOIN_CRYPTO) \
+ $(LIBUNIVALUE) \
+ $(LIBLEVELDB) \
+ $(LIBLEVELDB_SSE42) \
+ $(BOOST_LIBS) \
+ $(LIBMEMENV) \
+ $(LIBSECP256K1) \
+ $(EVENT_LIBS) \
+ $(CRYPTO_LIBS) \
+ $(EVENT_PTHREADS_LIBS)
# test_bitcoin binary #
BITCOIN_TESTS =\
@@ -39,6 +91,8 @@ BITCOIN_TESTS =\
test/bip32_tests.cpp \
test/blockchain_tests.cpp \
test/blockencodings_tests.cpp \
+ test/blockfilter_tests.cpp \
+ test/blockfilter_index_tests.cpp \
test/bloom_tests.cpp \
test/bswap_tests.cpp \
test/checkqueue_tests.cpp \
@@ -48,13 +102,15 @@ BITCOIN_TESTS =\
test/cuckoocache_tests.cpp \
test/denialofservice_tests.cpp \
test/descriptor_tests.cpp \
+ test/flatfile_tests.cpp \
+ test/fs_tests.cpp \
test/getarg_tests.cpp \
test/hash_tests.cpp \
test/key_io_tests.cpp \
test/key_tests.cpp \
test/limitedmap_tests.cpp \
test/dbwrapper_tests.cpp \
- test/main_tests.cpp \
+ test/validation_tests.cpp \
test/mempool_tests.cpp \
test/merkle_tests.cpp \
test/merkleblock_tests.cpp \
@@ -81,6 +137,8 @@ BITCOIN_TESTS =\
test/sigopcount_tests.cpp \
test/skiplist_tests.cpp \
test/streams_tests.cpp \
+ test/sync_tests.cpp \
+ test/util_threadnames_tests.cpp \
test/timedata_tests.cpp \
test/torcontrol_tests.cpp \
test/transaction_tests.cpp \
@@ -92,17 +150,29 @@ BITCOIN_TESTS =\
test/validation_block_tests.cpp \
test/versionbits_tests.cpp
+if ENABLE_PROPERTY_TESTS
+BITCOIN_TESTS += \
+ test/key_properties.cpp
+
+BITCOIN_TEST_SUITE += \
+ test/gen/crypto_gen.cpp \
+ test/gen/crypto_gen.h
+endif
+
if ENABLE_WALLET
BITCOIN_TESTS += \
- wallet/test/accounting_tests.cpp \
+ wallet/test/db_tests.cpp \
wallet/test/psbt_wallet_tests.cpp \
wallet/test/wallet_tests.cpp \
wallet/test/wallet_crypto_tests.cpp \
- wallet/test/coinselector_tests.cpp
+ wallet/test/coinselector_tests.cpp \
+ wallet/test/init_tests.cpp
BITCOIN_TEST_SUITE += \
wallet/test/wallet_test_fixture.cpp \
- wallet/test/wallet_test_fixture.h
+ wallet/test/wallet_test_fixture.h \
+ wallet/test/init_test_fixture.cpp \
+ wallet/test/init_test_fixture.h
endif
test_test_bitcoin_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
@@ -116,44 +186,158 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
+test_test_bitcoin_LDADD += $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS)
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
if ENABLE_ZMQ
-test_test_bitcoin_LDADD += $(ZMQ_LIBS)
+test_test_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
-#
-
-# test_bitcoin_fuzzy binary #
-test_test_bitcoin_fuzzy_SOURCES = test/test_bitcoin_fuzzy.cpp
-test_test_bitcoin_fuzzy_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_test_bitcoin_fuzzy_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_test_bitcoin_fuzzy_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-
-test_test_bitcoin_fuzzy_LDADD = \
- $(LIBUNIVALUE) \
- $(LIBBITCOIN_SERVER) \
- $(LIBBITCOIN_COMMON) \
- $(LIBBITCOIN_UTIL) \
- $(LIBBITCOIN_CONSENSUS) \
- $(LIBBITCOIN_CRYPTO) \
- $(LIBBITCOIN_CRYPTO_SSE41) \
- $(LIBBITCOIN_CRYPTO_AVX2) \
- $(LIBBITCOIN_CRYPTO_SHANI) \
- $(LIBSECP256K1)
-
-test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
-#
+
+if ENABLE_FUZZ
+test_fuzz_block_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_DESERIALIZE=1
+test_fuzz_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_block_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTRANSACTION_DESERIALIZE=1
+test_fuzz_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_blocklocator_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_blocklocator_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKLOCATOR_DESERIALIZE=1
+test_fuzz_blocklocator_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_blocklocator_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blocklocator_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_blockmerkleroot_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_blockmerkleroot_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKMERKLEROOT=1
+test_fuzz_blockmerkleroot_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_blockmerkleroot_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blockmerkleroot_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_addrman_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_addrman_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRMAN_DESERIALIZE=1
+test_fuzz_addrman_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_addrman_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_addrman_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_blockheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_blockheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKHEADER_DESERIALIZE=1
+test_fuzz_blockheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_blockheader_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blockheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_banentry_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_banentry_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBANENTRY_DESERIALIZE=1
+test_fuzz_banentry_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_banentry_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_txundo_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_txundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXUNDO_DESERIALIZE=1
+test_fuzz_txundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_txundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_txundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_blockundo_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_blockundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKUNDO_DESERIALIZE=1
+test_fuzz_blockundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_blockundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blockundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_coins_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_coins_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DCOINS_DESERIALIZE=1
+test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_coins_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_netaddr_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_netaddr_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DNETADDR_DESERIALIZE=1
+test_fuzz_netaddr_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_netaddr_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_script_flags_SOURCES = $(FUZZ_SUITE) test/fuzz/script_flags.cpp
+test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_script_flags_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_flags_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_service_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_service_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSERVICE_DESERIALIZE=1
+test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_service_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_service_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_messageheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_messageheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGEHEADER_DESERIALIZE=1
+test_fuzz_messageheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_messageheader_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_messageheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_address_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_address_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRESS_DESERIALIZE=1
+test_fuzz_address_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_address_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_address_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_inv_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_inv_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DINV_DESERIALIZE=1
+test_fuzz_inv_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_inv_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_inv_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_bloomfilter_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_bloomfilter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOOMFILTER_DESERIALIZE=1
+test_fuzz_bloomfilter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_bloomfilter_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_bloomfilter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_diskblockindex_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_diskblockindex_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DDISKBLOCKINDEX_DESERIALIZE=1
+test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_diskblockindex_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1
+test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_txoutcompressor_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_txoutcompressor_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_blocktransactions_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_blocktransactions_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONS_DESERIALIZE=1
+test_fuzz_blocktransactions_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_blocktransactions_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blocktransactions_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+
+test_fuzz_blocktransactionsrequest_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_blocktransactionsrequest_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONSREQUEST_DESERIALIZE=1
+test_fuzz_blocktransactionsrequest_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blocktransactionsrequest_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
+endif # ENABLE_FUZZ
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
-CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES)
+CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) $(BITCOIN_TESTS:=.log)
CLEANFILES += $(CLEAN_BITCOIN_TEST)
+if TARGET_WINDOWS
bitcoin_test: $(TEST_BINARY)
+else
+if ENABLE_BENCH
+bitcoin_test: $(TEST_BINARY) $(BENCH_BINARY)
+else
+bitcoin_test: $(TEST_BINARY)
+endif
+endif
bitcoin_test_check: $(TEST_BINARY) FORCE
$(MAKE) check-TESTS TESTS=$^
@@ -162,10 +346,19 @@ bitcoin_test_clean : FORCE
rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY)
check-local: $(BITCOIN_TESTS:.cpp=.cpp.test)
+if BUILD_BITCOIN_TX
@echo "Running test/util/bitcoin-util-test.py..."
$(PYTHON) $(top_builddir)/test/util/bitcoin-util-test.py
+endif
@echo "Running test/util/rpcauth-test.py..."
$(PYTHON) $(top_builddir)/test/util/rpcauth-test.py
+if TARGET_WINDOWS
+else
+if ENABLE_BENCH
+ @echo "Running bench/bench_bitcoin -evals=1 -scaling=0..."
+ $(BENCH_BINARY) -evals=1 -scaling=0 > /dev/null
+endif
+endif
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
diff --git a/src/addrdb.cpp b/src/addrdb.cpp
index 59305ff187..c6083f5554 100644
--- a/src/addrdb.cpp
+++ b/src/addrdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <random.h>
#include <streams.h>
#include <tinyformat.h>
-#include <util.h>
+#include <util/system.h>
namespace {
@@ -105,19 +105,18 @@ bool DeserializeFileDB(const fs::path& path, Data& data)
}
-CBanDB::CBanDB()
+CBanDB::CBanDB(fs::path ban_list_path) : m_ban_list_path(std::move(ban_list_path))
{
- pathBanlist = GetDataDir() / "banlist.dat";
}
bool CBanDB::Write(const banmap_t& banSet)
{
- return SerializeFileDB("banlist", pathBanlist, banSet);
+ return SerializeFileDB("banlist", m_ban_list_path, banSet);
}
bool CBanDB::Read(banmap_t& banSet)
{
- return DeserializeFileDB(pathBanlist, banSet);
+ return DeserializeFileDB(m_ban_list_path, banSet);
}
CAddrDB::CAddrDB()
diff --git a/src/addrdb.h b/src/addrdb.h
index e39bd6f5ae..290b63dd12 100644
--- a/src/addrdb.h
+++ b/src/addrdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -43,6 +43,11 @@ public:
nCreateTime = nCreateTimeIn;
}
+ explicit CBanEntry(int64_t n_create_time_in, BanReason ban_reason_in) : CBanEntry(n_create_time_in)
+ {
+ banReason = ban_reason_in;
+ }
+
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
@@ -92,9 +97,9 @@ public:
class CBanDB
{
private:
- fs::path pathBanlist;
+ const fs::path m_ban_list_path;
public:
- CBanDB();
+ explicit CBanDB(fs::path ban_list_path);
bool Write(const banmap_t& banSet);
bool Read(banmap_t& banSet);
};
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 3337ec54db..8a5f78d1c5 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2012 Pieter Wuille
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,22 +11,22 @@
int CAddrInfo::GetTriedBucket(const uint256& nKey) const
{
- uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetHash().GetCheapHash();
- uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetHash().GetCheapHash();
+ uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetCheapHash();
+ uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetCheapHash();
return hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
}
int CAddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src) const
{
std::vector<unsigned char> vchSourceGroupKey = src.GetGroup();
- uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << vchSourceGroupKey).GetHash().GetCheapHash();
- uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetHash().GetCheapHash();
+ uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << vchSourceGroupKey).GetCheapHash();
+ uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetCheapHash();
return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
}
int CAddrInfo::GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
{
- uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << (fNew ? 'N' : 'K') << nBucket << GetKey()).GetHash().GetCheapHash();
+ uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << (fNew ? 'N' : 'K') << nBucket << GetKey()).GetCheapHash();
return hash1 % ADDRMAN_BUCKET_SIZE;
}
@@ -217,7 +217,7 @@ void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime
return;
// find a bucket it is in now
- int nRnd = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
+ int nRnd = insecure_rand.randrange(ADDRMAN_NEW_BUCKET_COUNT);
int nUBucket = -1;
for (unsigned int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT;
@@ -239,7 +239,9 @@ void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime
// Will moving this address into tried evict another entry?
if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
- LogPrint(BCLog::ADDRMAN, "Collision inserting element into tried table, moving %s to m_tried_collisions=%d\n", addr.ToString(), m_tried_collisions.size());
+ // Output the entry we'd be colliding with, for debugging purposes
+ auto colliding_entry = mapInfo.find(vvTried[tried_bucket][tried_bucket_pos]);
+ LogPrint(BCLog::ADDRMAN, "Collision inserting element into tried table (%s), moving %s to m_tried_collisions=%d\n", colliding_entry != mapInfo.end() ? colliding_entry->second.ToString() : "", addr.ToString(), m_tried_collisions.size());
if (m_tried_collisions.size() < ADDRMAN_SET_TRIED_COLLISION_SIZE) {
m_tried_collisions.insert(nId);
}
@@ -291,7 +293,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP
int nFactor = 1;
for (int n = 0; n < pinfo->nRefCount; n++)
nFactor *= 2;
- if (nFactor > 1 && (RandomInt(nFactor) != 0))
+ if (nFactor > 1 && (insecure_rand.randrange(nFactor) != 0))
return false;
} else {
pinfo = Create(addr, source, &nId);
@@ -356,12 +358,12 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
// Use a 50% chance for choosing between tried and new table entries.
if (!newOnly &&
- (nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
+ (nTried > 0 && (nNew == 0 || insecure_rand.randbool() == 0))) {
// use a tried node
double fChanceFactor = 1.0;
while (1) {
- int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT);
- int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
+ int nKBucket = insecure_rand.randrange(ADDRMAN_TRIED_BUCKET_COUNT);
+ int nKBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
while (vvTried[nKBucket][nKBucketPos] == -1) {
nKBucket = (nKBucket + insecure_rand.randbits(ADDRMAN_TRIED_BUCKET_COUNT_LOG2)) % ADDRMAN_TRIED_BUCKET_COUNT;
nKBucketPos = (nKBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE;
@@ -369,7 +371,7 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
int nId = vvTried[nKBucket][nKBucketPos];
assert(mapInfo.count(nId) == 1);
CAddrInfo& info = mapInfo[nId];
- if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
+ if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30))
return info;
fChanceFactor *= 1.2;
}
@@ -377,8 +379,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
// use a new node
double fChanceFactor = 1.0;
while (1) {
- int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
- int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
+ int nUBucket = insecure_rand.randrange(ADDRMAN_NEW_BUCKET_COUNT);
+ int nUBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
while (vvNew[nUBucket][nUBucketPos] == -1) {
nUBucket = (nUBucket + insecure_rand.randbits(ADDRMAN_NEW_BUCKET_COUNT_LOG2)) % ADDRMAN_NEW_BUCKET_COUNT;
nUBucketPos = (nUBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE;
@@ -386,7 +388,7 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
int nId = vvNew[nUBucket][nUBucketPos];
assert(mapInfo.count(nId) == 1);
CAddrInfo& info = mapInfo[nId];
- if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
+ if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30))
return info;
fChanceFactor *= 1.2;
}
@@ -482,7 +484,7 @@ void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr)
if (vAddr.size() >= nNodes)
break;
- int nRndPos = RandomInt(vRandom.size() - n) + n;
+ int nRndPos = insecure_rand.randrange(vRandom.size() - n) + n;
SwapRandom(n, nRndPos);
assert(mapInfo.count(vRandom[n]) == 1);
@@ -530,10 +532,6 @@ void CAddrMan::SetServices_(const CService& addr, ServiceFlags nServices)
info.nServices = nServices;
}
-int CAddrMan::RandomInt(int nMax){
- return GetRandInt(nMax);
-}
-
void CAddrMan::ResolveCollisions_()
{
for (std::set<int>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
@@ -565,12 +563,19 @@ void CAddrMan::ResolveCollisions_()
// Give address at least 60 seconds to successfully connect
if (GetAdjustedTime() - info_old.nLastTry > 60) {
- LogPrint(BCLog::ADDRMAN, "Swapping %s for %s in tried table\n", info_new.ToString(), info_old.ToString());
+ LogPrint(BCLog::ADDRMAN, "Replacing %s with %s in tried table\n", info_old.ToString(), info_new.ToString());
// Replaces an existing address already in the tried table with the new address
Good_(info_new, false, GetAdjustedTime());
erase_collision = true;
}
+ } else if (GetAdjustedTime() - info_new.nLastSuccess > ADDRMAN_TEST_WINDOW) {
+ // If the collision hasn't resolved in some reasonable amount of time,
+ // just evict the old entry -- we must not be able to
+ // connect to it for some reason.
+ LogPrint(BCLog::ADDRMAN, "Unable to test; replacing %s with %s in tried table anyway\n", info_old.ToString(), info_new.ToString());
+ Good_(info_new, false, GetAdjustedTime());
+ erase_collision = true;
}
} else { // Collision is not actually a collision anymore
Good_(info_new, false, GetAdjustedTime());
@@ -593,7 +598,7 @@ CAddrInfo CAddrMan::SelectTriedCollision_()
std::set<int>::iterator it = m_tried_collisions.begin();
// Selects a random element from m_tried_collisions
- std::advance(it, GetRandInt(m_tried_collisions.size()));
+ std::advance(it, insecure_rand.randrange(m_tried_collisions.size()));
int id_new = *it;
// If id_new not found in mapInfo remove it from m_tried_collisions
diff --git a/src/addrman.h b/src/addrman.h
index dc8ef8375b..e54184ce35 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -1,5 +1,5 @@
// Copyright (c) 2012 Pieter Wuille
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,7 @@
#include <random.h>
#include <sync.h>
#include <timedata.h>
-#include <util.h>
+#include <util/system.h>
#include <map>
#include <set>
@@ -23,33 +23,31 @@
*/
class CAddrInfo : public CAddress
{
-
-
public:
//! last try whatsoever by us (memory only)
- int64_t nLastTry;
+ int64_t nLastTry{0};
//! last counted attempt (memory only)
- int64_t nLastCountAttempt;
+ int64_t nLastCountAttempt{0};
private:
//! where knowledge about this address first came from
CNetAddr source;
//! last successful connection by us
- int64_t nLastSuccess;
+ int64_t nLastSuccess{0};
//! connection attempts since last successful attempt
- int nAttempts;
+ int nAttempts{0};
//! reference count in new sets (memory only)
- int nRefCount;
+ int nRefCount{0};
//! in tried set? (memory only)
- bool fInTried;
+ bool fInTried{false};
//! position in vRandom
- int nRandomPos;
+ int nRandomPos{-1};
friend class CAddrMan;
@@ -65,25 +63,12 @@ public:
READWRITE(nAttempts);
}
- void Init()
- {
- nLastSuccess = 0;
- nLastTry = 0;
- nLastCountAttempt = 0;
- nAttempts = 0;
- nRefCount = 0;
- fInTried = false;
- nRandomPos = -1;
- }
-
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
{
- Init();
}
CAddrInfo() : CAddress(), source()
{
- Init();
}
//! Calculate in which "tried" bucket this entry belongs
@@ -106,7 +91,6 @@ public:
//! Calculate the relative chance this entry should be given when selecting nodes to connect to
double GetChance(int64_t nNow = GetAdjustedTime()) const;
-
};
/** Stochastic address manager
@@ -182,41 +166,45 @@ public:
//! the maximum number of tried addr collisions to store
#define ADDRMAN_SET_TRIED_COLLISION_SIZE 10
+//! the maximum time we'll spend trying to resolve a tried table collision, in seconds
+static const int64_t ADDRMAN_TEST_WINDOW = 40*60; // 40 minutes
+
/**
* Stochastical (IP) address manager
*/
class CAddrMan
{
-private:
+protected:
//! critical section to protect the inner data structures
mutable CCriticalSection cs;
+private:
//! last used nId
- int nIdCount;
+ int nIdCount GUARDED_BY(cs);
//! table with information about all nIds
- std::map<int, CAddrInfo> mapInfo;
+ std::map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
//! find an nId based on its network address
- std::map<CNetAddr, int> mapAddr;
+ std::map<CNetAddr, int> mapAddr GUARDED_BY(cs);
//! randomly-ordered vector of all nIds
- std::vector<int> vRandom;
+ std::vector<int> vRandom GUARDED_BY(cs);
// number of "tried" entries
- int nTried;
+ int nTried GUARDED_BY(cs);
//! list of "tried" buckets
- int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE];
+ int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
//! number of (unique) "new" entries
- int nNew;
+ int nNew GUARDED_BY(cs);
//! list of "new" buckets
- int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE];
+ int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
//! last time Good was called (memory only)
- int64_t nLastGood;
+ int64_t nLastGood GUARDED_BY(cs);
//! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
std::set<int> m_tried_collisions;
@@ -229,58 +217,55 @@ protected:
FastRandomContext insecure_rand;
//! Find an entry.
- CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr);
+ CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! find an entry, creating it if necessary.
//! nTime and nServices of the found node are updated, if necessary.
- CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = nullptr);
+ CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Swap two elements in vRandom.
- void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2);
+ void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Move an entry from the "new" table(s) to the "tried" table
- void MakeTried(CAddrInfo& info, int nId);
+ void MakeTried(CAddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Delete an entry. It must not be in tried, and have refcount 0.
- void Delete(int nId);
+ void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Clear a position in a "new" table. This is the only place where entries are actually deleted.
- void ClearNew(int nUBucket, int nUBucketPos);
+ void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Mark an entry "good", possibly moving it from "new" to "tried".
- void Good_(const CService &addr, bool test_before_evict, int64_t time);
+ void Good_(const CService &addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Add an entry to the "new" table.
- bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty);
+ bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Mark an entry as attempted to connect.
- void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime);
+ void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Select an address to connect to, if newOnly is set to true, only the new table is selected from.
- CAddrInfo Select_(bool newOnly);
+ CAddrInfo Select_(bool newOnly) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
- void ResolveCollisions_();
+ void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Return a random to-be-evicted tried table address.
- CAddrInfo SelectTriedCollision_();
-
- //! Wraps GetRandInt to allow tests to override RandomInt and make it determinismistic.
- virtual int RandomInt(int nMax);
+ CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
#ifdef DEBUG_ADDRMAN
//! Perform consistency check. Returns an error code or zero.
- int Check_();
+ int Check_() EXCLUSIVE_LOCKS_REQUIRED(cs);
#endif
//! Select several addresses at once.
- void GetAddr_(std::vector<CAddress> &vAddr);
+ void GetAddr_(std::vector<CAddress> &vAddr) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Mark an entry as currently-connected-to.
- void Connected_(const CService &addr, int64_t nTime);
+ void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Update an entry's service bits.
- void SetServices_(const CService &addr, ServiceFlags nServices);
+ void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
public:
/**
@@ -472,7 +457,7 @@ public:
{
LOCK(cs);
std::vector<int>().swap(vRandom);
- nKey = GetRandHash();
+ nKey = insecure_rand.rand256();
for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
vvNew[bucket][entry] = -1;
diff --git a/src/amount.h b/src/amount.h
index 2bd367cba2..47968e80b1 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2016 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,6 @@
typedef int64_t CAmount;
static const CAmount COIN = 100000000;
-static const CAmount CENT = 1000000;
/** No amount larger than this (in satoshi) is valid.
*
diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp
index c7ddb17eb0..aa66d13102 100644
--- a/src/arith_uint256.cpp
+++ b/src/arith_uint256.cpp
@@ -1,12 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <arith_uint256.h>
#include <uint256.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <crypto/common.h>
#include <stdio.h>
@@ -176,7 +176,7 @@ unsigned int base_uint<BITS>::bits() const
for (int pos = WIDTH - 1; pos >= 0; pos--) {
if (pn[pos]) {
for (int nbits = 31; nbits > 0; nbits--) {
- if (pn[pos] & 1 << nbits)
+ if (pn[pos] & 1U << nbits)
return 32 * pos + nbits + 1;
}
return 32 * pos + 1;
diff --git a/src/arith_uint256.h b/src/arith_uint256.h
index e4c7575e2d..bd0360087d 100644
--- a/src/arith_uint256.h
+++ b/src/arith_uint256.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,6 +8,7 @@
#include <assert.h>
#include <cstring>
+#include <limits>
#include <stdexcept>
#include <stdint.h>
#include <string>
@@ -189,7 +190,7 @@ public:
{
// prefix operator
int i = 0;
- while (i < WIDTH && --pn[i] == (uint32_t)-1)
+ while (i < WIDTH && --pn[i] == std::numeric_limits<uint32_t>::max())
i++;
return *this;
}
diff --git a/src/attributes.h b/src/attributes.h
new file mode 100644
index 0000000000..45099bd8b8
--- /dev/null
+++ b/src/attributes.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_ATTRIBUTES_H
+#define BITCOIN_ATTRIBUTES_H
+
+#if defined(__has_cpp_attribute)
+# if __has_cpp_attribute(nodiscard)
+# define NODISCARD [[nodiscard]]
+# endif
+#endif
+#ifndef NODISCARD
+# if defined(_MSC_VER) && _MSC_VER >= 1700
+# define NODISCARD _Check_return_
+# else
+# define NODISCARD __attribute__((warn_unused_result))
+# endif
+#endif
+
+#endif // BITCOIN_ATTRIBUTES_H
diff --git a/src/banman.cpp b/src/banman.cpp
new file mode 100644
index 0000000000..47d64a8f31
--- /dev/null
+++ b/src/banman.cpp
@@ -0,0 +1,220 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2017 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 <banman.h>
+
+#include <netaddress.h>
+#include <ui_interface.h>
+#include <util/system.h>
+#include <util/time.h>
+
+
+BanMan::BanMan(fs::path ban_file, CClientUIInterface* client_interface, int64_t default_ban_time)
+ : m_client_interface(client_interface), m_ban_db(std::move(ban_file)), m_default_ban_time(default_ban_time)
+{
+ if (m_client_interface) m_client_interface->InitMessage(_("Loading banlist..."));
+
+ int64_t n_start = GetTimeMillis();
+ m_is_dirty = false;
+ banmap_t banmap;
+ if (m_ban_db.Read(banmap)) {
+ SetBanned(banmap); // thread save setter
+ SetBannedSetDirty(false); // no need to write down, just read data
+ SweepBanned(); // sweep out unused entries
+
+ LogPrint(BCLog::NET, "Loaded %d banned node ips/subnets from banlist.dat %dms\n",
+ banmap.size(), GetTimeMillis() - n_start);
+ } else {
+ LogPrintf("Invalid or missing banlist.dat; recreating\n");
+ SetBannedSetDirty(true); // force write
+ DumpBanlist();
+ }
+}
+
+BanMan::~BanMan()
+{
+ DumpBanlist();
+}
+
+void BanMan::DumpBanlist()
+{
+ SweepBanned(); // clean unused entries (if bantime has expired)
+
+ if (!BannedSetIsDirty()) return;
+
+ int64_t n_start = GetTimeMillis();
+
+ banmap_t banmap;
+ GetBanned(banmap);
+ if (m_ban_db.Write(banmap)) {
+ SetBannedSetDirty(false);
+ }
+
+ LogPrint(BCLog::NET, "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
+ banmap.size(), GetTimeMillis() - n_start);
+}
+
+void BanMan::ClearBanned()
+{
+ {
+ LOCK(m_cs_banned);
+ m_banned.clear();
+ m_is_dirty = true;
+ }
+ DumpBanlist(); //store banlist to disk
+ if (m_client_interface) m_client_interface->BannedListChanged();
+}
+
+int BanMan::IsBannedLevel(CNetAddr net_addr)
+{
+ // Returns the most severe level of banning that applies to this address.
+ // 0 - Not banned
+ // 1 - Automatic misbehavior ban
+ // 2 - Any other ban
+ int level = 0;
+ auto current_time = GetTime();
+ LOCK(m_cs_banned);
+ for (const auto& it : m_banned) {
+ CSubNet sub_net = it.first;
+ CBanEntry ban_entry = it.second;
+
+ if (current_time < ban_entry.nBanUntil && sub_net.Match(net_addr)) {
+ if (ban_entry.banReason != BanReasonNodeMisbehaving) return 2;
+ level = 1;
+ }
+ }
+ return level;
+}
+
+bool BanMan::IsBanned(CNetAddr net_addr)
+{
+ auto current_time = GetTime();
+ LOCK(m_cs_banned);
+ for (const auto& it : m_banned) {
+ CSubNet sub_net = it.first;
+ CBanEntry ban_entry = it.second;
+
+ if (current_time < ban_entry.nBanUntil && sub_net.Match(net_addr)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BanMan::IsBanned(CSubNet sub_net)
+{
+ auto current_time = GetTime();
+ LOCK(m_cs_banned);
+ banmap_t::iterator i = m_banned.find(sub_net);
+ if (i != m_banned.end()) {
+ CBanEntry ban_entry = (*i).second;
+ if (current_time < ban_entry.nBanUntil) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void BanMan::Ban(const CNetAddr& net_addr, const BanReason& ban_reason, int64_t ban_time_offset, bool since_unix_epoch)
+{
+ CSubNet sub_net(net_addr);
+ Ban(sub_net, ban_reason, ban_time_offset, since_unix_epoch);
+}
+
+void BanMan::Ban(const CSubNet& sub_net, const BanReason& ban_reason, int64_t ban_time_offset, bool since_unix_epoch)
+{
+ CBanEntry ban_entry(GetTime(), ban_reason);
+
+ int64_t normalized_ban_time_offset = ban_time_offset;
+ bool normalized_since_unix_epoch = since_unix_epoch;
+ if (ban_time_offset <= 0) {
+ normalized_ban_time_offset = m_default_ban_time;
+ normalized_since_unix_epoch = false;
+ }
+ ban_entry.nBanUntil = (normalized_since_unix_epoch ? 0 : GetTime()) + normalized_ban_time_offset;
+
+ {
+ LOCK(m_cs_banned);
+ if (m_banned[sub_net].nBanUntil < ban_entry.nBanUntil) {
+ m_banned[sub_net] = ban_entry;
+ m_is_dirty = true;
+ } else
+ return;
+ }
+ if (m_client_interface) m_client_interface->BannedListChanged();
+
+ //store banlist to disk immediately if user requested ban
+ if (ban_reason == BanReasonManuallyAdded) DumpBanlist();
+}
+
+bool BanMan::Unban(const CNetAddr& net_addr)
+{
+ CSubNet sub_net(net_addr);
+ return Unban(sub_net);
+}
+
+bool BanMan::Unban(const CSubNet& sub_net)
+{
+ {
+ LOCK(m_cs_banned);
+ if (m_banned.erase(sub_net) == 0) return false;
+ m_is_dirty = true;
+ }
+ if (m_client_interface) m_client_interface->BannedListChanged();
+ DumpBanlist(); //store banlist to disk immediately
+ return true;
+}
+
+void BanMan::GetBanned(banmap_t& banmap)
+{
+ LOCK(m_cs_banned);
+ // Sweep the banlist so expired bans are not returned
+ SweepBanned();
+ banmap = m_banned; //create a thread safe copy
+}
+
+void BanMan::SetBanned(const banmap_t& banmap)
+{
+ LOCK(m_cs_banned);
+ m_banned = banmap;
+ m_is_dirty = true;
+}
+
+void BanMan::SweepBanned()
+{
+ int64_t now = GetTime();
+ bool notify_ui = false;
+ {
+ LOCK(m_cs_banned);
+ banmap_t::iterator it = m_banned.begin();
+ while (it != m_banned.end()) {
+ CSubNet sub_net = (*it).first;
+ CBanEntry ban_entry = (*it).second;
+ if (now > ban_entry.nBanUntil) {
+ m_banned.erase(it++);
+ m_is_dirty = true;
+ notify_ui = true;
+ LogPrint(BCLog::NET, "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, sub_net.ToString());
+ } else
+ ++it;
+ }
+ }
+ // update UI
+ if (notify_ui && m_client_interface) {
+ m_client_interface->BannedListChanged();
+ }
+}
+
+bool BanMan::BannedSetIsDirty()
+{
+ LOCK(m_cs_banned);
+ return m_is_dirty;
+}
+
+void BanMan::SetBannedSetDirty(bool dirty)
+{
+ LOCK(m_cs_banned); //reuse m_banned lock for the m_is_dirty flag
+ m_is_dirty = dirty;
+}
diff --git a/src/banman.h b/src/banman.h
new file mode 100644
index 0000000000..a1a00309dd
--- /dev/null
+++ b/src/banman.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2017 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
+#define BITCOIN_BANMAN_H
+
+#include <cstdint>
+#include <memory>
+
+#include <addrdb.h>
+#include <fs.h>
+#include <sync.h>
+
+// NOTE: When adjusting this, update rpcnet:setban's help ("24h")
+static constexpr unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Default 24-hour ban
+
+class CClientUIInterface;
+class CNetAddr;
+class CSubNet;
+
+// Denial-of-service detection/prevention
+// The idea is to detect peers that are behaving
+// badly and disconnect/ban them, but do it in a
+// one-coding-mistake-won't-shatter-the-entire-network
+// way.
+// IMPORTANT: There should be nothing I can give a
+// node that it will forward on that will make that
+// node's peers drop it. If there is, an attacker
+// can isolate a node and/or try to split the network.
+// Dropping a node for sending stuff that is invalid
+// now but might be valid in a later version is also
+// dangerous, because it can cause a network split
+// between nodes running old code and nodes running
+// new code.
+
+class BanMan
+{
+public:
+ ~BanMan();
+ BanMan(fs::path ban_file, CClientUIInterface* client_interface, int64_t default_ban_time);
+ void Ban(const CNetAddr& net_addr, const BanReason& ban_reason, int64_t ban_time_offset = 0, bool since_unix_epoch = false);
+ void Ban(const CSubNet& sub_net, const BanReason& ban_reason, int64_t ban_time_offset = 0, bool since_unix_epoch = false);
+ void ClearBanned();
+ int IsBannedLevel(CNetAddr net_addr);
+ bool IsBanned(CNetAddr net_addr);
+ bool IsBanned(CSubNet sub_net);
+ bool Unban(const CNetAddr& net_addr);
+ bool Unban(const CSubNet& sub_net);
+ void GetBanned(banmap_t& banmap);
+ void DumpBanlist();
+
+private:
+ void SetBanned(const banmap_t& banmap);
+ bool BannedSetIsDirty();
+ //!set the "dirty" flag for the banlist
+ void SetBannedSetDirty(bool dirty = true);
+ //!clean unused entries (if bantime has expired)
+ void SweepBanned();
+
+ CCriticalSection m_cs_banned;
+ banmap_t m_banned GUARDED_BY(m_cs_banned);
+ bool m_is_dirty GUARDED_BY(m_cs_banned);
+ CClientUIInterface* m_client_interface = nullptr;
+ CBanDB m_ban_db;
+ const int64_t m_default_ban_time;
+};
+
+extern std::unique_ptr<BanMan> g_banman;
+#endif
diff --git a/src/base58.cpp b/src/base58.cpp
index feec2d4e05..e3d2853399 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,6 +6,7 @@
#include <hash.h>
#include <uint256.h>
+#include <util/strencodings.h>
#include <assert.h>
#include <string.h>
@@ -34,7 +35,7 @@ static const int8_t mapBase58[256] = {
bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
{
// Skip leading spaces.
- while (*psz && isspace(*psz))
+ while (*psz && IsSpace(*psz))
psz++;
// Skip and count leading '1's.
int zeroes = 0;
@@ -48,7 +49,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
std::vector<unsigned char> b256(size);
// Process the characters.
static_assert(sizeof(mapBase58)/sizeof(mapBase58[0]) == 256, "mapBase58.size() should be 256"); // guarantee not out of range
- while (*psz && !isspace(*psz)) {
+ while (*psz && !IsSpace(*psz)) {
// Decode base58 character
int carry = mapBase58[(uint8_t)*psz];
if (carry == -1) // Invalid b58 character
@@ -64,7 +65,7 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
psz++;
}
// Skip trailing spaces.
- while (isspace(*psz))
+ while (IsSpace(*psz))
psz++;
if (*psz != 0)
return false;
diff --git a/src/base58.h b/src/base58.h
index 8f2833bec9..d6e0299a1e 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,6 +14,8 @@
#ifndef BITCOIN_BASE58_H
#define BITCOIN_BASE58_H
+#include <attributes.h>
+
#include <string>
#include <vector>
@@ -33,13 +35,13 @@ std::string EncodeBase58(const std::vector<unsigned char>& vch);
* return true if decoding is successful.
* psz cannot be nullptr.
*/
-bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet);
+NODISCARD bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet);
/**
* Decode a base58-encoded string (str) into a byte vector (vchRet).
* return true if decoding is successful.
*/
-bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet);
+NODISCARD bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet);
/**
* Encode a byte vector into a base58-encoded string, including checksum
@@ -50,12 +52,12 @@ std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn);
* Decode a base58-encoded string (psz) that includes a checksum into a byte
* vector (vchRet), return true if decoding is successful
*/
-bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet);
+NODISCARD bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet);
/**
* Decode a base58-encoded string (str) that includes a checksum into a byte
* vector (vchRet), return true if decoding is successful
*/
-bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
+NODISCARD bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
#endif // BITCOIN_BASE58_H
diff --git a/src/bech32.cpp b/src/bech32.cpp
index c55f22b9b7..d6b29391a9 100644
--- a/src/bech32.cpp
+++ b/src/bech32.cpp
@@ -62,7 +62,7 @@ uint32_t PolyMod(const data& v)
// v, it corresponds to x^2 + v0*x + v1 mod g(x). As 1 mod g(x) = 1, that is the starting value
// for `c`.
uint32_t c = 1;
- for (auto v_i : v) {
+ for (const auto v_i : v) {
// We want to update `c` to correspond to a polynomial with one extra term. If the initial
// value of `c` consists of the coefficients of c(x) = f(x) mod g(x), we modify it to
// correspond to c'(x) = (f(x) * x + v_i) mod g(x), where v_i is the next input to
@@ -149,7 +149,7 @@ std::string Encode(const std::string& hrp, const data& values) {
data combined = Cat(values, checksum);
std::string ret = hrp + '1';
ret.reserve(ret.size() + combined.size());
- for (auto c : combined) {
+ for (const auto c : combined) {
ret += CHARSET[c];
}
return ret;
diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp
index 70bfd7d0bf..e7702ec461 100644
--- a/src/bench/base58.cpp
+++ b/src/bench/base58.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -49,7 +49,7 @@ static void Base58Decode(benchmark::State& state)
const char* addr = "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem";
std::vector<unsigned char> vch;
while (state.KeepRunning()) {
- DecodeBase58(addr, vch);
+ (void) DecodeBase58(addr, vch);
}
}
diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp
index 8b80e17391..3c4b453a23 100644
--- a/src/bench/bech32.cpp
+++ b/src/bench/bech32.cpp
@@ -6,7 +6,7 @@
#include <validation.h>
#include <bech32.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <vector>
#include <string>
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index de3e57b04f..f2b520e893 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -1,15 +1,19 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
+#include <chainparams.h>
+#include <test/setup_common.h>
+#include <validation.h>
+
+#include <algorithm>
#include <assert.h>
-#include <iostream>
#include <iomanip>
-#include <algorithm>
-#include <regex>
+#include <iostream>
#include <numeric>
+#include <regex>
void benchmark::ConsolePrinter::header()
{
@@ -108,6 +112,14 @@ void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double
printer.header();
for (const auto& p : benchmarks()) {
+ TestingSetup test{CBaseChainParams::REGTEST};
+ {
+ LOCK(cs_main);
+ assert(::ChainActive().Height() == 0);
+ const bool witness_enabled{IsWitnessEnabled(::ChainActive().Tip(), Params().GetConsensus())};
+ assert(witness_enabled);
+ }
+
if (!std::regex_match(p.first, baseMatch, reFilter)) {
continue;
}
diff --git a/src/bench/bench.h b/src/bench/bench.h
index 5d131c2aa8..35eeab3393 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index 92befdd593..3cf0bf9530 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,10 +6,8 @@
#include <crypto/sha256.h>
#include <key.h>
-#include <random.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#include <validation.h>
+#include <util/strencodings.h>
+#include <util/system.h>
#include <memory>
@@ -23,7 +21,8 @@ static const int64_t DEFAULT_PLOT_HEIGHT = 768;
static void SetupBenchArgs()
{
- gArgs.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
+ SetupHelpOptions(gArgs);
+
gArgs.AddArg("-list", "List benchmarks without executing them. Can be combined with -scaling and -filter", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-evals=<n>", strprintf("Number of measurement evaluations to perform. (default: %u)", DEFAULT_BENCH_EVALUATIONS), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), false, OptionsCategory::OPTIONS);
@@ -32,18 +31,6 @@ static void SetupBenchArgs()
gArgs.AddArg("-plot-plotlyurl=<uri>", strprintf("URL to use for plotly.js (default: %s)", DEFAULT_PLOT_PLOTLYURL), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-plot-width=<x>", strprintf("Plot width in pixel (default: %u)", DEFAULT_PLOT_WIDTH), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-plot-height=<x>", strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), false, OptionsCategory::OPTIONS);
-
- // Hidden
- gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
-}
-
-static fs::path SetDataDir()
-{
- fs::path ret = fs::temp_directory_path() / "bench_bitcoin" / fs::unique_path();
- fs::create_directories(ret);
- gArgs.ForceSetArg("-datadir", ret.string());
- return ret;
}
int main(int argc, char** argv)
@@ -61,14 +48,6 @@ int main(int argc, char** argv)
return EXIT_SUCCESS;
}
- // Set the datadir after parsing the bench options
- const fs::path bench_datadir{SetDataDir()};
-
- SHA256AutoDetect();
- RandomInit();
- ECC_Start();
- SetupEnvironment();
-
int64_t evaluations = gArgs.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS);
std::string regex_filter = gArgs.GetArg("-filter", DEFAULT_BENCH_FILTER);
std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING);
@@ -80,7 +59,7 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
- std::unique_ptr<benchmark::Printer> printer(new benchmark::ConsolePrinter());
+ std::unique_ptr<benchmark::Printer> printer = MakeUnique<benchmark::ConsolePrinter>();
std::string printer_arg = gArgs.GetArg("-printer", DEFAULT_BENCH_PRINTER);
if ("plot" == printer_arg) {
printer.reset(new benchmark::PlotlyPrinter(
@@ -91,9 +70,5 @@ int main(int argc, char** argv)
benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, regex_filter, is_list_only);
- fs::remove_all(bench_datadir);
-
- ECC_Stop();
-
return EXIT_SUCCESS;
}
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index 9b53c6b023..fb33c09ab2 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -1,56 +1,18 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
-#include <chainparams.h>
-#include <coins.h>
-#include <consensus/merkle.h>
#include <consensus/validation.h>
-#include <miner.h>
-#include <policy/policy.h>
-#include <pow.h>
-#include <scheduler.h>
-#include <txdb.h>
+#include <crypto/sha256.h>
+#include <test/util.h>
#include <txmempool.h>
-#include <utiltime.h>
#include <validation.h>
-#include <validationinterface.h>
-#include <boost/thread.hpp>
#include <list>
#include <vector>
-static std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
-{
- auto block = std::make_shared<CBlock>(
- BlockAssembler{Params()}
- .CreateNewBlock(coinbase_scriptPubKey, /* fMineWitnessTx */ true)
- ->block);
-
- block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
- block->hashMerkleRoot = BlockMerkleRoot(*block);
-
- return block;
-}
-
-
-static CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
-{
- auto block = PrepareBlock(coinbase_scriptPubKey);
-
- while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
- assert(++block->nNonce);
- }
-
- bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
- assert(processed);
-
- return CTxIn{block->vtx[0]->GetHash(), 0};
-}
-
-
static void AssembleBlock(benchmark::State& state)
{
const std::vector<unsigned char> op_true{OP_TRUE};
@@ -62,30 +24,6 @@ static void AssembleBlock(benchmark::State& state)
const CScript SCRIPT_PUB{CScript(OP_0) << std::vector<unsigned char>{witness_program.begin(), witness_program.end()}};
- // Switch to regtest so we can mine faster
- // Also segwit is active, so we can include witness transactions
- SelectParams(CBaseChainParams::REGTEST);
-
- InitScriptExecutionCache();
-
- boost::thread_group thread_group;
- CScheduler scheduler;
- {
- ::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
- ::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
- ::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
-
- const CChainParams& chainparams = Params();
- thread_group.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
- GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
- LoadGenesisBlock(chainparams);
- CValidationState state;
- ActivateBestChain(state, chainparams);
- assert(::chainActive.Tip() != nullptr);
- const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())};
- assert(witness_enabled);
- }
-
// Collect some loose transactions that spend the coinbases of our mined blocks
constexpr size_t NUM_BLOCKS{200};
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
@@ -110,11 +48,6 @@ static void AssembleBlock(benchmark::State& state)
while (state.KeepRunning()) {
PrepareBlock(SCRIPT_PUB);
}
-
- thread_group.interrupt_all();
- thread_group.join_all();
- GetMainSignals().FlushBackgroundCallbacks();
- GetMainSignals().UnregisterBackgroundSignalScheduler();
}
BENCHMARK(AssembleBlock, 700);
diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp
index 74169bcad7..1041a22303 100644
--- a/src/bench/ccoins_caching.cpp
+++ b/src/bench/ccoins_caching.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,8 +12,8 @@
// FIXME: Dedup with SetupDummyInputs in test/transaction_tests.cpp.
//
// Helper: create two dummy transactions, each with
-// two outputs. The first has 11 and 50 CENT outputs
-// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
+// two outputs. The first has 11 and 50 COIN outputs
+// paid to a TX_PUBKEY, the second 21 and 22 COIN outputs
// paid to a TX_PUBKEYHASH.
//
static std::vector<CMutableTransaction>
@@ -31,18 +31,18 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet)
// Create some dummy input transactions
dummyTransactions[0].vout.resize(2);
- dummyTransactions[0].vout[0].nValue = 11 * CENT;
+ dummyTransactions[0].vout[0].nValue = 11 * COIN;
dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
- dummyTransactions[0].vout[1].nValue = 50 * CENT;
+ dummyTransactions[0].vout[1].nValue = 50 * COIN;
dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
- AddCoins(coinsRet, dummyTransactions[0], 0);
+ AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
dummyTransactions[1].vout.resize(2);
- dummyTransactions[1].vout[0].nValue = 21 * CENT;
- dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID());
- dummyTransactions[1].vout[1].nValue = 22 * CENT;
- dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID());
- AddCoins(coinsRet, dummyTransactions[1], 0);
+ dummyTransactions[1].vout[0].nValue = 21 * COIN;
+ dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey()));
+ dummyTransactions[1].vout[1].nValue = 22 * COIN;
+ dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey()));
+ AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
return dummyTransactions;
}
@@ -72,15 +72,16 @@ static void CCoinsCaching(benchmark::State& state)
t1.vin[2].prevout.n = 1;
t1.vin[2].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
t1.vout.resize(2);
- t1.vout[0].nValue = 90 * CENT;
+ t1.vout[0].nValue = 90 * COIN;
t1.vout[0].scriptPubKey << OP_1;
// Benchmark.
+ const CTransaction tx_1(t1);
while (state.KeepRunning()) {
- bool success = AreInputsStandard(t1, coins);
+ bool success = AreInputsStandard(tx_1, coins);
assert(success);
- CAmount value = coins.GetValueIn(t1);
- assert(value == (50 + 21 + 22) * CENT);
+ CAmount value = coins.GetValueIn(tx_1);
+ assert(value == (50 + 21 + 22) * COIN);
}
}
diff --git a/src/bench/chacha20.cpp b/src/bench/chacha20.cpp
new file mode 100644
index 0000000000..69d8c96ec0
--- /dev/null
+++ b/src/bench/chacha20.cpp
@@ -0,0 +1,46 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <iostream>
+
+#include <bench/bench.h>
+#include <hash.h>
+#include <crypto/chacha20.h>
+
+/* Number of bytes to process per iteration */
+static const uint64_t BUFFER_SIZE_TINY = 64;
+static const uint64_t BUFFER_SIZE_SMALL = 256;
+static const uint64_t BUFFER_SIZE_LARGE = 1024*1024;
+
+static void CHACHA20(benchmark::State& state, size_t buffersize)
+{
+ std::vector<uint8_t> key(32,0);
+ ChaCha20 ctx(key.data(), key.size());
+ ctx.SetIV(0);
+ ctx.Seek(0);
+ std::vector<uint8_t> in(buffersize,0);
+ std::vector<uint8_t> out(buffersize,0);
+ while (state.KeepRunning()) {
+ ctx.Crypt(in.data(), out.data(), in.size());
+ }
+}
+
+static void CHACHA20_64BYTES(benchmark::State& state)
+{
+ CHACHA20(state, BUFFER_SIZE_TINY);
+}
+
+static void CHACHA20_256BYTES(benchmark::State& state)
+{
+ CHACHA20(state, BUFFER_SIZE_SMALL);
+}
+
+static void CHACHA20_1MB(benchmark::State& state)
+{
+ CHACHA20(state, BUFFER_SIZE_LARGE);
+}
+
+BENCHMARK(CHACHA20_64BYTES, 500000);
+BENCHMARK(CHACHA20_256BYTES, 250000);
+BENCHMARK(CHACHA20_1MB, 340);
diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp
index fac7e079a7..e325333c01 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -20,7 +20,7 @@ namespace block_bench {
static void DeserializeBlockTest(benchmark::State& state)
{
CDataStream stream((const char*)block_bench::block413567,
- (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
+ (const char*)block_bench::block413567 + sizeof(block_bench::block413567),
SER_NETWORK, PROTOCOL_VERSION);
char a = '\0';
stream.write(&a, 1); // Prevent compaction
@@ -28,14 +28,15 @@ static void DeserializeBlockTest(benchmark::State& state)
while (state.KeepRunning()) {
CBlock block;
stream >> block;
- assert(stream.Rewind(sizeof(block_bench::block413567)));
+ bool rewound = stream.Rewind(sizeof(block_bench::block413567));
+ assert(rewound);
}
}
static void DeserializeAndCheckBlockTest(benchmark::State& state)
{
CDataStream stream((const char*)block_bench::block413567,
- (const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
+ (const char*)block_bench::block413567 + sizeof(block_bench::block413567),
SER_NETWORK, PROTOCOL_VERSION);
char a = '\0';
stream.write(&a, 1); // Prevent compaction
@@ -45,10 +46,12 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state)
while (state.KeepRunning()) {
CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
stream >> block;
- assert(stream.Rewind(sizeof(block_bench::block413567)));
+ bool rewound = stream.Rewind(sizeof(block_bench::block413567));
+ assert(rewound);
CValidationState validationState;
- assert(CheckBlock(block, validationState, chainParams->GetConsensus()));
+ bool checked = CheckBlock(block, validationState, chainParams->GetConsensus());
+ assert(checked);
}
}
diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp
index 6e816f1bec..6ab542067a 100644
--- a/src/bench/checkqueue.cpp
+++ b/src/bench/checkqueue.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <checkqueue.h>
#include <prevector.h>
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index 20013d702b..f2ab03e20e 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -1,27 +1,22 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
-#include <wallet/wallet.h>
+#include <interfaces/chain.h>
#include <wallet/coinselection.h>
+#include <wallet/wallet.h>
#include <set>
-static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<OutputGroup>& groups)
+static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<std::unique_ptr<CWalletTx>>& wtxs)
{
- int nInput = 0;
-
static int nextLockTime = 0;
CMutableTransaction tx;
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
- tx.vout.resize(nInput + 1);
- tx.vout[nInput].nValue = nValue;
- CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx)));
-
- int nAge = 6 * 24;
- COutput output(wtx, nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
- groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0);
+ tx.vout.resize(1);
+ tx.vout[0].nValue = nValue;
+ wtxs.push_back(MakeUnique<CWalletTx>(&wallet, MakeTransactionRef(std::move(tx))));
}
// Simple benchmark for wallet coin selection. Note that it maybe be necessary
@@ -33,15 +28,23 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<Ou
// (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484)
static void CoinSelection(benchmark::State& state)
{
- const CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ auto chain = interfaces::MakeChain();
+ const CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
+ std::vector<std::unique_ptr<CWalletTx>> wtxs;
LOCK(wallet.cs_wallet);
// Add coins.
- std::vector<OutputGroup> groups;
for (int i = 0; i < 1000; ++i) {
- addCoin(1000 * COIN, wallet, groups);
+ addCoin(1000 * COIN, wallet, wtxs);
+ }
+ addCoin(3 * COIN, wallet, wtxs);
+
+ // Create groups
+ std::vector<OutputGroup> groups;
+ for (const auto& wtx : wtxs) {
+ COutput output(wtx.get(), 0 /* iIn */, 6 * 24 /* nDepthIn */, true /* spendable */, true /* solvable */, true /* safe */);
+ groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0);
}
- addCoin(3 * COIN, wallet, groups);
const CoinEligibilityFilter filter_standard(1, 6, 0);
const CoinSelectionParams coin_selection_params(true, 34, 148, CFeeRate(0), 0);
@@ -57,7 +60,8 @@ static void CoinSelection(benchmark::State& state)
}
typedef std::set<CInputCoin> CoinSet;
-static const CWallet testWallet("dummy", WalletDatabase::CreateDummy());
+static auto testChain = interfaces::MakeChain();
+static const CWallet testWallet(testChain.get(), WalletLocation(), WalletDatabase::CreateDummy());
std::vector<std::unique_ptr<CWalletTx>> wtxn;
// Copied from src/wallet/test/coinselector_tests.cpp
@@ -66,7 +70,7 @@ static void add_coin(const CAmount& nValue, int nInput, std::vector<OutputGroup>
CMutableTransaction tx;
tx.vout.resize(nInput + 1);
tx.vout[nInput].nValue = nValue;
- std::unique_ptr<CWalletTx> wtx(new CWalletTx(&testWallet, MakeTransactionRef(std::move(tx))));
+ std::unique_ptr<CWalletTx> wtx = MakeUnique<CWalletTx>(&testWallet, MakeTransactionRef(std::move(tx)));
set.emplace_back(COutput(wtx.get(), nInput, 0, true, true, true).GetInputCoin(), 0, true, 0, 0);
wtxn.emplace_back(std::move(wtx));
}
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index 7d907eaf10..dc0b054420 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,11 +9,12 @@
#include <hash.h>
#include <random.h>
#include <uint256.h>
-#include <utiltime.h>
+#include <util/time.h>
#include <crypto/ripemd160.h>
#include <crypto/sha1.h>
#include <crypto/sha256.h>
#include <crypto/sha512.h>
+#include <crypto/siphash.h>
/* Number of bytes to hash per iteration */
static const uint64_t BUFFER_SIZE = 1000*1000;
@@ -80,18 +81,16 @@ static void SipHash_32b(benchmark::State& state)
static void FastRandom_32bit(benchmark::State& state)
{
FastRandomContext rng(true);
- uint32_t x = 0;
while (state.KeepRunning()) {
- x += rng.rand32();
+ rng.rand32();
}
}
static void FastRandom_1bit(benchmark::State& state)
{
FastRandomContext rng(true);
- uint32_t x = 0;
while (state.KeepRunning()) {
- x += rng.randbool();
+ rng.randbool();
}
}
diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp
new file mode 100644
index 0000000000..80ff13612c
--- /dev/null
+++ b/src/bench/duplicate_inputs.cpp
@@ -0,0 +1,70 @@
+// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+#include <chainparams.h>
+#include <coins.h>
+#include <consensus/merkle.h>
+#include <consensus/validation.h>
+#include <miner.h>
+#include <policy/policy.h>
+#include <pow.h>
+#include <test/util.h>
+#include <txmempool.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+#include <list>
+#include <vector>
+
+
+static void DuplicateInputs(benchmark::State& state)
+{
+ const CScript SCRIPT_PUB{CScript(OP_TRUE)};
+
+ const CChainParams& chainparams = Params();
+
+ CBlock block{};
+ CMutableTransaction coinbaseTx{};
+ CMutableTransaction naughtyTx{};
+
+ LOCK(cs_main);
+ CBlockIndex* pindexPrev = ::ChainActive().Tip();
+ assert(pindexPrev != nullptr);
+ block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus());
+ block.nNonce = 0;
+ auto nHeight = pindexPrev->nHeight + 1;
+
+ // Make a coinbase TX
+ coinbaseTx.vin.resize(1);
+ coinbaseTx.vin[0].prevout.SetNull();
+ coinbaseTx.vout.resize(1);
+ coinbaseTx.vout[0].scriptPubKey = SCRIPT_PUB;
+ coinbaseTx.vout[0].nValue = GetBlockSubsidy(nHeight, chainparams.GetConsensus());
+ coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
+
+
+ naughtyTx.vout.resize(1);
+ naughtyTx.vout[0].nValue = 0;
+ naughtyTx.vout[0].scriptPubKey = SCRIPT_PUB;
+
+ uint64_t n_inputs = (((MAX_BLOCK_SERIALIZED_SIZE / WITNESS_SCALE_FACTOR) - (CTransaction(coinbaseTx).GetTotalSize() + CTransaction(naughtyTx).GetTotalSize())) / 41) - 100;
+ for (uint64_t x = 0; x < (n_inputs - 1); ++x) {
+ naughtyTx.vin.emplace_back(GetRandHash(), 0, CScript(), 0);
+ }
+ naughtyTx.vin.emplace_back(naughtyTx.vin.back());
+
+ block.vtx.push_back(MakeTransactionRef(std::move(coinbaseTx)));
+ block.vtx.push_back(MakeTransactionRef(std::move(naughtyTx)));
+
+ block.hashMerkleRoot = BlockMerkleRoot(block);
+
+ while (state.KeepRunning()) {
+ CValidationState cvstate{};
+ assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false));
+ assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate");
+ }
+}
+
+BENCHMARK(DuplicateInputs, 10);
diff --git a/src/bench/examples.cpp b/src/bench/examples.cpp
index b68c9cd156..e7ddd5a938 100644
--- a/src/bench/examples.cpp
+++ b/src/bench/examples.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
#include <validation.h>
-#include <utiltime.h>
+#include <util/time.h>
// Sanity test: this should loop ten times, and
// min/max/average should be close to 100ms.
diff --git a/src/bench/gcs_filter.cpp b/src/bench/gcs_filter.cpp
new file mode 100644
index 0000000000..535ad35571
--- /dev/null
+++ b/src/bench/gcs_filter.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+#include <blockfilter.h>
+
+static void ConstructGCSFilter(benchmark::State& state)
+{
+ GCSFilter::ElementSet elements;
+ for (int i = 0; i < 10000; ++i) {
+ GCSFilter::Element element(32);
+ element[0] = static_cast<unsigned char>(i);
+ element[1] = static_cast<unsigned char>(i >> 8);
+ elements.insert(std::move(element));
+ }
+
+ uint64_t siphash_k0 = 0;
+ while (state.KeepRunning()) {
+ GCSFilter filter({siphash_k0, 0, 20, 1 << 20}, elements);
+
+ siphash_k0++;
+ }
+}
+
+static void MatchGCSFilter(benchmark::State& state)
+{
+ GCSFilter::ElementSet elements;
+ for (int i = 0; i < 10000; ++i) {
+ GCSFilter::Element element(32);
+ element[0] = static_cast<unsigned char>(i);
+ element[1] = static_cast<unsigned char>(i >> 8);
+ elements.insert(std::move(element));
+ }
+ GCSFilter filter({0, 0, 20, 1 << 20}, elements);
+
+ while (state.KeepRunning()) {
+ filter.Match(GCSFilter::Element());
+ }
+}
+
+BENCHMARK(ConstructGCSFilter, 1000);
+BENCHMARK(MatchGCSFilter, 50 * 1000);
diff --git a/src/bench/lockedpool.cpp b/src/bench/lockedpool.cpp
index 55a00318c1..0712eab4bc 100644
--- a/src/bench/lockedpool.cpp
+++ b/src/bench/lockedpool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp
index d37291b900..ac8a182358 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,14 +9,14 @@
#include <list>
#include <vector>
-static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
+static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{
int64_t nTime = 0;
unsigned int nHeight = 1;
bool spendsCoinbase = false;
unsigned int sigOpCost = 4;
LockPoints lp;
- pool.addUnchecked(tx->GetHash(), CTxMemPoolEntry(
+ pool.addUnchecked(CTxMemPoolEntry(
tx, nFee, nTime, nHeight,
spendsCoinbase, sigOpCost, lp));
}
@@ -108,7 +108,7 @@ static void MempoolEviction(benchmark::State& state)
tx7.vout[1].nValue = 10 * COIN;
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
// Create transaction references outside the "hot loop"
const CTransactionRef tx1_r{MakeTransactionRef(tx1)};
const CTransactionRef tx2_r{MakeTransactionRef(tx2)};
@@ -127,7 +127,7 @@ static void MempoolEviction(benchmark::State& state)
AddTx(tx6_r, 1100LL, pool);
AddTx(tx7_r, 9000LL, pool);
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
- pool.TrimToSize(GetVirtualTransactionSize(tx1));
+ pool.TrimToSize(GetVirtualTransactionSize(*tx1_r));
}
}
diff --git a/src/bench/merkle_root.cpp b/src/bench/merkle_root.cpp
index fab12da311..bdb2bdbe3d 100644
--- a/src/bench/merkle_root.cpp
+++ b/src/bench/merkle_root.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bench/poly1305.cpp b/src/bench/poly1305.cpp
new file mode 100644
index 0000000000..16342d0fbe
--- /dev/null
+++ b/src/bench/poly1305.cpp
@@ -0,0 +1,41 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <iostream>
+
+#include <bench/bench.h>
+#include <crypto/poly1305.h>
+
+/* Number of bytes to process per iteration */
+static constexpr uint64_t BUFFER_SIZE_TINY = 64;
+static constexpr uint64_t BUFFER_SIZE_SMALL = 256;
+static constexpr uint64_t BUFFER_SIZE_LARGE = 1024*1024;
+
+static void POLY1305(benchmark::State& state, size_t buffersize)
+{
+ std::vector<unsigned char> tag(POLY1305_TAGLEN, 0);
+ std::vector<unsigned char> key(POLY1305_KEYLEN, 0);
+ std::vector<unsigned char> in(buffersize, 0);
+ while (state.KeepRunning())
+ poly1305_auth(tag.data(), in.data(), in.size(), key.data());
+}
+
+static void POLY1305_64BYTES(benchmark::State& state)
+{
+ POLY1305(state, BUFFER_SIZE_TINY);
+}
+
+static void POLY1305_256BYTES(benchmark::State& state)
+{
+ POLY1305(state, BUFFER_SIZE_SMALL);
+}
+
+static void POLY1305_1MB(benchmark::State& state)
+{
+ POLY1305(state, BUFFER_SIZE_LARGE);
+}
+
+BENCHMARK(POLY1305_64BYTES, 500000);
+BENCHMARK(POLY1305_256BYTES, 250000);
+BENCHMARK(POLY1305_1MB, 340);
diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp
index 7986d0da79..00e5d7e7a0 100644
--- a/src/bench/prevector.cpp
+++ b/src/bench/prevector.cpp
@@ -1,14 +1,22 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <compat.h>
#include <prevector.h>
#include <serialize.h>
#include <streams.h>
+#include <type_traits>
#include <bench/bench.h>
+// GCC 4.8 is missing some C++11 type_traits,
+// https://www.gnu.org/software/gcc/gcc-5/changes.html
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
+#define IS_TRIVIALLY_CONSTRUCTIBLE std::has_trivial_default_constructor
+#else
+#define IS_TRIVIALLY_CONSTRUCTIBLE std::is_trivially_default_constructible
+#endif
+
struct nontrivial_t {
int x;
nontrivial_t() :x(-1) {}
diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp
index f7f72605d7..0a99ea3184 100644
--- a/src/bench/rollingbloom.cpp
+++ b/src/bench/rollingbloom.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,6 @@ static void RollingBloom(benchmark::State& state)
CRollingBloomFilter filter(120000, 0.000001);
std::vector<unsigned char> data(32);
uint32_t count = 0;
- uint64_t match = 0;
while (state.KeepRunning()) {
count++;
data[0] = count;
@@ -25,7 +24,7 @@ static void RollingBloom(benchmark::State& state)
data[1] = count >> 16;
data[2] = count >> 8;
data[3] = count;
- match += filter.contains(data);
+ filter.contains(data);
}
}
diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp
new file mode 100644
index 0000000000..67d8a25564
--- /dev/null
+++ b/src/bench/rpc_mempool.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+#include <policy/policy.h>
+#include <rpc/blockchain.h>
+#include <txmempool.h>
+
+#include <univalue.h>
+
+#include <list>
+#include <vector>
+
+static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
+{
+ LockPoints lp;
+ pool.addUnchecked(CTxMemPoolEntry(tx, fee, /* time */ 0, /* height */ 1, /* spendsCoinbase */ false, /* sigOpCost */ 4, lp));
+}
+
+static void RpcMempool(benchmark::State& state)
+{
+ CTxMemPool pool;
+ LOCK2(cs_main, pool.cs);
+
+ for (int i = 0; i < 1000; ++i) {
+ CMutableTransaction tx = CMutableTransaction();
+ tx.vin.resize(1);
+ tx.vin[0].scriptSig = CScript() << OP_1;
+ tx.vin[0].scriptWitness.stack.push_back({1});
+ tx.vout.resize(1);
+ tx.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
+ tx.vout[0].nValue = i;
+ const CTransactionRef tx_r{MakeTransactionRef(tx)};
+ AddTx(tx_r, /* fee */ i, pool);
+ }
+
+ while (state.KeepRunning()) {
+ (void)MempoolToJSON(pool, /*verbose*/ true);
+ }
+}
+
+BENCHMARK(RpcMempool, 40);
diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp
index ae60588c2d..312b66e38a 100644
--- a/src/bench/verify_script.cpp
+++ b/src/bench/verify_script.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -76,7 +76,7 @@ static void VerifyScriptBench(benchmark::State& state)
CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit);
CScriptWitness& witness = txSpend.vin[0].scriptWitness;
witness.stack.emplace_back();
- key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back(), 0);
+ key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back());
witness.stack.back().push_back(static_cast<unsigned char>(SIGHASH_ALL));
witness.stack.push_back(ToByteVector(pubkey));
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
new file mode 100644
index 0000000000..46ca12826b
--- /dev/null
+++ b/src/bench/wallet_balance.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+#include <interfaces/chain.h>
+#include <key_io.h>
+#include <optional.h>
+#include <test/util.h>
+#include <validationinterface.h>
+#include <wallet/wallet.h>
+
+static void WalletBalance(benchmark::State& state, const bool set_dirty, const bool add_watchonly, const bool add_mine)
+{
+ const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE;
+
+ std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain();
+ CWallet wallet{chain.get(), WalletLocation(), WalletDatabase::CreateMock()};
+ {
+ bool first_run;
+ if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
+ wallet.handleNotifications();
+ }
+
+
+ const Optional<std::string> address_mine{add_mine ? Optional<std::string>{getnewaddress(wallet)} : nullopt};
+ if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);
+
+ for (int i = 0; i < 100; ++i) {
+ generatetoaddress(address_mine.get_value_or(ADDRESS_WATCHONLY));
+ generatetoaddress(ADDRESS_WATCHONLY);
+ }
+ SyncWithValidationInterfaceQueue();
+
+ auto bal = wallet.GetBalance(); // Cache
+
+ while (state.KeepRunning()) {
+ if (set_dirty) wallet.MarkDirty();
+ bal = wallet.GetBalance();
+ if (add_mine) assert(bal.m_mine_trusted > 0);
+ if (add_watchonly) assert(bal.m_watchonly_trusted > 0);
+ }
+}
+
+static void WalletBalanceDirty(benchmark::State& state) { WalletBalance(state, /* set_dirty */ true, /* add_watchonly */ true, /* add_mine */ true); }
+static void WalletBalanceClean(benchmark::State& state) { WalletBalance(state, /* set_dirty */ false, /* add_watchonly */ true, /* add_mine */ true); }
+static void WalletBalanceMine(benchmark::State& state) { WalletBalance(state, /* set_dirty */ false, /* add_watchonly */ false, /* add_mine */ true); }
+static void WalletBalanceWatch(benchmark::State& state) { WalletBalance(state, /* set_dirty */ false, /* add_watchonly */ true, /* add_mine */ false); }
+
+BENCHMARK(WalletBalanceDirty, 2500);
+BENCHMARK(WalletBalanceClean, 8000);
+BENCHMARK(WalletBalanceMine, 16000);
+BENCHMARK(WalletBalanceWatch, 8000);
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index a77e3d49b8..1009a771f8 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,11 +12,12 @@
#include <fs.h>
#include <rpc/client.h>
#include <rpc/protocol.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <memory>
#include <stdio.h>
+#include <tuple>
#include <event2/buffer.h>
#include <event2/keyvalq_struct.h>
@@ -24,6 +25,8 @@
#include <univalue.h>
+const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
+
static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
static const bool DEFAULT_NAMED=false;
@@ -31,10 +34,12 @@ static const int CONTINUE_EXECUTION=-1;
static void SetupCliArgs()
{
+ SetupHelpOptions(gArgs);
+
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
+ const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
- gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-version", "Print version and exit", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS);
@@ -43,18 +48,14 @@ static void SetupCliArgs()
gArgs.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-rpcclienttimeout=<n>", strprintf("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-rpcconnect=<ip>", strprintf("Send commands to node running on <ip> (default: %s)", DEFAULT_RPCCONNECT), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpccookiefile=<loc>", _("Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)"), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u, testnet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-rpcwait", "Wait for RPC server to start", false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcwallet=<walletname>", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind)", false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-stdin", "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.", false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-stdinrpcpass", strprintf("Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password."), false, OptionsCategory::OPTIONS);
-
- // Hidden
- gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-rpcwallet=<walletname>", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind). This changes the RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/<walletname>", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-stdin", "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-stdinrpcpass", "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password.", false, OptionsCategory::OPTIONS);
}
/** libevent event log callback */
@@ -104,14 +105,13 @@ static int AppInitRPC(int argc, char* argv[])
return EXIT_FAILURE;
}
if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
- std::string strUsage = strprintf("%s RPC client version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n";
+ std::string strUsage = PACKAGE_NAME " RPC client version " + FormatFullVersion() + "\n";
if (!gArgs.IsArgSet("-version")) {
- strUsage += "\nUsage:\n"
- " bitcoin-cli [options] <command> [params] " + strprintf("Send command to %s", PACKAGE_NAME) + "\n" +
- " bitcoin-cli [options] -named <command> [name=value] ... " + strprintf("Send command to %s (with named arguments)", PACKAGE_NAME) + "\n" +
- " bitcoin-cli [options] help List commands\n" +
- " bitcoin-cli [options] help <command> Get help for a command\n";
-
+ strUsage += "\n"
+ "Usage: bitcoin-cli [options] <command> [params] Send command to " PACKAGE_NAME "\n"
+ "or: bitcoin-cli [options] -named <command> [name=value]... Send command to " PACKAGE_NAME " (with named arguments)\n"
+ "or: bitcoin-cli [options] help List commands\n"
+ "or: bitcoin-cli [options] help <command> Get help for a command\n";
strUsage += "\n" + gArgs.GetHelpMessage();
}
@@ -137,11 +137,6 @@ static int AppInitRPC(int argc, char* argv[])
fprintf(stderr, "Error: %s\n", e.what());
return EXIT_FAILURE;
}
- if (gArgs.GetBoolArg("-rpcssl", false))
- {
- fprintf(stderr, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
- return EXIT_FAILURE;
- }
return CONTINUE_EXECUTION;
}
@@ -258,16 +253,12 @@ public:
}
result.pushKV("version", batch[ID_NETWORKINFO]["result"]["version"]);
result.pushKV("protocolversion", batch[ID_NETWORKINFO]["result"]["protocolversion"]);
- if (!batch[ID_WALLETINFO].isNull()) {
- result.pushKV("walletversion", batch[ID_WALLETINFO]["result"]["walletversion"]);
- result.pushKV("balance", batch[ID_WALLETINFO]["result"]["balance"]);
- }
result.pushKV("blocks", batch[ID_BLOCKCHAININFO]["result"]["blocks"]);
result.pushKV("timeoffset", batch[ID_NETWORKINFO]["result"]["timeoffset"]);
result.pushKV("connections", batch[ID_NETWORKINFO]["result"]["connections"]);
result.pushKV("proxy", batch[ID_NETWORKINFO]["result"]["networks"][0]["proxy"]);
result.pushKV("difficulty", batch[ID_BLOCKCHAININFO]["result"]["difficulty"]);
- result.pushKV("testnet", UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"].get_str() == "test"));
+ result.pushKV("chain", UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"]));
if (!batch[ID_WALLETINFO].isNull()) {
result.pushKV("walletversion", batch[ID_WALLETINFO]["result"]["walletversion"]);
result.pushKV("balance", batch[ID_WALLETINFO]["result"]["balance"]);
@@ -494,9 +485,6 @@ static int CommandLineRPC(int argc, char *argv[])
}
} while (fWait);
}
- catch (const boost::thread_interrupted&) {
- throw;
- }
catch (const std::exception& e) {
strPrint = std::string("error: ") + e.what();
nRet = EXIT_FAILURE;
@@ -514,6 +502,10 @@ static int CommandLineRPC(int argc, char *argv[])
int main(int argc, char* argv[])
{
+#ifdef WIN32
+ util::WinCmdLineArgs winArgs;
+ std::tie(argc, argv) = winArgs.get();
+#endif
SetupEnvironment();
if (!SetupNetworking()) {
fprintf(stderr, "Error: Initializing networking failed\n");
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 181e2bb1bc..ac1d62a8f4 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -18,9 +18,10 @@
#include <script/script.h>
#include <script/sign.h>
#include <univalue.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utilstrencodings.h>
+#include <util/rbf.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
#include <memory>
#include <stdio.h>
@@ -31,9 +32,12 @@ static bool fCreateBlank;
static std::map<std::string,UniValue> registers;
static const int CONTINUE_EXECUTION=-1;
+const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
+
static void SetupBitcoinTxArgs()
{
- gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
+ SetupHelpOptions(gArgs);
+
gArgs.AddArg("-create", "Create new, empty TX.", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-json", "Select JSON output", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-txid", "Output only the hex-encoded transaction id of the resultant transaction.", false, OptionsCategory::OPTIONS);
@@ -60,14 +64,10 @@ static void SetupBitcoinTxArgs()
"This command requires JSON registers:"
"prevtxs=JSON object, "
"privatekeys=JSON object. "
- "See signrawtransaction docs for format of sighash flags, JSON objects.", false, OptionsCategory::COMMANDS);
+ "See signrawtransactionwithkey docs for format of sighash flags, JSON objects.", false, OptionsCategory::COMMANDS);
gArgs.AddArg("load=NAME:FILENAME", "Load JSON file FILENAME into register NAME", false, OptionsCategory::REGISTER_COMMANDS);
gArgs.AddArg("set=NAME:JSON-STRING", "Set register NAME to given JSON-STRING", false, OptionsCategory::REGISTER_COMMANDS);
-
- // Hidden
- gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
- gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
}
//
@@ -98,11 +98,10 @@ static int AppInitRawTx(int argc, char* argv[])
if (argc < 2 || HelpRequested(gArgs)) {
// First part of help message is specific to this utility
- std::string strUsage = strprintf("%s bitcoin-tx utility version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n\n" +
- "Usage:\n"
- " bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n" +
- " bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n" +
- "\n";
+ std::string strUsage = PACKAGE_NAME " bitcoin-tx utility version " + FormatFullVersion() + "\n\n" +
+ "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n" +
+ "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n" +
+ "\n";
strUsage += gArgs.GetHelpMessage();
fprintf(stdout, "%s", strUsage.c_str());
@@ -239,10 +238,10 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
throw std::runtime_error("TX input missing separator");
// extract and validate TXID
- std::string strTxid = vStrInputParts[0];
- if ((strTxid.size() != 64) || !IsHex(strTxid))
+ uint256 txid;
+ if (!ParseHashStr(vStrInputParts[0], txid)) {
throw std::runtime_error("invalid TX input txid");
- uint256 txid(uint256S(strTxid));
+ }
static const unsigned int minTxOutSz = 9;
static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
@@ -254,7 +253,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
throw std::runtime_error("invalid TX input vout '" + strVout + "'");
// extract the optional sequence number
- uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max();
+ uint32_t nSequenceIn = CTxIn::SEQUENCE_FINAL;
if (vStrInputParts.size() > 2)
nSequenceIn = std::stoul(vStrInputParts[2]);
@@ -324,7 +323,7 @@ static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& str
}
if (bScriptHash) {
// Get the ID for the script, and then construct a P2SH destination for it.
- scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
+ scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
}
// construct TxOut, append to transaction output list
@@ -355,7 +354,7 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
if (vStrInputParts.size() < numkeys + 3)
throw std::runtime_error("incorrect number of multisig pubkeys");
- if (required < 1 || required > 20 || numkeys < 1 || numkeys > 20 || numkeys < required)
+ if (required < 1 || required > MAX_PUBKEYS_PER_MULTISIG || numkeys < 1 || numkeys > MAX_PUBKEYS_PER_MULTISIG || numkeys < required)
throw std::runtime_error("multisig parameter mismatch. Required " \
+ std::to_string(required) + " of " + std::to_string(numkeys) + "signatures.");
@@ -384,7 +383,7 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
CScript scriptPubKey = GetScriptForMultisig(required, pubkeys);
if (bSegWit) {
- for (CPubKey& pubkey : pubkeys) {
+ for (const CPubKey& pubkey : pubkeys) {
if (!pubkey.IsCompressed()) {
throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
}
@@ -398,7 +397,7 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
"redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
}
// Get the ID for the script, and then construct a P2SH destination for it.
- scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
+ scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
}
// construct TxOut, append to transaction output list
@@ -470,7 +469,7 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& str
throw std::runtime_error(strprintf(
"redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
}
- scriptPubKey = GetScriptForDestination(CScriptID(scriptPubKey));
+ scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
}
// construct TxOut, append to transaction output list
@@ -589,7 +588,10 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
if (!prevOut.checkObject(types))
throw std::runtime_error("prevtxs internal object typecheck fail");
- uint256 txid = ParseHashStr(prevOut["txid"].get_str(), "txid");
+ uint256 txid;
+ if (!ParseHashStr(prevOut["txid"].get_str(), txid)) {
+ throw std::runtime_error("txid must be hexadecimal string (not '" + prevOut["txid"].get_str() + "')");
+ }
const int nOut = prevOut["vout"].get_int();
if (nOut < 0)
@@ -814,11 +816,7 @@ static int CommandLineRawTx(int argc, char* argv[])
MutateTx(tx, key, value);
}
- OutputTx(tx);
- }
-
- catch (const boost::thread_interrupted&) {
- throw;
+ OutputTx(CTransaction(tx));
}
catch (const std::exception& e) {
strPrint = std::string("error: ") + e.what();
diff --git a/src/bitcoin-wallet-res.rc b/src/bitcoin-wallet-res.rc
new file mode 100644
index 0000000000..e9fa2dbb40
--- /dev/null
+++ b/src/bitcoin-wallet-res.rc
@@ -0,0 +1,35 @@
+#include <windows.h> // needed for VERSIONINFO
+#include "clientversion.h" // holds the needed client version information
+
+#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
+#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
+#define VER_FILEVERSION VER_PRODUCTVERSION
+#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_APP
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4" // U.S. English - multilingual (hex)
+ BEGIN
+ VALUE "CompanyName", "Bitcoin"
+ VALUE "FileDescription", "bitcoin-wallet (CLI tool for " PACKAGE_NAME " wallets)"
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "InternalName", "bitcoin-wallet"
+ VALUE "LegalCopyright", COPYRIGHT_STR
+ VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php."
+ VALUE "OriginalFilename", "bitcoin-wallet.exe"
+ VALUE "ProductName", "bitcoin-wallet"
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal)
+ END
+END
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
new file mode 100644
index 0000000000..32a539aac6
--- /dev/null
+++ b/src/bitcoin-wallet.cpp
@@ -0,0 +1,117 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#include <chainparams.h>
+#include <chainparamsbase.h>
+#include <consensus/consensus.h>
+#include <logging.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <wallet/wallettool.h>
+
+#include <stdio.h>
+
+const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
+
+static void SetupWalletToolArgs()
+{
+ SetupHelpOptions(gArgs);
+ SetupChainParamsBaseOptions();
+
+ gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-wallet=<wallet-name>", "Specify wallet name", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-debug=<category>", "Output debugging information (default: 0).", false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise.", false, OptionsCategory::DEBUG_TEST);
+
+ gArgs.AddArg("info", "Get wallet info", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("create", "Create new wallet file", false, OptionsCategory::COMMANDS);
+}
+
+static bool WalletAppInit(int argc, char* argv[])
+{
+ SetupWalletToolArgs();
+ std::string error_message;
+ if (!gArgs.ParseParameters(argc, argv, error_message)) {
+ fprintf(stderr, "Error parsing command line arguments: %s\n", error_message.c_str());
+ return false;
+ }
+ if (argc < 2 || HelpRequested(gArgs)) {
+ std::string usage = strprintf("%s bitcoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n\n" +
+ "wallet-tool is an offline tool for creating and interacting with Bitcoin Core wallet files.\n" +
+ "By default wallet-tool will act on wallets in the default mainnet wallet directory in the datadir.\n" +
+ "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n" +
+ "Usage:\n" +
+ " bitcoin-wallet [options] <command>\n\n" +
+ gArgs.GetHelpMessage();
+
+ fprintf(stdout, "%s", usage.c_str());
+ return false;
+ }
+
+ // check for printtoconsole, allow -debug
+ LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", gArgs.GetBoolArg("-debug", false));
+
+ if (!fs::is_directory(GetDataDir(false))) {
+ fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
+ return false;
+ }
+ // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
+ SelectParams(gArgs.GetChainName());
+
+ return true;
+}
+
+int main(int argc, char* argv[])
+{
+#ifdef WIN32
+ util::WinCmdLineArgs winArgs;
+ std::tie(argc, argv) = winArgs.get();
+#endif
+ SetupEnvironment();
+ RandomInit();
+ try {
+ if (!WalletAppInit(argc, argv)) return EXIT_FAILURE;
+ } catch (const std::exception& e) {
+ PrintExceptionContinue(&e, "WalletAppInit()");
+ return EXIT_FAILURE;
+ } catch (...) {
+ PrintExceptionContinue(nullptr, "WalletAppInit()");
+ return EXIT_FAILURE;
+ }
+
+ std::string method {};
+ for(int i = 1; i < argc; ++i) {
+ if (!IsSwitchChar(argv[i][0])) {
+ if (!method.empty()) {
+ fprintf(stderr, "Error: two methods provided (%s and %s). Only one method should be provided.\n", method.c_str(), argv[i]);
+ return EXIT_FAILURE;
+ }
+ method = argv[i];
+ }
+ }
+
+ if (method.empty()) {
+ fprintf(stderr, "No method provided. Run `bitcoin-wallet -help` for valid methods.\n");
+ return EXIT_FAILURE;
+ }
+
+ // A name must be provided when creating a file
+ if (method == "create" && !gArgs.IsArgSet("-wallet")) {
+ fprintf(stderr, "Wallet name must be provided when creating a new wallet.\n");
+ return EXIT_FAILURE;
+ }
+
+ std::string name = gArgs.GetArg("-wallet", "");
+
+ ECCVerifyHandle globalVerifyHandle;
+ ECC_Start();
+ if (!WalletTool::ExecuteWalletToolFunc(method, name))
+ return EXIT_FAILURE;
+ ECC_Stop();
+ return EXIT_SUCCESS;
+}
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 4d010c0d14..b31f86cdd9 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -11,18 +11,22 @@
#include <clientversion.h>
#include <compat.h>
#include <fs.h>
+#include <interfaces/chain.h>
#include <rpc/server.h>
#include <init.h>
#include <noui.h>
#include <shutdown.h>
-#include <util.h>
+#include <util/system.h>
#include <httpserver.h>
#include <httprpc.h>
-#include <utilstrencodings.h>
+#include <util/threadnames.h>
+#include <util/strencodings.h>
#include <walletinitinterface.h>
#include <stdio.h>
+const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
+
/* Introduction text for doxygen: */
/*! \mainpage Developer documentation
@@ -56,8 +60,13 @@ static void WaitForShutdown()
//
static bool AppInit(int argc, char* argv[])
{
+ InitInterfaces interfaces;
+ interfaces.chain = interfaces::MakeChain();
+
bool fRet = false;
+ util::ThreadRename("init");
+
//
// Parameters
//
@@ -71,17 +80,15 @@ static bool AppInit(int argc, char* argv[])
// Process help and version before taking care about datadir
if (HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
- std::string strUsage = strprintf("%s Daemon", PACKAGE_NAME) + " version " + FormatFullVersion() + "\n";
+ std::string strUsage = PACKAGE_NAME " Daemon version " + FormatFullVersion() + "\n";
if (gArgs.IsArgSet("-version"))
{
- strUsage += FormatParagraph(LicenseInfo());
+ strUsage += FormatParagraph(LicenseInfo()) + "\n";
}
else
{
- strUsage += "\nUsage:\n"
- " bitcoind [options] " + strprintf("Start %s Daemon", PACKAGE_NAME) + "\n";
-
+ strUsage += "\nUsage: bitcoind [options] Start " PACKAGE_NAME " Daemon\n";
strUsage += "\n" + gArgs.GetHelpMessage();
}
@@ -164,7 +171,7 @@ static bool AppInit(int argc, char* argv[])
// If locking the data directory failed, exit immediately
return false;
}
- fRet = AppInitMain();
+ fRet = AppInitMain(interfaces);
}
catch (const std::exception& e) {
PrintExceptionContinue(&e, "AppInit()");
@@ -178,13 +185,17 @@ static bool AppInit(int argc, char* argv[])
} else {
WaitForShutdown();
}
- Shutdown();
+ Shutdown(interfaces);
return fRet;
}
int main(int argc, char* argv[])
{
+#ifdef WIN32
+ util::WinCmdLineArgs winArgs;
+ std::tie(argc, argv) = winArgs.get();
+#endif
SetupEnvironment();
// Connect bitcoind signal handlers
diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp
index 391db0cfcb..f0fcf675eb 100644
--- a/src/blockencodings.cpp
+++ b/src/blockencodings.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,12 +6,13 @@
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <chainparams.h>
-#include <hash.h>
+#include <crypto/sha256.h>
+#include <crypto/siphash.h>
#include <random.h>
#include <streams.h>
#include <txmempool.h>
#include <validation.h>
-#include <util.h>
+#include <util/system.h>
#include <unordered_map>
@@ -162,7 +163,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
break;
}
- LogPrint(BCLog::CMPCTBLOCK, "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, SER_NETWORK, PROTOCOL_VERSION));
+ LogPrint(BCLog::CMPCTBLOCK, "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, PROTOCOL_VERSION));
return READ_STATUS_OK;
}
@@ -202,7 +203,7 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
// but that is expensive, and CheckBlock caches a block's
// "checked-status" (in the CBlock?). CBlock should be able to
// check its own merkle root and cache that check.
- if (state.CorruptionPossible())
+ if (state.GetReason() == ValidationInvalidReason::BLOCK_MUTATED)
return READ_STATUS_FAILED; // Possible Short ID collision
return READ_STATUS_CHECKBLOCK_FAILED;
}
diff --git a/src/blockencodings.h b/src/blockencodings.h
index 3a0828b307..0c2b83ebcf 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -52,12 +52,12 @@ public:
}
}
- uint16_t offset = 0;
+ int32_t offset = 0;
for (size_t j = 0; j < indexes.size(); j++) {
- if (uint64_t(indexes[j]) + uint64_t(offset) > std::numeric_limits<uint16_t>::max())
+ if (int32_t(indexes[j]) + offset > std::numeric_limits<uint16_t>::max())
throw std::ios_base::failure("indexes overflowed 16 bits");
indexes[j] = indexes[j] + offset;
- offset = indexes[j] + 1;
+ offset = int32_t(indexes[j]) + 1;
}
} else {
for (size_t i = 0; i < indexes.size(); i++) {
@@ -186,6 +186,9 @@ public:
READWRITE(prefilledtxn);
+ if (BlockTxCount() > std::numeric_limits<uint16_t>::max())
+ throw std::ios_base::failure("indexes overflowed 16 bits");
+
if (ser_action.ForRead())
FillShortTxIDSelector();
}
diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp
new file mode 100644
index 0000000000..787390be31
--- /dev/null
+++ b/src/blockfilter.cpp
@@ -0,0 +1,338 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <mutex>
+#include <sstream>
+
+#include <blockfilter.h>
+#include <crypto/siphash.h>
+#include <hash.h>
+#include <primitives/transaction.h>
+#include <script/script.h>
+#include <streams.h>
+
+/// SerType used to serialize parameters in GCS filter encoding.
+static constexpr int GCS_SER_TYPE = SER_NETWORK;
+
+/// Protocol version used to serialize parameters in GCS filter encoding.
+static constexpr int GCS_SER_VERSION = 0;
+
+static const std::map<BlockFilterType, std::string> g_filter_types = {
+ {BlockFilterType::BASIC, "basic"},
+};
+
+template <typename OStream>
+static void GolombRiceEncode(BitStreamWriter<OStream>& bitwriter, uint8_t P, uint64_t x)
+{
+ // Write quotient as unary-encoded: q 1's followed by one 0.
+ uint64_t q = x >> P;
+ while (q > 0) {
+ int nbits = q <= 64 ? static_cast<int>(q) : 64;
+ bitwriter.Write(~0ULL, nbits);
+ q -= nbits;
+ }
+ bitwriter.Write(0, 1);
+
+ // Write the remainder in P bits. Since the remainder is just the bottom
+ // P bits of x, there is no need to mask first.
+ bitwriter.Write(x, P);
+}
+
+template <typename IStream>
+static uint64_t GolombRiceDecode(BitStreamReader<IStream>& bitreader, uint8_t P)
+{
+ // Read unary-encoded quotient: q 1's followed by one 0.
+ uint64_t q = 0;
+ while (bitreader.Read(1) == 1) {
+ ++q;
+ }
+
+ uint64_t r = bitreader.Read(P);
+
+ return (q << P) + r;
+}
+
+// Map a value x that is uniformly distributed in the range [0, 2^64) to a
+// value uniformly distributed in [0, n) by returning the upper 64 bits of
+// x * n.
+//
+// See: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
+static uint64_t MapIntoRange(uint64_t x, uint64_t n)
+{
+#ifdef __SIZEOF_INT128__
+ return (static_cast<unsigned __int128>(x) * static_cast<unsigned __int128>(n)) >> 64;
+#else
+ // To perform the calculation on 64-bit numbers without losing the
+ // result to overflow, split the numbers into the most significant and
+ // least significant 32 bits and perform multiplication piece-wise.
+ //
+ // See: https://stackoverflow.com/a/26855440
+ uint64_t x_hi = x >> 32;
+ uint64_t x_lo = x & 0xFFFFFFFF;
+ uint64_t n_hi = n >> 32;
+ uint64_t n_lo = n & 0xFFFFFFFF;
+
+ uint64_t ac = x_hi * n_hi;
+ uint64_t ad = x_hi * n_lo;
+ uint64_t bc = x_lo * n_hi;
+ uint64_t bd = x_lo * n_lo;
+
+ uint64_t mid34 = (bd >> 32) + (bc & 0xFFFFFFFF) + (ad & 0xFFFFFFFF);
+ uint64_t upper64 = ac + (bc >> 32) + (ad >> 32) + (mid34 >> 32);
+ return upper64;
+#endif
+}
+
+uint64_t GCSFilter::HashToRange(const Element& element) const
+{
+ uint64_t hash = CSipHasher(m_params.m_siphash_k0, m_params.m_siphash_k1)
+ .Write(element.data(), element.size())
+ .Finalize();
+ return MapIntoRange(hash, m_F);
+}
+
+std::vector<uint64_t> GCSFilter::BuildHashedSet(const ElementSet& elements) const
+{
+ std::vector<uint64_t> hashed_elements;
+ hashed_elements.reserve(elements.size());
+ for (const Element& element : elements) {
+ hashed_elements.push_back(HashToRange(element));
+ }
+ std::sort(hashed_elements.begin(), hashed_elements.end());
+ return hashed_elements;
+}
+
+GCSFilter::GCSFilter(const Params& params)
+ : m_params(params), m_N(0), m_F(0), m_encoded{0}
+{}
+
+GCSFilter::GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter)
+ : m_params(params), m_encoded(std::move(encoded_filter))
+{
+ VectorReader stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);
+
+ uint64_t N = ReadCompactSize(stream);
+ m_N = static_cast<uint32_t>(N);
+ if (m_N != N) {
+ throw std::ios_base::failure("N must be <2^32");
+ }
+ m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_params.m_M);
+
+ // Verify that the encoded filter contains exactly N elements. If it has too much or too little
+ // data, a std::ios_base::failure exception will be raised.
+ BitStreamReader<VectorReader> bitreader(stream);
+ for (uint64_t i = 0; i < m_N; ++i) {
+ GolombRiceDecode(bitreader, m_params.m_P);
+ }
+ if (!stream.empty()) {
+ throw std::ios_base::failure("encoded_filter contains excess data");
+ }
+}
+
+GCSFilter::GCSFilter(const Params& params, const ElementSet& elements)
+ : m_params(params)
+{
+ size_t N = elements.size();
+ m_N = static_cast<uint32_t>(N);
+ if (m_N != N) {
+ throw std::invalid_argument("N must be <2^32");
+ }
+ m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_params.m_M);
+
+ CVectorWriter stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);
+
+ WriteCompactSize(stream, m_N);
+
+ if (elements.empty()) {
+ return;
+ }
+
+ BitStreamWriter<CVectorWriter> bitwriter(stream);
+
+ uint64_t last_value = 0;
+ for (uint64_t value : BuildHashedSet(elements)) {
+ uint64_t delta = value - last_value;
+ GolombRiceEncode(bitwriter, m_params.m_P, delta);
+ last_value = value;
+ }
+
+ bitwriter.Flush();
+}
+
+bool GCSFilter::MatchInternal(const uint64_t* element_hashes, size_t size) const
+{
+ VectorReader stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);
+
+ // Seek forward by size of N
+ uint64_t N = ReadCompactSize(stream);
+ assert(N == m_N);
+
+ BitStreamReader<VectorReader> bitreader(stream);
+
+ uint64_t value = 0;
+ size_t hashes_index = 0;
+ for (uint32_t i = 0; i < m_N; ++i) {
+ uint64_t delta = GolombRiceDecode(bitreader, m_params.m_P);
+ value += delta;
+
+ while (true) {
+ if (hashes_index == size) {
+ return false;
+ } else if (element_hashes[hashes_index] == value) {
+ return true;
+ } else if (element_hashes[hashes_index] > value) {
+ break;
+ }
+
+ hashes_index++;
+ }
+ }
+
+ return false;
+}
+
+bool GCSFilter::Match(const Element& element) const
+{
+ uint64_t query = HashToRange(element);
+ return MatchInternal(&query, 1);
+}
+
+bool GCSFilter::MatchAny(const ElementSet& elements) const
+{
+ const std::vector<uint64_t> queries = BuildHashedSet(elements);
+ return MatchInternal(queries.data(), queries.size());
+}
+
+const std::string& BlockFilterTypeName(BlockFilterType filter_type)
+{
+ static std::string unknown_retval = "";
+ auto it = g_filter_types.find(filter_type);
+ return it != g_filter_types.end() ? it->second : unknown_retval;
+}
+
+bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type) {
+ for (const auto& entry : g_filter_types) {
+ if (entry.second == name) {
+ filter_type = entry.first;
+ return true;
+ }
+ }
+ return false;
+}
+
+const std::vector<BlockFilterType>& AllBlockFilterTypes()
+{
+ static std::vector<BlockFilterType> types;
+
+ static std::once_flag flag;
+ std::call_once(flag, []() {
+ types.reserve(g_filter_types.size());
+ for (auto entry : g_filter_types) {
+ types.push_back(entry.first);
+ }
+ });
+
+ return types;
+}
+
+const std::string& ListBlockFilterTypes()
+{
+ static std::string type_list;
+
+ static std::once_flag flag;
+ std::call_once(flag, []() {
+ std::stringstream ret;
+ bool first = true;
+ for (auto entry : g_filter_types) {
+ if (!first) ret << ", ";
+ ret << entry.second;
+ first = false;
+ }
+ type_list = ret.str();
+ });
+
+ return type_list;
+}
+
+static GCSFilter::ElementSet BasicFilterElements(const CBlock& block,
+ const CBlockUndo& block_undo)
+{
+ GCSFilter::ElementSet elements;
+
+ for (const CTransactionRef& tx : block.vtx) {
+ for (const CTxOut& txout : tx->vout) {
+ const CScript& script = txout.scriptPubKey;
+ if (script.empty() || script[0] == OP_RETURN) continue;
+ elements.emplace(script.begin(), script.end());
+ }
+ }
+
+ for (const CTxUndo& tx_undo : block_undo.vtxundo) {
+ for (const Coin& prevout : tx_undo.vprevout) {
+ const CScript& script = prevout.out.scriptPubKey;
+ if (script.empty()) continue;
+ elements.emplace(script.begin(), script.end());
+ }
+ }
+
+ return elements;
+}
+
+BlockFilter::BlockFilter(BlockFilterType filter_type, const uint256& block_hash,
+ std::vector<unsigned char> filter)
+ : m_filter_type(filter_type), m_block_hash(block_hash)
+{
+ GCSFilter::Params params;
+ if (!BuildParams(params)) {
+ throw std::invalid_argument("unknown filter_type");
+ }
+ m_filter = GCSFilter(params, std::move(filter));
+}
+
+BlockFilter::BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo)
+ : m_filter_type(filter_type), m_block_hash(block.GetHash())
+{
+ GCSFilter::Params params;
+ if (!BuildParams(params)) {
+ throw std::invalid_argument("unknown filter_type");
+ }
+ m_filter = GCSFilter(params, BasicFilterElements(block, block_undo));
+}
+
+bool BlockFilter::BuildParams(GCSFilter::Params& params) const
+{
+ switch (m_filter_type) {
+ case BlockFilterType::BASIC:
+ params.m_siphash_k0 = m_block_hash.GetUint64(0);
+ params.m_siphash_k1 = m_block_hash.GetUint64(1);
+ params.m_P = BASIC_FILTER_P;
+ params.m_M = BASIC_FILTER_M;
+ return true;
+ case BlockFilterType::INVALID:
+ return false;
+ }
+
+ return false;
+}
+
+uint256 BlockFilter::GetHash() const
+{
+ const std::vector<unsigned char>& data = GetEncodedFilter();
+
+ uint256 result;
+ CHash256().Write(data.data(), data.size()).Finalize(result.begin());
+ return result;
+}
+
+uint256 BlockFilter::ComputeHeader(const uint256& prev_header) const
+{
+ const uint256& filter_hash = GetHash();
+
+ uint256 result;
+ CHash256()
+ .Write(filter_hash.begin(), filter_hash.size())
+ .Write(prev_header.begin(), prev_header.size())
+ .Finalize(result.begin());
+ return result;
+}
diff --git a/src/blockfilter.h b/src/blockfilter.h
new file mode 100644
index 0000000000..914b94fec1
--- /dev/null
+++ b/src/blockfilter.h
@@ -0,0 +1,170 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_BLOCKFILTER_H
+#define BITCOIN_BLOCKFILTER_H
+
+#include <stdint.h>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include <primitives/block.h>
+#include <serialize.h>
+#include <uint256.h>
+#include <undo.h>
+#include <util/bytevectorhash.h>
+
+/**
+ * This implements a Golomb-coded set as defined in BIP 158. It is a
+ * compact, probabilistic data structure for testing set membership.
+ */
+class GCSFilter
+{
+public:
+ typedef std::vector<unsigned char> Element;
+ typedef std::unordered_set<Element, ByteVectorHash> ElementSet;
+
+ struct Params
+ {
+ uint64_t m_siphash_k0;
+ uint64_t m_siphash_k1;
+ uint8_t m_P; //!< Golomb-Rice coding parameter
+ uint32_t m_M; //!< Inverse false positive rate
+
+ Params(uint64_t siphash_k0 = 0, uint64_t siphash_k1 = 0, uint8_t P = 0, uint32_t M = 1)
+ : m_siphash_k0(siphash_k0), m_siphash_k1(siphash_k1), m_P(P), m_M(M)
+ {}
+ };
+
+private:
+ Params m_params;
+ uint32_t m_N; //!< Number of elements in the filter
+ uint64_t m_F; //!< Range of element hashes, F = N * M
+ std::vector<unsigned char> m_encoded;
+
+ /** Hash a data element to an integer in the range [0, N * M). */
+ uint64_t HashToRange(const Element& element) const;
+
+ std::vector<uint64_t> BuildHashedSet(const ElementSet& elements) const;
+
+ /** Helper method used to implement Match and MatchAny */
+ bool MatchInternal(const uint64_t* sorted_element_hashes, size_t size) const;
+
+public:
+
+ /** Constructs an empty filter. */
+ explicit GCSFilter(const Params& params = Params());
+
+ /** Reconstructs an already-created filter from an encoding. */
+ GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter);
+
+ /** Builds a new filter from the params and set of elements. */
+ GCSFilter(const Params& params, const ElementSet& elements);
+
+ uint32_t GetN() const { return m_N; }
+ const Params& GetParams() const { return m_params; }
+ const std::vector<unsigned char>& GetEncoded() const { return m_encoded; }
+
+ /**
+ * Checks if the element may be in the set. False positives are possible
+ * with probability 1/M.
+ */
+ bool Match(const Element& element) const;
+
+ /**
+ * Checks if any of the given elements may be in the set. False positives
+ * are possible with probability 1/M per element checked. This is more
+ * efficient that checking Match on multiple elements separately.
+ */
+ bool MatchAny(const ElementSet& elements) const;
+};
+
+constexpr uint8_t BASIC_FILTER_P = 19;
+constexpr uint32_t BASIC_FILTER_M = 784931;
+
+enum class BlockFilterType : uint8_t
+{
+ BASIC = 0,
+ INVALID = 255,
+};
+
+/** Get the human-readable name for a filter type. Returns empty string for unknown types. */
+const std::string& BlockFilterTypeName(BlockFilterType filter_type);
+
+/** Find a filter type by its human-readable name. */
+bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type);
+
+/** Get a list of known filter types. */
+const std::vector<BlockFilterType>& AllBlockFilterTypes();
+
+/** Get a comma-separated list of known filter type names. */
+const std::string& ListBlockFilterTypes();
+
+/**
+ * Complete block filter struct as defined in BIP 157. Serialization matches
+ * payload of "cfilter" messages.
+ */
+class BlockFilter
+{
+private:
+ BlockFilterType m_filter_type = BlockFilterType::INVALID;
+ uint256 m_block_hash;
+ GCSFilter m_filter;
+
+ bool BuildParams(GCSFilter::Params& params) const;
+
+public:
+
+ BlockFilter() = default;
+
+ //! Reconstruct a BlockFilter from parts.
+ BlockFilter(BlockFilterType filter_type, const uint256& block_hash,
+ std::vector<unsigned char> filter);
+
+ //! Construct a new BlockFilter of the specified type from a block.
+ BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo);
+
+ BlockFilterType GetFilterType() const { return m_filter_type; }
+ const uint256& GetBlockHash() const { return m_block_hash; }
+ const GCSFilter& GetFilter() const { return m_filter; }
+
+ const std::vector<unsigned char>& GetEncodedFilter() const
+ {
+ return m_filter.GetEncoded();
+ }
+
+ //! Compute the filter hash.
+ uint256 GetHash() const;
+
+ //! Compute the filter header given the previous one.
+ uint256 ComputeHeader(const uint256& prev_header) const;
+
+ template <typename Stream>
+ void Serialize(Stream& s) const {
+ s << m_block_hash
+ << static_cast<uint8_t>(m_filter_type)
+ << m_filter.GetEncoded();
+ }
+
+ template <typename Stream>
+ void Unserialize(Stream& s) {
+ std::vector<unsigned char> encoded_filter;
+ uint8_t filter_type;
+
+ s >> m_block_hash
+ >> filter_type
+ >> encoded_filter;
+
+ m_filter_type = static_cast<BlockFilterType>(filter_type);
+
+ GCSFilter::Params params;
+ if (!BuildParams(params)) {
+ throw std::ios_base::failure("unknown filter_type");
+ }
+ m_filter = GCSFilter(params, std::move(encoded_filter));
+ }
+};
+
+#endif // BITCOIN_BLOCKFILTER_H
diff --git a/src/bloom.cpp b/src/bloom.cpp
index 799e0eef00..7732cee275 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -38,17 +38,6 @@ CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, c
{
}
-// Private constructor used by CRollingBloomFilter
-CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn) :
- vData((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)) / 8),
- isFull(false),
- isEmpty(true),
- nHashFuncs((unsigned int)(vData.size() * 8 / nElements * LN2)),
- nTweak(nTweakIn),
- nFlags(BLOOM_UPDATE_NONE)
-{
-}
-
inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const
{
// 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
@@ -164,11 +153,11 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
insert(COutPoint(hash, i));
else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
{
- txnouttype type;
std::vector<std::vector<unsigned char> > vSolutions;
- if (Solver(txout.scriptPubKey, type, vSolutions) &&
- (type == TX_PUBKEY || type == TX_MULTISIG))
+ txnouttype type = Solver(txout.scriptPubKey, vSolutions);
+ if (type == TX_PUBKEY || type == TX_MULTISIG) {
insert(COutPoint(hash, i));
+ }
}
break;
}
diff --git a/src/bloom.h b/src/bloom.h
index 71386f52fa..7d3aa878b0 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -53,10 +53,6 @@ private:
unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const;
- // Private constructor for CRollingBloomFilter, no restrictions on size
- CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak);
- friend class CRollingBloomFilter;
-
public:
/**
* Creates a new bloom filter which will provide the given fp rate when filled with the given number of elements
diff --git a/src/chain.cpp b/src/chain.cpp
index 79e8bdfa44..5520d8149a 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -59,10 +59,11 @@ const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
return pindex;
}
-CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime) const
+CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime, int height) const
{
- std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime,
- [](CBlockIndex* pBlock, const int64_t& time) -> bool { return pBlock->GetBlockTimeMax() < time; });
+ std::pair<int64_t, int> blockparams = std::make_pair(nTime, height);
+ std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), blockparams,
+ [](CBlockIndex* pBlock, const std::pair<int64_t, int>& blockparams) -> bool { return pBlock->GetBlockTimeMax() < blockparams.first || pBlock->nHeight < blockparams.second; });
return (lower == vChain.end() ? nullptr : *lower);
}
diff --git a/src/chain.h b/src/chain.h
index 8e6ac8d821..dd9cc2a598 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,6 +8,7 @@
#include <arith_uint256.h>
#include <consensus/params.h>
+#include <flatfile.h>
#include <primitives/block.h>
#include <tinyformat.h>
#include <uint256.h>
@@ -18,7 +19,7 @@
* Maximum amount of time that a block timestamp is allowed to exceed the
* current network-adjusted time before the block will be accepted.
*/
-static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
+static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
/**
* Timestamp window used as a grace period by code that compares external
@@ -26,7 +27,15 @@ static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
* to block timestamps. This should be set at least as high as
* MAX_FUTURE_BLOCK_TIME.
*/
-static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
+static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
+
+/**
+ * Maximum gap between node time and block time used
+ * for the "Catching up..." mode in GUI.
+ *
+ * Ref: https://github.com/bitcoin/bitcoin/pull/1026
+ */
+static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60;
class CBlockFileInfo
{
@@ -82,46 +91,6 @@ public:
}
};
-struct CDiskBlockPos
-{
- int nFile;
- unsigned int nPos;
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED));
- READWRITE(VARINT(nPos));
- }
-
- CDiskBlockPos() {
- SetNull();
- }
-
- CDiskBlockPos(int nFileIn, unsigned int nPosIn) {
- nFile = nFileIn;
- nPos = nPosIn;
- }
-
- friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) {
- return (a.nFile == b.nFile && a.nPos == b.nPos);
- }
-
- friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) {
- return !(a == b);
- }
-
- void SetNull() { nFile = -1; nPos = 0; }
- bool IsNull() const { return (nFile == -1); }
-
- std::string ToString() const
- {
- return strprintf("CBlockDiskPos(nFile=%i, nPos=%i)", nFile, nPos);
- }
-
-};
-
enum BlockStatus: uint32_t {
//! Unused.
BLOCK_VALID_UNKNOWN = 0,
@@ -258,8 +227,8 @@ public:
nNonce = block.nNonce;
}
- CDiskBlockPos GetBlockPos() const {
- CDiskBlockPos ret;
+ FlatFilePos GetBlockPos() const {
+ FlatFilePos ret;
if (nStatus & BLOCK_HAVE_DATA) {
ret.nFile = nFile;
ret.nPos = nDataPos;
@@ -267,8 +236,8 @@ public:
return ret;
}
- CDiskBlockPos GetUndoPos() const {
- CDiskBlockPos ret;
+ FlatFilePos GetUndoPos() const {
+ FlatFilePos ret;
if (nStatus & BLOCK_HAVE_UNDO) {
ret.nFile = nFile;
ret.nPos = nUndoPos;
@@ -294,6 +263,15 @@ public:
return *phashBlock;
}
+ /**
+ * Check whether this block's and all previous blocks' transactions have been
+ * downloaded (and stored to disk) at some point.
+ *
+ * Does not imply the transactions are consensus-valid (ConnectTip might fail)
+ * Does not imply the transactions are still stored on disk. (IsBlockPruned might return true)
+ */
+ bool HaveTxsDownloaded() const { return nChainTx != 0; }
+
int64_t GetBlockTime() const
{
return (int64_t)nTime;
@@ -487,8 +465,8 @@ public:
/** Find the last common block between this chain and a block index entry. */
const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
- /** Find the earliest block with timestamp equal or greater than the given. */
- CBlockIndex* FindEarliestAtLeast(int64_t nTime) const;
+ /** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */
+ CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
};
#endif // BITCOIN_CHAIN_H
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index b517717c97..b8e0ea23dd 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -1,18 +1,21 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
-#include <consensus/merkle.h>
+#include <chainparamsseeds.h>
+#include <consensus/merkle.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <versionbitsinfo.h>
#include <assert.h>
-#include <chainparamsseeds.h>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
{
@@ -53,23 +56,9 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
}
-void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
-{
- consensus.vDeployments[d].nStartTime = nStartTime;
- consensus.vDeployments[d].nTimeout = nTimeout;
-}
-
/**
* Main network
*/
-/**
- * What makes a good checkpoint block?
- * + Is surrounded by blocks with reasonable timestamps
- * (no blocks before with a timestamp after, none after with
- * timestamp before)
- * + Contains no strange transactions
- */
-
class CMainParams : public CChainParams {
public:
CMainParams() {
@@ -102,10 +91,10 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.
// The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000028822fef1c230963535a90d");
+ consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000051dc8b82f450202ecb3d471");
// By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8"); //534292
+ consensus.defaultAssumeValid = uint256S("0x0000000000000000000f1c54590ee18d15ec70e68c8cd4cfbadb1b4f11697eee"); //563378
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -118,6 +107,8 @@ public:
pchMessageStart[3] = 0xd9;
nDefaultPort = 8333;
nPruneAfterHeight = 100000;
+ m_assumed_blockchain_size = 240;
+ m_assumed_chain_state_size = 3;
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
@@ -136,6 +127,7 @@ public:
vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch"); // Jonas Schnelli, only supports x1, x5, x9, and xd
vSeeds.emplace_back("seed.btc.petertodd.org"); // Peter Todd, only supports x1, x5, x9, and xd
vSeeds.emplace_back("seed.bitcoin.sprovoost.nl"); // Sjors Provoost
+ vSeeds.emplace_back("dnsseed.emzy.de"); // Stephan Oeste
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
@@ -170,10 +162,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from rpc: getchaintxstats 4096 0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8
- /* nTime */ 1532884444,
- /* nTxCount */ 331282217,
- /* dTxRate */ 2.4
+ // Data from rpc: getchaintxstats 4096 0000000000000000000f1c54590ee18d15ec70e68c8cd4cfbadb1b4f11697eee
+ /* nTime */ 1550374134,
+ /* nTxCount */ 383732546,
+ /* dTxRate */ 3.685496590998308
};
/* disable fallback fee on mainnet */
@@ -227,6 +219,8 @@ public:
pchMessageStart[3] = 0x07;
nDefaultPort = 18333;
nPruneAfterHeight = 1000;
+ m_assumed_blockchain_size = 30;
+ m_assumed_chain_state_size = 2;
genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
@@ -279,14 +273,14 @@ public:
*/
class CRegTestParams : public CChainParams {
public:
- CRegTestParams() {
+ explicit CRegTestParams(const ArgsManager& args) {
strNetworkID = "regtest";
consensus.nSubsidyHalvingInterval = 150;
consensus.BIP16Exception = uint256();
- consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests)
+ consensus.BIP34Height = 500; // BIP34 activated on regtest (Used in functional tests)
consensus.BIP34Hash = uint256();
- consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests)
- consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests)
+ consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in functional tests)
+ consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in functional tests)
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@@ -316,6 +310,10 @@ public:
pchMessageStart[3] = 0xda;
nDefaultPort = 18444;
nPruneAfterHeight = 1000;
+ m_assumed_blockchain_size = 0;
+ m_assumed_chain_state_size = 0;
+
+ UpdateVersionBitsParametersFromArgs(args);
genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
@@ -352,23 +350,65 @@ public:
/* enable fallback fee on regtest */
m_fallback_fee_enabled = true;
}
+
+ /**
+ * Allows modifying the Version Bits regtest parameters.
+ */
+ void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+ {
+ consensus.vDeployments[d].nStartTime = nStartTime;
+ consensus.vDeployments[d].nTimeout = nTimeout;
+ }
+ void UpdateVersionBitsParametersFromArgs(const ArgsManager& args);
};
-static std::unique_ptr<CChainParams> globalChainParams;
+void CRegTestParams::UpdateVersionBitsParametersFromArgs(const ArgsManager& args)
+{
+ if (!args.IsArgSet("-vbparams")) return;
+
+ for (const std::string& strDeployment : args.GetArgs("-vbparams")) {
+ std::vector<std::string> vDeploymentParams;
+ boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":"));
+ if (vDeploymentParams.size() != 3) {
+ throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end");
+ }
+ int64_t nStartTime, nTimeout;
+ if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
+ throw std::runtime_error(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
+ }
+ if (!ParseInt64(vDeploymentParams[2], &nTimeout)) {
+ throw std::runtime_error(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2]));
+ }
+ bool found = false;
+ for (int j=0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
+ if (vDeploymentParams[0] == VersionBitsDeploymentInfo[j].name) {
+ UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
+ found = true;
+ LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
+ break;
+ }
+ }
+ if (!found) {
+ throw std::runtime_error(strprintf("Invalid deployment (%s)", vDeploymentParams[0]));
+ }
+ }
+}
+
+static std::unique_ptr<const CChainParams> globalChainParams;
const CChainParams &Params() {
assert(globalChainParams);
return *globalChainParams;
}
-std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain)
+std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain)
{
if (chain == CBaseChainParams::MAIN)
return std::unique_ptr<CChainParams>(new CMainParams());
else if (chain == CBaseChainParams::TESTNET)
return std::unique_ptr<CChainParams>(new CTestNetParams());
else if (chain == CBaseChainParams::REGTEST)
- return std::unique_ptr<CChainParams>(new CRegTestParams());
+ return std::unique_ptr<CChainParams>(new CRegTestParams(gArgs));
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}
@@ -377,8 +417,3 @@ void SelectParams(const std::string& network)
SelectBaseParams(network);
globalChainParams = CreateChainParams(network);
}
-
-void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
-{
- globalChainParams->UpdateVersionBitsParameters(d, nStartTime, nTimeout);
-}
diff --git a/src/chainparams.h b/src/chainparams.h
index 344cbb1a8a..6ff3dbb7e5 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -67,6 +67,10 @@ public:
/** Policy: Filter transactions that do not match well-defined patterns */
bool RequireStandard() const { return fRequireStandard; }
uint64_t PruneAfterHeight() const { return nPruneAfterHeight; }
+ /** Minimum free space (in GB) needed for data directory */
+ uint64_t AssumedBlockchainSize() const { return m_assumed_blockchain_size; }
+ /** Minimum free space (in GB) needed for data directory when pruned; Does not include prune target*/
+ uint64_t AssumedChainStateSize() const { return m_assumed_chain_state_size; }
/** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */
bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; }
/** Return the BIP70 network string (main, test or regtest) */
@@ -80,7 +84,6 @@ public:
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
const ChainTxData& TxData() const { return chainTxData; }
- void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
protected:
CChainParams() {}
@@ -88,6 +91,8 @@ protected:
CMessageHeader::MessageStartChars pchMessageStart;
int nDefaultPort;
uint64_t nPruneAfterHeight;
+ uint64_t m_assumed_blockchain_size;
+ uint64_t m_assumed_chain_state_size;
std::vector<std::string> vSeeds;
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
std::string bech32_hrp;
@@ -107,7 +112,7 @@ protected:
* @returns a CChainParams* of the chosen chain.
* @throws a std::runtime_error if the chain is not supported.
*/
-std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain);
+std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain);
/**
* Return the currently selected parameters. This won't change after app
@@ -121,9 +126,4 @@ const CChainParams &Params();
*/
void SelectParams(const std::string& chain);
-/**
- * Allows modifying the Version Bits regtest parameters.
- */
-void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
-
#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index da9f3e3209..f0559a319a 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -1,13 +1,13 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparamsbase.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilmemory.h>
+#include <util/system.h>
+#include <util/memory.h>
#include <assert.h>
@@ -20,6 +20,7 @@ void SetupChainParamsBaseOptions()
gArgs.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
"This is intended for regression testing tools and app development.", true, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-testnet", "Use the test chain", false, OptionsCategory::CHAINPARAMS);
+ gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)", true, OptionsCategory::CHAINPARAMS);
}
static std::unique_ptr<CBaseChainParams> globalChainBaseParams;
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 9f8bbafcd5..355df043d3 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h
index 6e2b3c34a2..4b982a4715 100644
--- a/src/chainparamsseeds.h
+++ b/src/chainparamsseeds.h
@@ -8,1076 +8,785 @@
* IPv4 as well as onion addresses are wrapped inside an IPv6 address accordingly.
*/
static SeedSpec6 pnSeed6_main[] = {
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x13,0x05,0x7f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x1d,0x8b,0x78}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0x40,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x84,0x64,0x2f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x01,0x61,0x04}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0xae,0x74}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x45,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x4b,0x0f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x6c,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x65,0x8c,0xc2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x85,0x0d,0x38}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xaf,0x18,0x07}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbd,0x85,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x4f,0x0e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x35,0x10,0x85}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x65,0x8b,0xa6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xb2,0x4e,0x8b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbd,0xb0,0x11}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xe4,0x40,0x47}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0x50,0x43,0xa2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0e,0xc0,0x08,0x1b}, 21301},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x59,0xc1,0xc9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x08,0x12,0x26,0x7a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0x73,0x60,0x3f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0e,0x02,0x7c,0x54}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0e,0x03,0xaa,0x01}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x5e,0x1c,0xfa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x6f,0xac,0x6a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x7d,0xe0,0x54}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe1,0xa0,0x1a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe2,0xe7,0x7a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe3,0xcc,0x4e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xee,0x84,0xbc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xf0,0x43,0xcc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x19,0x8d,0xba}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x78,0xeb,0xb9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x8a,0xbc,0x3c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xd3,0xe5,0x07}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xdc,0x4e,0xa1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe1,0x22,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe8,0x88,0x77}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1b,0x44,0x83,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x98,0x00,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xaf,0x00,0xde}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe5,0x10,0xea}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe9,0x06,0x46}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x8e,0x22,0xfd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xab,0xcb,0x57}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xbc,0xc8,0xaa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xd8,0x41,0x29}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe3,0x45,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1b,0x21,0x0b,0xc1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x18,0x0b,0x8b}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x1c,0x0a,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x1f,0xcb,0x71}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x91,0x6a,0x3d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xa5,0x11,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xb3,0xcc,0x8e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0x60,0xba}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xd2,0xac,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xd3,0x66,0x81}, 62734},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x30,0x40,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x78,0xa3,0xb5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x86,0xa7,0x5b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbf,0xe1,0xae}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc0,0x29,0x20}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc2,0x0a,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc8,0x22,0x12}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xcd,0x08,0x4e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x1b,0x64,0x2c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x66,0x45,0x46}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x22,0xd9,0x7a,0xb2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xe6,0x40,0x1d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xe7,0xe1,0x2a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x24,0x03,0xac,0x0d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x24,0xfb,0xa3,0x2a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x88,0x61,0xf6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x99,0x01,0x96}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x99,0x01,0x9d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xe4,0x5c,0x6e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xfc,0x0e,0x16}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x1b,0x65,0xe0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x66,0x86,0x55}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x68,0xe1,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x29,0x56,0x68,0x5e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x29,0xaa,0x40,0x08}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xe5,0x4c,0x2d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xf8,0xa0,0x97}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x20,0x41,0x13}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x3e,0xc6,0x2e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x13,0x88,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x14,0xf6,0x75}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0x45,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcd,0x70}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa0,0xc3,0x79}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa3,0x76,0x33}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0x81,0x9f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xb7,0xec,0xfe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe3,0x65,0xb0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xe5,0x4c,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x28,0x84,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x2d,0x22,0x7a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x30,0xb1,0xde}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x13,0x22,0xec}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0x42,0xc4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcc,0x15}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcd,0xa1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1e,0x2a,0x90}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x8a,0x8b,0xc3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa5,0xf5,0xdd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0x81,0x9b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa0,0x34}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa0,0x38}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x2c,0x52}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x7e,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xa5,0x91}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xa8,0xc9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xee,0xee,0xb0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xf2,0x83,0xa8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x14,0x67,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xee,0xbb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x36,0xcc,0xf6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x4a,0x80,0x8a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x5e,0xe0,0x63}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xbb,0x01,0x53}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xdf,0xe8,0x3a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x61,0x60,0xc6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xbb,0x24,0x30}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xda,0x10,0x51}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xdf,0x42,0xde}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xfe,0x80,0x0f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xfe,0x80,0xc5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x02,0xbd,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x1c,0x63,0x51}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x1f,0xaa,0x33}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x7e,0xc2,0xbe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x0f,0x00,0x11}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x1d,0x00,0x25}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x3b,0x60,0x0b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0xe1,0x80,0xbf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x54,0x62,0x45}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xc5,0x04,0x5c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xdf,0x88,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0xad,0xe0,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0xe5,0xd0,0xa6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x7d,0x83,0x37}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x0d,0xc1,0xce}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x1f,0xaa,0x35}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x23,0x43,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4c,0x60,0xe6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x52,0xb1,0x8e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x0f,0x03,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0xaf,0x8d,0xf3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x90,0x2f,0x99}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0xe8,0x26,0x7a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x26,0xc0,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x55,0x41,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x5b,0xe3,0xbc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0xb4,0x24,0x0e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3b,0x6a,0xd0,0x44}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3c,0x46,0x49,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0xa0,0xea,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2b,0xc6,0x38}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2d,0x00,0x0f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x6b,0xc8,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x85,0xc2,0x9c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x8a,0x0b,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xb6,0xab,0x74}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xc3,0xc1,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd2,0xa1,0xf9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x8d,0xe4,0x12}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x8f,0x25,0x2e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x22,0xe7,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x27,0xea,0x31}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x6e,0x19,0x1a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x79,0x23,0x03}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x13,0x9b,0x58}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x85,0xc2,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x8a,0x03,0xe0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x92,0x46,0xd8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x4e,0xa3,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x78,0x6e,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x83,0xa0,0x1f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x12,0xac,0x10}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xa0,0x80,0xd7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x55,0x4a,0xf2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x6e,0x84,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x72,0x21,0x5a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xb4,0x40,0x5f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xc2,0x26,0xfa}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x44,0x65,0xf9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x80,0x24,0x5a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x94,0x3c,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xde,0xa4,0xbc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x0b,0x8b,0x43}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x2b,0xbf,0x76}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x3d,0x89,0x9d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xc1,0xb8,0x0c}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xd2,0xe4,0xcb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xe1,0x86,0x1a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x0c,0x62,0xf6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc7,0x0a,0x4b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x27,0x31,0xc7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x29,0xab,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x29,0xab,0xe0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x22,0x01}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x2e,0x1b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0xe1,0x02}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x9f,0x86,0x3a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xb5,0xa0,0x50}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xde,0xc0,0x58}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x0f,0x4a,0x48}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xd7,0x0c,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xfd,0x48,0x77}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc9,0xe4,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xca,0x80,0x13}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x1e,0xda,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x3d,0x23,0xaf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x3d,0xab,0x16}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x7d,0xc2,0x19}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x23,0x62,0x0c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x3c,0x41,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x71,0x21,0x83}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x55,0xe2,0x4c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x67,0xab,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0xac,0xfc,0x1d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x22,0x60,0x87}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x44,0x30,0x95}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x5d,0xa1,0xa2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xa2,0xc0,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x0b,0xae,0x47}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x32,0xf0,0x7c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x46,0x20,0xd7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xd3,0xc4,0xe8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xea,0x70,0x16}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xfd,0xed,0x00}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xf1,0xc0,0x28}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x76,0xc0,0x77}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x7a,0xed,0x7c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x9f,0x06,0xa7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x0a,0x9d,0x3a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x5c,0x88,0x4b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x0f,0xe6,0x70}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x53,0x4f,0x34}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x7e,0x0e,0x1b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x4c,0x89,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x40,0xa6,0xe6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xbf,0x4f,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x25,0xaa,0x6a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x46,0x6b,0x53}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x5f,0xe2,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x6f,0xac,0x86}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xa3,0x88,0x88}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xea,0x32,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xcb,0x0d,0x39}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xef,0x25,0x0c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf0,0xa8,0x13}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf4,0xdb,0xa4}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x1f,0x43,0x9c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x22,0x02,0x7e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x6c,0xbb,0xf6}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x6d,0xa3,0x99}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x82,0xa1,0x4e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0xc0,0x23,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0xf8,0x41,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x2e,0xc2,0xa3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x4d,0x06,0x88}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x62,0xc4,0x59}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x9a,0x61,0xa8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa5,0xeb,0x77}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa9,0x23,0xeb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xb6,0xa7,0x89}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x52,0x43,0xb6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x52,0x4d,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x54,0x36,0x1a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd0,0xe0,0xd9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd0,0xe3,0x35}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xdc,0x2b,0xe4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xfe,0xbc,0xeb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0a,0xfb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x1c,0xcd,0x91}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x42,0x46,0x59}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x84,0xe6,0x90}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd1,0xe0,0x4f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd3,0xfc,0x68}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xe5,0x1c,0x3c}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0d,0x54}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x10,0xb6}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x12,0xe0,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x1b,0x60,0x25}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x6c,0xc4,0x48}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xba,0xf3,0xdc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xe4,0xc2,0xbb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x48,0xc6,0x44}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x4a,0xe0,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x60,0x40,0x06}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x75,0xa6,0x4d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x76,0xec,0x45}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xab,0x1b,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xbb,0x50,0xdd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xd9,0x70,0xe1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xf5,0x8d,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x2b,0xab,0x5b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x66,0x0a,0xfb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x76,0xea,0xb2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x90,0xc5,0x5d}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa1,0x6d,0xbe}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc1,0x66,0xe4}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc1,0x6d,0xc7}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc7,0x66,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc8,0xcc,0x77}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xca,0xc5,0xe0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd4,0x07,0xf2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd4,0x82,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd5,0xd0,0x10}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd9,0x43,0x11}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x6c,0x1b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x80,0x51}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x32,0x86,0x08}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x4e,0x21,0x87}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x85,0xae}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x37,0x82,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x4d,0x27,0x2e}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x89,0x29,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x96,0x25,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x95,0x46,0x30}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x97,0xe9,0xda}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa2,0x2b,0x9a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa4,0x83,0xf2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa4,0x83,0xf3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd1,0x08,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xec,0x87,0xfb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf3,0x3b,0x29}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf9,0x0d,0xdf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xfa,0x56,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x5e,0xeb,0xa1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x75,0x01,0x1b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xdd,0x0b,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf3,0x80,0x0d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x10,0x26,0xda}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x26,0x03,0xf9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x4b,0x1a,0xac}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xc8,0x6a,0x80}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd5,0x40,0x15}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xe2,0xa4,0xa1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf5,0x1b,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xfb,0xa1,0xcd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x05,0x01,0x48}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x0a,0x29,0x29}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0xc2,0x0c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x5f,0xf1,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd4,0xfa,0xdb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd7,0x86,0xc3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf5,0x1b,0xd1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xfe,0x28,0x98}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xff,0xc1,0x1c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x0a,0x70,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x5d,0x02,0x4c}, 54382},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x5e,0xac,0x21}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x81,0x00,0x7e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xaa,0xe8,0xf5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc3,0xe8,0x27}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x91,0xa8,0x9f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xaa,0xee,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc3,0xe8,0xc5}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x44,0x7a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xeb,0x89}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xf5,0xa7,0xf6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x08,0x23,0x11}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x69,0x05,0x71}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x6a,0x83,0xb3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x4f,0x44,0x56}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x78,0x08,0x05}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xef,0xca,0xef}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x62,0xc6,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x95,0x6a,0xec}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xcf,0xec,0xaf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x23,0x1d,0x03}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x26,0x60,0x46}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x8e,0x41,0x97}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xa3,0xe0,0xc3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xda,0x30,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xdc,0xa5,0xcd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xe5,0x86,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xf1,0x31,0xf2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x19,0x20,0x4d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x29,0x59,0xaa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x32,0x8f,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x3d,0x43,0xb7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x89,0x1a,0xd2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0xb1,0xc2,0xd7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x9d,0xb1,0x3a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xe0,0xa3,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xec,0xc4,0xa9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xf6,0x2e,0x84}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x63,0x40,0x4c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x01,0x64,0x31}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x0a,0x9b,0x58}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x1b,0x3b,0xf6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xa3,0x84,0x49}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xb3,0xf0,0x83}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xcd,0x51,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xd4,0x4b,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xd9,0x82,0x93}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xe6,0x60,0x2a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xec,0x65,0x34}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0xbf,0xcb,0x12}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x41,0x07,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xf8,0xac,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x2e,0x39,0x11}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x6e,0x0b,0x65}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0xf0,0x25,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x41,0x04,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x41,0xc0,0x9f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x53,0xed,0xb9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x6e,0x7d,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0xa0,0x3b}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x87,0x00,0xbb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x9a,0x71,0xe3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x8f,0x6d,0x44}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc3,0x2a,0x86}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xca,0x43,0x6b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdd,0x47,0x73}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe0,0x00,0xe3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe0,0x01,0x11}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe1,0xec,0x91}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe4,0x2d,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe7,0xe5,0x88}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xee,0x64,0xf9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x1b,0x8e,0x1d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdd,0x46,0x89}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x23,0x84,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x2a,0x25,0x8d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x36,0x10,0x90}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x3e,0x22,0xb8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xb1,0x02,0xb5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xf9,0xa9,0x24}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xff,0xb0,0x6d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x4b,0x12,0x97}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x4f,0xcc,0xde}, 10333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x5f,0x64,0x9b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x71,0x83,0x86}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xba,0xe7,0xf0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x7b,0x50,0x2f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xaa,0x0d,0x0f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xab,0xc9,0x44}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xb3,0xc5,0x98}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbe,0xcd,0x19}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x3b,0x87,0x94}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbe,0xce,0x97}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbf,0x83,0xb1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xd0,0x84,0xd6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x68,0x61,0xf7}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x9c,0x23,0x08}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xb1,0x6a,0xbd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xb5,0x2c,0x68}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xc6,0x61,0xd7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xec,0xc6,0xfd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xed,0x40,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf2,0xe8,0x5c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x54,0x86,0x6b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x69,0xb7,0xb7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xbf,0x82,0x64}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd5,0xa1,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xc7,0xad,0x71}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x2a,0x02,0x71}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x5e,0xe1,0x3d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0xed,0x18}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9e,0x27,0x40}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa3,0x47,0x7e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa3,0x6a,0x8b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd0,0xa3,0xd6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd5,0x8f,0x0d}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xe2,0x4d,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x14,0xe3,0x27}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x17,0x43,0x55}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x03,0x4a,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x17,0x80,0x41}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x1b,0x08,0xf2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x05,0x1f,0xfb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x1b,0x81,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x7e,0x64,0x94}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x4a,0x06,0x69}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x74,0xa0,0x66}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x07,0x40,0xf9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x0a,0x6a,0x31}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x19,0xc5,0x7d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x1d,0x07,0x67}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x7f,0x82,0x11}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xa2,0xd1,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xc6,0xed,0x4c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xee,0x03,0x56}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0xa5,0x22,0xfd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x2c,0xa2,0x32}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x38,0x88,0x69}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x3b,0xa6,0x8b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x3c,0x61,0x15}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x4f,0x6b,0x90}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xe0,0xc0,0xc9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0xbe,0xac,0xd1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x23,0x97,0x4c}, 8334},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x4a,0xc1,0x7f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x50,0x85,0xbf}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x50,0xa8,0x39}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x55,0x0e,0x6a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x64,0x2c,0x3a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xfa,0x04,0x4a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xfa,0x05,0x4a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x20,0xa2,0x95}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x9c,0x63,0xf0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x9c,0x67,0x48}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x63,0xa8,0x66}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xc2,0x2a,0x0a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xa8,0x65,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xab,0x71,0x34}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc5,0x40,0x03}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc7,0xc0,0x55}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc8,0x43,0xa1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xdc,0x10,0xfd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xed,0x04,0x1a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0xc6,0xa5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xb4,0x55,0x5d}, 33244},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x04,0x0b,0x1d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x31,0xc2,0x3a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc8,0x43,0xa2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xcf,0x84,0x2a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xed,0x04,0xca}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x9b,0x48,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xb7,0x25,0xa2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xaf,0x03,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xdc,0xc0,0x39}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x3d,0x66,0x05}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x6a,0x88,0xc3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x6e,0x5f,0xc9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xac,0x68,0x77}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6e,0x04,0x28,0x93}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x70,0xbb,0xb2,0x74}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x69,0x8b,0x2a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x5a,0xab,0x9e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xce,0xb1,0x15}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xed,0x6f,0x9c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x44,0x2f,0x52}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x74,0x58,0x4b,0x6e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x74,0xfa,0xc1,0xea}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x75,0x8d,0x8a,0xf0}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x43,0xc9,0x28}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x59,0xe5,0xb2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0xd3,0xa7,0x5a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0x4f,0x40,0x9a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xc8,0x05,0xba}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xfe,0xad,0x27}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0x02,0x80,0x6b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0xcb,0xa3,0x80}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x01,0x44,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0x1c,0x04,0xe6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0x1c,0x82,0xd2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0x1f,0x8f,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0xdc,0x0e,0x5c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0xdc,0x0e,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7c,0x12,0x85,0xdc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7e,0xcf,0x27,0x16}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x4d,0x25,0xd6}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x7d,0x64,0x02}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0x59,0x4e,0x57}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0xcc,0x4b,0x03}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x9e,0x4a,0xed}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0xd5,0x20,0xb0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x71,0x29,0x77}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x71,0x29,0x7d}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x72,0x0a,0xe9}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xbc,0x28,0xbf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x84,0x94,0x82,0x33}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0xff,0xe2,0xe9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x87,0x17,0xc2,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x19,0x89,0xdc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x37,0x0a,0xf9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0xf3,0x20,0x26}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0xf3,0x40,0x17}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0xe2,0x22,0x2e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0x3b,0x60,0x10}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0xa2,0xa0,0xe8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0xc7,0xe4,0x54}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xbc,0x2a,0x24}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x00,0x70,0x5c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x03,0x1a,0xbe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x87,0x17,0xc4,0x18}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x87,0x54,0xcf,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x3b,0x81,0x7d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x3d,0xef,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x75,0xa4,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0x82,0x29,0x52}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x86,0x47,0xbc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x8a,0x89,0x28}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x91,0x81,0x1f,0x93}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x47,0x4c,0x35}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x47,0x4c,0xec}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0xd2,0xe4,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0xe5,0x00,0x8f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0xd5,0x06,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0xdf,0x52,0x8b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8e,0x00,0x82,0x31}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8e,0x00,0x82,0x35}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x76,0x8d,0xe8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0x42,0x3a,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0x5f,0x82,0x11}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0xbb,0x24,0xe9}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0xf9,0x4c,0x66}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x7d,0xe0,0x2c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x04,0x63,0x96}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x85,0x81,0x61}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x9f,0x67,0xa1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x8c,0xc9,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x8c,0xe5,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0xb5,0x68,0x84}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0xb5,0x86,0xc1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa0,0x10,0x87,0xbb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xdd,0xe0,0x3f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa5,0xa5,0x84,0x44}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa5,0xc2,0x23,0xcb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0xe6,0x46,0x91}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa9,0x2c,0x22,0xcb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa9,0x30,0xa3,0xb0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaa,0x4b,0xa2,0xb4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaa,0x4b,0xc3,0xa8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x7d,0x81,0xbb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x7d,0xe0,0x6b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x30,0xec,0xfa}, 8887},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x42,0xcf,0x7e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x8f,0x8c,0xba}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x83,0x8e,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x40,0x4f,0xb6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x55,0x5d,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x8c,0x80,0xef}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0xae,0x83,0xab}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0x08,0x04,0x13}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xd9,0x90,0x44}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xd9,0x90,0xfc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xfd,0x2f,0xca}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0x9b,0x40,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xde,0x64,0x76}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xff,0xa8,0x1b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xff,0xa8,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa3,0x9e,0xe4,0x7d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa5,0xe3,0x60,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa9,0xe5,0xee,0x11}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xab,0x19,0xa5,0x91}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x60,0xa1,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x62,0xc1,0x2d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x67,0xa4,0x4b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x6e,0x08,0xe9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd1,0x35,0x72}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd4,0xc0,0x75}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xf3,0x40,0x31}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xff,0xe0,0xb9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x64,0x83,0x97}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x71,0x42,0xe6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x8a,0x3e,0x5a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x0a,0x88,0x19}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x17,0x0d,0x1b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x18,0xdc,0x8d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x6a,0xfc,0xad}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xab,0x21,0xb1,0x09}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x48,0xe4,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x60,0xa1,0xf4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x66,0xe4,0x96}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x76,0x88,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x2e,0x41,0x08}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd4,0xc1,0x23}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xef,0x21,0x55}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xf3,0x40,0x30}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x73,0x81,0x25}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x0c,0x06,0x3b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x6b,0xb8,0x1d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7b,0x0a,0xc0}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7e,0xa7,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb1,0x34,0xad,0x3f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x4e,0xe2,0xb2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x84,0x04,0x7b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xaf,0x90,0x7a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xdd,0x42,0xd4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xec,0x82,0xe5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xb9,0xeb,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xdf,0x82,0xfe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x00,0x47,0x88}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x0c,0x20,0x27}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x55,0x40,0xd4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x7c,0xa2,0xd1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x80,0xc0,0x15}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x97,0x85,0x38}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xc1,0x60,0xc9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xf8,0xc8,0x7e}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x07,0x58}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x22,0x90}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xff,0x29,0x15}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb3,0x30,0xfb,0x29}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb6,0xf7,0xee,0xa9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x6f,0x1d,0x1c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x40,0x0c,0x6d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb4,0xe9,0x6a,0xab}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0xa6,0xa8,0xd2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x42,0xe3,0x46}, 12060},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x6f,0x6c,0x38}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x46,0x21,0xbe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5f,0x26,0xda}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x08,0xac,0x79}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0b,0x52,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x69,0x46,0x64}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x69,0x46,0x65}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0c,0x07,0x26}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0c,0xec,0xf2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x14,0xe2,0x94}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x15,0xd8,0x86}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x16,0xe8,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xb8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xd9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x3c,0xc7}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x1c,0x4c,0xb3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x1f,0x88,0x45}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0x89,0xaf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0x8a,0x54}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0xb6,0x7b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x2f,0x84,0x6d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x35,0x80,0xb4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3f,0xac,0x0e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x68,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0x8b,0x36}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x2c,0x4e,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x2f,0x84,0x37}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x33,0x80,0x1b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3b,0x64,0x6b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x43,0xaf,0x4b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x43,0xcc,0x4c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x43,0xcc,0x50}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x46,0x69,0x4a}, 8339},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x4d,0x80,0x45}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x4d,0x81,0xb0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x55,0x03,0x89}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x55,0x03,0x8c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x56,0x0f,0x17}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x56,0x0f,0x19}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x66,0x47,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x75,0x4a,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x79,0xad,0xdf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x7f,0x11,0xa7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x9a,0x9c,0x32}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x80,0x28,0x7a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x91,0x83,0xda}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x93,0xed,0xa9}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xa2,0x80,0x53}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb7,0xa1,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xbd,0xc7,0xf8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xd7,0xe0,0x6b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x05,0x88,0x46}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x1f,0x04,0xca}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x1b,0x50,0x7e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x41,0xd4,0x31}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x74,0x8c,0x7f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x4f,0x91}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd6,0x80,0x12}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd6,0x80,0xaf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe3,0x40,0x13}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xea,0xf1,0xac}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xfd,0x02,0x7d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x0a,0x08,0xd3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x91,0x16,0xca}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xa5,0x4c,0xdc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xac,0xa5,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb1,0x05,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb7,0x83,0x4b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xba,0xd0,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xd7,0xe0,0x16}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xe0,0x50,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xe1,0x10,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xf3,0x70,0xd6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xf4,0xc1,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xf8,0xa0,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x13,0x88,0x90}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x44,0x26,0xf3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x44,0xf0,0x59}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x06,0x54}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x4d,0x79}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x01,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd9,0x09,0xa8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x02,0x85,0x5b}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xb8,0xc6,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xd2,0xea,0x26}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x5c,0x81,0x05}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x79,0xaa,0xb4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xd3,0xcc,0x44}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x8b,0x23,0x8f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa2,0x64,0x9c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa2,0xd2,0x5b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa9,0x06,0x7f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xaf,0x3b,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xde,0xed,0x10}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa2,0x65,0xfa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xce,0xca,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xcf,0x0c,0xf4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xcf,0x0c,0xf5}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xe4,0x65,0x9d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x17,0xb5,0x87}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x31,0x2b,0xdb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x6a,0x1e,0xad}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x8a,0xe0,0xe6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xe0,0x16,0x2d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x70,0xc0,0x49}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xaa,0xa6,0x0c}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x0f,0xe7,0xec}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x6a,0xd8,0x14}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xa5,0x10,0x21}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xb5,0x50,0x4d}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xba,0xa0,0xfd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xf6,0x56,0x20}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x16,0x68,0x17}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x31,0x4b,0xe9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x5b,0xf4,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xf7,0x0d,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xf7,0x0d,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x00,0xcb,0x15}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x26,0xa8,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x2b,0x8d,0x1c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x5f,0xe1,0xf8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x7b,0xe0,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9a,0xeb,0x4f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xa9,0x63,0x52}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc4,0x1c,0x62,0x15}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc4,0xdc,0x43,0x97}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xc9,0x00,0x51}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0x9b,0x06,0x2b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0xbd,0xec,0xfa}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0xea,0x45,0x92}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x8f,0x0c,0x69}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xbb,0x1c,0x02}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x44,0xc5,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x2c,0xe7,0xa0}, 6333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x3a,0x66,0x23}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x89,0xca,0xaf}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x7f,0xe0,0x32}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xc1,0x06,0x0e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xc9,0x6e,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xb6,0x81,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xbc,0xcc,0x66}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xbc,0xcc,0x9b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf4,0x31,0xe0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf9,0xe6,0x25}, 15738},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x53,0x7b,0x2e}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x6d,0x43,0x47}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x7a,0x80,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc9,0xee,0xdf,0xa5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x2f,0xe1,0xf2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x3c,0x02,0x43}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x7a,0x80,0xb9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x99,0xc7,0xb6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x9f,0x88,0x36}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0xa8,0x10,0xe8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x0b,0x47,0x01}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0xa2,0x50,0xdb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0xb2,0x8f,0x0d}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x0f,0x0b,0x04}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x0f,0x0b,0x08}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x8a,0xa5,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0x7b,0x0b,0x8b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xfd,0xa3,0xe2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xbc,0x10,0x10}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x4d,0x12,0x19}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x56,0xa1,0x53}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x64,0x89,0xcc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0x7d,0xa9,0xa2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xae,0x37,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xb6,0x92,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x5d,0x42,0xc6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x62,0xc4,0xf9}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x6b,0xe0,0xca}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x6e,0x41,0x72}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x76,0xeb,0xbe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x9f,0x89,0x92}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xa1,0x04,0xa4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xc5,0x0d,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0xd3,0x6d,0xa5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x97,0x26,0x5c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x20,0xe5,0xe6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x33,0x0e,0x48}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x7a,0xd0,0x83}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x7e,0x6e,0xc6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x83,0xee,0x50}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x38,0x6c,0x51}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x6e,0xab,0x76}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x7c,0xa0,0xc7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x80,0x2c,0x31}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x95,0xeb,0xb9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xc7,0xaf,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xed,0x60,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x43,0x63,0x8e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x49,0x96,0x84}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x4d,0xe0,0x91}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x55,0x5a,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x5c,0x65,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x70,0x85,0x5c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xe3,0x84,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x0a,0x64,0xb6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x39,0xf0,0x45}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x5b,0xcd,0x86}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x73,0xe0,0xfc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x83,0x0c,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x84,0x4c,0xb8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x7d,0x43,0x6c}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x98,0xa1,0xaa}, 45893},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x9b,0x03,0xd8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x9c,0x6c,0x3f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xdb,0xa2,0x92}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x24,0xb3,0x1b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xb8,0x08,0x1a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf5,0xda,0xf2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x0c,0xcc,0x56}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xb4,0x46,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xb9,0xe2,0xe1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x47,0xcb,0x4f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xc2,0xa4,0xd3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf0,0xa8,0xe2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x14,0x82,0x48}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xa9,0x07,0x6f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xb6,0xc0,0x07}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xc7,0x63,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdb,0x58,0xe8,0xe5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x09,0xb4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x40,0x2f,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xa9,0x0e,0x5a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0xf5,0x01,0xcd}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0x82,0x80,0x3a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0xbf,0xa9,0x5a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdd,0x7f,0x2b,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xef,0xc1,0xd2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0x11,0xca,0xce}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x10,0xf2,0x28,0x73,0x97,0x0b,0x20,0x68}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x10,0xf6,0x1a,0xa2,0xae,0x9d,0x42,0x86}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x0a,0x0d,0x05,0xc1,0xe1,0xb5,0xc4}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x2a,0x19,0x57,0xb6,0x1e,0x05,0x6e}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x2d,0x0f,0xac,0x2a,0xaf,0xe4,0xc2}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x71,0x04,0x52,0x66,0x71,0x82,0x74}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x14,0x82,0x05,0x30,0xb1,0x45,0x7e,0x28}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x18,0xac,0x39,0x54,0x39,0x01,0xa2,0x57}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x18,0xd5,0x3c,0x77,0x82,0x9a,0x6f,0xe6}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0x66,0x16,0x4f,0xb3,0x9d,0xb0,0x87}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0x69,0x07,0x8b,0xb7,0xd5,0x58,0x60}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0xac,0x22,0xb1,0xbb,0x18,0x11,0x60}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0xf6,0x14,0x7f,0xe7,0xe9,0xdd,0xd1}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0xfa,0x31,0x26,0x97,0xf1,0x60,0x0d}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x24,0x57,0x0f,0x34,0xa3,0x13,0x4b,0x99}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x28,0xf4,0x25,0x12,0xbc,0x91,0x2e,0x53}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0x55,0x0f,0xa9,0xfd,0xe5,0x5d,0x86}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0xba,0x18,0x28,0x52,0xae,0x75,0x01}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0xf3,0x78,0xfc,0xa1,0x38,0xe6,0xed}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x30,0x01,0x0b,0xf6,0xbe,0x62,0xcc,0xe5}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x30,0xa8,0x3a,0xfb,0xb6,0xd5,0x2b,0xd7}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x30,0xe6,0x04,0x4d,0xae,0x7f,0x74,0x9d}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x02,0x0d,0xaf,0xb4,0x75,0xda,0xf9}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x23,0x3d,0x03,0xd7,0x71,0xd5,0x01}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x24,0x02,0x11,0xb6,0x00,0xb4,0xcb}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x2f,0x14,0x53,0xcd,0xdc,0x4f,0x03}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0x57,0x24,0x8d,0xa0,0xb9,0x3b,0xc9}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x38,0x6f,0x38,0x46,0xb9,0x95,0x01,0x88}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x38,0xa8,0x31,0x8a,0xe7,0xdc,0xae,0xe1}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x38,0xeb,0x1e,0x88,0xad,0xdb,0x18,0x1c}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0x39,0x27,0xe3,0x47,0x58,0x36,0x5c}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0x7d,0x3f,0xa4,0x86,0xad,0x4e,0xbb}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0xfd,0x31,0x81,0xb2,0xc7,0x5c,0x5e}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x04,0x01,0x21,0x57,0x68,0x4e,0xf2,0xd6}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x04,0x3a,0x1a,0x64,0xbd,0x14,0xfb,0x16}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x04,0x7d,0x00,0xbb,0xae,0x1e,0x29,0x48}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x08,0x43,0x9b,0x9e,0xcd,0x0a,0x66,0x55}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x08,0x86,0x3c,0x19,0xad,0xdd,0x9a,0x58}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x08,0xba,0x09,0xf8,0x9e,0xad,0x0f,0x21}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x0c,0x06,0x12,0x4c,0xa4,0x82,0xa7,0x61}, 8333},
- {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x0c,0xda,0x0b,0x84,0x8d,0x4c,0xd1,0xe6}, 8333},
- {{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x00,0x20,0x0a,0x71,0x85,0x8b,0x83,0xf7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0x85,0x27,0x3d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xef,0xc1,0x74}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xef,0xc1,0x78}, 8333},
+ {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x1c,0xbd,0x3b,0xc0,0xad,0xe7,0xbf,0x44}, 8333},
+ {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0x46,0x15,0x0d,0x8d,0x65,0x0d,0xe4}, 8333},
+ {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0x99,0x3f,0x36,0xd0,0x03,0xf4,0x7a}, 8333},
+ {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0xb6,0x39,0x10,0xa3,0xdc,0x7b,0xfa}, 8333},
+ {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0xec,0x02,0xb5,0x52,0x5b,0xfb,0x3c}, 8333},
{{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x00,0xc5,0x23,0x5d,0xa1,0x0d,0x00,0xe0}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0x3a,0x23,0xfb,0xbb,0x8a,0xed,0x5b}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0x64,0x0d,0x3d,0x51,0xff,0x59,0x38}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x10,0xfd,0x13,0x69,0x71,0x5e,0x6a,0xa7}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x14,0xd5,0x17,0x58,0xb1,0x7d,0x5e,0xb1}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0x17,0x26,0x34,0x9f,0xc9,0x1b,0xc4}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0x1a,0x27,0x17,0x94,0x41,0xc1,0xeb}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0x75,0x0b,0xc8,0xb1,0xc2,0x01,0xb4}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0xb5,0x31,0x85,0x51,0xa2,0x03,0x5d}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0xc3,0x0f,0xeb,0xb4,0x71,0x49,0xd1}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x18,0xdd,0x3b,0xd5,0x41,0x8f,0x0c,0x1e}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x19,0x30,0x62,0xbc,0xaa,0x09,0x6b}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x53,0x14,0xbd,0xb8,0xd9,0x7a,0xa2}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x60,0x08,0x2b,0x94,0xfd,0xa4,0x52}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0x85,0x2e,0x50,0xba,0x7d,0x0a,0x1a}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x1c,0xff,0x2d,0x43,0x51,0xf9,0xb8,0x89}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0x74,0x22,0x1a,0x47,0x50,0xeb,0x12}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0x8f,0x2d,0x83,0xe0,0xf5,0xe3,0x1f}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0x92,0x37,0x1f,0x9d,0xfb,0x98,0xcd}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x20,0xf3,0x39,0xa2,0x39,0xca,0x03,0x8c}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0x1c,0x20,0x85,0x51,0x8d,0x9c,0x97}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0x51,0x00,0x0c,0x52,0x4c,0xa1,0x80}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0x53,0x3b,0x95,0xa4,0x30,0x40,0xf3}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x28,0xf6,0x30,0xa4,0x30,0xd9,0x12,0x01}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x2c,0x5f,0x1a,0xde,0x71,0x8f,0x60,0x9d}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x2c,0xc0,0x1b,0x38,0xe7,0xaf,0xae,0x80}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x00,0x3d,0xc4,0x52,0x4d,0x3c,0xe2}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x60,0x2e,0x81,0x51,0x8f,0x63,0xbc}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x68,0x05,0x07,0xbc,0xaf,0xdb,0xad}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0x8f,0x00,0xf3,0x93,0x5d,0x6a,0x1b}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0xce,0x33,0x01,0xd2,0xd0,0x9b,0xbc}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x30,0xdb,0x31,0x45,0x43,0x81,0xf1,0x47}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x34,0xa3,0x22,0x98,0xb7,0xcd,0x22,0xf6}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x04,0x1e,0x01,0x60,0xbc,0x48,0x79,0x1d}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x00,0x42,0xb4,0xfc,0x3f,0x74,0xaf,0xfb}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x04,0x7a,0x16,0xaa,0xd0,0xc9,0x30,0xa4}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0x9c,0x34,0x81,0xd9,0x73,0x5d,0xad}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0xbe,0x31,0x4a,0x26,0xb2,0xef,0xef}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0xf3,0x3d,0xaf,0x3f,0x21,0x0b,0xac}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x0c,0x1f,0x20,0xf4,0xb9,0xac,0x99,0xdb}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x0c,0x70,0x10,0x5c,0x77,0xde,0x9f,0x7d}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x00,0xed,0x20,0x0c,0xb9,0xac,0x34,0xdb}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfd,0x30,0x57,0x08,0x5b,0xb7,0x03,0x25,0x5d}, 8333},
- {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfd,0x08,0xd1,0x13,0xc6,0x5d,0x0a,0xb1,0x17}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0x07,0x39,0x5e,0xcd,0x3a,0x82,0xf2}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0x8b,0x34,0xb5,0xe8,0xe3,0xee,0xd7}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0x9c,0x07,0x38,0x7f,0xb9,0x78,0x5c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x14,0x01,0x03,0x93,0xba,0x7f,0xc3,0x13}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x14,0x49,0x21,0xd9,0xa0,0x5e,0x32,0xf5}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x14,0x98,0x36,0xb6,0xa2,0x9b,0x12,0xa4}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0x3d,0x36,0x49,0xb8,0xf5,0x35,0xd9}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0x57,0x32,0x93,0x43,0x8b,0x73,0xde}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0xb0,0x15,0xd3,0x43,0x1c,0xbf,0xec}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0xb1,0x28,0x8b,0x51,0xc9,0xdb,0x37}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x18,0xd5,0x2a,0x37,0x68,0x06,0x97,0x97}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0x42,0x3a,0x1c,0x94,0x2f,0x7f,0x08}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0x7a,0x2f,0xb7,0xe7,0xd5,0x7e,0xe2}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0xc6,0x38,0xc6,0x43,0x8b,0x73,0xde}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0xd6,0x2f,0x48,0xfa,0x1b,0x51,0xc1}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0xda,0x2f,0xdf,0xb0,0x91,0xdb,0xe5}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0xf3,0x0b,0x9e,0xa1,0x4a,0x41,0xf3}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0x15,0x04,0x73,0x9d,0x21,0xcc,0x3c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0x5d,0xee,0xa3,0xa3,0xc8,0xea,0x79}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0x7c,0x19,0xb1,0xe7,0x58,0x1c,0x46}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0xcb,0x06,0xb0,0x46,0xcc,0xc2,0x7d}, 8333},
+ {{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x0c,0xbc,0x5a,0xce,0xa6,0x25,0x39,0xd1}, 8333},
+ {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x38,0xe5,0x36,0xc1,0xd0,0xee,0x5d,0x98}, 8333},
+ {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x3c,0x5c,0x0c,0x6c,0x39,0xcf,0x69,0xd3}, 8333},
+ {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0x96,0x0e,0xf4,0xba,0x63,0x8d,0x15}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0x6a,0x21,0x12,0xe0,0x6b,0xb8,0x81}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0x99,0x16,0x55,0xe7,0x82,0x93,0x40}, 8333},
{{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0xcd,0x1c,0xd9,0x54,0xe6,0x5a,0x6e}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0xef,0x0b,0xc1,0x95,0xf0,0xa6,0x58}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0x09,0x2e,0xa4,0x47,0xee,0x3c,0x9d}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0x27,0x33,0x0a,0x94,0x41,0xdc,0x2d}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0x36,0x3c,0x78,0x43,0x1d,0xd5,0x59}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0xdd,0x2a,0xcb,0xb8,0xa9,0x5a,0xde}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0x69,0x2c,0xb3,0xb5,0x7b,0x31,0x1c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0xbf,0x33,0xd4,0x9d,0x29,0x8e,0xdc}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0xe0,0x14,0x2e,0x3e,0xd6,0xb1,0x82}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0xf3,0x16,0x75,0xc3,0xed,0x5b,0xe7}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x2c,0x4c,0x21,0xd6,0x94,0x6c,0xef,0x01}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x2c,0xd6,0x3f,0x49,0xa1,0xec,0x07,0x36}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x1d,0x1c,0xd6,0xba,0x5a,0x29,0x35}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x2b,0x34,0x0f,0xe7,0x23,0xb1,0x5e}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x34,0x2d,0x96,0xb5,0x7f,0xb0,0xe6}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0x6b,0x08,0x72,0xb4,0xbc,0xd7,0x9f}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0xa4,0x11,0x90,0x43,0x15,0x0e,0x53}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0xc3,0x13,0x62,0x52,0x1f,0x52,0xc5}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0xe7,0x3e,0x5c,0xda,0x3f,0x64,0x66}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x39,0x02,0x23,0xa0,0x4a,0xfd,0xfd}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x77,0x14,0xcd,0xf7,0xde,0xde,0xe8}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x98,0x01,0xa5,0x46,0x35,0x2b,0x50}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0x9d,0x0d,0xb2,0xa0,0xe6,0x29,0xa2}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0xf7,0x15,0xb2,0x30,0x12,0x3a,0x74}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0x09,0x29,0x41,0x43,0x44,0x48,0x38}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0x09,0x37,0xb7,0x31,0xb5,0x8e,0x3d}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0x77,0x2d,0xac,0xb6,0x91,0x71,0x9c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0x8a,0x24,0xf3,0xa1,0x41,0xc1,0x94}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0xba,0x3b,0x3e,0x43,0x0c,0xfb,0x74}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0xc4,0x2f,0x2a,0x93,0x57,0xb1,0xae}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x38,0xe2,0x02,0x3f,0xb4,0xf6,0x6a,0xd1}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x3c,0x56,0x21,0x71,0x9d,0x80,0xd3,0x60}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x3c,0xab,0x14,0x21,0x3c,0xa4,0x1a,0x8e}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x00,0x3f,0x24,0x41,0x68,0x06,0x97,0x97}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x04,0x24,0x03,0x21,0x52,0xb3,0x56,0x33}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x04,0x7c,0x32,0xef,0xa7,0xa8,0xa2,0xb4}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x04,0xa7,0x3c,0xdd,0x9d,0x1b,0x07,0x08}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x04,0xc3,0x3a,0x54,0x9d,0x1c,0x2a,0xd7}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x13,0x3a,0xe3,0xbd,0xd2,0x66,0xd8}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x18,0x0c,0xf4,0x27,0xf2,0xb5,0xf5}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x55,0x33,0xf7,0x6d,0xbd,0x53,0xc4}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x68,0x1b,0xaa,0xb1,0x74,0xb7,0x64}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0x78,0x21,0xcf,0x2b,0x5b,0x28,0x60}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0xa4,0xe1,0xd1,0x79,0xec,0x7c,0xee}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0xb3,0x39,0x2c,0xab,0x0d,0xae,0x6b}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x08,0xff,0x35,0x2f,0xb2,0x08,0x56,0x04}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0x2f,0x17,0x93,0xfa,0x42,0xac,0xdc}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0x36,0x02,0x5f,0xa0,0xd0,0xe8,0x71}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x00,0xd3,0x06,0x9e,0xd0,0xa0,0x1b,0x73}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x10,0x9f,0x37,0x9e,0xae,0xff,0x39,0x57}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x10,0xa5,0x2f,0x7d,0xab,0x07,0x9c,0x7b}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x14,0x62,0x3f,0xe1,0xb2,0xcf,0xdc,0xf0}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x18,0x0b,0x29,0xbe,0x34,0x29,0xfe,0xde}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x18,0x57,0x02,0x4c,0x46,0xf4,0x7d,0xc9}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x18,0xd5,0x0a,0x69,0x4b,0x4a,0x6e,0x8b}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x1c,0x20,0x25,0xa2,0x3f,0x5d,0x2d,0xa4}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x1c,0x96,0x24,0xdc,0xa7,0x53,0xd6,0xf2}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x1c,0xe7,0x05,0x33,0x26,0xf3,0x2a,0xab}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x20,0x65,0x30,0x08,0x76,0xb5,0xcb,0x06}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x20,0xb2,0x04,0x34,0x43,0x87,0xf5,0xe1}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x20,0xff,0x14,0x7c,0x84,0x0c,0xb0,0xdb}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x24,0x36,0x3c,0x96,0x91,0xe9,0x2d,0xe3}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x24,0x4c,0x18,0x17,0xae,0x9f,0x8a,0x38}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x28,0x4c,0x29,0xce,0x88,0xb5,0xc8,0x6f}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x28,0x5a,0x00,0x5c,0xc1,0x6b,0x11,0x9a}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x2c,0x5f,0x0a,0x51,0xa6,0x71,0x3d,0x90}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x30,0x65,0x32,0x55,0x4b,0x21,0xe5,0x20}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0x1d,0x2d,0xfa,0x89,0x2f,0x43,0x66}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0x50,0x30,0x2f,0x23,0xb3,0xa3,0x3a}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0x56,0x23,0x08,0xd0,0xb5,0x79,0x70}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0x70,0x34,0x6d,0xaf,0x23,0xd4,0x1b}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x34,0xba,0x20,0xc2,0x9a,0x5a,0xdd,0x02}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0x46,0x11,0x33,0xa6,0x8c,0xea,0x80}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0xef,0x31,0xea,0x6c,0xd1,0x45,0xdb}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x1f,0xc3,0x5a,0xcc,0x00,0x28,0xd3}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x49,0x15,0x39,0xfe,0x22,0x5b,0x3b}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x5e,0x2e,0xcd,0x88,0xee,0x78,0x7c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x3c,0x74,0x01,0x94,0x4f,0x94,0x0e,0x1b}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x04,0xc4,0x34,0x92,0x4d,0x56,0x35,0xdd}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x04,0xe7,0x35,0xf2,0xae,0x92,0xcb,0xcd}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x08,0x50,0x2b,0x2f,0xad,0xbf,0xfa,0x7e}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x08,0xba,0x0f,0x4f,0x3e,0x75,0xb0,0x0b}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x00,0x9e,0x32,0x94,0xc2,0xb5,0x67,0xd7}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x0c,0x74,0x08,0x1b,0xa2,0xfb,0xaa,0x90}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x14,0x6b,0x2c,0xc2,0xb2,0xa5,0x0d,0xb7}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x18,0xd3,0x16,0x02,0x2a,0x06,0xc5,0x62}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x24,0xa7,0x0e,0xe0,0x72,0xcc,0x7f,0x75}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x28,0x62,0x13,0x84,0xb4,0xb8,0x40,0x6f}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x30,0xc4,0x36,0x98,0x92,0xa5,0x3a,0xf9}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x34,0x0b,0x12,0x70,0x4d,0x61,0x08,0x57}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x3c,0xb3,0x27,0x73,0x4d,0xa3,0x0d,0x4c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x3c,0xdf,0x08,0xab,0xa3,0x31,0x0d,0x75}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x04,0xd1,0x36,0x6f,0x4f,0x91,0xea,0xfb}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x08,0x3f,0x0b,0x1c,0xc1,0xa4,0xad,0x71}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0x67,0x13,0xc5,0xa6,0x9c,0xb0,0x99}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0xaa,0x20,0xc7,0xaa,0x6f,0xd3,0x18}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x10,0xdf,0x16,0xc3,0xb3,0x51,0xe8,0x24}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x14,0x64,0x25,0x5e,0x92,0x08,0x80,0x12}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x14,0xe1,0x01,0xb8,0xb2,0x56,0xff,0x4c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x18,0x0c,0x0e,0xbf,0x2a,0x63,0x93,0xc0}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x18,0xfb,0x09,0xd7,0xaf,0x8d,0xa5,0xd5}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0xa1,0x3e,0x8e,0xab,0x02,0xed,0xbe}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0xd7,0x3f,0xe8,0xe8,0x0f,0x53,0xf9}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x20,0xd8,0x10,0x62,0x26,0x84,0x32,0xc2}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x19,0x37,0x3e,0xda,0x40,0x1e,0x51}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x2b,0x1a,0xc2,0xfd,0xcc,0xaf,0x6a}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x42,0x2d,0x34,0x9e,0x97,0x36,0xa0}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0x6c,0x24,0xf1,0x3c,0x0f,0x65,0xfc}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0xc4,0x15,0xe7,0xd0,0xcb,0x7a,0x52}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0x5e,0x02,0xb3,0xa3,0x00,0x31,0x7e}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0x14,0x21,0x5c,0x88,0xe3,0x4e,0xe0}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0xac,0x3a,0x51,0xb2,0xda,0x71,0x2d}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0xa6,0x0e,0xeb,0xc3,0xed,0x5b,0xe7}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0x2f,0x16,0xd5,0x52,0x5a,0x10,0x7e}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0xb1,0x25,0x57,0x43,0x1c,0xf3,0xe1}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x10,0x56,0x29,0x0d,0xa6,0x71,0x3d,0x90}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x18,0x65,0x14,0xfe,0xd0,0xa7,0x1f,0x72}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x2c,0x3c,0x30,0x06,0xa4,0x86,0x93,0xc3}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x2c,0x73,0x33,0x13,0xf2,0x1a,0x96,0xda}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x30,0x50,0xfb,0xff,0xa2,0x50,0x33,0x86}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0x28,0x04,0x94,0xfd,0xaa,0x56,0xcd}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x04,0x54,0x18,0x7d,0x3e,0x75,0xb0,0x0b}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x0c,0x2c,0x1d,0xcc,0xfa,0x42,0x41,0xa3}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0x4a,0x20,0xd4,0x4d,0xaa,0xeb,0x5a}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0xa7,0x16,0x12,0x9a,0x18,0x31,0xe5}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0xc8,0x3a,0x0a,0xa6,0x8d,0xf7,0x99}, 8333},
{{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x37,0x32,0x4e,0xd0,0xcb,0x9f,0x45}, 22475},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x58,0x2d,0x7c,0xbc,0x51,0x6e,0xe0}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x9e,0x1b,0x03,0x43,0x8e,0xb5,0x17}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x9f,0x30,0xfc,0x54,0xbc,0x96,0x85}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xa2,0x07,0x60,0xa6,0xb3,0x31,0x39}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xa4,0x1b,0x25,0xb8,0xc7,0x38,0xff}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xd3,0x10,0x49,0xfd,0x91,0x71,0x2c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0x32,0x2d,0xa7,0xc1,0x11,0xdd,0x82}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0x91,0x1e,0x07,0x5d,0x3d,0x7e,0xb1}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0xe5,0x03,0xc7,0xb7,0x36,0x91,0x28}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0xf4,0x30,0xd4,0xe0,0x20,0x53,0xfa}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x2c,0xfc,0x22,0x21,0x98,0xe5,0xee,0xd7}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x30,0x16,0x0a,0xed,0x61,0x07,0x04,0xdf}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x30,0x3e,0x3e,0x8a,0xd0,0x6a,0xd1,0x37}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x30,0xee,0x19,0xd6,0x6e,0x7b,0x90,0x8e}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x2c,0x3e,0xcc,0xc2,0xa2,0x1e,0x31}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xc1,0x36,0x1e,0xa6,0x9c,0xb0,0x99}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x30,0xfe,0x1c,0x89,0xd0,0xb4,0x4d,0x18}, 8333},
{{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x74,0x1d,0xf1,0xe7,0x32,0xe5,0xe3}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x96,0x2e,0x2d,0xcb,0x17,0xc3,0xbd}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0xf3,0x35,0x84,0xd0,0xa4,0x0a,0xa5}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xe6,0x10,0x92,0xd0,0xcb,0x75,0x76}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xec,0x06,0x11,0xe0,0x5f,0xdf,0x3d}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xf5,0x39,0x38,0xb4,0x54,0x47,0x17}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x38,0xf8,0x14,0xce,0x88,0x09,0x77,0x86}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x2c,0x10,0xa4,0xbb,0xfa,0xe0,0x9d}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x35,0x2a,0x8e,0xe7,0x9f,0x62,0xfd}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x40,0x07,0x7b,0xc2,0xbb,0x00,0x79}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0x65,0x2a,0xdf,0xb8,0xde,0x17,0x81}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0x7c,0x01,0x29,0xd0,0xcb,0x6e,0x8b}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0x51,0x10,0xd8,0x9d,0x58,0x70,0x59}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0x5d,0x01,0x02,0x2a,0xa2,0x51,0x9a}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0x96,0x0f,0xe0,0xaf,0xc6,0x22,0x70}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0xa0,0x22,0xcc,0xa0,0xb3,0xd9,0xda}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x0c,0x0d,0x0d,0xe2,0xb9,0x4f,0x07,0x74}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x0c,0xff,0x0c,0x79,0xaa,0x69,0xcb,0x82}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0xa8,0x0f,0xb1,0x88,0xe3,0xfb,0x19}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x19,0x3d,0x23,0xd0,0xb4,0xf8,0x31}, 18652},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x45,0x23,0x42,0xd0,0xcb,0xd6,0xca}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x5f,0x31,0x05,0xd0,0xb4,0x60,0xb6}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0xa1,0x02,0xfb,0xd0,0xcb,0x1e,0x8f}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0xa3,0x36,0xe0,0xe0,0x20,0x53,0xfa}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0xeb,0x3b,0x30,0xd0,0xa4,0x0a,0xa5}, 8333},
{{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x10,0x4e,0x08,0xaf,0xb3,0xaa,0xf3,0x00}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x10,0x63,0x10,0xc4,0x93,0xfd,0x77,0xb5}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x10,0xdd,0x3d,0x0d,0xda,0xee,0xcc,0xda}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x18,0x83,0x22,0xe3,0xaf,0x92,0x33,0xc7}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x1c,0x0a,0x15,0x83,0x94,0x73,0x5f,0x2e}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x1c,0x44,0x2b,0x70,0x9d,0xe7,0xa7,0xcc}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x1c,0xbb,0x06,0x46,0xd2,0xcf,0xfd,0x00}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x20,0x51,0x34,0x8d,0xdc,0x5a,0xc3,0xc2}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x24,0xf8,0x19,0x8a,0xd0,0x23,0x65,0x80}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0x32,0x2e,0xa8,0xb8,0x17,0x2b,0xb0}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0x6d,0x3c,0xef,0x43,0x86,0x49,0x37}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x2c,0xb1,0x17,0x19,0x53,0x98,0xe4,0x44}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0x53,0x8a,0x5e,0x25,0xe4,0x35,0x2d}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0x7b,0x23,0x09,0xb3,0x47,0x3f,0xdc}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0x84,0x1e,0x46,0x8a,0x72,0x75,0x0f}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0xa8,0x23,0x04,0x9d,0x47,0x7f,0xdf}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0xb9,0x2e,0xa0,0xe8,0x0c,0x53,0xe5}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x30,0xcf,0x3e,0x04,0xa8,0x8b,0x4f,0xe8}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x34,0x27,0x2c,0x62,0xbd,0x53,0xf1,0x2d}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x34,0x45,0x1b,0xcb,0xb8,0xb5,0x96,0x53}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x38,0x74,0x29,0x5f,0x9d,0xe2,0xcf,0x3c}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x38,0xbc,0x03,0xf1,0x52,0xc4,0xea,0x47}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x38,0xc9,0x39,0x4f,0xbe,0xa2,0xfd,0x60}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x38,0xe8,0x23,0x91,0xb6,0xb2,0x90,0xc1}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x3c,0x43,0x03,0xf1,0xb4,0x89,0xf8,0xb8}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x04,0xc5,0x2a,0xe2,0xb6,0x43,0x38,0x66}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x04,0xdb,0x3a,0x7f,0x87,0xb0,0xf8,0x76}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x08,0xbe,0x0c,0xe8,0xb8,0xc5,0x52,0x12}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x00,0xac,0x2e,0xab,0x2f,0x99,0x80,0xc4}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0x0a,0x19,0x23,0x52,0xa0,0x7a,0xb2}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x00,0xc2,0x17,0x15,0xb8,0x0b,0x71,0x21}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0x8c,0x0e,0xe1,0x51,0x99,0xbf,0x8a}, 8333},
- {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0xbb,0x03,0xf5,0xa6,0x70,0xb0,0x45}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x14,0x34,0x07,0x1f,0xb8,0x50,0xba,0xb1}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x14,0x4a,0x36,0xe8,0x51,0x9a,0xbb,0x69}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x20,0xfc,0x26,0xef,0xed,0x26,0xc7,0x37}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x04,0x54,0x01,0x20,0x88,0xe8,0x02,0xfb}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x08,0x01,0x16,0x20,0xbc,0x22,0x95,0xbc}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x08,0xa0,0x1f,0xdb,0xab,0x00,0x0b,0xc2}, 8333},
+ {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0xf6,0x3d,0x48,0x43,0x86,0x49,0x37}, 8333},
{{0x20,0x01,0x13,0xd8,0x1c,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333},
- {{0x20,0x01,0x13,0xd8,0x1c,0x01,0x20,0x00,0x24,0x70,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x14,0xba,0x19,0x00,0x00,0x00,0x00,0x00,0x07,0x54,0xf2,0x71,0x15,0x1c}, 8333},
- {{0x20,0x01,0x16,0x08,0x00,0x10,0x01,0x56,0x00,0x38,0x00,0x00,0x00,0x00,0x26,0x5c}, 8333},
{{0x20,0x01,0x16,0x20,0x09,0x23,0x00,0x00,0x75,0xbe,0xed,0x92,0x1a,0x01,0x06,0x41}, 8333},
{{0x20,0x01,0x16,0x80,0x01,0x01,0x00,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x18,0x38,0x20,0x00,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333},
- {{0x20,0x01,0x19,0xc0,0x00,0x01,0x08,0x01,0x08,0x01,0xff,0x00,0x04,0x6c,0x00,0x02}, 8333},
- {{0x20,0x01,0x19,0xf0,0x00,0x00,0x20,0x4f,0x54,0x00,0x00,0xff,0xfe,0x05,0x2d,0x2e}, 8333},
- {{0x20,0x01,0x19,0xf0,0x50,0x00,0x8c,0x8b,0x54,0x00,0x00,0xff,0xfe,0x1f,0xc0,0x23}, 8333},
- {{0x20,0x01,0x19,0xf0,0x00,0x05,0x17,0xa7,0x54,0x00,0x00,0xff,0xfe,0x87,0xcc,0x21}, 8333},
- {{0x20,0x01,0x19,0xf0,0x5c,0x01,0x06,0x3b,0x54,0x00,0x01,0xff,0xfe,0x47,0x2e,0xde}, 8333},
+ {{0x20,0x01,0x19,0x70,0x5a,0xe2,0x2b,0x00,0x30,0xbd,0x79,0x10,0x0c,0x84,0x7a,0x8f}, 8333},
+ {{0x20,0x01,0x19,0x70,0x5d,0x56,0xaa,0x01,0x1e,0x75,0x08,0xff,0xfe,0xad,0xda,0x48}, 8333},
+ {{0x20,0x01,0x19,0xf0,0x03,0x00,0x10,0x45,0x02,0x25,0x90,0xff,0xfe,0xc9,0x29,0xb3}, 8333},
+ {{0x20,0x01,0x19,0xf0,0x00,0x05,0x1f,0x93,0x54,0x00,0x01,0xff,0xfe,0x7a,0xc6,0x5a}, 8333},
+ {{0x20,0x01,0x19,0xf0,0x6c,0x01,0x04,0xbd,0x54,0x00,0x01,0xff,0xfe,0x76,0x4d,0xb6}, 8333},
{{0x20,0x01,0x19,0xf0,0xac,0x01,0x02,0xfb,0x54,0x00,0x00,0xff,0xfe,0x5b,0xc3,0xff}, 8333},
+ {{0x20,0x01,0x1a,0x48,0x00,0x07,0xaf,0x1a,0x75,0xf8,0x2c,0x47,0x32,0x85,0xd5,0x0e}, 8333},
+ {{0x20,0x01,0x1a,0xf8,0x40,0x10,0xa0,0x94,0x33,0x33,0x00,0x00,0x00,0x00,0x8c,0x38}, 8333},
{{0x20,0x01,0x1a,0xf8,0x40,0x70,0xa0,0x16,0x33,0x33,0x00,0x00,0x00,0x00,0x5a,0xfb}, 8333},
{{0x20,0x01,0x1a,0xf8,0x47,0x00,0xa0,0x71,0x44,0x44,0x00,0x00,0x00,0x00,0xe2,0x6e}, 8333},
- {{0x20,0x01,0x1b,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaa,0xaa,0x00,0x21}, 8333},
{{0x20,0x01,0x02,0x00,0x00,0x00,0x88,0x01,0x50,0x54,0x00,0xff,0xfe,0xf2,0x01,0xd0}, 8333},
- {{0x20,0x01,0x41,0x28,0x61,0x35,0x00,0x10,0x02,0x0c,0x29,0xff,0xfe,0x69,0x9e,0x81}, 8333},
{{0x20,0x01,0x41,0x28,0x61,0x35,0x20,0x10,0x02,0x1e,0x0b,0xff,0xfe,0xe8,0xa3,0xc0}, 8333},
- {{0x20,0x01,0x41,0x28,0x61,0x35,0xe0,0x01,0x50,0x54,0x00,0xff,0xfe,0x37,0xe9,0xeb}, 8333},
- {{0x20,0x01,0x41,0x78,0x00,0x06,0x14,0x27,0x00,0x62,0x01,0x16,0x01,0x88,0x00,0x85}, 8333},
- {{0x20,0x01,0x41,0xc9,0x00,0x01,0x04,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x31}, 8333},
- {{0x20,0x01,0x41,0xd0,0x10,0x00,0x1e,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x10,0x04,0x1f,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x10,0x04,0x24,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x10,0x08,0x1c,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x10,0x08,0x27,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x10,0x00,0x1f,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x10,0x04,0x18,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x10,0x04,0x19,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 18555},
+ {{0x20,0x01,0x41,0xd0,0x10,0x04,0x1f,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x10,0x08,0x2b,0xed,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x01,0x45,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x01,0x7d,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x01,0x81,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x01,0x53,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x01,0x85,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x01,0x86,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x01,0x8b,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x01,0xa5,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x01,0xab,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x01,0xaf,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x01,0xb4,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x01,0xb5,0xce,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x01,0xd2,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x01,0xda,0xbd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x01,0xe1,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x01,0xf1,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x02,0x03,0x10,0xbd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x02,0x16,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x02,0x53,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x02,0x8c,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x02,0x94,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x02,0x9c,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x02,0xa5,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x01,0xf8,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x01,0xf9,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x02,0x34,0xb7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x02,0x49,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x02,0x5c,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x02,0x84,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x02,0xab,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x02,0x0c,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x02,0xc9,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x03,0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0x25}, 8333},
- {{0x20,0x01,0x41,0xd0,0x03,0x03,0x01,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x03,0x03,0x19,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x02,0xc3,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x03,0x03,0x19,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
{{0x20,0x01,0x41,0xd0,0x03,0x03,0x25,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a}, 8333},
- {{0x20,0x01,0x41,0xd0,0x03,0x03,0x41,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x03,0x03,0x0d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x04,0x03,0x05,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x52,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xe2}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x52,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xe3}, 8333},
- {{0x20,0x01,0x41,0xd0,0x06,0x02,0x00,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x06,0x02,0x06,0xca,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x06,0x02,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x06,0x04,0x01,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x07,0x00,0x04,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x07,0x00,0x04,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x08,0x00,0x02,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x03,0x03,0x41,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 58333},
+ {{0x20,0x01,0x41,0xd0,0x03,0x03,0x4c,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x03,0x03,0x05,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x03,0x03,0x67,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x03,0x03,0x68,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x06,0x02,0x17,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x06,0x02,0x18,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x06,0x02,0x03,0xb7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x06,0x02,0x08,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x06,0x02,0x0b,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x08,0x00,0x01,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x08,0x00,0x03,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x08,0x10,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x08,0x1b,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0x25,0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0x7a,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0x8f,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0x9c,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0xb3,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0xb7,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x08,0x3f,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x08,0x43,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x08,0xbb,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x08,0xbe,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x08,0xc6,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x08,0xca,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x08,0xd4,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0xd8,0x44,0x13,0x37,0x00,0x00,0x00,0x00,0x10,0x17}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0xdb,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x08,0x0d,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0x0d,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x08,0xe3,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x3b,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x08,0xea,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x12,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x27,0xed,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x29,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8139},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x2b,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x0a,0x40,0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x63,0x5b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6a,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x06,0xa1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x42,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8312},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x4c,0x49,0x00,0x00,0x00,0x00,0x0a,0xca,0x79,0x29}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x69,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x69,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6a,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6c,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6f,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x07,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf8,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf9,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6c,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf2,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf9,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0d,0x0d,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x0e,0x11,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x01,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x12,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x0e,0x13,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x02,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x09,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x41,0xd0,0x00,0x0e,0x0e,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x41,0xf0,0x00,0x61,0x00,0x00,0x72,0xf3,0x95,0xff,0xfe,0x09,0x75,0x21}, 8333},
- {{0x20,0x01,0x41,0xf0,0x00,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333},
- {{0x20,0x01,0x46,0x42,0xe5,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbe,0xef}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x1d,0x08,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x1d,0x08,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333},
+ {{0x20,0x01,0x41,0xf0,0x00,0x00,0x00,0x04,0x00,0x62,0x69,0x74,0x63,0x6f,0x69,0x6e}, 8333},
+ {{0x20,0x01,0x04,0x70,0x00,0x18,0x0b,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x20,0x01,0x04,0x70,0x1c,0x62,0xb1,0x70,0xbb,0xff,0x53,0xf1,0xed,0xbf,0x99,0xdf}, 42434},
{{0x20,0x01,0x04,0x70,0x1f,0x06,0x15,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x20,0x01,0x04,0x70,0x1f,0x06,0x0c,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x20,0x01,0x04,0x70,0x1f,0x07,0x08,0x03,0x02,0x0c,0x29,0xff,0xfe,0x2d,0x58,0x79}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x09,0x03,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x0b,0x05,0x6e,0x7e,0x5c,0xf8,0xff,0xfe,0x32,0x53,0x02}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x0b,0x08,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x0b,0x08,0xfe,0x00,0xc4,0x43,0x38,0xe5,0x28,0x27,0x13}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x0b,0x09,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x10,0x07,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x20,0x01,0x04,0x70,0x1f,0x08,0x03,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x20,0x01,0x04,0x70,0x1f,0x0a,0x18,0xdd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x20,0x01,0x04,0x70,0x1f,0x15,0x11,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x15,0x1b,0x95,0x2c,0x3e,0x8a,0x9a,0x24,0xe1,0x70,0x84}, 8333},
{{0x20,0x01,0x04,0x70,0x1f,0x15,0x0c,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x15,0x0e,0x9b,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xef}, 8333},
- {{0x20,0x01,0x04,0x70,0x1f,0x17,0x02,0x2a,0x08,0xd2,0x72,0xbf,0xa5,0x64,0x21,0xfb}, 8333},
{{0x20,0x01,0x04,0x70,0x1f,0x17,0x00,0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}, 8333},
+ {{0x20,0x01,0x04,0x70,0x1f,0x1a,0x01,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x20,0x01,0x04,0x70,0x1f,0x1b,0x05,0xa6,0x02,0x16,0x3e,0xff,0xfe,0x24,0x11,0x62}, 8333},
- {{0x20,0x01,0x04,0x70,0x21,0x79,0xde,0xad,0xde,0xaf,0x00,0x00,0x2e,0x70,0x9d,0x8b}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x25,0x04,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x27,0x04,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x20,0x01,0x04,0x70,0x00,0x28,0x03,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333},
+ {{0x20,0x01,0x04,0x70,0x00,0x41,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x20,0x01,0x04,0x70,0x6c,0x80,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x04,0x70,0x6c,0x80,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x04,0x70,0x00,0x07,0x06,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x20,0x01,0x04,0x70,0x00,0x07,0x0b,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x08,0x02,0xe1,0x44,0xff,0x65,0x4e,0xe5,0x3e,0xad,0x59}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x08,0x02,0xe1,0x70,0x58,0x53,0xf6,0x56,0x81,0x5b,0xe4}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x08,0x02,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x08,0x07,0xb3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17}, 8333},
- {{0x20,0x01,0x04,0x70,0x8a,0x2f,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe9,0x98}, 8333},
- {{0x20,0x01,0x04,0x70,0xa0,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x20,0x01,0x04,0x70,0x00,0x0a,0x08,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x20,0x01,0x04,0x70,0x00,0x08,0x0b,0xd3,0x4d,0x25,0xca,0x57,0xa5,0xb7,0xc6,0xc4}, 8333},
{{0x20,0x01,0x04,0x70,0x00,0x0a,0x0c,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x20,0x01,0x04,0x70,0xb3,0xd5,0x00,0x01,0x64,0x1c,0x6b,0xff,0xfe,0x9d,0xbc,0xcf}, 8333},
- {{0x20,0x01,0x04,0x70,0xc1,0x44,0xca,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09}, 8333},
- {{0x20,0x01,0x04,0x70,0xd0,0x0d,0x00,0x00,0x36,0x64,0xa9,0xff,0xfe,0x9a,0x51,0x50}, 8333},
- {{0x20,0x01,0x04,0x70,0xdb,0xf2,0xaa,0xaa,0x00,0x00,0x00,0x00,0x0b,0x17,0xc0,0x1c}, 8333},
- {{0x20,0x01,0x48,0x02,0x78,0x02,0x01,0x03,0xbe,0x76,0x4e,0xff,0xfe,0x21,0x19,0xf9}, 8333},
+ {{0x20,0x01,0x04,0x70,0xc1,0x44,0xca,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23}, 8333},
+ {{0x20,0x01,0x04,0x70,0xc3,0xc4,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x02}, 8333},
+ {{0x20,0x01,0x04,0x70,0xe6,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x48,0xf8,0x10,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xba}, 8333},
- {{0x20,0x01,0x4b,0x99,0x00,0x01,0x00,0x01,0x02,0x16,0x3e,0xff,0xfe,0xbd,0x85,0xba}, 8333},
- {{0x20,0x01,0x4b,0xa0,0xba,0xbe,0x26,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x48,0xf8,0x90,0x15,0x14,0x22,0x3d,0xc0,0xfc,0xf2,0x77,0x2f,0x57,0xbc}, 8333},
{{0x20,0x01,0x4b,0xa0,0xba,0xbe,0x08,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x4b,0xa0,0xca,0xfe,0x02,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x05,0x79,0x92,0x84,0x00,0xbc,0x10,0xbe,0x5d,0xf1,0xf6,0xd2,0x41,0x94}, 8333},
- {{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x40,0x00,0x00,0x00,0x00,0xff,0x10,0x04,0x15}, 8333},
+ {{0x20,0x01,0x06,0x28,0x22,0xa0,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12}, 8333},
{{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x40,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x91}, 8333},
- {{0x20,0x01,0x06,0x7c,0x25,0x64,0x05,0x20,0x78,0x00,0x48,0x17,0x52,0xec,0x0d,0x8f}, 8333},
- {{0x20,0x01,0x07,0x08,0x01,0x50,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x29}, 8333},
+ {{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x42,0x00,0x00,0x00,0x00,0xff,0x10,0xbe,0xd6}, 8333},
+ {{0x20,0x01,0x06,0x7c,0x21,0xec,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a}, 8333},
+ {{0x20,0x01,0x08,0xd8,0x09,0x0b,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x2f,0xc0}, 8333},
+ {{0x20,0x01,0x08,0xd8,0x09,0x1c,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0xd4,0x25}, 8333},
{{0x20,0x01,0x09,0x80,0x23,0x1b,0x00,0x01,0x8e,0x89,0xa5,0xff,0xfe,0xe3,0xf8,0xbe}, 8333},
{{0x20,0x01,0x09,0x80,0xad,0xe8,0x00,0x01,0x14,0xfc,0xfd,0x6d,0x60,0x8c,0xf6,0x69}, 8333},
+ {{0x20,0x01,0x09,0x81,0xbd,0xbd,0x00,0x01,0xc5,0x06,0x7d,0x38,0x4b,0x47,0xda,0x15}, 8333},
+ {{0x20,0x01,0x09,0x82,0x27,0xf2,0x00,0x01,0x72,0x71,0xbc,0xff,0xfe,0x94,0xd5,0xbb}, 8333},
+ {{0x20,0x01,0x09,0x84,0x26,0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x09,0x84,0xae,0xc7,0x00,0x01,0xdc,0xb7,0x02,0x9a,0x7e,0xda,0xb9,0xa2}, 8333},
{{0x20,0x01,0x09,0x85,0x79,0xaf,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35}, 8333},
- {{0x20,0x01,0x0b,0xc8,0x22,0x5f,0x01,0x0e,0x05,0x05,0x65,0x73,0x75,0x73,0x0d,0x0a}, 8333},
+ {{0x20,0x01,0x09,0x85,0xcb,0x69,0x00,0x00,0x02,0x0c,0x29,0xff,0xfe,0xaf,0xdd,0x5e}, 8333},
+ {{0x20,0x01,0xb0,0x11,0x30,0x0d,0x18,0x70,0x9c,0x87,0xd4,0xff,0xfe,0x9c,0x2d,0x0f}, 8333},
+ {{0x20,0x01,0xb0,0x30,0x24,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d}, 8333},
+ {{0x20,0x01,0x0b,0xc8,0x31,0xd7,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x01,0x0b,0xc8,0x32,0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x20,0x01,0x0b,0xc8,0x33,0xac,0x19,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26}, 8333},
{{0x20,0x01,0x0b,0xc8,0x39,0x9f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x01,0x0b,0xc8,0x3c,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333},
- {{0x20,0x01,0x0b,0xc8,0x44,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0f}, 8333},
- {{0x20,0x02,0x26,0x1b,0x64,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x1b,0x64,0x2c}, 8333},
- {{0x20,0x02,0x29,0x56,0x68,0x5e,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x56,0x68,0x5e}, 8333},
- {{0x20,0x02,0x2d,0x7b,0x67,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0x7b,0x67,0x4f}, 8333},
- {{0x20,0x02,0x2d,0xf9,0x5e,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0xf9,0x5e,0x40}, 8333},
- {{0x20,0x02,0x2e,0x04,0x78,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x04,0x78,0x4b}, 8333},
- {{0x20,0x02,0x2f,0x58,0xfe,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x58,0xfe,0x42}, 8333},
- {{0x20,0x02,0x2f,0x58,0xfe,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x58,0xfe,0x62}, 8333},
+ {{0x20,0x01,0x0b,0xc8,0x3d,0xc1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x42}, 8333},
+ {{0x20,0x01,0x0b,0xc8,0x44,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x3b}, 8333},
+ {{0x20,0x01,0x0b,0xc8,0x44,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x35}, 8333},
+ {{0x20,0x01,0x0b,0xc8,0x47,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x23}, 8333},
+ {{0x20,0x01,0x0d,0xa8,0x80,0x01,0x23,0x03,0x1c,0xf4,0x44,0x66,0x3f,0x1a,0x7e,0xdb}, 8333},
+ {{0x20,0x01,0x0d,0xa8,0xd8,0x00,0x07,0x41,0x65,0x2d,0x52,0xdb,0x57,0x13,0x45,0x15}, 8333},
+ {{0x20,0x02,0x17,0xe5,0x10,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xe5,0x10,0xea}, 8333},
+ {{0x20,0x02,0x1f,0x2b,0x8c,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x2b,0x8c,0xbe}, 8333},
{{0x20,0x02,0x2f,0x59,0x30,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x59,0x30,0xf3}, 8333},
- {{0x20,0x02,0x2f,0x5a,0x3c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5a,0x3c,0x1c}, 10011},
{{0x20,0x02,0x2f,0x5a,0x56,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5a,0x56,0x2a}, 8333},
- {{0x20,0x02,0x2f,0x5b,0xa5,0xf9,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5b,0xa5,0xf9}, 8333},
- {{0x20,0x02,0x2f,0x5b,0xb0,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5b,0xb0,0x86}, 8333},
- {{0x20,0x02,0x32,0x3f,0xa6,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x3f,0xa6,0x1b}, 8333},
- {{0x20,0x02,0x33,0xff,0x69,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x02,0x3e,0x92,0x46,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x92,0x46,0xd8}, 8333},
{{0x20,0x02,0x3f,0x62,0xe6,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x62,0xe6,0xbb}, 8333},
- {{0x20,0x02,0x4b,0x63,0x50,0xb4,0x12,0x34,0x40,0x59,0xbf,0x54,0xe0,0x88,0x7d,0xaa}, 8333},
- {{0x20,0x02,0x05,0x09,0x6a,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x09,0x6a,0xc5}, 8333},
- {{0x20,0x02,0x51,0xa9,0x9c,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0xa9,0x9c,0xc9}, 8333},
- {{0x20,0x02,0x54,0xfb,0xa1,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x02,0x5b,0xc2,0x54,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0xc2,0x54,0x28}, 8333},
- {{0x20,0x02,0x5b,0xce,0x12,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0xce,0x12,0x53}, 8333},
- {{0x20,0x02,0x5d,0x68,0xd2,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0x68,0xd2,0x70}, 8333},
+ {{0x20,0x02,0x40,0x4e,0xa3,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x4e,0xa3,0x0a}, 8333},
+ {{0x20,0x02,0x43,0xdb,0x96,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xdb,0x96,0x16}, 8333},
+ {{0x20,0x02,0x43,0xe5,0xa1,0xfa,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xe5,0xa1,0xfa}, 8333},
+ {{0x20,0x02,0x52,0x66,0x0a,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x66,0x0a,0xfb}, 8333},
{{0x20,0x02,0x5d,0xbd,0x91,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0xbd,0x91,0xa9}, 8333},
- {{0x20,0x02,0x5f,0xd3,0x89,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xd3,0x89,0x44}, 8333},
- {{0x20,0x02,0x67,0x38,0x88,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x38,0x88,0x69}, 8333},
- {{0x20,0x02,0x67,0xe9,0xfe,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xe9,0xfe,0x16}, 8333},
- {{0x20,0x02,0x67,0xfa,0x04,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xfa,0x04,0x4a}, 8333},
- {{0x20,0x02,0x67,0xfa,0x04,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xfa,0x04,0x4b}, 8333},
- {{0x20,0x02,0x68,0x25,0xd4,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x25,0xd4,0x25}, 8333},
- {{0x20,0x02,0x6a,0x0e,0x3e,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x0e,0x3e,0xa8}, 10011},
- {{0x20,0x02,0x6b,0xb4,0x47,0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0xb4,0x47,0x5c}, 41888},
- {{0x20,0x02,0x6b,0xb4,0x54,0xbc,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0xb4,0x54,0xbc}, 8333},
- {{0x20,0x02,0x6c,0x3d,0xd8,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x3d,0xd8,0x8a}, 8333},
- {{0x20,0x02,0x70,0x4a,0xd6,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x4a,0xd6,0xd4}, 9997},
- {{0x20,0x02,0x71,0x69,0x8b,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x71,0x69,0x8b,0x2a}, 8333},
- {{0x20,0x02,0x72,0x37,0xfc,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x72,0x37,0xfc,0xf6}, 20188},
- {{0x20,0x02,0x78,0x19,0x7e,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x19,0x7e,0x80}, 7743},
- {{0x20,0x02,0x84,0x94,0x82,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x94,0x82,0x33}, 8333},
- {{0x20,0x02,0x84,0x94,0x84,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x94,0x84,0xfc}, 8333},
- {{0x20,0x02,0x92,0x47,0x4c,0xec,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x47,0x4c,0xec}, 8333},
- {{0x20,0x02,0x95,0x38,0x73,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x38,0x73,0x5d}, 8333},
- {{0x20,0x02,0xad,0xcd,0xb8,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0xcd,0xb8,0x8c}, 8333},
- {{0x20,0x02,0xb0,0x25,0x5c,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x25,0x5c,0x52}, 8333},
+ {{0x20,0x02,0x62,0x7e,0x33,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x7e,0x33,0x3d}, 8333},
+ {{0x20,0x02,0x6b,0x9b,0x48,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0x9b,0x48,0x6c}, 8333},
+ {{0x20,0x02,0x6d,0xcb,0x7c,0xba,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xcb,0x7c,0xba}, 8333},
+ {{0x20,0x02,0x7c,0xf8,0xe3,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xf8,0xe3,0x3e}, 8333},
+ {{0x20,0x02,0x8e,0x00,0x82,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x00,0x82,0x31}, 8333},
+ {{0x20,0x02,0x8e,0x00,0x82,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x00,0x82,0x33}, 8333},
{{0x20,0x02,0xb0,0x7e,0xa7,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x7e,0xa7,0x0a}, 8333},
{{0x20,0x02,0xb2,0xc9,0xe6,0xfc,0x00,0x10,0x3d,0x5c,0xe3,0xad,0x08,0x13,0x9c,0x46}, 8333},
{{0x20,0x02,0xb4,0xb2,0x36,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0xb2,0x36,0x12}, 8333},
+ {{0x20,0x02,0xb6,0x10,0x1c,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x10,0x1c,0xa2}, 8333},
{{0x20,0x02,0xb6,0x10,0x1c,0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x10,0x1c,0xa3}, 8333},
- {{0x20,0x02,0xb8,0x5f,0x26,0xda,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x5f,0x26,0xda}, 8333},
- {{0x20,0x02,0xb9,0x23,0xb6,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x23,0xb6,0x7b}, 8333},
+ {{0x20,0x02,0xb8,0x45,0x33,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x20,0x02,0xb9,0x46,0x69,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x46,0x69,0x4a}, 8339},
{{0x20,0x02,0xb9,0x60,0x5e,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x60,0x5e,0x18}, 8333},
- {{0x20,0x02,0xbc,0x48,0xd6,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x48,0xd6,0x06}, 8333},
- {{0x20,0x02,0xc1,0x3a,0xc4,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x20,0x02,0xc1,0x6a,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xc1,0x6a,0x1c,0x08}, 8333},
- {{0x20,0x02,0xc1,0x6a,0x1d,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0xc1,0x6a,0x1d,0x12}, 8333},
{{0x20,0x02,0xc2,0x3f,0x8f,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0x3f,0x8f,0xc5}, 8333},
{{0x20,0x02,0xc2,0xa5,0x10,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa5,0x10,0x21}, 8333},
- {{0x20,0x02,0xc2,0xa5,0x10,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa5,0x10,0xfe}, 8333},
- {{0x20,0x02,0xc3,0x9a,0xa4,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x9a,0xa4,0xa8}, 8333},
- {{0x20,0x02,0xcb,0x82,0xd0,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x82,0xd0,0x2d}, 8333},
+ {{0x20,0x02,0xc6,0x2c,0xe7,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0xc6,0x2c,0xe7,0xa0}, 6333},
+ {{0x20,0x02,0xca,0x99,0xc7,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xca,0x99,0xc7,0xb6}, 8333},
{{0x20,0x02,0xd0,0x35,0x27,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x35,0x27,0x34}, 8333},
- {{0x20,0x02,0xd2,0xd3,0x6d,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0xd3,0x6d,0xa5}, 8333},
- {{0x20,0x02,0xd4,0x53,0x91,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x53,0x91,0x74}, 8333},
- {{0x20,0x02,0xd9,0x17,0x0d,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0xd9,0x17,0x0d,0x95}, 8333},
- {{0x20,0x03,0x00,0x0a,0x11,0x14,0x10,0x01,0x6a,0xb5,0x99,0xff,0xfe,0xb0,0x87,0x70}, 8333},
- {{0x24,0x00,0x26,0x50,0x04,0x80,0xbc,0x00,0xbc,0xaf,0x7c,0x49,0x8c,0x9e,0x7c,0xdf}, 8333},
- {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x1f,0xec,0x00}, 8333},
- {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x3e,0x57,0x1b}, 8333},
- {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x3e,0x57,0xef}, 8333},
- {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb4,0x71,0xf1}, 8333},
- {{0x24,0x00,0x89,0x02,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb9,0xc5,0x9c}, 8333},
- {{0x24,0x00,0xdd,0x01,0x10,0x34,0x0e,0x00,0xf2,0x1f,0xaf,0xff,0xfe,0xdc,0x16,0x4d}, 8333},
- {{0x24,0x00,0xdd,0x08,0x10,0x01,0x01,0x20,0xf0,0xf7,0xd9,0xda,0x8b,0x5b,0x58,0xd7}, 8333},
- {{0x24,0x01,0x18,0x00,0x78,0x00,0x01,0x02,0xbe,0x76,0x4e,0xff,0xfe,0x1c,0x0a,0x7d}, 8333},
- {{0x24,0x01,0x18,0x00,0x78,0x01,0x01,0x01,0xbe,0x76,0x4e,0xff,0xfe,0x1c,0x0f,0x4b}, 8333},
- {{0x24,0x02,0x1f,0x00,0x81,0x00,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x24,0x04,0x7a,0x83,0x94,0xe0,0x7f,0x00,0x85,0x8f,0x8a,0x7d,0x3a,0x8c,0x26,0xdd}, 8333},
- {{0x24,0x04,0xc8,0x05,0x0d,0x00,0x01,0x01,0x71,0x6a,0xcf,0xf7,0xc9,0xab,0xa5,0x95}, 8333},
+ {{0x20,0x02,0xd0,0x6e,0x5d,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x6e,0x5d,0x1a}, 8333},
+ {{0x20,0x02,0xd8,0xda,0xb9,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0xd8,0xda,0xb9,0x49}, 8333},
+ {{0x24,0x00,0x24,0x10,0xa9,0x60,0x48,0x00,0x18,0xbe,0xd6,0x24,0x70,0x18,0xcd,0x2f}, 8333},
+ {{0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x03,0xe1,0xb0,0x01}, 8333},
+ {{0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x5c,0xd2,0xa0,0x01}, 8333},
+ {{0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x04,0xc6,0x80,0x01}, 8333},
+ {{0x24,0x00,0x61,0x80,0x01,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x07,0x97,0xa0,0x01}, 8333},
+ {{0x24,0x00,0x85,0x00,0x13,0x02,0x08,0x17,0x01,0x50,0x00,0x95,0x01,0x30,0x00,0x17}, 8333},
+ {{0x24,0x01,0x18,0x00,0x78,0x00,0x01,0x06,0xbe,0x76,0x4e,0xff,0xfe,0x1c,0x18,0x79}, 8333},
+ {{0x24,0x01,0x39,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x24,0x01,0xa4,0x00,0x32,0x00,0x56,0x00,0x3c,0x16,0x2d,0xeb,0xab,0xce,0x70,0xcd}, 8333},
+ {{0x24,0x01,0xb1,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x01,0x00}, 8333},
+ {{0x24,0x01,0xb1,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x01,0x02}, 8333},
+ {{0x24,0x02,0x1f,0x00,0x81,0x00,0x02,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x24,0x03,0xbd,0x80,0xc0,0x00,0x00,0x01,0x01,0x03,0x02,0x02,0x02,0x16,0x01,0x82}, 8333},
+ {{0x24,0x05,0x65,0x80,0xc5,0xc0,0x17,0x00,0x6c,0xd2,0xb7,0x2e,0x74,0x0e,0x43,0x11}, 8333},
+ {{0x24,0x05,0x08,0x00,0x10,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x20,0x01}, 8333},
+ {{0x24,0x05,0x98,0x00,0xb5,0x60,0x09,0x6d,0x06,0x30,0xc2,0x8e,0xa7,0x9a,0xa1,0x82}, 8333},
{{0x24,0x05,0xaa,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40}, 8333},
{{0x24,0x09,0x00,0x10,0xca,0x20,0x1d,0xf0,0x02,0x24,0xe8,0xff,0xfe,0x1f,0x60,0xd9}, 8333},
- {{0x26,0x00,0x1f,0x14,0x06,0xae,0xd9,0x00,0x65,0x50,0x3f,0xc5,0xe0,0x74,0xa7,0x2c}, 8333},
- {{0x26,0x00,0x1f,0x14,0x06,0xd0,0x2e,0x03,0x64,0x0e,0x19,0x37,0x99,0x60,0x32,0xe9}, 8333},
- {{0x26,0x00,0x1f,0x14,0x06,0xd0,0x2e,0x03,0x07,0x61,0x6e,0x21,0x95,0x2c,0xde,0x5b}, 8333},
{{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x26,0x9a,0x34,0x52,0x2e,0xdf,0x10,0x11}, 8333},
{{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x07,0xbc,0x58,0x79,0x44,0x63,0x15,0xdd}, 8333},
{{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xa2,0x8b,0x5a,0x16,0x84,0x9c,0xfe,0x41}, 8333},
{{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xa7,0x0f,0xe7,0x28,0xe8,0xe1,0x2c,0x2e}, 8333},
- {{0x26,0x00,0x1f,0x16,0x0b,0x32,0x31,0x02,0x04,0x40,0x0f,0xab,0xd8,0xa2,0xcc,0x59}, 8333},
- {{0x26,0x00,0x1f,0x18,0x00,0x3d,0x46,0x00,0x69,0x9a,0xd6,0xb3,0x76,0xe8,0x9b,0x8d}, 48333},
- {{0x26,0x00,0x1f,0x18,0x03,0xf8,0xf9,0x0f,0x2b,0x39,0x20,0x1b,0xe9,0xa4,0xe8,0x82}, 8333},
- {{0x26,0x00,0x1f,0x18,0x60,0x9f,0xda,0x02,0xb2,0x83,0xb1,0x6e,0xaa,0xc4,0x74,0x9f}, 8333},
- {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x28,0x9e,0x61}, 8333},
+ {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x0c,0x4d,0x74}, 8333},
+ {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x2b,0xbf,0x38}, 8333},
{{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x91,0x3e,0x49}, 8333},
- {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb9,0x36,0xfc}, 8333},
- {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x39,0x76,0x8b}, 8333},
- {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x8e,0x8a,0xe1}, 8333},
+ {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb6,0x19,0xf2}, 8333},
{{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x91,0x6a,0x29}, 8333},
- {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xa7,0xe0,0xf9}, 8333},
- {{0x26,0x00,0x3c,0x02,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x8e,0xbc,0xd9}, 8333},
+ {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xd8,0x85,0xa2}, 8333},
+ {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xd8,0xdb,0x38}, 8333},
{{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x28,0x14,0x45}, 8333},
- {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x7a,0x1e,0xb2}, 8333},
- {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb0,0x5f,0xc4}, 8333},
- {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xe0,0x23,0x3e}, 8333},
- {{0x26,0x00,0x6c,0x40,0x79,0x00,0x31,0x9f,0x83,0x90,0xe8,0xaf,0x5a,0x2c,0x9b,0x0b}, 8333},
- {{0x26,0x00,0x6c,0x44,0x46,0x7f,0xf8,0x9c,0x72,0x2d,0x84,0x24,0xd4,0x81,0xd1,0x55}, 8333},
- {{0x26,0x00,0x88,0x01,0x83,0x06,0xe9,0x00,0xdc,0xe8,0x6a,0x03,0x95,0x92,0xa0,0x53}, 8333},
+ {{0x26,0x01,0x01,0x47,0x43,0x00,0x0e,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0c}, 8333},
+ {{0x26,0x01,0x01,0x47,0x43,0x00,0x0e,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x91}, 8333},
{{0x26,0x01,0x01,0x86,0xc1,0x00,0x6b,0xcd,0x16,0xbd,0xce,0xa1,0x23,0x5d,0x1c,0x19}, 8333},
{{0x26,0x01,0x01,0x8d,0x46,0x00,0x5f,0x32,0x20,0xe7,0xb3,0xff,0xfe,0xcf,0x0a,0x99}, 8333},
- {{0x26,0x01,0x01,0xc2,0x0f,0x00,0x29,0xb0,0x92,0x2b,0x34,0xff,0xfe,0xa8,0x41,0x18}, 8333},
- {{0x26,0x01,0x02,0x82,0x80,0x00,0x20,0xb0,0x67,0xf8,0xfa,0x63,0xe0,0x56,0xdd,0x23}, 8333},
- {{0x26,0x01,0x04,0x0a,0xc2,0x00,0x37,0xe8,0x95,0x28,0xd4,0x53,0x63,0x58,0x9f,0x2a}, 8333},
- {{0x26,0x01,0x06,0x46,0x41,0x01,0x16,0x03,0x58,0x09,0x1b,0xff,0xfe,0x55,0x66,0x78}, 8333},
- {{0x26,0x01,0x00,0xc0,0xc1,0x00,0x18,0x80,0x02,0x1f,0x5b,0xff,0xfe,0x3c,0x6e,0x84}, 8333},
- {{0x26,0x01,0x00,0xc8,0x41,0x00,0x07,0x70,0x02,0x3e,0xe1,0xff,0xfe,0xbe,0x73,0x6d}, 8333},
- {{0x26,0x03,0x30,0x00,0x09,0x03,0xc5,0xf1,0x46,0x8a,0x5b,0xff,0xfe,0x9e,0x89,0xdc}, 8333},
+ {{0x26,0x01,0x02,0x40,0x46,0x01,0xec,0xee,0x30,0x9a,0xf9,0xde,0xb6,0x4d,0x87,0xdf}, 8333},
+ {{0x26,0x01,0x02,0x40,0x81,0x00,0x25,0x6b,0x02,0x0c,0x29,0xff,0xfe,0x5e,0xd7,0x07}, 8333},
+ {{0x26,0x01,0x06,0x46,0xc2,0x02,0x53,0x01,0x10,0x1b,0xa0,0x96,0xef,0xba,0xc1,0x0a}, 8333},
+ {{0x26,0x01,0x08,0x07,0x80,0x00,0x95,0x08,0x99,0x93,0xd2,0xb3,0x00,0x1a,0x82,0x25}, 8333},
+ {{0x26,0x01,0x00,0xc8,0x41,0x00,0x07,0x70,0x0c,0x37,0x80,0x7b,0x98,0xcc,0xbd,0x7e}, 8333},
+ {{0x26,0x02,0x01,0x00,0x61,0x54,0xd6,0xe3,0x2c,0x91,0xd0,0xde,0xb0,0x32,0xb0,0xa4}, 8333},
+ {{0x26,0x02,0x01,0x00,0x61,0x54,0xd6,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60}, 8333},
+ {{0x26,0x02,0x00,0x61,0x78,0x6c,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x26,0x02,0xff,0x83,0x0f,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75}, 8333},
+ {{0x26,0x02,0xff,0x83,0x0f,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76}, 8333},
{{0x26,0x03,0x30,0x05,0x30,0x00,0x50,0x00,0xbc,0x5a,0x72,0xac,0x36,0xe9,0x17,0x5e}, 8333},
- {{0x26,0x03,0x30,0x22,0x05,0x01,0x78,0x00,0x49,0x5c,0x72,0x8c,0xed,0x5d,0x5d,0x75}, 8333},
- {{0x26,0x04,0x01,0x80,0x00,0x01,0x03,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x4d}, 8333},
- {{0x26,0x04,0x67,0xc0,0x20,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x26,0x04,0x8d,0x80,0x01,0x00,0x00,0x00,0x80,0x65,0x4c,0x57,0x66,0x7a,0xb7,0x0f}, 8333},
- {{0x26,0x04,0x8d,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0xf3,0x40,0x31}, 8333},
+ {{0x26,0x04,0x00,0x00,0x00,0xc1,0x01,0x00,0x6b,0xc1,0xf9,0x8a,0x97,0xf9,0x38,0x45}, 8333},
+ {{0x26,0x04,0x2d,0x80,0xc8,0x08,0x85,0x7b,0x08,0xd6,0x9e,0x1c,0x71,0x31,0x4b,0xea}, 8333},
+ {{0x26,0x04,0x40,0x80,0x10,0x08,0x00,0x00,0x96,0xde,0x80,0xff,0xfe,0x62,0xe6,0x50}, 8333},
+ {{0x26,0x04,0x43,0x00,0x00,0x0a,0x01,0x04,0xb6,0x99,0xba,0xff,0xfe,0xaa,0x51,0x09}, 8333},
+ {{0x26,0x04,0x55,0x00,0xc2,0x26,0x7f,0x00,0x2d,0x96,0xed,0x64,0xce,0x45,0x09,0xa6}, 8333},
+ {{0x26,0x04,0x8d,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0xf3,0x40,0x30}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf8,0xe0,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf8,0xf0,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0x00,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0x10,0x01}, 8333},
@@ -1087,452 +796,486 @@ static SeedSpec6 pnSeed6_main[] = {
{{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x10,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x20,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x30,0x01}, 8333},
- {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x03,0x01,0x80,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x38,0xf0,0x01}, 8333},
- {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x46,0xf0,0x01}, 8333},
- {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xb2,0x90,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x06,0x62,0xc0,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x1a,0xc4,0xb0,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0x40,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0x50,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0x60,0x01}, 8333},
- {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0xc0,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0xd0,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0xe0,0x01}, 8333},
- {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0xf0,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x00,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x20,0x01}, 8333},
{{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x30,0x01}, 8333},
- {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x26,0x1f,0x60,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x0c,0xd7,0x40,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x07,0x29,0xb0,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x11,0xa9,0x80,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x59,0x90,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x0c,0xbb,0xf0,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x0e,0xe8,0xe0,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x03,0x70,0xf0,0x01}, 8333},
+ {{0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x0a,0x52,0x60,0x01}, 8333},
{{0x26,0x05,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50}, 8333},
- {{0x26,0x05,0x60,0x00,0xe8,0xc8,0x67,0x01,0x75,0x62,0xde,0x11,0x24,0x5c,0xf6,0xba}, 8333},
+ {{0x26,0x05,0x98,0x80,0x00,0x00,0x01,0xcf,0x02,0x25,0x90,0xff,0xfe,0xc9,0x29,0xb3}, 8333},
{{0x26,0x05,0x98,0x80,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x33}, 8333},
{{0x26,0x05,0x98,0x80,0x02,0x01,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x4b,0x7c}, 8333},
- {{0x26,0x05,0x98,0x80,0x02,0x01,0x00,0x06,0x0e,0xc4,0x7a,0xff,0xfe,0x6c,0xa6,0x60}, 8333},
+ {{0x26,0x05,0xa0,0x00,0x4a,0x87,0x95,0x01,0xd6,0x13,0xfb,0xf8,0x1e,0x82,0x8d,0x3c}, 8333},
{{0x26,0x05,0xa0,0x00,0xf3,0x43,0xb7,0x00,0x50,0x54,0x00,0xff,0xfe,0xa7,0x01,0x31}, 8333},
+ {{0x26,0x05,0xa6,0x01,0x0a,0x41,0x1a,0x00,0x0a,0x00,0x27,0xff,0xfe,0xfc,0x47,0x59}, 8333},
{{0x26,0x05,0xae,0x00,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03}, 8333},
{{0x26,0x05,0xc0,0x00,0x2a,0x0a,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02}, 8333},
- {{0x26,0x05,0xf7,0x00,0x00,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x37,0x24,0x08,0x1c}, 8333},
- {{0x26,0x05,0xf7,0x00,0x00,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x38,0xc1,0x2b,0x84}, 8333},
- {{0x26,0x06,0xdf,0x00,0x00,0x07,0x00,0x04,0x4c,0xaa,0x2c,0x79,0xb6,0x19,0x27,0xc9}, 8333},
- {{0x26,0x07,0x44,0x80,0x00,0x02,0x00,0x01,0x00,0x38,0x01,0x02,0x00,0x69,0x00,0x70}, 8333},
- {{0x26,0x07,0x53,0x00,0x01,0x20,0x0b,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x26,0x07,0x53,0x00,0x02,0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x56}, 8333},
- {{0x26,0x07,0x53,0x00,0x02,0x03,0x12,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x26,0x07,0x53,0x00,0x02,0x03,0x14,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0f}, 8333},
- {{0x26,0x07,0x53,0x00,0x02,0x03,0x19,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x26,0x07,0x53,0x00,0x02,0x03,0x00,0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x26,0x05,0xe0,0x00,0x1c,0x00,0x80,0xe8,0x98,0x4e,0xa6,0x97,0x97,0xa3,0x50,0xed}, 8333},
+ {{0x26,0x05,0xe0,0x00,0x1c,0x0d,0x43,0x7b,0x50,0x54,0x00,0xff,0xfe,0x1b,0x29,0x13}, 8333},
+ {{0x26,0x05,0xe0,0x00,0x90,0x93,0xa7,0x00,0x98,0x53,0x44,0x64,0x5f,0x78,0xc4,0x84}, 8333},
+ {{0x26,0x05,0xf7,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x10,0x4e,0x43,0xbd}, 8333},
+ {{0x26,0x05,0xf7,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x31,0x5b,0x54}, 8333},
+ {{0x26,0x05,0xf7,0x00,0x01,0x00,0x0c,0x10,0x55,0x75,0x8e,0x73,0xb0,0x7c,0xbf,0x5a}, 8333},
+ {{0x26,0x06,0x60,0x00,0xc1,0x49,0x88,0x30,0x50,0x54,0x00,0xff,0xfe,0x78,0x66,0xff}, 8333},
+ {{0x26,0x07,0x1c,0x00,0x00,0x0a,0x00,0x06,0x3c,0x1c,0x1b,0x0d,0x0b,0xa4,0x8e,0xa9}, 8333},
+ {{0x26,0x07,0x1c,0x00,0x00,0x0a,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00}, 8333},
+ {{0x26,0x07,0x53,0x00,0x01,0x20,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x26,0x07,0x53,0x00,0x02,0x03,0x2f,0xac,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x26,0x07,0x53,0x00,0x02,0x03,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x26,0x07,0x53,0x00,0x02,0x03,0x06,0xbc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 18333},
+ {{0x26,0x07,0x53,0x00,0x02,0x03,0x00,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
{{0x26,0x07,0x53,0x00,0x00,0x60,0x10,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x26,0x07,0x53,0x00,0x00,0x60,0x12,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x26,0x07,0x53,0x00,0x00,0x60,0x13,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x60,0x1b,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x60,0x22,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x60,0x02,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x60,0x28,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x60,0x2c,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
{{0x26,0x07,0x53,0x00,0x00,0x60,0x3d,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x60,0x09,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x60,0x0a,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x61,0x0c,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x26,0x07,0x53,0x00,0x00,0x61,0x0f,0x5b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x26,0x07,0x90,0x00,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x00,0x03,0x6b,0x05,0xa5}, 8333},
+ {{0x26,0x07,0x53,0x00,0x00,0x60,0x57,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
+ {{0x26,0x07,0x53,0x00,0x00,0x60,0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x26,0x07,0x53,0x00,0x00,0x60,0x09,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x26,0x07,0x53,0x00,0x00,0x60,0xcf,0xf1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 28633},
+ {{0x26,0x07,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x21,0xbf,0x32}, 8333},
{{0x26,0x07,0xf1,0x78,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06}, 8333},
{{0x26,0x07,0xf1,0xc0,0x08,0x23,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xbb,0xd1}, 8333},
- {{0x26,0x07,0xf1,0xc0,0x08,0x46,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0xd0,0x0e}, 8333},
- {{0x26,0x07,0xf2,0xd8,0x40,0x05,0x00,0x0d,0xa8,0xa2,0xee,0xff,0xfe,0xe0,0xa8,0x59}, 8333},
- {{0x26,0x07,0xf4,0x70,0x00,0x14,0x00,0x0a,0x02,0x1d,0x7d,0xff,0xfe,0x01,0xbc,0xee}, 8333},
+ {{0x26,0x07,0xf2,0xc0,0xf0,0x0e,0x03,0x00,0x02,0x01,0x2e,0xff,0xfe,0x67,0x91,0x30}, 8333},
{{0x26,0x07,0xfa,0x18,0x00,0x00,0xbe,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x12}, 8333},
- {{0x26,0x07,0xfd,0x70,0x00,0x4a,0xba,0xbe,0xb0,0x0b,0x01,0xe5,0x00,0x00,0x00,0x01}, 8333},
- {{0x26,0x07,0xfe,0xa8,0xe2,0xdf,0xf8,0x7e,0x4b,0x8e,0x8a,0x8c,0x81,0x67,0xec,0x0d}, 8333},
- {{0x26,0x07,0xfe,0xa8,0x0e,0x60,0x05,0x74,0xfd,0xbc,0xad,0xd5,0xea,0xbd,0x4d,0x9e}, 8333},
- {{0x26,0x10,0x01,0xa0,0x01,0x03,0x00,0x4a,0xde,0xad,0xbe,0xaf,0x00,0x00,0xca,0xfe}, 8333},
- {{0x26,0x10,0x01,0xa0,0x01,0x03,0x00,0x4a,0xde,0xad,0xbe,0xef,0x00,0x01,0xca,0xfe}, 8333},
- {{0x28,0x01,0x00,0x80,0x09,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63}, 8333},
+ {{0x26,0x07,0xff,0x28,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x17,0x6e,0xc4,0xa5}, 8333},
+ {{0x26,0x07,0xff,0x28,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x65,0xaf,0x9a,0xfb}, 8333},
+ {{0x26,0x20,0x00,0x71,0x40,0x00,0x00,0x00,0x01,0x92,0x00,0x30,0x01,0x20,0x01,0x10}, 8333},
+ {{0x28,0x01,0x00,0x84,0x00,0x00,0x10,0x34,0x76,0xd4,0x35,0xff,0xfe,0x7f,0x50,0x33}, 8333},
{{0x28,0x03,0x15,0x00,0x12,0x00,0xc4,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x28,0x04,0x01,0x4c,0x65,0x82,0x60,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x28,0x04,0x01,0x4d,0xba,0xa6,0x96,0x2c,0x04,0x86,0x47,0xf6,0xc1,0x61,0xa7,0x9d}, 8333},
+ {{0x2a,0x00,0x13,0xa0,0x30,0x15,0x00,0x01,0x00,0x85,0x00,0x14,0x00,0x79,0x00,0x26}, 8333},
{{0x2a,0x00,0x16,0xd8,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0x6a,0xc2,0x61}, 8333},
- {{0x2a,0x00,0x1a,0x48,0x78,0x10,0x01,0x01,0xbe,0x76,0x4e,0xff,0xfe,0x08,0xc7,0x74}, 8333},
- {{0x2a,0x00,0x1c,0x48,0x00,0x06,0x01,0x08,0xa6,0xbf,0x01,0xff,0xfe,0x16,0x35,0xc1}, 8333},
- {{0x2a,0x00,0x1c,0x60,0x00,0x00,0x00,0x12,0xe2,0xd5,0x5e,0xff,0xfe,0x09,0x25,0x7d}, 8333},
- {{0x2a,0x00,0x1c,0xa8,0x00,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xe9,0xf4,0x38}, 8333},
- {{0x2a,0x00,0x48,0x02,0x03,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf9}, 8333},
- {{0x2a,0x00,0x7c,0x80,0x00,0x00,0x00,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333},
+ {{0x2a,0x00,0x17,0x68,0x20,0x01,0x00,0x24,0x00,0x00,0x00,0x00,0x01,0x48,0x02,0x18}, 8333},
+ {{0x2a,0x00,0x18,0x38,0x00,0x36,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0xed,0x85}, 8333},
+ {{0x2a,0x00,0x1a,0x28,0x11,0x57,0x02,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x6a}, 8333},
+ {{0x2a,0x00,0x1c,0x48,0x00,0x06,0x02,0x03,0x0a,0x60,0x6e,0xff,0xfe,0x44,0x80,0x86}, 8333},
+ {{0x2a,0x00,0x1f,0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x26}, 8333},
+ {{0x2a,0x00,0x7c,0x80,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x0e}, 8333},
{{0x2a,0x00,0x8a,0x60,0xe0,0x12,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21}, 8333},
- {{0x2a,0x00,0xbb,0xe0,0x00,0x00,0x00,0x42,0x02,0x22,0x64,0xff,0xfe,0x9a,0xe2,0x06}, 8333},
+ {{0x2a,0x00,0xab,0x00,0x06,0x03,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333},
{{0x2a,0x00,0xbb,0xe0,0x00,0xcc,0x00,0x00,0x66,0x51,0x06,0xff,0xfe,0x0e,0x94,0x18}, 8333},
- {{0x2a,0x00,0xc4,0x40,0x00,0x10,0x1c,0x62,0x12,0x34,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x00,0xc4,0x40,0x00,0x40,0x03,0x3b,0x9d,0x1c,0x77,0x26,0x55,0x71,0xc8,0x62}, 8333},
- {{0x2a,0x00,0x0c,0x70,0x00,0x01,0x02,0x13,0x02,0x46,0x00,0x56,0x00,0x95,0x00,0x01}, 8333},
- {{0x2a,0x00,0x0e,0xe2,0x12,0x00,0x19,0x00,0x02,0x0c,0x29,0xff,0xfe,0x81,0xa0,0xa3}, 8333},
- {{0x2a,0x00,0xf9,0x40,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x10,0x86}, 8333},
- {{0x2a,0x00,0xf9,0x40,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x18,0x4b}, 8333},
- {{0x2a,0x01,0x02,0x38,0x43,0x43,0x77,0x00,0x03,0xe6,0xf6,0x5c,0x5e,0x57,0x51,0x1c}, 8333},
- {{0x2a,0x01,0x02,0x38,0x43,0xa6,0x65,0x00,0x5e,0x5c,0x24,0xbb,0x5e,0x39,0xd9,0x6f}, 8333},
+ {{0x2a,0x00,0x0c,0xa8,0x0a,0x1f,0x30,0x25,0x41,0x21,0x5c,0xa1,0x00,0x3b,0x44,0x69}, 8333},
+ {{0x2a,0x00,0x0c,0xa8,0x0a,0x1f,0x90,0x91,0x94,0x5e,0x80,0xa3,0x83,0x0a,0x78,0xcf}, 8333},
+ {{0x2a,0x01,0x02,0x38,0x43,0x3c,0x53,0x00,0x7a,0x61,0x3e,0x1a,0x27,0xf4,0x9d,0xc2}, 8333},
{{0x2a,0x01,0x42,0x40,0x0a,0x21,0x98,0x3b,0x00,0x00,0x00,0x00,0xc0,0xa8,0x00,0x32}, 8333},
- {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0x2e,0xa3,0x76,0x33,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0x53,0xa9,0x21,0xb8,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x01,0x4d,0x60,0x00,0x03,0x00,0x01,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x10,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x1d,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x23,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 9002},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x2a,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x31,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x37,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x3f,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x41,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x18,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x2a,0x9b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x2e,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x2e,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x2e,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x35,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x03,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0d,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0e,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0e,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0f,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0f,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x10,0x41,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x20,0x13,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x62,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x70,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x61,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x70,0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x93,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x21,0x23,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x30,0x71,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x30,0x74,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x27,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3a,0x12,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3a,0x1d,0xcb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3a,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 21775},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3a,0x07,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x10,0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x1a,0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x27,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 10731},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x2d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x2d,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x21,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x31,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x42,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x52,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x3d,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x41,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x05,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x23,0x6a,0xca,0xfe,0x00,0x00,0x00,0x00,0x00,0x05}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x32,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x40,0x53,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x62,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x71,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x82,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x90,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x53,0x29,0x00,0x00,0x00,0x00,0x00,0x50,0x01,0x09}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x40,0x93,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x13,0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x22,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x24,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x54,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x32,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x41,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 5001},
- {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x42,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x53,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x53,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x93,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x00,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x50,0x53,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x72,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x50,0x72,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x73,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x51,0x82,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x33,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x60,0x41,0xf0,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x33}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x54,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x44,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x60,0x92,0xd7,0xbd,0x0a,0x39,0x3e,0x52,0xb6,0x5d}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x60,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x60,0x63,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x74,0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x21,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x22,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x61,0x60,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x61,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x12,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x14,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x21,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x61,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x81,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x02,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x62,0x33,0xac,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x34,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x41,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x42,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x71,0x01,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x2b,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x71,0x32,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x04,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0d,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0d,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x72,0x15,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0e,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0e,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x72,0x18,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x72,0x29,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x73,0x16,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x1c,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x29,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x2d,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x24,0xeb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x52,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x22,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x30,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x40,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x60,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x81,0xb7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x01,0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x34,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x04,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x50,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x51,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x23}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x02,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x21,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x01,0x92,0x62,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x1c,0x0c,0x77,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x01,0x04,0xf8,0x02,0x00,0x10,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x24,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x32,0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x02,0x00,0x44,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x63,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x72,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x90,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x40,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x60,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x11,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x04,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x53,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x80,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x37}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x80,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x02,0x02,0x32,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x53,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x72,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x10,0x54,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x13,0xcf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x16,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x17,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x1e,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x0d,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x33}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x03,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x02,0x11,0x0f,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x02,0x12,0x1e,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x12,0x03,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x13,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x11}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 15000},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x2e,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x2f,0xcf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x34,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x34,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x39,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8335},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x3c,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x02,0x21,0x3c,0x82,0xfe,0xa1,0x00,0x00,0x00,0x00,0x06,0x66}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x06,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x02,0x21,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x02,0x21,0x0f,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x10,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x22,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x43,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x61,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x74,0x6a,0x01,0x01,0x00,0x01,0x00,0x01,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x82,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x91,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0b,0x10,0x50,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x10,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x1f,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x22,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x35,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x42,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x48,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x0d,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x24,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x33,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x3b,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x5d,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x67,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x71,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x42,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x56,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x01,0x05,0xc0,0x00,0x10,0x6e,0xb1,0x89,0xb8,0xbb,0x58,0x02,0x5a,0x60,0x50}, 8333},
- {{0x2a,0x01,0x06,0x80,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x01,0x06,0xf0,0xff,0xff,0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x8d,0xcb}, 8333},
- {{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333},
- {{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x10,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x18,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x19,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x1c,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x25,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x25,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x26,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x2d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x2d,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x03,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x06,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x0d,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0xc0,0x10,0x12,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x01,0x04,0xf9,0xc0,0x10,0x17,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x01,0x5d,0x00,0x00,0x01,0x04,0xb6,0xd2,0xbf,0x9c,0xff,0xfe,0x45,0xb8,0x34}, 8333},
+ {{0x2a,0x01,0x07,0x9c,0xce,0xbe,0x70,0xcc,0x1a,0x03,0x73,0xff,0xfe,0x48,0xe6,0x91}, 8333},
{{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333},
{{0x2a,0x01,0x07,0xa7,0x00,0x02,0x12,0x18,0x0e,0xc4,0x7a,0xff,0xfe,0x83,0x83,0xc4}, 8333},
{{0x2a,0x01,0x07,0xa7,0x00,0x02,0x12,0x88,0xea,0x39,0x35,0xff,0xfe,0xf0,0xc4,0x29}, 8333},
- {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x15,0x5c,0x34,0x6c,0x08,0xf5,0x71,0x9f,0xa6,0xb6}, 8333},
- {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x15,0x65,0x94,0x84,0x50,0x9b,0x2a,0x3b,0xa7,0x73}, 8333},
- {{0x2a,0x01,0x07,0xc8,0xaa,0xaa,0x03,0x73,0x50,0x54,0x00,0xff,0xfe,0xb3,0x29,0x47}, 8333},
- {{0x2a,0x01,0x07,0xc8,0xaa,0xb5,0x03,0xe6,0x50,0x54,0x00,0xff,0xfe,0xd7,0x4e,0x54}, 8333},
- {{0x2a,0x01,0x07,0xc8,0xaa,0xba,0x03,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x33}, 8333},
- {{0x2a,0x01,0x07,0xc8,0xaa,0xbd,0x03,0xd5,0x50,0x54,0x00,0xff,0xfe,0x95,0xf5,0x86}, 8333},
- {{0x2a,0x01,0x07,0xc8,0xaa,0xc1,0x04,0x53,0x0c,0x50,0xfa,0x3a,0x02,0x29,0x85,0x04}, 8333},
- {{0x2a,0x01,0x07,0xc8,0xaa,0xc7,0x00,0x5e,0x50,0x54,0x00,0xff,0xfe,0xe9,0xbd,0xf7}, 8333},
+ {{0x2a,0x01,0x07,0xc8,0xaa,0xba,0x00,0x18,0x50,0x54,0x00,0xff,0xfe,0x2b,0xdf,0x20}, 8333},
+ {{0x2a,0x01,0x07,0xc8,0xff,0xfa,0x05,0x0e,0x30,0x35,0x74,0x1b,0xbe,0x02,0xb5,0xde}, 8333},
{{0x2a,0x01,0xbe,0x00,0x00,0x10,0x02,0x01,0x00,0x00,0x00,0x80,0xce,0xce,0x00,0x01}, 8333},
- {{0x2a,0x01,0xcb,0x00,0x02,0xca,0xb7,0x00,0x20,0x79,0xb3,0x3f,0xcf,0x5a,0x59,0x58}, 8333},
- {{0x2a,0x01,0xcb,0x00,0x00,0xb3,0xd3,0x00,0x90,0xfd,0xe3,0xb1,0x28,0xde,0x11,0x6c}, 8333},
+ {{0x2a,0x01,0xcb,0x00,0x05,0xbe,0xd5,0x00,0x02,0x27,0x0e,0xff,0xfe,0x28,0xc5,0x65}, 8333},
+ {{0x2a,0x01,0xcb,0x00,0x00,0xb3,0xd3,0x00,0x92,0x76,0x8a,0x8c,0x74,0xbf,0x2a,0x88}, 8333},
{{0x2a,0x01,0xcb,0x14,0x00,0xb8,0xa5,0x00,0xdd,0x9d,0x80,0xf5,0xd3,0x05,0x68,0xf9}, 8333},
- {{0x2a,0x01,0x00,0xd0,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x45}, 8333},
+ {{0x2a,0x01,0x0e,0x0a,0x00,0x20,0x91,0x20,0x7c,0x3f,0x56,0x43,0x99,0x78,0x18,0x25}, 8333},
{{0x2a,0x01,0x0e,0x0a,0x00,0x0d,0x6e,0xa0,0x00,0x56,0xde,0xab,0x1b,0x2f,0x30,0x0b}, 8333},
- {{0x2a,0x01,0x0e,0x34,0xec,0xfd,0x19,0x10,0x58,0xfb,0xc2,0xff,0xfe,0xac,0x57,0x1f}, 8333},
- {{0x2a,0x01,0x0e,0x34,0xee,0xd7,0x66,0x70,0xe1,0x50,0x6b,0xb0,0xf1,0x1b,0xd6,0xd8}, 8333},
- {{0x2a,0x01,0x0e,0x35,0x24,0x33,0xe3,0x20,0x9c,0x8e,0x6f,0xf0,0x99,0x0f,0xf0,0x6e}, 8333},
- {{0x2a,0x01,0x0e,0x35,0x2e,0xe5,0x06,0x10,0x02,0x1f,0xd0,0xff,0xfe,0x4e,0x74,0x60}, 8333},
- {{0x2a,0x01,0x0e,0x35,0x8b,0xe7,0x53,0xd0,0xb8,0xd5,0xde,0x58,0x95,0xb5,0xdd,0x16}, 8333},
- {{0x2a,0x01,0x0e,0x35,0x8b,0xff,0x70,0xb0,0x1e,0x1b,0x0d,0xff,0xfe,0x0b,0x23,0x6d}, 8333},
- {{0x2a,0x02,0x12,0x05,0x34,0xc3,0xba,0xe0,0xba,0xae,0xed,0xff,0xfe,0xea,0x94,0x45}, 8333},
- {{0x2a,0x02,0x12,0x05,0x50,0x04,0xde,0x00,0x0c,0x84,0x04,0xa1,0xe7,0x60,0xcf,0x90}, 8333},
- {{0x2a,0x02,0x12,0x05,0x50,0x76,0xee,0x00,0xd6,0xc9,0xef,0xff,0xfe,0x65,0xfb,0xfb}, 8333},
- {{0x2a,0x02,0x12,0x05,0xc6,0xbe,0x84,0xe0,0xca,0x2a,0x14,0xff,0xfe,0x0b,0x80,0x3b}, 8333},
- {{0x2a,0x02,0x12,0x06,0x45,0xc3,0xbe,0x80,0xd4,0xa4,0x32,0x15,0xaa,0xf0,0x85,0xaa}, 8333},
- {{0x2a,0x02,0x12,0x0b,0x2c,0x2a,0x5e,0xc0,0x10,0xdd,0x31,0xff,0xfe,0x42,0x50,0x79}, 8333},
- {{0x2a,0x02,0x12,0x0b,0x2c,0x3f,0x3f,0xc0,0x10,0xdd,0x31,0xff,0xfe,0x42,0x50,0x79}, 8333},
- {{0x2a,0x02,0x12,0x1e,0x3e,0x87,0x00,0x00,0x7d,0x3a,0xfe,0x09,0xb6,0x19,0x6b,0x4b}, 8333},
- {{0x2a,0x02,0x01,0x68,0x42,0x0b,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20}, 8333},
- {{0x2a,0x02,0x01,0x68,0x4a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39}, 8333},
- {{0x2a,0x02,0x01,0x68,0x4a,0x35,0x00,0x00,0x2e,0x44,0xfd,0xff,0xfe,0x9a,0x46,0xdc}, 8333},
+ {{0x2a,0x01,0x0e,0x34,0xec,0x16,0x93,0xf0,0x72,0x5d,0xd8,0xd2,0xbb,0x90,0xea,0xbf}, 8333},
+ {{0x2a,0x01,0x0e,0x34,0xee,0x33,0x16,0x40,0xc4,0x18,0x3c,0x3a,0x8f,0xf6,0x3e,0xab}, 8333},
+ {{0x2a,0x01,0x0e,0x34,0xee,0xd7,0x66,0x70,0x28,0xc0,0x18,0x3c,0x77,0x83,0x7d,0xc3}, 8333},
+ {{0x2a,0x01,0x0e,0x35,0x2f,0x7d,0xa0,0xb0,0x59,0xc2,0x3c,0x8a,0x95,0xa2,0xc4,0xd1}, 8333},
+ {{0x2a,0x01,0x0e,0x35,0x87,0xba,0xd0,0xc0,0x75,0xa2,0x9f,0x39,0xef,0xcb,0xf5,0x9f}, 8333},
+ {{0x2a,0x02,0x12,0x0b,0xc3,0xc5,0xce,0xf0,0xec,0x82,0xa4,0x3d,0x04,0xd6,0x0d,0xc2}, 8333},
+ {{0x2a,0x02,0x12,0x0b,0xc3,0xd1,0xf2,0xd0,0xee,0xa8,0x6b,0xff,0xfe,0xfc,0x22,0x65}, 8333},
+ {{0x2a,0x02,0x01,0x68,0x40,0x4c,0x00,0x00,0xee,0xa8,0x6b,0xff,0xfe,0xf3,0x7d,0x5c}, 8333},
{{0x2a,0x02,0x01,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x05,0x17,0x10,0xb6}, 8333},
- {{0x2a,0x02,0x01,0x80,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18}, 8333},
- {{0x2a,0x02,0x18,0x10,0x1d,0x13,0x72,0x00,0x84,0x8b,0xc4,0xc4,0x52,0x6b,0xe6,0x57}, 8333},
- {{0x2a,0x02,0x18,0x1f,0x00,0x00,0x21,0x61,0x08,0xf0,0x54,0xb2,0x22,0x2c,0xb3,0x15}, 8333},
- {{0x2a,0x02,0x20,0xc8,0x14,0x22,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa3}, 8333},
- {{0x2a,0x02,0x21,0x68,0x08,0x0d,0x06,0xe8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x02,0x01,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x5b,0x8f,0x53,0x8c}, 8333},
+ {{0x2a,0x02,0x01,0xb8,0x00,0x10,0x01,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x02,0x21,0x68,0x0d,0x05,0x2c,0x00,0x02,0x16,0x3e,0xff,0xfe,0xf7,0xa0,0x99}, 8333},
{{0x2a,0x02,0x25,0x28,0x05,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333},
+ {{0x2a,0x02,0x25,0x28,0x00,0xfa,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x27,0x70,0x00,0x17,0x00,0x00,0x02,0x1a,0x4a,0xff,0xfe,0x7b,0x17,0x5f}, 8333},
+ {{0x2a,0x02,0x27,0x70,0x00,0x05,0x00,0x00,0x02,0x1a,0x4a,0xff,0xfe,0x44,0x83,0x70}, 8333},
{{0x2a,0x02,0x28,0x08,0x54,0x01,0x00,0x00,0x02,0x25,0x90,0xff,0xfe,0x4e,0xee,0x42}, 8333},
{{0x2a,0x02,0x03,0x90,0x90,0x00,0x00,0x00,0x02,0x18,0x7d,0xff,0xfe,0x10,0xbe,0x33}, 8333},
- {{0x2a,0x02,0x7a,0xa0,0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xbd,0x4e,0x12,0x19}, 8333},
+ {{0x2a,0x02,0x07,0x50,0x00,0x07,0x0c,0x11,0x50,0x54,0x00,0xff,0xfe,0x43,0xeb,0x81}, 8333},
{{0x2a,0x02,0x7a,0xa0,0x16,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x90,0xeb,0xa2}, 8333},
- {{0x2a,0x02,0x7b,0x40,0x50,0xd0,0xe0,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0x7b,0x40,0x50,0xd0,0xe3,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0x7b,0x40,0xc2,0x87,0x53,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0x7b,0x40,0xd4,0x18,0x60,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0x7b,0x40,0xd4,0x18,0x6a,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0x3e,0x4d,0x9e,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0x50,0xd1,0xe0,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0x59,0x28,0x0f,0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0x59,0x2f,0xa5,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x82,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x89,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x8b,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x8d,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0xd4,0x18,0x6f,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x81,0x08,0x23,0x40,0x1c,0x18,0x00,0x7a,0x23,0x1e,0x14,0x30,0x7f,0x12}, 8333},
{{0x2a,0x02,0x81,0x08,0x9c,0x3f,0xdd,0x18,0x92,0x2b,0x34,0xff,0xfe,0x30,0xac,0x42}, 8333},
- {{0x2a,0x02,0x81,0x09,0x9a,0xc0,0x2a,0x2b,0x70,0x7a,0xad,0x1a,0x07,0x0c,0x84,0xa9}, 8333},
{{0x2a,0x02,0x81,0x0d,0x8a,0x40,0x36,0xf8,0x9a,0xf2,0xb3,0xff,0xfe,0xe8,0x6d,0x7a}, 8333},
- {{0x2a,0x02,0x81,0x0d,0x98,0x40,0x7e,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27}, 8333},
+ {{0x2a,0x02,0x83,0x88,0xe3,0x01,0x71,0x80,0x02,0x01,0x2e,0xff,0xfe,0x82,0xb3,0xcc}, 8333},
+ {{0x2a,0x02,0x09,0x08,0x02,0x13,0x54,0xa0,0x39,0xbf,0xd4,0xaa,0x60,0xb2,0xd9,0xc3}, 8333},
+ {{0x2a,0x02,0x09,0x08,0x04,0xf0,0x7e,0x1c,0x50,0x54,0x00,0xff,0xfe,0xb7,0xce,0x4b}, 8333},
{{0x2a,0x02,0x09,0x30,0x00,0x01,0x00,0x00,0x02,0x50,0x56,0xff,0xfe,0x8e,0x28,0x19}, 8333},
- {{0x2a,0x02,0xc2,0x00,0x00,0x01,0x00,0x10,0x00,0x02,0x00,0x04,0x03,0x34,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x00,0x00,0x01,0x00,0x10,0x00,0x02,0x00,0x05,0x02,0x27,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x00,0x00,0x01,0x00,0x10,0x00,0x02,0x00,0x05,0x08,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x0a,0x80,0x00,0x00,0x20,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
{{0x2a,0x02,0xc2,0x05,0x00,0x00,0x51,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x05,0x20,0x08,0x02,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x05,0x20,0x08,0x71,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x05,0x20,0x09,0x78,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x05,0x20,0x14,0x19,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x05,0x20,0x14,0x35,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x05,0x20,0x15,0x24,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x05,0x20,0x10,0x62,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x05,0x20,0x16,0x43,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x05,0x20,0x17,0x21,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x05,0x20,0x18,0x17,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x05,0x20,0x18,0x82,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x05,0x30,0x02,0x27,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x02,0x90,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x05,0x30,0x02,0x65,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x00,0x00,0x38,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x07,0x20,0x07,0x46,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x08,0x65,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x07,0x20,0x09,0x02,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x11,0x25,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x02,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x29,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x10,0x77,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x07,0x20,0x12,0x48,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x13,0x31,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x07,0x20,0x14,0x41,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x07,0x20,0x14,0x56,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x71,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x81,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x85,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x94,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x49,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x99,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 18333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x37,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x39,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x07,0x20,0x15,0x59,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x30,0x01,0x58,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x30,0x01,0x76,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x30,0x01,0x77,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x66,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x16,0x23,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x16,0x93,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x19,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x37,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x44,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x47,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x58,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x73,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x81,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x89,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x14,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x30,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x32,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x37,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x47,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x74,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x10,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x14,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x20,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x02,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x35,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x07,0x30,0x01,0x93,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xc2,0x07,0x30,0x02,0x12,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x15,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x24,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x44,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0x0c,0x7f,0x7c,0x2c,0xa8,0x00,0x42,0x8d,0x5c,0xff,0xfe,0x74,0x14,0x55}, 8333},
- {{0x2a,0x02,0x0c,0x7f,0xd8,0x26,0x19,0x01,0x02,0x0c,0x29,0xff,0xfe,0x11,0x9d,0x0e}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x41,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x56,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x71,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x72,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x76,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x84,0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0xce,0x80,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x03,0x40,0x00,0x00,0x02,0x04,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333},
- {{0x2a,0x03,0x73,0x80,0x03,0x00,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x2a,0x03,0x73,0x80,0x03,0x00,0x00,0x07,0xa1,0x9f,0xeb,0x0b,0x0a,0xe0,0x6a,0xad}, 8333},
- {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x12,0x19,0x60,0x01}, 8333},
+ {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x01,0xb9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x01,0xb9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a}, 8333},
+ {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x01,0xe2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x03,0xb0,0xc0,0x00,0x01,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x69,0x30,0x01}, 8333},
+ {{0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x03,0xba,0xb0,0x01}, 8333},
+ {{0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x08,0xce,0x40,0x01}, 8333},
+ {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x01,0x16,0x50,0x01}, 8333},
+ {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x01,0x2a,0x00,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xfb,0x60,0x01}, 8333},
+ {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x04,0x09,0x10,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0x90,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xa0,0x01}, 8333},
- {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xb0,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xe0,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xf0,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x00,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x10,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x20,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x40,0x01}, 8333},
- {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x01}, 8333},
{{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x5e,0x48,0xd0,0x01}, 8333},
- {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xc7,0xf0,0x01}, 8333},
- {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0xe9,0xf0,0x01}, 8333},
- {{0x2a,0x03,0xff,0x40,0x4e,0xd1,0x10,0x04,0xa2,0x36,0x9f,0xff,0xfe,0xb4,0xf9,0xf8}, 8333},
- {{0x2a,0x04,0x21,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94}, 8333},
- {{0x2a,0x04,0x21,0x80,0x00,0x01,0x00,0x06,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333},
- {{0x2a,0x04,0x52,0xc0,0x01,0x01,0x01,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x6d}, 8333},
- {{0x2a,0x04,0xdb,0xc3,0xff,0xfe,0x00,0x00,0xe6,0x1f,0x13,0xff,0xfe,0x95,0x84,0x01}, 8333},
- {{0x2a,0x05,0x35,0x80,0xd4,0x00,0x14,0x0d,0xda,0x6e,0x82,0x6e,0xe7,0x71,0x41,0x00}, 8333},
- {{0x2a,0x05,0xbe,0xc0,0x00,0x01,0x00,0x01,0x02,0x16,0x3e,0xff,0xfe,0x73,0xd2,0x0a}, 8333},
- {{0x2a,0x06,0x3d,0x80,0x00,0x0b,0x00,0x01,0x48,0xb4,0xbe,0xdd,0x69,0x64,0x54,0xac}, 8333},
- {{0x2a,0x06,0x3d,0x80,0x00,0x0b,0x00,0x01,0xae,0x1f,0x6b,0xff,0xfe,0x13,0xc1,0x3e}, 8333},
- {{0x2a,0x06,0x3d,0x80,0x00,0x0b,0x00,0x02,0xae,0x1f,0x6b,0xff,0xfe,0x13,0xc1,0x3e}, 8333},
- {{0x2a,0x06,0x3d,0x80,0x00,0x0b,0x00,0x02,0x0e,0xc4,0x7a,0xff,0xfe,0x96,0xb5,0x70}, 8333},
- {{0x2a,0x07,0x57,0x40,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xad,0x9c,0xec}, 8333},
- {{0x2a,0x07,0x57,0x40,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xb5,0x30,0x82}, 8333},
- {{0x2a,0x07,0x57,0x41,0x00,0x00,0x0d,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x03,0xee,0x40,0x00,0x00,0x02,0x94,0x02,0x50,0x56,0xff,0xfe,0x8d,0x4a,0xd7}, 8333},
+ {{0x2a,0x04,0x21,0x80,0x00,0x01,0x00,0x0c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x15}, 8333},
+ {{0x2a,0x07,0x04,0x40,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x0c,0xa0,0x18,0x17}, 8333},
+ {{0x2a,0x0a,0xc8,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0xbc,0x4a,0x3c,0x6d,0x03,0xa9,0x4e,0x1f,0x55}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd1,0x13,0xd8,0x3b,0x11,0xa3,0x88,0x84,0x80,0x61}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0xec,0x32,0xc1,0x59,0x9c,0xd8,0x46,0xd5,0x48}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd0,0x4b,0x2b,0xe5,0x74,0xc4,0xb0,0x1c,0x49,0xb1}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd1,0x79,0x73,0x7d,0x9b,0x37,0xab,0x3b,0xc0,0x43}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xda,0x0d,0xe1,0xd2,0x65,0x18,0xfc,0xf5,0x2a,0xdc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd2,0x3a,0x8f,0x2a,0xb7,0x71,0x8c,0xd3,0x67,0xdf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xde,0xfc,0xb8,0x18,0xa5,0x0f,0x26,0x6e,0x99,0xec}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdf,0x34,0xea,0x00,0x93,0xac,0x32,0x62,0x3d,0x37}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdb,0x29,0x3c,0xb5,0x05,0x98,0x81,0xdb,0x7d,0xd4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x1e,0x17,0xcf,0x86,0x53,0xf6,0x3b,0xb7,0x51}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x79,0xc1,0x8f,0x29,0x44,0xf2,0xdc,0x00,0xf6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdd,0xe8,0x28,0x36,0x77,0x7f,0x46,0x37,0x03,0x3d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe7,0x2c,0x05,0xb5,0x95,0x59,0xc5,0x00,0x6c,0x5a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe1,0x0f,0x31,0xe2,0xb5,0xc9,0xc2,0x17,0x78,0x5d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe2,0x48,0xa0,0x9f,0xe2,0x1a,0xca,0x30,0x6e,0xa4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe3,0x09,0x6b,0x3b,0x41,0x2d,0xd5,0xe5,0x9b,0x65}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0xe7,0x24,0xcf,0xd9,0x86,0xd0,0x09,0x57,0xb0}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0x3c,0x49,0x0b,0xc1,0x74,0xc2,0x92,0x86,0xe1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0x73,0x9c,0xc9,0x5f,0x44,0x2b,0xe7,0xec,0x96}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0xa5,0x34,0x24,0x5e,0x50,0x8d,0x6f,0x15,0x6a}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x17,0x9b,0x08,0xdc,0xbe,0x24,0xe3,0x01,0x6e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x79,0x89,0x41,0x5c,0x21,0x07,0xc4,0x8a,0xa9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xea,0xb6,0xeb,0xd2,0x5a,0x58,0x00,0x16,0x61,0x0f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0xe7,0x4c,0xbd,0x60,0xb0,0x77,0x2a,0xc9,0xd2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xec,0x58,0xf9,0x46,0x23,0x0e,0xea,0xf2,0x9b,0x27}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xed,0x9a,0xa8,0x65,0x39,0x49,0x0e,0xc8,0x7c,0xed}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xed,0xef,0x28,0x1d,0xef,0x42,0x35,0xa7,0x98,0x92}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0x0d,0x2c,0x85,0x41,0x08,0x29,0x94,0xdf,0xec}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0x75,0x23,0x93,0x83,0xf1,0x6b,0x11,0xb5,0x84}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf7,0x21,0x13,0xe2,0xe6,0x5e,0x12,0x93,0xa9,0xa4}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf7,0x88,0x7c,0x41,0x55,0x51,0x3d,0x31,0xf0,0xb8}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0x69,0x87,0x6d,0x58,0x95,0x47,0xaf,0x8d,0x65}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0xe3,0xf1,0x48,0xf5,0xbf,0x41,0x86,0x66,0x67}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfb,0x68,0x1a,0x6a,0xd8,0xdd,0xd1,0x93,0x5b,0x34}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfb,0x68,0x8f,0x10,0x92,0x98,0x2d,0xa2,0xfe,0xec}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfc,0x0d,0xe4,0x8d,0x80,0x39,0x6e,0x06,0x03,0x1d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x00,0x7e,0x59,0x8c,0xb6,0xf4,0x0e,0x3b,0xee,0x24}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf2,0x9b,0xff,0x28,0x09,0x12,0xa0,0x6d,0x68,0x0e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf3,0x34,0x88,0x19,0xb0,0x4d,0xcf,0xfa,0x2f,0x0a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf5,0x84,0x56,0x84,0x3b,0xab,0x01,0x6f,0x0a,0xc0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf6,0x70,0xdb,0x84,0x34,0x79,0x58,0xda,0x8b,0x66}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfc,0x9b,0x2f,0xc4,0x14,0x8b,0xd8,0xb5,0xe0,0x28}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfd,0x8e,0x09,0x64,0xda,0xd3,0xc6,0xaa,0x94,0x4a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x06,0xc1,0xe7,0xaf,0x38,0x13,0x99,0x7e,0x9a,0x16}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x00,0xa5,0xf3,0xe1,0x60,0x00,0xd2,0xa9,0xfd,0x8a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x01,0x9f,0x61,0x55,0x17,0x00,0xc2,0x86,0xe0,0x93}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x61,0x59,0x61,0x66,0xed,0xc7,0xda,0xcb,0x78}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xce,0xb2,0x1a,0x69,0x50,0xd8,0x18,0x4a,0xb3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xa6,0x52,0x02,0x0a,0x0b,0x55,0xdd,0x04,0xb7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xc3,0x22,0x35,0xb2,0x60,0x64,0x6b,0xae,0x5b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xe3,0x4c,0xc4,0x79,0xfd,0xc4,0x45,0x7b,0xe5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0x3c,0x08,0x6c,0x6b,0xa6,0x76,0xd4,0x89,0xb3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0x88,0x5c,0x5c,0xcd,0x79,0x80,0x8b,0x6a,0xe6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0xf4,0x58,0x9b,0x4c,0x04,0x2e,0xf6,0x29,0x43}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0xf9,0x9c,0xf1,0x0c,0xb8,0x46,0xbf,0x3d,0x71}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0xc2,0x1a,0x9d,0x5b,0xd3,0x31,0x41,0xb7,0x18}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x04,0x56,0xe1,0x55,0xd6,0xbc,0xda,0xb0,0xbd,0xdb}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0f,0x47,0xe2,0x4c,0xab,0x4b,0x34,0xb4,0x93,0xb8}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0f,0xee,0x48,0xfd,0x8e,0x22,0x11,0x9e,0xf8,0x4f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x08,0xed,0x51,0x58,0x05,0xcb,0xe5,0x28,0x09,0x49}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0c,0x6d,0x02,0x65,0xbe,0x59,0x3b,0xcb,0x68,0x21}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0d,0x1f,0xd6,0xf4,0x9b,0x55,0x23,0x54,0xe4,0xbb}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0d,0x41,0x8f,0x78,0x99,0x35,0xec,0xef,0xd9,0x3c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x11,0x95,0xca,0x69,0x77,0x8d,0x58,0xbe,0x26,0xa1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0d,0xef,0x55,0x07,0xe2,0xcc,0x6f,0x3a,0xe7,0x42}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0xa6,0xf8,0x28,0x19,0xe2,0x0e,0x9c,0xd8,0xc1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x11,0x85,0x5d,0xea,0x21,0x08,0x53,0x8c,0x65,0xd6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x12,0x95,0x07,0xac,0xca,0xcb,0x8b,0xce,0x9f,0x58}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x13,0xf0,0x58,0x06,0x5c,0x2c,0xb7,0x56,0x85,0xe5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x14,0xf3,0x4c,0xdd,0xb5,0x58,0x3b,0x7a,0x87,0xf9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x15,0xb8,0x88,0x54,0x43,0xc7,0xbe,0x1e,0xcd,0xf6}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0x2a,0xf3,0x4f,0x5d,0xd7,0xf8,0x8e,0x87,0xe2}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1e,0xbd,0x3a,0x3d,0x81,0x38,0xd2,0xcb,0xe6,0xcc}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1f,0xad,0x40,0xc8,0x73,0x8f,0x3c,0x31,0xf5,0x48}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x19,0x14,0x9e,0x58,0x02,0xc5,0x9f,0x09,0x00,0x7b}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0x1f,0x7b,0x2d,0xed,0xae,0xf3,0xb3,0xe5,0xab}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0xa3,0x68,0x59,0x09,0x9c,0xaa,0x8e,0x0c,0xaa}, 42434},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1d,0xd4,0xc9,0xb2,0xc8,0x87,0xc6,0x39,0x9a,0x8b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1b,0x28,0x39,0x47,0xf7,0xf9,0x07,0x5c,0x19,0x73}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0x82,0xde,0xec,0xba,0x1d,0x9e,0x7a,0xf5,0x97}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0xa5,0x01,0xa7,0xcf,0xbb,0x72,0xa9,0x9f,0xc8}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0xf2,0x12,0x3c,0xf5,0x14,0x19,0x91,0x41,0x51}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x20,0x03,0xd7,0x3f,0x79,0xd7,0x1b,0xf2,0x40,0x7d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x22,0x45,0x02,0x56,0x89,0x14,0x17,0x38,0x37,0xe3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x27,0xb6,0x8f,0x8b,0xf0,0x06,0x42,0x39,0xa5,0x80}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x22,0x28,0x04,0xea,0x09,0xa8,0x5b,0xfd,0xfd,0xe7}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x23,0xf4,0xc4,0xe5,0xd7,0xda,0xaa,0x1f,0x02,0xfc}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0xf8,0x29,0x1c,0xe0,0x5e,0x9b,0x45,0xa6,0x42}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0x2a,0x5b,0x90,0x85,0x8f,0x08,0xe5,0x10,0xb1}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0xda,0x54,0x38,0xfa,0xfa,0x75,0x75,0x94,0x9d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2f,0x8f,0xfa,0x2b,0x18,0x40,0xb2,0xbc,0x55,0x8b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2f,0x49,0x9b,0xbc,0xe6,0x3a,0x9a,0x50,0xc6,0x66}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x28,0x09,0x61,0x65,0x34,0xcc,0xb9,0x62,0xdc,0xf5}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x55,0xb1,0xa1,0xce,0x35,0xc0,0xb9,0x7e,0x3c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x0e,0x75,0xb8,0x99,0xc1,0x60,0x7d,0x9c,0x48}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0x63,0x48,0x37,0x97,0xfb,0x42,0xde,0xbc,0x20}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x29,0x0a,0x89,0x09,0x50,0xa7,0x62,0x08,0x13,0x62}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x29,0x83,0x29,0x6f,0xbb,0xac,0xaa,0x06,0x8d,0xbf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x56,0xa8,0xba,0xd2,0xc4,0x4a,0x4a,0x07,0xd2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x5d,0xc0,0x01,0x4f,0x5f,0xa4,0x6f,0x63,0x9f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x5e,0xd4,0x8d,0x5a,0xe3,0xf2,0x61,0x3d,0x77}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x89,0xcc,0x31,0x39,0xe1,0xd2,0x77,0x5a,0x83}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x17,0xcd,0xf9,0xb9,0xfc,0x06,0x89,0x6d,0xaa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x4e,0x5a,0x0a,0xd6,0xed,0x4c,0x72,0xfc,0x55}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x63,0x72,0x16,0xbd,0x1a,0x23,0xd3,0xb3,0xeb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2d,0x04,0xa2,0x45,0xcb,0xc5,0x2b,0xf2,0x05,0x60}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0x7c,0xd9,0x21,0x3e,0x4a,0x31,0x4b,0x2e,0x42}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x37,0x20,0x5b,0x0a,0x9d,0xb3,0x3f,0x92,0x75,0x66}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0x7b,0x87,0xc2,0x7e,0xd8,0xe9,0xbb,0x14,0xed}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0xb0,0x34,0xf5,0x03,0xda,0x45,0x7c,0x07,0x31}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x31,0x6a,0xd6,0xb6,0xc2,0x18,0xcb,0x97,0x48,0x15}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x33,0x96,0x4a,0xd7,0x00,0xc0,0xe4,0x3a,0x52,0xda}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x34,0x39,0x2a,0x7a,0x53,0x4b,0x5d,0x28,0x53,0xdf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x78,0xe8,0x90,0xcb,0x74,0x7b,0x7d,0xdd,0xc0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x68,0x04,0x47,0x7f,0x1d,0xda,0x15,0xd2,0x36}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xc1,0xf2,0xd7,0x30,0xdd,0x5c,0x7f,0xb2,0x9e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3b,0x6a,0xad,0xbc,0xd5,0x41,0x30,0x8b,0xe0,0x5a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0x6d,0x7b,0x51,0xa9,0x07,0x1e,0x6b,0x60,0x66}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x42,0x58,0x16,0x65,0x14,0x68,0x65,0x9c,0xde,0x69}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0x1e,0x48,0xa0,0x0b,0x6e,0x41,0xb9,0xc0,0xc7}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0x7f,0x1e,0xa0,0x8e,0xfb,0x8c,0xab,0x85,0xa4}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0x08,0xd5,0x88,0x11,0x93,0x65,0x29,0xa1,0x17}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0x71,0x2a,0x9c,0x0a,0x8d,0x16,0x6f,0x2e,0x72}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0xa3,0x60,0xda,0x52,0xfa,0xca,0x05,0x94,0xdc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x48,0x3e,0x36,0x19,0x51,0x47,0xca,0x8e,0x7e,0xea}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4c,0xd5,0x26,0xb9,0x54,0x90,0x72,0xc9,0x7e,0xcb}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x57,0x84,0xf2,0x6c,0xe0,0x9c,0x63,0x7a,0xb7,0x3e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xaf,0x88,0x1d,0xfc,0xd0,0x99,0x63,0xc0,0xbb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xe2,0x50,0x4e,0x13,0x11,0x2b,0x9b,0x62,0xd9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x3c,0xca,0xe4,0x3a,0x6c,0xe9,0x34,0x60,0x9e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x07,0x0a,0x5f,0x2b,0x41,0x13,0xe1,0xb3,0x5c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x56,0x8c,0x3c,0xd6,0x38,0x8d,0xff,0x5f,0x2a,0x56}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x52,0x86,0x09,0x6e,0x04,0x0a,0x9d,0x2c,0x1a,0x9d}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x54,0xac,0x5c,0x52,0x2d,0x32,0xd9,0xee,0xd3,0xe1}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x55,0x47,0xce,0x4a,0xdf,0x92,0x83,0xd2,0xb9,0x76}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5e,0x9f,0x1a,0x66,0x3b,0x63,0x4e,0x82,0x52,0x86}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5f,0x5c,0x31,0xa7,0x9e,0x7d,0x5c,0x31,0xe4,0x7c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x94,0x61,0x0f,0x81,0x8a,0x58,0x78,0xc1,0xa0}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x95,0x50,0xd6,0x2e,0xf7,0xd2,0xe6,0x3a,0x56}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5b,0x8a,0xb2,0x86,0xf4,0x65,0xd9,0xde,0x85,0x10}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x67,0x93,0x13,0xc6,0x15,0x48,0x5b,0x95,0x83,0x71}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5a,0xd6,0x96,0x82,0x6a,0x91,0x4d,0x35,0x9d,0x4e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x60,0xdf,0x3f,0x5b,0xb2,0x4d,0x84,0xdb,0xce,0xd8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x61,0xd2,0x22,0x3f,0x22,0xe1,0xb0,0x01,0xdb,0x56}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x63,0x7f,0xce,0x1c,0x28,0x70,0x30,0xdd,0xb9,0x32}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x63,0xc0,0xa7,0x9b,0x34,0xfd,0x18,0x6a,0x6f,0x24}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x65,0x5c,0xcb,0x14,0x63,0x1c,0x0b,0x03,0x6d,0x70}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0x06,0x50,0xfa,0x6f,0xde,0xca,0x5d,0x2e,0x1f}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0x24,0xbe,0xb4,0x1e,0x49,0x20,0x64,0x6d,0x7e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x65,0xfa,0xa1,0x96,0xf6,0x75,0x85,0xbc,0x33,0x26}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0x19,0xbd,0x64,0x4f,0xe9,0xea,0xe6,0x2a,0x7c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0xf7,0x29,0x92,0x02,0x62,0x73,0xd3,0xd9,0xa8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x68,0xb4,0x13,0x28,0xf0,0x71,0xe2,0xcb,0x06,0xf1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x68,0xbd,0x95,0xca,0xd6,0x84,0x0d,0xf1,0x77,0x19}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6c,0x62,0x5b,0x0d,0x91,0x66,0xd0,0xca,0x10,0x2d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6c,0x62,0xc5,0x19,0x94,0x5b,0xcd,0x20,0xd9,0x73}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x76,0xa6,0xaa,0x68,0x61,0x90,0xfc,0x8a,0x30,0x47}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0xf5,0x9c,0x66,0x35,0xff,0xc8,0x0d,0x06,0xd4}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x73,0x27,0x2e,0x38,0xa7,0xb4,0x12,0x3a,0x2e,0x3e}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0x5a,0xb7,0xfd,0x9c,0x55,0x12,0xc0,0x79,0x19}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x71,0xcd,0x60,0x77,0x1e,0xee,0x78,0x42,0x33,0xe1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x72,0xea,0x3a,0x77,0xe6,0xfc,0x6f,0x67,0x8a,0x3c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x73,0x57,0x97,0x7f,0xfd,0x71,0x86,0xf4,0xb7,0xb7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x74,0xe4,0x79,0xcc,0x23,0xf5,0x74,0xad,0xa5,0x79}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x75,0xa3,0xd9,0xb3,0xf8,0x35,0xbd,0xac,0xf2,0xab}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0x8a,0x79,0x0e,0x19,0x97,0xa1,0xed,0xc7,0x14}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x79,0x4b,0x68,0x5e,0xb4,0x58,0xc9,0x0e,0xf7,0x22}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x79,0x9b,0x9f,0xaa,0xc2,0xdf,0xa2,0x2a,0x09,0xf4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x79,0xf8,0x6f,0x87,0x89,0x96,0x28,0xd9,0xd6,0x3c}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7a,0x4c,0x71,0x22,0xb9,0x53,0x89,0x19,0x12,0x43}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7e,0x75,0x7e,0xb4,0xa7,0x4a,0x1f,0x23,0x83,0x3b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7d,0x3f,0x6d,0xa4,0xb8,0x8e,0x5f,0xf9,0x5e,0x48}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7d,0xea,0xa4,0xbf,0xd2,0x28,0x74,0x5f,0x95,0xc4}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x80,0x2e,0xce,0xc9,0xec,0xbf,0x47,0xa5,0x6e,0x8f}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x81,0x1f,0x33,0xf7,0x83,0x06,0x24,0xc7,0xe3,0xb8}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x81,0xad,0xc4,0x87,0xd8,0x42,0x9f,0xce,0x61,0xe0}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0x7c,0x88,0xc1,0xba,0x47,0xf6,0x41,0x94,0xbd}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0xeb,0xe7,0xe3,0xc7,0x1c,0xf2,0x87,0xb6,0x6d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x85,0x78,0x78,0x7f,0xa0,0x96,0x11,0x35,0x30,0x12}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8e,0xc7,0x27,0x24,0xa7,0xb0,0x99,0xfb,0xfd,0xfe}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0x40,0x2b,0x4b,0xfd,0xf8,0x11,0xef,0x2e,0x24}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x91,0x1d,0x25,0x50,0x79,0x57,0xaa,0xdf,0x32,0x19}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x93,0x26,0xc3,0x88,0x96,0xa5,0x7d,0x34,0xe1,0xb5}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x94,0xd0,0xbd,0xc8,0x55,0x80,0x6a,0x77,0x5a,0xa1}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0x8e,0xe7,0xfb,0xfe,0x4f,0xb0,0xf7,0xda,0xcc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0x5e,0x44,0x97,0x2b,0xb4,0x20,0xdc,0xc9,0xcb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x85,0xc9,0xb0,0xc1,0x2c,0x88,0x88,0xfb,0xbe,0xfc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0xdc,0xd4,0xb3,0xf4,0x47,0x8a,0x3c,0x67,0x87}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8c,0xbd,0xbe,0xca,0x5a,0xe6,0x19,0x6c,0x41,0x56}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x91,0x90,0x89,0xb8,0xc4,0x74,0x24,0xba,0xa9,0x35}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x93,0xd0,0x32,0x45,0xa4,0x9a,0x18,0xc6,0x2a,0x67}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0x7f,0x05,0xa0,0x51,0x9f,0xa2,0x3c,0xdf,0x23}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xc2,0x95,0x03,0xda,0x05,0xf3,0x4b,0x4d,0xb3}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9b,0x8d,0x4a,0xe3,0xb4,0x7e,0x28,0x29,0xd0,0x77}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9b,0xef,0xc4,0x81,0xbd,0x6e,0x81,0xa1,0x09,0x1a}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9c,0x63,0x3c,0x3f,0x72,0x44,0x59,0x69,0xcf,0x14}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa7,0xd8,0xfa,0xdd,0xd3,0x63,0x60,0xd9,0xe1,0xbd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa0,0x84,0xcb,0x7b,0xeb,0xe2,0x8c,0xbf,0x73,0xd8}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa1,0x1d,0xe8,0xbb,0x02,0xdf,0xff,0xd4,0x3a,0x1f}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa9,0x2b,0xb6,0xf4,0xb7,0x2c,0x67,0x04,0xf8,0x9d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaa,0x24,0x4a,0xc5,0x19,0xce,0xe1,0x4c,0x00,0xc9}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0x72,0x51,0x38,0x35,0x04,0x00,0x77,0x3a,0x8d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb6,0x87,0x3a,0x47,0xaa,0xa1,0x80,0xfb,0x6e,0x2f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa2,0x64,0x1d,0x40,0x49,0x57,0x27,0xed,0x6f,0x99}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa5,0x03,0xcd,0xbf,0x60,0x8c,0xd8,0xe8,0xb6,0xbd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa5,0x43,0xde,0xb2,0xd5,0xa6,0x35,0xa6,0x19,0x9a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa6,0x73,0x84,0x9a,0x0b,0x2f,0x3e,0x01,0x28,0x31}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaf,0x4a,0x68,0xec,0xad,0xce,0xdb,0x6f,0x7b,0x73}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaf,0x73,0x2d,0x48,0xc9,0xc4,0x76,0x65,0x9f,0xc2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaa,0xb7,0x04,0x8c,0x87,0xc6,0x38,0x3b,0x0a,0xf6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0xb1,0xeb,0x86,0xa4,0x4b,0xaf,0xcb,0x84,0x17}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xad,0x11,0x6f,0xf5,0x46,0x78,0xa0,0xa2,0x71,0x95}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb6,0xe1,0xcf,0xd0,0x58,0x02,0x66,0x54,0x0b,0xfe}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0xbd,0x5b,0x30,0x31,0xce,0x31,0x90,0x3e,0x8d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb3,0x2e,0x2f,0x02,0x4a,0xe0,0x3b,0x7c,0x02,0xe7}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbe,0x76,0x19,0x14,0xe8,0x85,0x04,0xdd,0xfc,0xc3}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc3,0xf2,0xb1,0xea,0xf8,0x40,0xe9,0xec,0x32,0x02}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0x9e,0x5b,0x5c,0xd8,0xd0,0xdd,0x64,0x11,0xad}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb2,0x66,0xca,0xcb,0x2d,0xa8,0xc4,0xb6,0x88,0x14}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb8,0x03,0xce,0x85,0xec,0x64,0x57,0xd3,0x6c,0x38}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb8,0xd7,0x4d,0xd1,0x39,0x41,0x0e,0x47,0x51,0xdf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb9,0xb0,0xa6,0x00,0x1a,0x4a,0x41,0x8f,0x88,0xb4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbb,0x57,0x4d,0xce,0xa0,0x53,0x4d,0x8f,0xcd,0x4f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbc,0x9b,0xd4,0x08,0x44,0xe7,0x4d,0x2d,0xc3,0x1f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc0,0xdc,0xd7,0x19,0x2f,0x48,0xf6,0xc2,0x73,0xb5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc2,0x9b,0xfa,0xb8,0xbb,0xf8,0x41,0x5b,0x92,0x63}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc2,0xfb,0xae,0x8e,0xc7,0xac,0x11,0x2f,0xc7,0x02}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc4,0x42,0x01,0x09,0xe1,0xc1,0x89,0xeb,0x80,0x20}, 8333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc6,0x29,0x70,0x15,0x68,0xf9,0x60,0x34,0x64,0xf0}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xca,0x09,0x6f,0xc9,0x91,0xd0,0xd7,0xa3,0x9b,0x50}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcc,0xa1,0xd8,0x38,0xd3,0x74,0x8f,0x95,0x40,0x03}, 8333}
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0xf6,0xda,0x2a,0x7f,0x69,0x90,0xad,0x89,0xe4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcb,0x9b,0xa0,0x84,0x5a,0x86,0x90,0x78,0x4f,0x82}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcc,0x13,0x59,0xde,0x4a,0xbb,0x9b,0x4e,0x2b,0x35}, 8333}
};
static SeedSpec6 pnSeed6_test[] = {
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
deleted file mode 100644
index 816d854db3..0000000000
--- a/src/checkpoints.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2009-2017 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 <checkpoints.h>
-
-#include <chain.h>
-#include <chainparams.h>
-#include <reverse_iterator.h>
-#include <validation.h>
-
-#include <stdint.h>
-
-
-namespace Checkpoints {
-
- CBlockIndex* GetLastCheckpoint(const CCheckpointData& data)
- {
- const MapCheckpoints& checkpoints = data.mapCheckpoints;
-
- for (const MapCheckpoints::value_type& i : reverse_iterate(checkpoints))
- {
- const uint256& hash = i.second;
- CBlockIndex* pindex = LookupBlockIndex(hash);
- if (pindex) {
- return pindex;
- }
- }
- return nullptr;
- }
-
-} // namespace Checkpoints
diff --git a/src/checkpoints.h b/src/checkpoints.h
deleted file mode 100644
index 564b486393..0000000000
--- a/src/checkpoints.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2009-2017 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_CHECKPOINTS_H
-#define BITCOIN_CHECKPOINTS_H
-
-#include <uint256.h>
-
-#include <map>
-
-class CBlockIndex;
-struct CCheckpointData;
-
-/**
- * Block-chain checkpoints are compiled-in sanity checks.
- * They are updated every release or three.
- */
-namespace Checkpoints
-{
-
-//! Returns last CBlockIndex* that is a checkpoint
-CBlockIndex* GetLastCheckpoint(const CCheckpointData& data);
-
-} //namespace Checkpoints
-
-#endif // BITCOIN_CHECKPOINTS_H
diff --git a/src/checkqueue.h b/src/checkqueue.h
index 84360d0716..978e23a7c4 100644
--- a/src/checkqueue.h
+++ b/src/checkqueue.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/clientversion.cpp b/src/clientversion.cpp
index a3eb127ca8..5d9eaea6d0 100644
--- a/src/clientversion.cpp
+++ b/src/clientversion.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/clientversion.h b/src/clientversion.h
index d7321fad86..363094b696 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/coins.cpp b/src/coins.cpp
index 8dfb35c2eb..3ef9e0463c 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,6 +6,7 @@
#include <consensus/consensus.h>
#include <random.h>
+#include <version.h>
bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
@@ -244,7 +245,7 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
return true;
}
-static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut(), SER_NETWORK, PROTOCOL_VERSION);
+static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut(), PROTOCOL_VERSION);
static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT;
const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid)
diff --git a/src/coins.h b/src/coins.h
index 89685ce4b2..482e233e8c 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <primitives/transaction.h>
#include <compressor.h>
#include <core_memusage.h>
-#include <hash.h>
+#include <crypto/siphash.h>
#include <memusage.h>
#include <serialize.h>
#include <uint256.h>
@@ -285,8 +285,8 @@ public:
* Note that lightweight clients may not know anything besides the hash of previous transactions,
* so may not be able to calculate this.
*
- * @param[in] tx transaction for which we are checking input total
- * @return Sum of value of all inputs (scriptSigs)
+ * @param[in] tx transaction for which we are checking input total
+ * @return Sum of value of all inputs (scriptSigs)
*/
CAmount GetValueIn(const CTransaction& tx) const;
@@ -294,21 +294,25 @@ public:
bool HaveInputs(const CTransaction& tx) const;
private:
+ /**
+ * @note this is marked const, but may actually append to `cacheCoins`, increasing
+ * memory usage.
+ */
CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const;
};
//! Utility function to add all of a transaction's outputs to a cache.
-// When check is false, this assumes that overwrites are only possible for coinbase transactions.
-// When check is true, the underlying view may be queried to determine whether an addition is
-// an overwrite.
+//! When check is false, this assumes that overwrites are only possible for coinbase transactions.
+//! When check is true, the underlying view may be queried to determine whether an addition is
+//! an overwrite.
// TODO: pass in a boolean to limit these possible overwrites to known
// (pre-BIP34) cases.
void AddCoins(CCoinsViewCache& cache, const CTransaction& tx, int nHeight, bool check = false);
//! Utility function to find any unspent output with a given txid.
-// This function can be quite expensive because in the event of a transaction
-// which is not found in the cache, it can cause up to MAX_OUTPUTS_PER_BLOCK
-// lookups to database, so it should be used with care.
+//! This function can be quite expensive because in the event of a transaction
+//! which is not found in the cache, it can cause up to MAX_OUTPUTS_PER_BLOCK
+//! lookups to database, so it should be used with care.
const Coin& AccessByTxid(const CCoinsViewCache& cache, const uint256& txid);
#endif // BITCOIN_COINS_H
diff --git a/src/compat.h b/src/compat.h
index 920b3f776d..68f6eb692c 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,21 +10,7 @@
#include <config/bitcoin-config.h>
#endif
-#include <type_traits>
-
-// GCC 4.8 is missing some C++11 type_traits,
-// https://www.gnu.org/software/gcc/gcc-5/changes.html
-#if defined(__GNUC__) && __GNUC__ < 5
-#define IS_TRIVIALLY_CONSTRUCTIBLE std::is_trivial
-#else
-#define IS_TRIVIALLY_CONSTRUCTIBLE std::is_trivially_constructible
-#endif
-
#ifdef WIN32
-#ifdef _WIN32_WINNT
-#undef _WIN32_WINNT
-#endif
-#define _WIN32_WINNT 0x0501
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
@@ -102,8 +88,15 @@ typedef void* sockopt_arg_type;
typedef char* sockopt_arg_type;
#endif
+// Note these both should work with the current usage of poll, but best to be safe
+// WIN32 poll is broken https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
+// __APPLE__ poll is broke https://github.com/bitcoin/bitcoin/pull/14336#issuecomment-437384408
+#if defined(__linux__)
+#define USE_POLL
+#endif
+
bool static inline IsSelectableSocket(const SOCKET& s) {
-#ifdef WIN32
+#if defined(USE_POLL) || defined(WIN32)
return true;
#else
return (s < FD_SETSIZE);
diff --git a/src/compat/assumptions.h b/src/compat/assumptions.h
new file mode 100644
index 0000000000..6e7b4d3ded
--- /dev/null
+++ b/src/compat/assumptions.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+// Compile-time verification of assumptions we make.
+
+#ifndef BITCOIN_COMPAT_ASSUMPTIONS_H
+#define BITCOIN_COMPAT_ASSUMPTIONS_H
+
+#include <limits>
+
+// Assumption: We assume that the macro NDEBUG is not defined.
+// Example(s): We use assert(...) extensively with the assumption of it never
+// being a noop at runtime.
+#if defined(NDEBUG)
+# error "Bitcoin cannot be compiled without assertions."
+#endif
+
+// Assumption: We assume a C++11 (ISO/IEC 14882:2011) compiler (minimum requirement).
+// Example(s): We assume the presence of C++11 features everywhere :-)
+// Note: MSVC does not report the expected __cplusplus value due to legacy
+// reasons.
+#if !defined(_MSC_VER)
+// ISO Standard C++11 [cpp.predefined]p1:
+// "The name __cplusplus is defined to the value 201103L when compiling a C++
+// translation unit."
+static_assert(__cplusplus >= 201103L, "C++11 standard assumed");
+#endif
+
+// Assumption: We assume the floating-point types to fulfill the requirements of
+// IEC 559 (IEEE 754) standard.
+// Example(s): Floating-point division by zero in ConnectBlock, CreateTransaction
+// and EstimateMedianVal.
+static_assert(std::numeric_limits<float>::is_iec559, "IEEE 754 float assumed");
+static_assert(std::numeric_limits<double>::is_iec559, "IEEE 754 double assumed");
+
+// Assumption: We assume eight bits per byte (obviously, but remember: don't
+// trust -- verify!).
+// Example(s): Everywhere :-)
+static_assert(std::numeric_limits<unsigned char>::digits == 8, "8-bit byte assumed");
+
+// Assumption: We assume floating-point widths.
+// Example(s): Type punning in serialization code (ser_{float,double}_to_uint{32,64}).
+static_assert(sizeof(float) == 4, "32-bit float assumed");
+static_assert(sizeof(double) == 8, "64-bit double assumed");
+
+// Assumption: We assume integer widths.
+// Example(s): GetSizeOfCompactSize and WriteCompactSize in the serialization
+// code.
+static_assert(sizeof(short) == 2, "16-bit short assumed");
+static_assert(sizeof(int) == 4, "32-bit int assumed");
+
+// Assumption: We assume size_t to be 32-bit or 64-bit.
+// Example(s): size_t assumed to be at least 32-bit in ecdsa_signature_parse_der_lax(...).
+// size_t assumed to be 32-bit or 64-bit in MallocUsage(...).
+static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t assumed to be 32-bit or 64-bit");
+static_assert(sizeof(size_t) == sizeof(void*), "Sizes of size_t and void* assumed to be equal");
+
+// Some important things we are NOT assuming (non-exhaustive list):
+// * We are NOT assuming a specific value for std::endian::native.
+// * We are NOT assuming a specific value for std::locale("").name().
+// * We are NOT assuming a specific value for std::numeric_limits<char>::is_signed.
+
+#endif // BITCOIN_COMPAT_ASSUMPTIONS_H
diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h
index bfb80bd632..fe47f4899f 100644
--- a/src/compat/byteswap.h
+++ b/src/compat/byteswap.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compat/endian.h b/src/compat/endian.h
index 4f244c3930..c5cf7a46cc 100644
--- a/src/compat/endian.h
+++ b/src/compat/endian.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp
index b1cbe9f72a..4de4fd7f45 100644
--- a/src/compat/glibc_compat.cpp
+++ b/src/compat/glibc_compat.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -67,6 +67,8 @@ __asm(".symver log2f_old,log2f@GLIBC_2.2.5");
__asm(".symver log2f_old,log2f@GLIBC_2.4");
#elif defined(__aarch64__)
__asm(".symver log2f_old,log2f@GLIBC_2.17");
+#elif defined(__riscv)
+__asm(".symver log2f_old,log2f@GLIBC_2.27");
#endif
extern "C" float __wrap_log2f(float x)
{
diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp
index 1c22dc073c..1ef66e27b4 100644
--- a/src/compat/glibc_sanity.cpp
+++ b/src/compat/glibc_sanity.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp
index 257665a061..e6e6208e40 100644
--- a/src/compat/glibcxx_sanity.cpp
+++ b/src/compat/glibcxx_sanity.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compat/strnlen.cpp b/src/compat/strnlen.cpp
index f7344d39f5..93a034a664 100644
--- a/src/compat/strnlen.cpp
+++ b/src/compat/strnlen.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compressor.cpp b/src/compressor.cpp
index da639a01af..a2d9af8805 100644
--- a/src/compressor.cpp
+++ b/src/compressor.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/compressor.h b/src/compressor.h
index 6bd68529d4..c1eda503c8 100644
--- a/src/compressor.h
+++ b/src/compressor.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index 650635a766..788fa4e55b 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp
index 07cd109cc1..b47d9774ca 100644
--- a/src/consensus/merkle.cpp
+++ b/src/consensus/merkle.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <consensus/merkle.h>
#include <hash.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
/* WARNING! If you're reading this because you're learning about crypto
and/or designing a new system that will use merkle trees, keep in mind
diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h
index 01d75b1329..7675877de5 100644
--- a/src/consensus/merkle.h
+++ b/src/consensus/merkle.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 0559304fc2..6c3a201f4f 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/consensus/tx_check.cpp b/src/consensus/tx_check.cpp
new file mode 100644
index 0000000000..23ed3ecb53
--- /dev/null
+++ b/src/consensus/tx_check.cpp
@@ -0,0 +1,57 @@
+// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/tx_check.h>
+
+#include <primitives/transaction.h>
+#include <consensus/validation.h>
+
+bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
+{
+ // Basic checks that don't depend on any context
+ if (tx.vin.empty())
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vin-empty");
+ if (tx.vout.empty())
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-empty");
+ // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
+ if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-oversize");
+
+ // Check for negative or overflow output values
+ CAmount nValueOut = 0;
+ for (const auto& txout : tx.vout)
+ {
+ if (txout.nValue < 0)
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-negative");
+ if (txout.nValue > MAX_MONEY)
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-vout-toolarge");
+ nValueOut += txout.nValue;
+ if (!MoneyRange(nValueOut))
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
+ }
+
+ // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
+ if (fCheckDuplicateInputs) {
+ std::set<COutPoint> vInOutPoints;
+ for (const auto& txin : tx.vin)
+ {
+ if (!vInOutPoints.insert(txin.prevout).second)
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
+ }
+ }
+
+ if (tx.IsCoinBase())
+ {
+ if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-length");
+ }
+ else
+ {
+ for (const auto& txin : tx.vin)
+ if (txin.prevout.IsNull())
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-prevout-null");
+ }
+
+ return true;
+}
diff --git a/src/consensus/tx_check.h b/src/consensus/tx_check.h
new file mode 100644
index 0000000000..bcfdf36bf9
--- /dev/null
+++ b/src/consensus/tx_check.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CONSENSUS_TX_CHECK_H
+#define BITCOIN_CONSENSUS_TX_CHECK_H
+
+/**
+ * Context-independent transaction checking code that can be called outside the
+ * bitcoin server and doesn't depend on chain or mempool state. Transaction
+ * verification code that does call server functions or depend on server state
+ * belongs in tx_verify.h/cpp instead.
+ */
+
+class CTransaction;
+class CValidationState;
+
+bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);
+
+#endif // BITCOIN_CONSENSUS_TX_CHECK_H
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index be73d0a2f9..4b93cae848 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
// TODO remove the following dependencies
#include <chain.h>
#include <coins.h>
-#include <utilmoneystr.h>
+#include <util/moneystr.h>
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
@@ -156,60 +156,11 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
return nSigOps;
}
-bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
-{
- // Basic checks that don't depend on any context
- if (tx.vin.empty())
- return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
- if (tx.vout.empty())
- return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
- // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
- if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
-
- // Check for negative or overflow output values
- CAmount nValueOut = 0;
- for (const auto& txout : tx.vout)
- {
- if (txout.nValue < 0)
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
- if (txout.nValue > MAX_MONEY)
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
- nValueOut += txout.nValue;
- if (!MoneyRange(nValueOut))
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
- }
-
- // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
- if (fCheckDuplicateInputs) {
- std::set<COutPoint> vInOutPoints;
- for (const auto& txin : tx.vin)
- {
- if (!vInOutPoints.insert(txin.prevout).second)
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
- }
- }
-
- if (tx.IsCoinBase())
- {
- if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
- return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
- }
- else
- {
- for (const auto& txin : tx.vin)
- if (txin.prevout.IsNull())
- return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
- }
-
- return true;
-}
-
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
{
// are the actual inputs available?
if (!inputs.HaveInputs(tx)) {
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-missingorspent", false,
+ return state.Invalid(ValidationInvalidReason::TX_MISSING_INPUTS, false, REJECT_INVALID, "bad-txns-inputs-missingorspent",
strprintf("%s: inputs missing/spent", __func__));
}
@@ -221,28 +172,27 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
// If prev is coinbase, check that it's matured
if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
- return state.Invalid(false,
- REJECT_INVALID, "bad-txns-premature-spend-of-coinbase",
+ return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_INVALID, "bad-txns-premature-spend-of-coinbase",
strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
}
// Check for negative or overflow input values
nValueIn += coin.out.nValue;
if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
}
}
const CAmount value_out = tx.GetValueOut();
if (nValueIn < value_out) {
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-in-belowout",
strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
}
// Tally transaction fees
const CAmount txfee_aux = nValueIn - value_out;
if (!MoneyRange(txfee_aux)) {
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-fee-outofrange");
}
txfee = txfee_aux;
diff --git a/src/consensus/tx_verify.h b/src/consensus/tx_verify.h
index 50db1775a3..3519fc555d 100644
--- a/src/consensus/tx_verify.h
+++ b/src/consensus/tx_verify.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -17,9 +17,6 @@ class CValidationState;
/** Transaction validation functions */
-/** Context-independent validity checks */
-bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);
-
namespace Consensus {
/**
* Check whether all inputs of this transaction are valid (no double spends and amounts)
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index 28d3c4a119..2e23f4b3a4 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -22,6 +22,78 @@ static const unsigned char REJECT_NONSTANDARD = 0x40;
static const unsigned char REJECT_INSUFFICIENTFEE = 0x42;
static const unsigned char REJECT_CHECKPOINT = 0x43;
+/** A "reason" why something was invalid, suitable for determining whether the
+ * provider of the object should be banned/ignored/disconnected/etc.
+ * These are much more granular than the rejection codes, which may be more
+ * useful for some other use-cases.
+ */
+enum class ValidationInvalidReason {
+ // txn and blocks:
+ NONE, //!< not actually invalid
+ CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
+ /**
+ * Invalid by a change to consensus rules more recent than SegWit.
+ * Currently unused as there are no such consensus rule changes, and any download
+ * sources realistically need to support SegWit in order to provide useful data,
+ * so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
+ * is uninteresting.
+ */
+ RECENT_CONSENSUS_CHANGE,
+ // Only blocks (or headers):
+ CACHED_INVALID, //!< this object was cached as being invalid, but we don't know why
+ BLOCK_INVALID_HEADER, //!< invalid proof of work or time too old
+ BLOCK_MUTATED, //!< the block's data didn't match the data committed to by the PoW
+ BLOCK_MISSING_PREV, //!< We don't have the previous block the checked one is built on
+ BLOCK_INVALID_PREV, //!< A block this one builds on is invalid
+ BLOCK_TIME_FUTURE, //!< block timestamp was > 2 hours in the future (or our clock is bad)
+ BLOCK_CHECKPOINT, //!< the block failed to meet one of our checkpoints
+ // Only loose txn:
+ TX_NOT_STANDARD, //!< didn't meet our local policy rules
+ TX_MISSING_INPUTS, //!< a transaction was missing some of its inputs
+ TX_PREMATURE_SPEND, //!< transaction spends a coinbase too early, or violates locktime/sequence locks
+ /**
+ * Transaction might be missing a witness, have a witness prior to SegWit
+ * activation, or witness may have been malleated (which includes
+ * non-standard witnesses).
+ */
+ TX_WITNESS_MUTATED,
+ /**
+ * Tx already in mempool or conflicts with a tx in the chain
+ * (if it conflicts with another tx in mempool, we use MEMPOOL_POLICY as it failed to reach the RBF threshold)
+ * TODO: Currently this is only used if the transaction already exists in the mempool or on chain,
+ * TODO: ATMP's fMissingInputs and a valid CValidationState being used to indicate missing inputs
+ */
+ TX_CONFLICT,
+ TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/RBF/etc limits
+};
+
+inline bool IsTransactionReason(ValidationInvalidReason r)
+{
+ return r == ValidationInvalidReason::NONE ||
+ r == ValidationInvalidReason::CONSENSUS ||
+ r == ValidationInvalidReason::RECENT_CONSENSUS_CHANGE ||
+ r == ValidationInvalidReason::TX_NOT_STANDARD ||
+ r == ValidationInvalidReason::TX_PREMATURE_SPEND ||
+ r == ValidationInvalidReason::TX_MISSING_INPUTS ||
+ r == ValidationInvalidReason::TX_WITNESS_MUTATED ||
+ r == ValidationInvalidReason::TX_CONFLICT ||
+ r == ValidationInvalidReason::TX_MEMPOOL_POLICY;
+}
+
+inline bool IsBlockReason(ValidationInvalidReason r)
+{
+ return r == ValidationInvalidReason::NONE ||
+ r == ValidationInvalidReason::CONSENSUS ||
+ r == ValidationInvalidReason::RECENT_CONSENSUS_CHANGE ||
+ r == ValidationInvalidReason::CACHED_INVALID ||
+ r == ValidationInvalidReason::BLOCK_INVALID_HEADER ||
+ r == ValidationInvalidReason::BLOCK_MUTATED ||
+ r == ValidationInvalidReason::BLOCK_MISSING_PREV ||
+ r == ValidationInvalidReason::BLOCK_INVALID_PREV ||
+ r == ValidationInvalidReason::BLOCK_TIME_FUTURE ||
+ r == ValidationInvalidReason::BLOCK_CHECKPOINT;
+}
+
/** Capture information about block/transaction validation */
class CValidationState {
private:
@@ -30,32 +102,24 @@ private:
MODE_INVALID, //!< network rule violation (DoS value may be set)
MODE_ERROR, //!< run-time error
} mode;
- int nDoS;
+ ValidationInvalidReason m_reason;
std::string strRejectReason;
unsigned int chRejectCode;
- bool corruptionPossible;
std::string strDebugMessage;
public:
- CValidationState() : mode(MODE_VALID), nDoS(0), chRejectCode(0), corruptionPossible(false) {}
- bool DoS(int level, bool ret = false,
- unsigned int chRejectCodeIn=0, const std::string &strRejectReasonIn="",
- bool corruptionIn=false,
- const std::string &strDebugMessageIn="") {
+ CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE), chRejectCode(0) {}
+ bool Invalid(ValidationInvalidReason reasonIn, bool ret = false,
+ unsigned int chRejectCodeIn=0, const std::string &strRejectReasonIn="",
+ const std::string &strDebugMessageIn="") {
+ m_reason = reasonIn;
chRejectCode = chRejectCodeIn;
strRejectReason = strRejectReasonIn;
- corruptionPossible = corruptionIn;
strDebugMessage = strDebugMessageIn;
if (mode == MODE_ERROR)
return ret;
- nDoS += level;
mode = MODE_INVALID;
return ret;
}
- bool Invalid(bool ret = false,
- unsigned int _chRejectCode=0, const std::string &_strRejectReason="",
- const std::string &_strDebugMessage="") {
- return DoS(0, ret, _chRejectCode, _strRejectReason, false, _strDebugMessage);
- }
bool Error(const std::string& strRejectReasonIn) {
if (mode == MODE_VALID)
strRejectReason = strRejectReasonIn;
@@ -71,19 +135,7 @@ public:
bool IsError() const {
return mode == MODE_ERROR;
}
- bool IsInvalid(int &nDoSOut) const {
- if (IsInvalid()) {
- nDoSOut = nDoS;
- return true;
- }
- return false;
- }
- bool CorruptionPossible() const {
- return corruptionPossible;
- }
- void SetCorruptionPossible() {
- corruptionPossible = true;
- }
+ ValidationInvalidReason GetReason() const { return m_reason; }
unsigned int GetRejectCode() const { return chRejectCode; }
std::string GetRejectReason() const { return strRejectReason; }
std::string GetDebugMessage() const { return strDebugMessage; }
@@ -95,16 +147,16 @@ public:
// weight = (stripped_size * 3) + total_size.
static inline int64_t GetTransactionWeight(const CTransaction& tx)
{
- return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
+ return ::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, PROTOCOL_VERSION);
}
static inline int64_t GetBlockWeight(const CBlock& block)
{
- return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
+ return ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, PROTOCOL_VERSION);
}
static inline int64_t GetTransactionInputWeight(const CTxIn& txin)
{
// scriptWitness size is added here because witnesses and txins are split up in segwit serialization.
- return ::GetSerializeSize(txin, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(txin, SER_NETWORK, PROTOCOL_VERSION) + ::GetSerializeSize(txin.scriptWitness.stack, SER_NETWORK, PROTOCOL_VERSION);
+ return ::GetSerializeSize(txin, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(txin, PROTOCOL_VERSION) + ::GetSerializeSize(txin.scriptWitness.stack, PROTOCOL_VERSION);
}
#endif // BITCOIN_CONSENSUS_VALIDATION_H
diff --git a/src/core_io.h b/src/core_io.h
index ebddcc2a04..19fb7b29f6 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,26 +6,36 @@
#define BITCOIN_CORE_IO_H
#include <amount.h>
+#include <attributes.h>
#include <string>
#include <vector>
class CBlock;
+class CBlockHeader;
class CScript;
class CTransaction;
struct CMutableTransaction;
-struct PartiallySignedTransaction;
class uint256;
class UniValue;
// core_read.cpp
CScript ParseScript(const std::string& s);
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
-bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true);
-bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
-uint256 ParseHashStr(const std::string&, const std::string& strName);
+NODISCARD bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true);
+NODISCARD bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
+bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header);
+
+/**
+ * Parse a hex string into 256 bits
+ * @param[in] strHex a hex-formatted, 64-character string
+ * @param[out] result the result of the parasing
+ * @returns true if successful, false if not
+ *
+ * @see ParseHashV for an RPC-oriented version of this
+ */
+bool ParseHashStr(const std::string& strHex, uint256& result);
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
-bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error);
int ParseSighashString(const UniValue& sighash);
// core_write.cpp
diff --git a/src/core_memusage.h b/src/core_memusage.h
index 6c03938d0c..6f1ace9980 100644
--- a/src/core_memusage.h
+++ b/src/core_memusage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 4337c38282..a879a375ce 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,8 +11,8 @@
#include <serialize.h>
#include <streams.h>
#include <univalue.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <version.h>
#include <boost/algorithm/string/classification.hpp>
@@ -145,6 +145,20 @@ bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no
return false;
}
+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);
+ try {
+ ser_header >> header;
+ } catch (const std::exception&) {
+ return false;
+ }
+ return true;
+}
+
bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
{
if (!IsHex(strHexBlk))
@@ -162,31 +176,13 @@ bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
return true;
}
-bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
+bool ParseHashStr(const std::string& strHex, uint256& result)
{
- std::vector<unsigned char> tx_data = DecodeBase64(base64_tx.c_str());
- CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION);
- try {
- ss_data >> psbt;
- if (!ss_data.empty()) {
- error = "extra data after PSBT";
- return false;
- }
- } catch (const std::exception& e) {
- error = e.what();
+ if ((strHex.size() != 64) || !IsHex(strHex))
return false;
- }
- return true;
-}
-uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
-{
- if (!IsHex(strHex)) // Note: IsHex("") is false
- throw std::runtime_error(strName + " must be hexadecimal string (not '" + strHex + "')");
-
- uint256 result;
result.SetHex(strHex);
- return result;
+ return true;
}
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName)
diff --git a/src/core_write.cpp b/src/core_write.cpp
index 1272266235..765a170307 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,9 +12,9 @@
#include <serialize.h>
#include <streams.h>
#include <univalue.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
UniValue ValueFromAmount(const CAmount& amount)
{
@@ -141,8 +141,7 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
out.pushKV("hex", HexStr(script.begin(), script.end()));
std::vector<std::vector<unsigned char>> solns;
- txnouttype type;
- Solver(script, type, solns);
+ txnouttype type = Solver(script, solns);
out.pushKV("type", GetTxnOutputType(type));
CTxDestination address;
@@ -182,7 +181,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
entry.pushKV("version", tx.nVersion);
- entry.pushKV("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION));
+ entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
entry.pushKV("weight", GetTransactionWeight(tx));
entry.pushKV("locktime", (int64_t)tx.nLockTime);
diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp
index bf7a252349..2dc2133434 100644
--- a/src/crypto/aes.cpp
+++ b/src/crypto/aes.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,36 +12,6 @@ extern "C" {
#include <crypto/ctaes/ctaes.c>
}
-AES128Encrypt::AES128Encrypt(const unsigned char key[16])
-{
- AES128_init(&ctx, key);
-}
-
-AES128Encrypt::~AES128Encrypt()
-{
- memset(&ctx, 0, sizeof(ctx));
-}
-
-void AES128Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const
-{
- AES128_encrypt(&ctx, 1, ciphertext, plaintext);
-}
-
-AES128Decrypt::AES128Decrypt(const unsigned char key[16])
-{
- AES128_init(&ctx, key);
-}
-
-AES128Decrypt::~AES128Decrypt()
-{
- memset(&ctx, 0, sizeof(ctx));
-}
-
-void AES128Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const
-{
- AES128_decrypt(&ctx, 1, plaintext, ciphertext);
-}
-
AES256Encrypt::AES256Encrypt(const unsigned char key[32])
{
AES256_init(&ctx, key);
@@ -182,35 +152,3 @@ AES256CBCDecrypt::~AES256CBCDecrypt()
{
memset(iv, 0, sizeof(iv));
}
-
-AES128CBCEncrypt::AES128CBCEncrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn)
- : enc(key), pad(padIn)
-{
- memcpy(iv, ivIn, AES_BLOCKSIZE);
-}
-
-AES128CBCEncrypt::~AES128CBCEncrypt()
-{
- memset(iv, 0, AES_BLOCKSIZE);
-}
-
-int AES128CBCEncrypt::Encrypt(const unsigned char* data, int size, unsigned char* out) const
-{
- return CBCEncrypt(enc, iv, data, size, pad, out);
-}
-
-AES128CBCDecrypt::AES128CBCDecrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn)
- : dec(key), pad(padIn)
-{
- memcpy(iv, ivIn, AES_BLOCKSIZE);
-}
-
-AES128CBCDecrypt::~AES128CBCDecrypt()
-{
- memset(iv, 0, AES_BLOCKSIZE);
-}
-
-int AES128CBCDecrypt::Decrypt(const unsigned char* data, int size, unsigned char* out) const
-{
- return CBCDecrypt(dec, iv, data, size, pad, out);
-}
diff --git a/src/crypto/aes.h b/src/crypto/aes.h
index 2dec8d9558..e06c8de272 100644
--- a/src/crypto/aes.h
+++ b/src/crypto/aes.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
@@ -12,33 +12,8 @@ extern "C" {
}
static const int AES_BLOCKSIZE = 16;
-static const int AES128_KEYSIZE = 16;
static const int AES256_KEYSIZE = 32;
-/** An encryption class for AES-128. */
-class AES128Encrypt
-{
-private:
- AES128_ctx ctx;
-
-public:
- explicit AES128Encrypt(const unsigned char key[16]);
- ~AES128Encrypt();
- void Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const;
-};
-
-/** A decryption class for AES-128. */
-class AES128Decrypt
-{
-private:
- AES128_ctx ctx;
-
-public:
- explicit AES128Decrypt(const unsigned char key[16]);
- ~AES128Decrypt();
- void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const;
-};
-
/** An encryption class for AES-256. */
class AES256Encrypt
{
@@ -89,30 +64,4 @@ private:
unsigned char iv[AES_BLOCKSIZE];
};
-class AES128CBCEncrypt
-{
-public:
- AES128CBCEncrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn);
- ~AES128CBCEncrypt();
- int Encrypt(const unsigned char* data, int size, unsigned char* out) const;
-
-private:
- const AES128Encrypt enc;
- const bool pad;
- unsigned char iv[AES_BLOCKSIZE];
-};
-
-class AES128CBCDecrypt
-{
-public:
- AES128CBCDecrypt(const unsigned char key[AES128_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn);
- ~AES128CBCDecrypt();
- int Decrypt(const unsigned char* data, int size, unsigned char* out) const;
-
-private:
- const AES128Decrypt dec;
- const bool pad;
- unsigned char iv[AES_BLOCKSIZE];
-};
-
#endif // BITCOIN_CRYPTO_AES_H
diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp
index ac4470f04f..42a17f02ff 100644
--- a/src/crypto/chacha20.cpp
+++ b/src/crypto/chacha20.cpp
@@ -71,7 +71,7 @@ void ChaCha20::Seek(uint64_t pos)
input[13] = pos >> 32;
}
-void ChaCha20::Output(unsigned char* c, size_t bytes)
+void ChaCha20::Keystream(unsigned char* c, size_t bytes)
{
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
@@ -178,3 +178,133 @@ void ChaCha20::Output(unsigned char* c, size_t bytes)
c += 64;
}
}
+
+void ChaCha20::Crypt(const unsigned char* m, unsigned char* c, size_t bytes)
+{
+ uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+ uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+ unsigned char *ctarget = nullptr;
+ unsigned char tmp[64];
+ unsigned int i;
+
+ if (!bytes) return;
+
+ j0 = input[0];
+ j1 = input[1];
+ j2 = input[2];
+ j3 = input[3];
+ j4 = input[4];
+ j5 = input[5];
+ j6 = input[6];
+ j7 = input[7];
+ j8 = input[8];
+ j9 = input[9];
+ j10 = input[10];
+ j11 = input[11];
+ j12 = input[12];
+ j13 = input[13];
+ j14 = input[14];
+ j15 = input[15];
+
+ for (;;) {
+ if (bytes < 64) {
+ // if m has fewer than 64 bytes available, copy m to tmp and
+ // read from tmp instead
+ for (i = 0;i < bytes;++i) tmp[i] = m[i];
+ m = tmp;
+ ctarget = c;
+ c = tmp;
+ }
+ x0 = j0;
+ x1 = j1;
+ x2 = j2;
+ x3 = j3;
+ x4 = j4;
+ x5 = j5;
+ x6 = j6;
+ x7 = j7;
+ x8 = j8;
+ x9 = j9;
+ x10 = j10;
+ x11 = j11;
+ x12 = j12;
+ x13 = j13;
+ x14 = j14;
+ x15 = j15;
+ for (i = 20;i > 0;i -= 2) {
+ QUARTERROUND( x0, x4, x8,x12)
+ QUARTERROUND( x1, x5, x9,x13)
+ QUARTERROUND( x2, x6,x10,x14)
+ QUARTERROUND( x3, x7,x11,x15)
+ QUARTERROUND( x0, x5,x10,x15)
+ QUARTERROUND( x1, x6,x11,x12)
+ QUARTERROUND( x2, x7, x8,x13)
+ QUARTERROUND( x3, x4, x9,x14)
+ }
+ x0 += j0;
+ x1 += j1;
+ x2 += j2;
+ x3 += j3;
+ x4 += j4;
+ x5 += j5;
+ x6 += j6;
+ x7 += j7;
+ x8 += j8;
+ x9 += j9;
+ x10 += j10;
+ x11 += j11;
+ x12 += j12;
+ x13 += j13;
+ x14 += j14;
+ x15 += j15;
+
+ x0 ^= ReadLE32(m + 0);
+ x1 ^= ReadLE32(m + 4);
+ x2 ^= ReadLE32(m + 8);
+ x3 ^= ReadLE32(m + 12);
+ x4 ^= ReadLE32(m + 16);
+ x5 ^= ReadLE32(m + 20);
+ x6 ^= ReadLE32(m + 24);
+ x7 ^= ReadLE32(m + 28);
+ x8 ^= ReadLE32(m + 32);
+ x9 ^= ReadLE32(m + 36);
+ x10 ^= ReadLE32(m + 40);
+ x11 ^= ReadLE32(m + 44);
+ x12 ^= ReadLE32(m + 48);
+ x13 ^= ReadLE32(m + 52);
+ x14 ^= ReadLE32(m + 56);
+ x15 ^= ReadLE32(m + 60);
+
+ ++j12;
+ if (!j12) ++j13;
+
+ WriteLE32(c + 0, x0);
+ WriteLE32(c + 4, x1);
+ WriteLE32(c + 8, x2);
+ WriteLE32(c + 12, x3);
+ WriteLE32(c + 16, x4);
+ WriteLE32(c + 20, x5);
+ WriteLE32(c + 24, x6);
+ WriteLE32(c + 28, x7);
+ WriteLE32(c + 32, x8);
+ WriteLE32(c + 36, x9);
+ WriteLE32(c + 40, x10);
+ WriteLE32(c + 44, x11);
+ WriteLE32(c + 48, x12);
+ WriteLE32(c + 52, x13);
+ WriteLE32(c + 56, x14);
+ WriteLE32(c + 60, x15);
+
+ if (bytes <= 64) {
+ if (bytes < 64) {
+ for (i = 0;i < bytes;++i) ctarget[i] = c[i];
+ }
+ input[12] = j12;
+ input[13] = j13;
+ return;
+ }
+ bytes -= 64;
+ c += 64;
+ m += 64;
+ }
+}
diff --git a/src/crypto/chacha20.h b/src/crypto/chacha20.h
index a305977bcd..5a4674f4a8 100644
--- a/src/crypto/chacha20.h
+++ b/src/crypto/chacha20.h
@@ -8,7 +8,8 @@
#include <stdint.h>
#include <stdlib.h>
-/** A PRNG class for ChaCha20. */
+/** A class for ChaCha20 256-bit stream cipher developed by Daniel J. Bernstein
+ https://cr.yp.to/chacha/chacha-20080128.pdf */
class ChaCha20
{
private:
@@ -17,10 +18,17 @@ private:
public:
ChaCha20();
ChaCha20(const unsigned char* key, size_t keylen);
- void SetKey(const unsigned char* key, size_t keylen);
- void SetIV(uint64_t iv);
- void Seek(uint64_t pos);
- void Output(unsigned char* output, size_t bytes);
+ void SetKey(const unsigned char* key, size_t keylen); //!< set key with flexible keylength; 256bit recommended */
+ void SetIV(uint64_t iv); // set the 64bit nonce
+ void Seek(uint64_t pos); // set the 64bit block counter
+
+ /** outputs the keystream of size <bytes> into <c> */
+ void Keystream(unsigned char* c, size_t bytes);
+
+ /** enciphers the message <input> of length <bytes> and write the enciphered representation into <output>
+ * Used for encryption and decryption (XOR)
+ */
+ void Crypt(const unsigned char* input, unsigned char* output, size_t bytes);
};
#endif // BITCOIN_CRYPTO_CHACHA20_H
diff --git a/src/crypto/common.h b/src/crypto/common.h
index 6e9d6dc82a..e7bb020a19 100644
--- a/src/crypto/common.h
+++ b/src/crypto/common.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/hkdf_sha256_32.cpp b/src/crypto/hkdf_sha256_32.cpp
new file mode 100644
index 0000000000..9cea5995ec
--- /dev/null
+++ b/src/crypto/hkdf_sha256_32.cpp
@@ -0,0 +1,21 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <crypto/hkdf_sha256_32.h>
+
+#include <assert.h>
+#include <string.h>
+
+CHKDF_HMAC_SHA256_L32::CHKDF_HMAC_SHA256_L32(const unsigned char* ikm, size_t ikmlen, const std::string& salt)
+{
+ CHMAC_SHA256((const unsigned char*)salt.c_str(), salt.size()).Write(ikm, ikmlen).Finalize(m_prk);
+}
+
+void CHKDF_HMAC_SHA256_L32::Expand32(const std::string& info, unsigned char hash[OUTPUT_SIZE])
+{
+ // expand a 32byte key (single round)
+ assert(info.size() <= 128);
+ static const unsigned char one[1] = {1};
+ CHMAC_SHA256(m_prk, 32).Write((const unsigned char*)info.data(), info.size()).Write(one, 1).Finalize(hash);
+}
diff --git a/src/crypto/hkdf_sha256_32.h b/src/crypto/hkdf_sha256_32.h
new file mode 100644
index 0000000000..fa1e42aec1
--- /dev/null
+++ b/src/crypto/hkdf_sha256_32.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_HKDF_SHA256_32_H
+#define BITCOIN_CRYPTO_HKDF_SHA256_32_H
+
+#include <crypto/hmac_sha256.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A rfc5869 HKDF implementation with HMAC_SHA256 and fixed key output length of 32 bytes (L=32) */
+class CHKDF_HMAC_SHA256_L32
+{
+private:
+ unsigned char m_prk[32];
+ static const size_t OUTPUT_SIZE = 32;
+
+public:
+ CHKDF_HMAC_SHA256_L32(const unsigned char* ikm, size_t ikmlen, const std::string& salt);
+ void Expand32(const std::string& info, unsigned char hash[OUTPUT_SIZE]);
+};
+
+#endif // BITCOIN_CRYPTO_HKDF_SHA256_32_H
diff --git a/src/crypto/hmac_sha256.cpp b/src/crypto/hmac_sha256.cpp
index d4afe1439f..0ba99ae274 100644
--- a/src/crypto/hmac_sha256.cpp
+++ b/src/crypto/hmac_sha256.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h
index 4fb30b7ac0..d31fda1dd1 100644
--- a/src/crypto/hmac_sha256.h
+++ b/src/crypto/hmac_sha256.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/hmac_sha512.cpp b/src/crypto/hmac_sha512.cpp
index d9c4d04100..d70aee843b 100644
--- a/src/crypto/hmac_sha512.cpp
+++ b/src/crypto/hmac_sha512.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/hmac_sha512.h b/src/crypto/hmac_sha512.h
index ab84ee7652..1ea9a3671e 100644
--- a/src/crypto/hmac_sha512.h
+++ b/src/crypto/hmac_sha512.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/poly1305.cpp b/src/crypto/poly1305.cpp
new file mode 100644
index 0000000000..8a86c9601c
--- /dev/null
+++ b/src/crypto/poly1305.cpp
@@ -0,0 +1,141 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+// Based on the public domain implementation by Andrew Moon
+// poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
+
+#include <crypto/common.h>
+#include <crypto/poly1305.h>
+
+#include <string.h>
+
+#define mul32x32_64(a,b) ((uint64_t)(a) * (b))
+
+void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
+ uint32_t t0,t1,t2,t3;
+ uint32_t h0,h1,h2,h3,h4;
+ uint32_t r0,r1,r2,r3,r4;
+ uint32_t s1,s2,s3,s4;
+ uint32_t b, nb;
+ size_t j;
+ uint64_t t[5];
+ uint64_t f0,f1,f2,f3;
+ uint64_t g0,g1,g2,g3,g4;
+ uint64_t c;
+ unsigned char mp[16];
+
+ /* clamp key */
+ t0 = ReadLE32(key+0);
+ t1 = ReadLE32(key+4);
+ t2 = ReadLE32(key+8);
+ t3 = ReadLE32(key+12);
+
+ /* precompute multipliers */
+ r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
+ r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
+ r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
+ r3 = t2 & 0x3f03fff; t3 >>= 8;
+ r4 = t3 & 0x00fffff;
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ /* init state */
+ h0 = 0;
+ h1 = 0;
+ h2 = 0;
+ h3 = 0;
+ h4 = 0;
+
+ /* full blocks */
+ if (inlen < 16) goto poly1305_donna_atmost15bytes;
+poly1305_donna_16bytes:
+ m += 16;
+ inlen -= 16;
+
+ t0 = ReadLE32(m-16);
+ t1 = ReadLE32(m-12);
+ t2 = ReadLE32(m-8);
+ t3 = ReadLE32(m-4);
+
+ h0 += t0 & 0x3ffffff;
+ h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
+ h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
+ h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
+ h4 += (t3 >> 8) | (1 << 24);
+
+
+poly1305_donna_mul:
+ t[0] = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
+ t[1] = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
+ t[2] = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
+ t[3] = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
+ t[4] = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
+
+ h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26);
+ t[1] += c; h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26);
+ t[2] += b; h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26);
+ t[3] += b; h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26);
+ t[4] += b; h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26);
+ h0 += b * 5;
+
+ if (inlen >= 16) goto poly1305_donna_16bytes;
+
+ /* final bytes */
+poly1305_donna_atmost15bytes:
+ if (!inlen) goto poly1305_donna_finish;
+
+ for (j = 0; j < inlen; j++) mp[j] = m[j];
+ mp[j++] = 1;
+ for (; j < 16; j++) mp[j] = 0;
+ inlen = 0;
+
+ t0 = ReadLE32(mp+0);
+ t1 = ReadLE32(mp+4);
+ t2 = ReadLE32(mp+8);
+ t3 = ReadLE32(mp+12);
+
+ h0 += t0 & 0x3ffffff;
+ h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
+ h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
+ h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
+ h4 += (t3 >> 8);
+
+ goto poly1305_donna_mul;
+
+poly1305_donna_finish:
+ b = h0 >> 26; h0 = h0 & 0x3ffffff;
+ h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
+ h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
+ h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
+ h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
+ h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff;
+ h1 += b;
+
+ g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
+ g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
+ g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
+ g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
+ g4 = h4 + b - (1 << 26);
+
+ b = (g4 >> 31) - 1;
+ nb = ~b;
+ h0 = (h0 & nb) | (g0 & b);
+ h1 = (h1 & nb) | (g1 & b);
+ h2 = (h2 & nb) | (g2 & b);
+ h3 = (h3 & nb) | (g3 & b);
+ h4 = (h4 & nb) | (g4 & b);
+
+ f0 = ((h0 ) | (h1 << 26)) + (uint64_t)ReadLE32(&key[16]);
+ f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)ReadLE32(&key[20]);
+ f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)ReadLE32(&key[24]);
+ f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)ReadLE32(&key[28]);
+
+ WriteLE32(&out[ 0], f0); f1 += (f0 >> 32);
+ WriteLE32(&out[ 4], f1); f2 += (f1 >> 32);
+ WriteLE32(&out[ 8], f2); f3 += (f2 >> 32);
+ WriteLE32(&out[12], f3);
+}
diff --git a/src/crypto/poly1305.h b/src/crypto/poly1305.h
new file mode 100644
index 0000000000..1598b013b9
--- /dev/null
+++ b/src/crypto/poly1305.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_POLY1305_H
+#define BITCOIN_CRYPTO_POLY1305_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define POLY1305_KEYLEN 32
+#define POLY1305_TAGLEN 16
+
+void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen,
+ const unsigned char key[POLY1305_KEYLEN]);
+
+#endif // BITCOIN_CRYPTO_POLY1305_H
diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp
index 51468ec8d0..edee06cc34 100644
--- a/src/crypto/ripemd160.cpp
+++ b/src/crypto/ripemd160.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -256,7 +256,7 @@ CRIPEMD160& CRIPEMD160::Write(const unsigned char* data, size_t len)
ripemd160::Transform(s, buf);
bufsize = 0;
}
- while (end >= data + 64) {
+ while (end - data >= 64) {
// Process full chunks directly from the source.
ripemd160::Transform(s, data);
bytes += 64;
diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp
index dc96ac507a..3dcdcb186e 100644
--- a/src/crypto/sha1.cpp
+++ b/src/crypto/sha1.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -163,7 +163,7 @@ CSHA1& CSHA1::Write(const unsigned char* data, size_t len)
sha1::Transform(s, buf);
bufsize = 0;
}
- while (end >= data + 64) {
+ while (end - data >= 64) {
// Process full chunks directly from the source.
sha1::Transform(s, data);
bytes += 64;
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index fbdbef0bc6..cab37e0322 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index 31b2b3b3df..028ee14345 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp
index dff4d8da1a..4e6aa363f7 100644
--- a/src/crypto/sha512.cpp
+++ b/src/crypto/sha512.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -168,7 +168,7 @@ CSHA512& CSHA512::Write(const unsigned char* data, size_t len)
sha512::Transform(s, buf);
bufsize = 0;
}
- while (end >= data + 128) {
+ while (end - data >= 128) {
// Process full chunks directly from the source.
sha512::Transform(s, data);
data += 128;
diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h
index cd1023bc85..4118ac1b18 100644
--- a/src/crypto/sha512.h
+++ b/src/crypto/sha512.h
@@ -17,7 +17,7 @@ private:
uint64_t bytes;
public:
- static const size_t OUTPUT_SIZE = 64;
+ static constexpr size_t OUTPUT_SIZE = 64;
CSHA512();
CSHA512& Write(const unsigned char* data, size_t len);
diff --git a/src/crypto/siphash.cpp b/src/crypto/siphash.cpp
new file mode 100644
index 0000000000..e81957111a
--- /dev/null
+++ b/src/crypto/siphash.cpp
@@ -0,0 +1,173 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <crypto/siphash.h>
+
+#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
+
+#define SIPROUND do { \
+ v0 += v1; v1 = ROTL(v1, 13); v1 ^= v0; \
+ v0 = ROTL(v0, 32); \
+ v2 += v3; v3 = ROTL(v3, 16); v3 ^= v2; \
+ v0 += v3; v3 = ROTL(v3, 21); v3 ^= v0; \
+ v2 += v1; v1 = ROTL(v1, 17); v1 ^= v2; \
+ v2 = ROTL(v2, 32); \
+} while (0)
+
+CSipHasher::CSipHasher(uint64_t k0, uint64_t k1)
+{
+ v[0] = 0x736f6d6570736575ULL ^ k0;
+ v[1] = 0x646f72616e646f6dULL ^ k1;
+ v[2] = 0x6c7967656e657261ULL ^ k0;
+ v[3] = 0x7465646279746573ULL ^ k1;
+ count = 0;
+ tmp = 0;
+}
+
+CSipHasher& CSipHasher::Write(uint64_t data)
+{
+ uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+
+ assert(count % 8 == 0);
+
+ v3 ^= data;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= data;
+
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ v[3] = v3;
+
+ count += 8;
+ return *this;
+}
+
+CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size)
+{
+ uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+ uint64_t t = tmp;
+ int c = count;
+
+ while (size--) {
+ t |= ((uint64_t)(*(data++))) << (8 * (c % 8));
+ c++;
+ if ((c & 7) == 0) {
+ v3 ^= t;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= t;
+ t = 0;
+ }
+ }
+
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ v[3] = v3;
+ count = c;
+ tmp = t;
+
+ return *this;
+}
+
+uint64_t CSipHasher::Finalize() const
+{
+ uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+
+ uint64_t t = tmp | (((uint64_t)count) << 56);
+
+ v3 ^= t;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= t;
+ v2 ^= 0xFF;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ return v0 ^ v1 ^ v2 ^ v3;
+}
+
+uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
+{
+ /* Specialized implementation for efficiency */
+ uint64_t d = val.GetUint64(0);
+
+ uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
+ uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
+ uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
+ uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
+
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(1);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(2);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(3);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ v3 ^= ((uint64_t)4) << 59;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= ((uint64_t)4) << 59;
+ v2 ^= 0xFF;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ return v0 ^ v1 ^ v2 ^ v3;
+}
+
+uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra)
+{
+ /* Specialized implementation for efficiency */
+ uint64_t d = val.GetUint64(0);
+
+ uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
+ uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
+ uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
+ uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
+
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(1);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(2);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = val.GetUint64(3);
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ d = (((uint64_t)36) << 56) | extra;
+ v3 ^= d;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= d;
+ v2 ^= 0xFF;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ return v0 ^ v1 ^ v2 ^ v3;
+}
diff --git a/src/crypto/siphash.h b/src/crypto/siphash.h
new file mode 100644
index 0000000000..b312f913f9
--- /dev/null
+++ b/src/crypto/siphash.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_SIPHASH_H
+#define BITCOIN_CRYPTO_SIPHASH_H
+
+#include <stdint.h>
+
+#include <uint256.h>
+
+/** SipHash-2-4 */
+class CSipHasher
+{
+private:
+ uint64_t v[4];
+ uint64_t tmp;
+ int count;
+
+public:
+ /** Construct a SipHash calculator initialized with 128-bit key (k0, k1) */
+ CSipHasher(uint64_t k0, uint64_t k1);
+ /** Hash a 64-bit integer worth of data
+ * It is treated as if this was the little-endian interpretation of 8 bytes.
+ * This function can only be used when a multiple of 8 bytes have been written so far.
+ */
+ CSipHasher& Write(uint64_t data);
+ /** Hash arbitrary bytes. */
+ CSipHasher& Write(const unsigned char* data, size_t size);
+ /** Compute the 64-bit SipHash-2-4 of the data written so far. The object remains untouched. */
+ uint64_t Finalize() const;
+};
+
+/** Optimized SipHash-2-4 implementation for uint256.
+ *
+ * It is identical to:
+ * SipHasher(k0, k1)
+ * .Write(val.GetUint64(0))
+ * .Write(val.GetUint64(1))
+ * .Write(val.GetUint64(2))
+ * .Write(val.GetUint64(3))
+ * .Finalize()
+ */
+uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val);
+uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra);
+
+#endif // BITCOIN_CRYPTO_SIPHASH_H
diff --git a/src/cuckoocache.h b/src/cuckoocache.h
index 15f6873961..4d0b094fa2 100644
--- a/src/cuckoocache.h
+++ b/src/cuckoocache.h
@@ -397,7 +397,7 @@ public:
std::array<uint32_t, 8> locs = compute_hashes(e);
// Make sure we have not already inserted this element
// If we have, make sure that it does not get deleted
- for (uint32_t loc : locs)
+ for (const uint32_t loc : locs)
if (table[loc] == e) {
please_keep(loc);
epoch_flags[loc] = last_epoch;
@@ -405,7 +405,7 @@ public:
}
for (uint8_t depth = 0; depth < depth_limit; ++depth) {
// First try to insert to an empty slot, if one exists
- for (uint32_t loc : locs) {
+ for (const uint32_t loc : locs) {
if (!collection_flags.bit_is_set(loc))
continue;
table[loc] = std::move(e);
@@ -467,7 +467,7 @@ public:
inline bool contains(const Element& e, const bool erase) const
{
std::array<uint32_t, 8> locs = compute_hashes(e);
- for (uint32_t loc : locs)
+ for (const uint32_t loc : locs)
if (table[loc] == e) {
if (erase)
allow_erase(loc);
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
index e401b5fb1b..34896f7ab2 100644
--- a/src/dbwrapper.cpp
+++ b/src/dbwrapper.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -78,7 +78,7 @@ static void SetMaxOpenFiles(leveldb::Options *options) {
// do not interfere with select() loops. On 64-bit Unix hosts this value is
// also OK, because up to that amount LevelDB will use an mmap
// implementation that does not use extra file descriptors (the fds are
- // closed after being mmaped).
+ // closed after being mmap'ed).
//
// Increasing the value beyond the default is dangerous because LevelDB will
// fall back to a non-mmap implementation when the file count is too large.
@@ -115,7 +115,7 @@ static leveldb::Options GetOptions(size_t nCacheSize)
}
CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
- : m_name(fs::basename(path))
+ : m_name{path.stem().string()}
{
penv = nullptr;
readoptions.verify_checksums = true;
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index 2a5e0cab00..416f5e8399 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,8 +9,8 @@
#include <fs.h>
#include <serialize.h>
#include <streams.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <version.h>
#include <leveldb/db.h>
diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp
new file mode 100644
index 0000000000..eeec6dec25
--- /dev/null
+++ b/src/dummywallet.cpp
@@ -0,0 +1,86 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <stdio.h>
+#include <util/system.h>
+#include <walletinitinterface.h>
+
+class CWallet;
+
+namespace interfaces {
+class Chain;
+}
+
+class DummyWalletInit : public WalletInitInterface {
+public:
+
+ bool HasWalletSupport() const override {return false;}
+ void AddWalletOptions() const override;
+ bool ParameterInteraction() const override {return true;}
+ void Construct(InitInterfaces& interfaces) const override {LogPrintf("No wallet support compiled in!\n");}
+};
+
+void DummyWalletInit::AddWalletOptions() const
+{
+ gArgs.AddHiddenArgs({
+ "-addresstype",
+ "-avoidpartialspends",
+ "-changetype",
+ "-disablewallet",
+ "-discardfee=<amt>",
+ "-fallbackfee=<amt>",
+ "-keypool=<n>",
+ "-maxtxfee=<amt>",
+ "-mintxfee=<amt>",
+ "-paytxfee=<amt>",
+ "-rescan",
+ "-salvagewallet",
+ "-spendzeroconfchange",
+ "-txconfirmtarget=<n>",
+ "-upgradewallet",
+ "-wallet=<path>",
+ "-walletbroadcast",
+ "-walletdir=<dir>",
+ "-walletnotify=<cmd>",
+ "-walletrbf",
+ "-zapwallettxes=<mode>",
+ "-dblogsize=<n>",
+ "-flushwallet",
+ "-privdb",
+ "-walletrejectlongchains",
+ });
+}
+
+const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
+
+fs::path GetWalletDir()
+{
+ throw std::logic_error("Wallet function called in non-wallet build.");
+}
+
+std::vector<fs::path> ListWalletDir()
+{
+ throw std::logic_error("Wallet function called in non-wallet build.");
+}
+
+std::vector<std::shared_ptr<CWallet>> GetWallets()
+{
+ throw std::logic_error("Wallet function called in non-wallet build.");
+}
+
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning)
+{
+ throw std::logic_error("Wallet function called in non-wallet build.");
+}
+
+namespace interfaces {
+
+class Wallet;
+
+std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet)
+{
+ throw std::logic_error("Wallet function called in non-wallet build.");
+}
+
+} // namespace interfaces
diff --git a/src/flatfile.cpp b/src/flatfile.cpp
new file mode 100644
index 0000000000..8a8f7b681c
--- /dev/null
+++ b/src/flatfile.cpp
@@ -0,0 +1,98 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <stdexcept>
+
+#include <flatfile.h>
+#include <logging.h>
+#include <tinyformat.h>
+#include <util/system.h>
+
+FlatFileSeq::FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size) :
+ m_dir(std::move(dir)),
+ m_prefix(prefix),
+ m_chunk_size(chunk_size)
+{
+ if (chunk_size == 0) {
+ throw std::invalid_argument("chunk_size must be positive");
+ }
+}
+
+std::string FlatFilePos::ToString() const
+{
+ return strprintf("FlatFilePos(nFile=%i, nPos=%i)", nFile, nPos);
+}
+
+fs::path FlatFileSeq::FileName(const FlatFilePos& pos) const
+{
+ return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile);
+}
+
+FILE* FlatFileSeq::Open(const FlatFilePos& pos, bool read_only)
+{
+ if (pos.IsNull()) {
+ return nullptr;
+ }
+ fs::path path = FileName(pos);
+ fs::create_directories(path.parent_path());
+ FILE* file = fsbridge::fopen(path, read_only ? "rb": "rb+");
+ if (!file && !read_only)
+ file = fsbridge::fopen(path, "wb+");
+ if (!file) {
+ LogPrintf("Unable to open file %s\n", path.string());
+ return nullptr;
+ }
+ if (pos.nPos && fseek(file, pos.nPos, SEEK_SET)) {
+ LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string());
+ fclose(file);
+ return nullptr;
+ }
+ return file;
+}
+
+size_t FlatFileSeq::Allocate(const FlatFilePos& pos, size_t add_size, bool& out_of_space)
+{
+ out_of_space = false;
+
+ unsigned int n_old_chunks = (pos.nPos + m_chunk_size - 1) / m_chunk_size;
+ unsigned int n_new_chunks = (pos.nPos + add_size + m_chunk_size - 1) / m_chunk_size;
+ if (n_new_chunks > n_old_chunks) {
+ size_t old_size = pos.nPos;
+ size_t new_size = n_new_chunks * m_chunk_size;
+ size_t inc_size = new_size - old_size;
+
+ if (CheckDiskSpace(m_dir, inc_size)) {
+ FILE *file = Open(pos);
+ if (file) {
+ LogPrintf("Pre-allocating up to position 0x%x in %s%05u.dat\n", new_size, m_prefix, pos.nFile);
+ AllocateFileRange(file, pos.nPos, inc_size);
+ fclose(file);
+ return inc_size;
+ }
+ } else {
+ out_of_space = true;
+ }
+ }
+ return 0;
+}
+
+bool FlatFileSeq::Flush(const FlatFilePos& pos, bool finalize)
+{
+ FILE* file = Open(FlatFilePos(pos.nFile, 0)); // Avoid fseek to nPos
+ if (!file) {
+ return error("%s: failed to open file %d", __func__, pos.nFile);
+ }
+ if (finalize && !TruncateFile(file, pos.nPos)) {
+ fclose(file);
+ return error("%s: failed to truncate file %d", __func__, pos.nFile);
+ }
+ if (!FileCommit(file)) {
+ fclose(file);
+ return error("%s: failed to commit file %d", __func__, pos.nFile);
+ }
+
+ fclose(file);
+ return true;
+}
diff --git a/src/flatfile.h b/src/flatfile.h
new file mode 100644
index 0000000000..374ceff411
--- /dev/null
+++ b/src/flatfile.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_FLATFILE_H
+#define BITCOIN_FLATFILE_H
+
+#include <string>
+
+#include <fs.h>
+#include <serialize.h>
+
+struct FlatFilePos
+{
+ int nFile;
+ unsigned int nPos;
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED));
+ READWRITE(VARINT(nPos));
+ }
+
+ FlatFilePos() : nFile(-1), nPos(0) {}
+
+ FlatFilePos(int nFileIn, unsigned int nPosIn) :
+ nFile(nFileIn),
+ nPos(nPosIn)
+ {}
+
+ friend bool operator==(const FlatFilePos &a, const FlatFilePos &b) {
+ return (a.nFile == b.nFile && a.nPos == b.nPos);
+ }
+
+ friend bool operator!=(const FlatFilePos &a, const FlatFilePos &b) {
+ return !(a == b);
+ }
+
+ void SetNull() { nFile = -1; nPos = 0; }
+ bool IsNull() const { return (nFile == -1); }
+
+ std::string ToString() const;
+};
+
+/**
+ * FlatFileSeq represents a sequence of numbered files storing raw data. This class facilitates
+ * access to and efficient management of these files.
+ */
+class FlatFileSeq
+{
+private:
+ const fs::path m_dir;
+ const char* const m_prefix;
+ const size_t m_chunk_size;
+
+public:
+ /**
+ * Constructor
+ *
+ * @param dir The base directory that all files live in.
+ * @param prefix A short prefix given to all file names.
+ * @param chunk_size Disk space is pre-allocated in multiples of this amount.
+ */
+ FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size);
+
+ /** Get the name of the file at the given position. */
+ fs::path FileName(const FlatFilePos& pos) const;
+
+ /** Open a handle to the file at the given position. */
+ FILE* Open(const FlatFilePos& pos, bool read_only = false);
+
+ /**
+ * Allocate additional space in a file after the given starting position. The amount allocated
+ * will be the minimum multiple of the sequence chunk size greater than add_size.
+ *
+ * @param[in] pos The starting position that bytes will be allocated after.
+ * @param[in] add_size The minimum number of bytes to be allocated.
+ * @param[out] out_of_space Whether the allocation failed due to insufficient disk space.
+ * @return The number of bytes successfully allocated.
+ */
+ size_t Allocate(const FlatFilePos& pos, size_t add_size, bool& out_of_space);
+
+ /**
+ * Commit a file to disk, and optionally truncate off extra pre-allocated bytes if final.
+ *
+ * @param[in] pos The first unwritten position in the file to be flushed.
+ * @param[in] finalize True if no more data will be written to this file.
+ * @return true on success, false on failure.
+ */
+ bool Flush(const FlatFilePos& pos, bool finalize = false);
+};
+
+#endif // BITCOIN_FLATFILE_H
diff --git a/src/fs.cpp b/src/fs.cpp
index 570ed3e2ee..7b422b8d70 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -1,15 +1,223 @@
#include <fs.h>
+#ifndef WIN32
+#include <fcntl.h>
+#else
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <codecvt>
+#include <windows.h>
+#endif
+
namespace fsbridge {
FILE *fopen(const fs::path& p, const char *mode)
{
+#ifndef WIN32
return ::fopen(p.string().c_str(), mode);
+#else
+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> utf8_cvt;
+ return ::_wfopen(p.wstring().c_str(), utf8_cvt.from_bytes(mode).c_str());
+#endif
+}
+
+#ifndef WIN32
+
+static std::string GetErrorReason() {
+ return std::strerror(errno);
+}
+
+FileLock::FileLock(const fs::path& file)
+{
+ fd = open(file.string().c_str(), O_RDWR);
+ if (fd == -1) {
+ reason = GetErrorReason();
+ }
+}
+
+FileLock::~FileLock()
+{
+ if (fd != -1) {
+ close(fd);
+ }
+}
+
+bool FileLock::TryLock()
+{
+ if (fd == -1) {
+ return false;
+ }
+ struct flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ if (fcntl(fd, F_SETLK, &lock) == -1) {
+ reason = GetErrorReason();
+ return false;
+ }
+ return true;
+}
+#else
+
+static std::string GetErrorReason() {
+ wchar_t* err;
+ FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<WCHAR*>(&err), 0, nullptr);
+ std::wstring err_str(err);
+ LocalFree(err);
+ return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(err_str);
+}
+
+FileLock::FileLock(const fs::path& file)
+{
+ hFile = CreateFileW(file.wstring().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ reason = GetErrorReason();
+ }
+}
+
+FileLock::~FileLock()
+{
+ if (hFile != INVALID_HANDLE_VALUE) {
+ CloseHandle(hFile);
+ }
+}
+
+bool FileLock::TryLock()
+{
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+ _OVERLAPPED overlapped = {0};
+ if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, std::numeric_limits<DWORD>::max(), std::numeric_limits<DWORD>::max(), &overlapped)) {
+ reason = GetErrorReason();
+ return false;
+ }
+ return true;
+}
+#endif
+
+std::string get_filesystem_error_message(const fs::filesystem_error& e)
+{
+#ifndef WIN32
+ return e.what();
+#else
+ // Convert from Multi Byte to utf-16
+ std::string mb_string(e.what());
+ int size = MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), nullptr, 0);
+
+ std::wstring utf16_string(size, L'\0');
+ MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), &*utf16_string.begin(), size);
+ // Convert from utf-16 to utf-8
+ return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>().to_bytes(utf16_string);
+#endif
+}
+
+#ifdef WIN32
+#ifdef __GLIBCXX__
+
+// reference: https://github.com/gcc-mirror/gcc/blob/gcc-7_3_0-release/libstdc%2B%2B-v3/include/std/fstream#L270
+
+static std::string openmodeToStr(std::ios_base::openmode mode)
+{
+ switch (mode & ~std::ios_base::ate) {
+ case std::ios_base::out:
+ case std::ios_base::out | std::ios_base::trunc:
+ return "w";
+ case std::ios_base::out | std::ios_base::app:
+ case std::ios_base::app:
+ return "a";
+ case std::ios_base::in:
+ return "r";
+ case std::ios_base::in | std::ios_base::out:
+ return "r+";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::trunc:
+ return "w+";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::app:
+ case std::ios_base::in | std::ios_base::app:
+ return "a+";
+ case std::ios_base::out | std::ios_base::binary:
+ case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+ return "wb";
+ case std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+ case std::ios_base::app | std::ios_base::binary:
+ return "ab";
+ case std::ios_base::in | std::ios_base::binary:
+ return "rb";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::binary:
+ return "r+b";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+ return "w+b";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+ case std::ios_base::in | std::ios_base::app | std::ios_base::binary:
+ return "a+b";
+ default:
+ return std::string();
+ }
}
-FILE *freopen(const fs::path& p, const char *mode, FILE *stream)
+void ifstream::open(const fs::path& p, std::ios_base::openmode mode)
{
- return ::freopen(p.string().c_str(), mode, stream);
+ close();
+ mode |= std::ios_base::in;
+ m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
+ if (m_file == nullptr) {
+ return;
+ }
+ m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
+ rdbuf(&m_filebuf);
+ if (mode & std::ios_base::ate) {
+ seekg(0, std::ios_base::end);
+ }
}
+void ifstream::close()
+{
+ if (m_file != nullptr) {
+ m_filebuf.close();
+ fclose(m_file);
+ }
+ m_file = nullptr;
+}
+
+void ofstream::open(const fs::path& p, std::ios_base::openmode mode)
+{
+ close();
+ mode |= std::ios_base::out;
+ m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
+ if (m_file == nullptr) {
+ return;
+ }
+ m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
+ rdbuf(&m_filebuf);
+ if (mode & std::ios_base::ate) {
+ seekp(0, std::ios_base::end);
+ }
+}
+
+void ofstream::close()
+{
+ if (m_file != nullptr) {
+ m_filebuf.close();
+ fclose(m_file);
+ }
+ m_file = nullptr;
+}
+#else // __GLIBCXX__
+
+static_assert(sizeof(*fs::path().BOOST_FILESYSTEM_C_STR) == sizeof(wchar_t),
+ "Warning: This build is using boost::filesystem ofstream and ifstream "
+ "implementations which will fail to open paths containing multibyte "
+ "characters. You should delete this static_assert to ignore this warning, "
+ "or switch to a different C++ standard library like the Microsoft C++ "
+ "Standard Library (where boost uses non-standard extensions to construct "
+ "stream objects with wide filenames), or the GNU libstdc++ library (where "
+ "a more complicated workaround has been implemented above).");
+
+#endif // __GLIBCXX__
+#endif // WIN32
+
} // fsbridge
diff --git a/src/fs.h b/src/fs.h
index abb4be254b..c713297d6e 100644
--- a/src/fs.h
+++ b/src/fs.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,10 +7,13 @@
#include <stdio.h>
#include <string>
+#if defined WIN32 && defined __GLIBCXX__
+#include <ext/stdio_filebuf.h>
+#endif
+#define BOOST_FILESYSTEM_NO_DEPRECATED
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
-#include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
/** Filesystem operations and types */
namespace fs = boost::filesystem;
@@ -18,7 +21,76 @@ namespace fs = boost::filesystem;
/** Bridge operations to C stdio */
namespace fsbridge {
FILE *fopen(const fs::path& p, const char *mode);
- FILE *freopen(const fs::path& p, const char *mode, FILE *stream);
+
+ class FileLock
+ {
+ public:
+ FileLock() = delete;
+ FileLock(const FileLock&) = delete;
+ FileLock(FileLock&&) = delete;
+ explicit FileLock(const fs::path& file);
+ ~FileLock();
+ bool TryLock();
+ std::string GetReason() { return reason; }
+
+ private:
+ std::string reason;
+#ifndef WIN32
+ int fd = -1;
+#else
+ void* hFile = (void*)-1; // INVALID_HANDLE_VALUE
+#endif
+ };
+
+ std::string get_filesystem_error_message(const fs::filesystem_error& e);
+
+ // GNU libstdc++ specific workaround for opening UTF-8 paths on Windows.
+ //
+ // On Windows, it is only possible to reliably access multibyte file paths through
+ // `wchar_t` APIs, not `char` APIs. But because the C++ standard doesn't
+ // require ifstream/ofstream `wchar_t` constructors, and the GNU library doesn't
+ // provide them (in contrast to the Microsoft C++ library, see
+ // https://stackoverflow.com/questions/821873/how-to-open-an-stdfstream-ofstream-or-ifstream-with-a-unicode-filename/822032#822032),
+ // Boost is forced to fall back to `char` constructors which may not work properly.
+ //
+ // Work around this issue by creating stream objects with `_wfopen` in
+ // combination with `__gnu_cxx::stdio_filebuf`. This workaround can be removed
+ // with an upgrade to C++17, where streams can be constructed directly from
+ // `std::filesystem::path` objects.
+
+#if defined WIN32 && defined __GLIBCXX__
+ class ifstream : public std::istream
+ {
+ public:
+ ifstream() = default;
+ explicit ifstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in) { open(p, mode); }
+ ~ifstream() { close(); }
+ void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::in);
+ bool is_open() { return m_filebuf.is_open(); }
+ void close();
+
+ private:
+ __gnu_cxx::stdio_filebuf<char> m_filebuf;
+ FILE* m_file = nullptr;
+ };
+ class ofstream : public std::ostream
+ {
+ public:
+ ofstream() = default;
+ explicit ofstream(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out) { open(p, mode); }
+ ~ofstream() { close(); }
+ void open(const fs::path& p, std::ios_base::openmode mode = std::ios_base::out);
+ bool is_open() { return m_filebuf.is_open(); }
+ void close();
+
+ private:
+ __gnu_cxx::stdio_filebuf<char> m_filebuf;
+ FILE* m_file = nullptr;
+ };
+#else // !(WIN32 && __GLIBCXX__)
+ typedef fs::ifstream ifstream;
+ typedef fs::ofstream ofstream;
+#endif // WIN32 && __GLIBCXX__
};
#endif // BITCOIN_FS_H
diff --git a/src/hash.cpp b/src/hash.cpp
index d31e094540..26150e5ca8 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2017 The Bitcoin Core developers
+// Copyright (c) 2013-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -77,171 +77,3 @@ void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char he
num[3] = (nChild >> 0) & 0xFF;
CHMAC_SHA512(chainCode.begin(), chainCode.size()).Write(&header, 1).Write(data, 32).Write(num, 4).Finalize(output);
}
-
-#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
-
-#define SIPROUND do { \
- v0 += v1; v1 = ROTL(v1, 13); v1 ^= v0; \
- v0 = ROTL(v0, 32); \
- v2 += v3; v3 = ROTL(v3, 16); v3 ^= v2; \
- v0 += v3; v3 = ROTL(v3, 21); v3 ^= v0; \
- v2 += v1; v1 = ROTL(v1, 17); v1 ^= v2; \
- v2 = ROTL(v2, 32); \
-} while (0)
-
-CSipHasher::CSipHasher(uint64_t k0, uint64_t k1)
-{
- v[0] = 0x736f6d6570736575ULL ^ k0;
- v[1] = 0x646f72616e646f6dULL ^ k1;
- v[2] = 0x6c7967656e657261ULL ^ k0;
- v[3] = 0x7465646279746573ULL ^ k1;
- count = 0;
- tmp = 0;
-}
-
-CSipHasher& CSipHasher::Write(uint64_t data)
-{
- uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
-
- assert(count % 8 == 0);
-
- v3 ^= data;
- SIPROUND;
- SIPROUND;
- v0 ^= data;
-
- v[0] = v0;
- v[1] = v1;
- v[2] = v2;
- v[3] = v3;
-
- count += 8;
- return *this;
-}
-
-CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size)
-{
- uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
- uint64_t t = tmp;
- int c = count;
-
- while (size--) {
- t |= ((uint64_t)(*(data++))) << (8 * (c % 8));
- c++;
- if ((c & 7) == 0) {
- v3 ^= t;
- SIPROUND;
- SIPROUND;
- v0 ^= t;
- t = 0;
- }
- }
-
- v[0] = v0;
- v[1] = v1;
- v[2] = v2;
- v[3] = v3;
- count = c;
- tmp = t;
-
- return *this;
-}
-
-uint64_t CSipHasher::Finalize() const
-{
- uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
-
- uint64_t t = tmp | (((uint64_t)count) << 56);
-
- v3 ^= t;
- SIPROUND;
- SIPROUND;
- v0 ^= t;
- v2 ^= 0xFF;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- return v0 ^ v1 ^ v2 ^ v3;
-}
-
-uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
-{
- /* Specialized implementation for efficiency */
- uint64_t d = val.GetUint64(0);
-
- uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
- uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
- uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
- uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
-
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(1);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(2);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(3);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- v3 ^= ((uint64_t)4) << 59;
- SIPROUND;
- SIPROUND;
- v0 ^= ((uint64_t)4) << 59;
- v2 ^= 0xFF;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- return v0 ^ v1 ^ v2 ^ v3;
-}
-
-uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra)
-{
- /* Specialized implementation for efficiency */
- uint64_t d = val.GetUint64(0);
-
- uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
- uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
- uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
- uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
-
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(1);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(2);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = val.GetUint64(3);
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- d = (((uint64_t)36) << 56) | extra;
- v3 ^= d;
- SIPROUND;
- SIPROUND;
- v0 ^= d;
- v2 ^= 0xFF;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- return v0 ^ v1 ^ v2 ^ v3;
-}
diff --git a/src/hash.h b/src/hash.h
index 75353e0c0f..c295568a3e 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -1,11 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_HASH_H
#define BITCOIN_HASH_H
+#include <crypto/common.h>
#include <crypto/ripemd160.h>
#include <crypto/sha256.h>
#include <prevector.h>
@@ -138,6 +139,15 @@ public:
return result;
}
+ /**
+ * Returns the first 64 bits from the resulting hash.
+ */
+ inline uint64_t GetCheapHash() {
+ unsigned char result[CHash256::OUTPUT_SIZE];
+ ctx.Finalize(result);
+ return ReadLE64(result);
+ }
+
template<typename T>
CHashWriter& operator<<(const T& obj) {
// Serialize to this stream
@@ -194,39 +204,4 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
-/** SipHash-2-4 */
-class CSipHasher
-{
-private:
- uint64_t v[4];
- uint64_t tmp;
- int count;
-
-public:
- /** Construct a SipHash calculator initialized with 128-bit key (k0, k1) */
- CSipHasher(uint64_t k0, uint64_t k1);
- /** Hash a 64-bit integer worth of data
- * It is treated as if this was the little-endian interpretation of 8 bytes.
- * This function can only be used when a multiple of 8 bytes have been written so far.
- */
- CSipHasher& Write(uint64_t data);
- /** Hash arbitrary bytes. */
- CSipHasher& Write(const unsigned char* data, size_t size);
- /** Compute the 64-bit SipHash-2-4 of the data written so far. The object remains untouched. */
- uint64_t Finalize() const;
-};
-
-/** Optimized SipHash-2-4 implementation for uint256.
- *
- * It is identical to:
- * SipHasher(k0, k1)
- * .Write(val.GetUint64(0))
- * .Write(val.GetUint64(1))
- * .Write(val.GetUint64(2))
- * .Write(val.GetUint64(3))
- * .Finalize()
- */
-uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val);
-uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra);
-
#endif // BITCOIN_HASH_H
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 0e5b497960..fcf760a4c6 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,9 +11,10 @@
#include <rpc/server.h>
#include <random.h>
#include <sync.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <ui_interface.h>
+#include <walletinitinterface.h>
#include <crypto/hmac_sha256.h>
#include <stdio.h>
@@ -30,7 +31,7 @@ static const char* WWW_AUTH_HEADER_DATA = "Basic realm=\"jsonrpc\"";
class HTTPRPCTimer : public RPCTimerBase
{
public:
- HTTPRPCTimer(struct event_base* eventBase, std::function<void(void)>& func, int64_t millis) :
+ HTTPRPCTimer(struct event_base* eventBase, std::function<void()>& func, int64_t millis) :
ev(eventBase, false, func)
{
struct timeval tv;
@@ -52,7 +53,7 @@ public:
{
return "HTTP";
}
- RPCTimerBase* NewTimer(std::function<void(void)>& func, int64_t millis) override
+ RPCTimerBase* NewTimer(std::function<void()>& func, int64_t millis) override
{
return new HTTPRPCTimer(base, func, millis);
}
@@ -240,12 +241,12 @@ bool StartHTTPRPC()
return false;
RegisterHTTPHandler("/", true, HTTPReq_JSONRPC);
-#ifdef ENABLE_WALLET
- // ifdef can be removed once we switch to better endpoint support and API versioning
- RegisterHTTPHandler("/wallet/", false, HTTPReq_JSONRPC);
-#endif
- assert(EventBase());
- httpRPCTimerInterface = MakeUnique<HTTPRPCTimerInterface>(EventBase());
+ if (g_wallet_init_interface.HasWalletSupport()) {
+ RegisterHTTPHandler("/wallet/", false, HTTPReq_JSONRPC);
+ }
+ struct event_base* eventBase = EventBase();
+ assert(eventBase);
+ httpRPCTimerInterface = MakeUnique<HTTPRPCTimerInterface>(eventBase);
RPCSetTimerInterface(httpRPCTimerInterface.get());
return true;
}
@@ -259,9 +260,9 @@ void StopHTTPRPC()
{
LogPrint(BCLog::RPC, "Stopping HTTP RPC server\n");
UnregisterHTTPHandler("/", true);
-#ifdef ENABLE_WALLET
- UnregisterHTTPHandler("/wallet/", false);
-#endif
+ if (g_wallet_init_interface.HasWalletSupport()) {
+ UnregisterHTTPHandler("/wallet/", false);
+ }
if (httpRPCTimerInterface) {
RPCUnsetTimerInterface(httpRPCTimerInterface.get());
httpRPCTimerInterface.reset();
diff --git a/src/httprpc.h b/src/httprpc.h
index ccae29b45d..2230a8ca4e 100644
--- a/src/httprpc.h
+++ b/src/httprpc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -23,7 +23,7 @@ void StopHTTPRPC();
/** Start HTTP REST subsystem.
* Precondition; HTTP and RPC has been started.
*/
-bool StartREST();
+void StartREST();
/** Interrupt RPC REST subsystem.
*/
void InterruptREST();
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 9daf3d1968..63639fa3e0 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,22 +6,23 @@
#include <chainparamsbase.h>
#include <compat.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/threadnames.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <netbase.h>
#include <rpc/protocol.h> // For HTTP status codes
+#include <shutdown.h>
#include <sync.h>
#include <ui_interface.h>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
+#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
-#include <future>
#include <event2/thread.h>
#include <event2/buffer.h>
@@ -69,7 +70,7 @@ class WorkQueue
{
private:
/** Mutex protects entire object */
- std::mutex cs;
+ Mutex cs;
std::condition_variable cond;
std::deque<std::unique_ptr<WorkItem>> queue;
bool running;
@@ -88,7 +89,7 @@ public:
/** Enqueue a work item */
bool Enqueue(WorkItem* item)
{
- std::unique_lock<std::mutex> lock(cs);
+ LOCK(cs);
if (queue.size() >= maxDepth) {
return false;
}
@@ -102,7 +103,7 @@ public:
while (true) {
std::unique_ptr<WorkItem> i;
{
- std::unique_lock<std::mutex> lock(cs);
+ WAIT_LOCK(cs, lock);
while (running && queue.empty())
cond.wait(lock);
if (!running)
@@ -116,7 +117,7 @@ public:
/** Interrupt and exit loops */
void Interrupt()
{
- std::unique_lock<std::mutex> lock(cs);
+ LOCK(cs);
running = false;
cond.notify_all();
}
@@ -124,7 +125,6 @@ public:
struct HTTPPathHandler
{
- HTTPPathHandler() {}
HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler):
prefix(_prefix), exactMatch(_exactMatch), handler(_handler)
{
@@ -224,21 +224,25 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
}
std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
- LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
- RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString());
-
// Early address-based allow check
if (!ClientAllowed(hreq->GetPeer())) {
+ LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Client network is not allowed RPC access\n",
+ hreq->GetPeer().ToString());
hreq->WriteReply(HTTP_FORBIDDEN);
return;
}
// Early reject unknown HTTP methods
if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
+ LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Unknown HTTP request method\n",
+ hreq->GetPeer().ToString());
hreq->WriteReply(HTTP_BADMETHOD);
return;
}
+ LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
+ RequestMethodString(hreq->GetRequestMethod()), SanitizeString(hreq->GetURI(), SAFE_CHARS_URI).substr(0, 100), hreq->GetPeer().ToString());
+
// Find registered handler for prefix
std::string strURI = hreq->GetURI();
std::string path;
@@ -281,7 +285,7 @@ static void http_reject_request_cb(struct evhttp_request* req, void*)
/** Event dispatcher thread */
static bool ThreadHTTP(struct event_base* base)
{
- RenameThread("bitcoin-http");
+ util::ThreadRename("http");
LogPrint(BCLog::HTTP, "Entering http event loop\n");
event_base_dispatch(base);
// Event loop will be interrupted by InterruptHTTPServer()
@@ -292,26 +296,26 @@ static bool ThreadHTTP(struct event_base* base)
/** Bind HTTP server to specified addresses */
static bool HTTPBindAddresses(struct evhttp* http)
{
- int defaultPort = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
+ int http_port = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
std::vector<std::pair<std::string, uint16_t> > endpoints;
// Determine what addresses to bind to
- if (!gArgs.IsArgSet("-rpcallowip")) { // Default to loopback if not allowing external IPs
- endpoints.push_back(std::make_pair("::1", defaultPort));
- endpoints.push_back(std::make_pair("127.0.0.1", defaultPort));
+ if (!(gArgs.IsArgSet("-rpcallowip") && gArgs.IsArgSet("-rpcbind"))) { // Default to loopback if not allowing external IPs
+ endpoints.push_back(std::make_pair("::1", http_port));
+ endpoints.push_back(std::make_pair("127.0.0.1", http_port));
+ if (gArgs.IsArgSet("-rpcallowip")) {
+ LogPrintf("WARNING: option -rpcallowip was specified without -rpcbind; this doesn't usually make sense\n");
+ }
if (gArgs.IsArgSet("-rpcbind")) {
LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n");
}
} else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address
for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) {
- int port = defaultPort;
+ int port = http_port;
std::string host;
SplitHostPort(strRPCBind, port, host);
endpoints.push_back(std::make_pair(host, port));
}
- } else { // No specific bind address specified, bind to any
- endpoints.push_back(std::make_pair("::", defaultPort));
- endpoints.push_back(std::make_pair("0.0.0.0", defaultPort));
}
// Bind addresses
@@ -319,6 +323,10 @@ static bool HTTPBindAddresses(struct evhttp* http)
LogPrint(BCLog::HTTP, "Binding RPC on address %s port %i\n", i->first, i->second);
evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? nullptr : i->first.c_str(), i->second);
if (bind_handle) {
+ CNetAddr addr;
+ if (i->first.empty() || (LookupHost(i->first.c_str(), addr, false) && addr.IsBindAny())) {
+ LogPrintf("WARNING: the RPC server is not safe to expose to untrusted networks such as the public internet\n");
+ }
boundSockets.push_back(bind_handle);
} else {
LogPrintf("Binding RPC on address %s port %i failed.\n", i->first, i->second);
@@ -328,9 +336,9 @@ static bool HTTPBindAddresses(struct evhttp* http)
}
/** Simple wrapper to set thread name and run work queue */
-static void HTTPWorkQueueRun(WorkQueue<HTTPClosure>* queue)
+static void HTTPWorkQueueRun(WorkQueue<HTTPClosure>* queue, int worker_num)
{
- RenameThread("bitcoin-httpworker");
+ util::ThreadRename(strprintf("httpworker.%i", worker_num));
queue->Run();
}
@@ -352,20 +360,13 @@ bool InitHTTPServer()
if (!InitHTTPAllowList())
return false;
- if (gArgs.GetBoolArg("-rpcssl", false)) {
- uiInterface.ThreadSafeMessageBox(
- "SSL mode for RPC (-rpcssl) is no longer supported.",
- "", CClientUIInterface::MSG_ERROR);
- return false;
- }
-
// Redirect libevent's logging to our own log
event_set_log_callback(&libevent_log_cb);
// Update libevent's log handling. Returns false if our version of
// libevent doesn't support debug logging, in which case we should
// clear the BCLog::LIBEVENT flag.
- if (!UpdateHTTPServerLogging(g_logger->WillLogCategory(BCLog::LIBEVENT))) {
- g_logger->DisableCategory(BCLog::LIBEVENT);
+ if (!UpdateHTTPServerLogging(LogInstance().WillLogCategory(BCLog::LIBEVENT))) {
+ LogInstance().DisableCategory(BCLog::LIBEVENT);
}
#ifdef WIN32
@@ -420,7 +421,6 @@ bool UpdateHTTPServerLogging(bool enable) {
}
std::thread threadHTTP;
-std::future<bool> threadResult;
static std::vector<std::thread> g_thread_http_workers;
void StartHTTPServer()
@@ -428,12 +428,10 @@ void StartHTTPServer()
LogPrint(BCLog::HTTP, "Starting HTTP server\n");
int rpcThreads = std::max((long)gArgs.GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
- std::packaged_task<bool(event_base*)> task(ThreadHTTP);
- threadResult = task.get_future();
- threadHTTP = std::thread(std::move(task), eventBase);
+ threadHTTP = std::thread(ThreadHTTP, eventBase);
for (int i = 0; i < rpcThreads; i++) {
- g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue);
+ g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue, i);
}
}
@@ -441,10 +439,6 @@ void InterruptHTTPServer()
{
LogPrint(BCLog::HTTP, "Interrupting HTTP server\n");
if (eventHTTP) {
- // Unlisten sockets
- for (evhttp_bound_socket *socket : boundSockets) {
- evhttp_del_accept_socket(eventHTTP, socket);
- }
// Reject requests on current connections
evhttp_set_gencb(eventHTTP, http_reject_request_cb, nullptr);
}
@@ -464,20 +458,14 @@ void StopHTTPServer()
delete workQueue;
workQueue = nullptr;
}
+ // Unlisten sockets, these are what make the event loop running, which means
+ // that after this and all connections are closed the event loop will quit.
+ for (evhttp_bound_socket *socket : boundSockets) {
+ evhttp_del_accept_socket(eventHTTP, socket);
+ }
+ boundSockets.clear();
if (eventBase) {
LogPrint(BCLog::HTTP, "Waiting for HTTP event thread to exit\n");
- // Exit the event loop as soon as there are no active events.
- event_base_loopexit(eventBase, nullptr);
- // Give event loop a few seconds to exit (to send back last RPC responses), then break it
- // Before this was solved with event_base_loopexit, but that didn't work as expected in
- // at least libevent 2.0.21 and always introduced a delay. In libevent
- // master that appears to be solved, so in the future that solution
- // could be used again (if desirable).
- // (see discussion in https://github.com/bitcoin/bitcoin/pull/6990)
- if (threadResult.valid() && threadResult.wait_for(std::chrono::milliseconds(2000)) == std::future_status::timeout) {
- LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n");
- event_base_loopbreak(eventBase);
- }
threadHTTP.join();
}
if (eventHTTP) {
@@ -505,7 +493,7 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data)
delete self;
}
-HTTPEvent::HTTPEvent(struct event_base* base, bool _deleteWhenTriggered, const std::function<void(void)>& _handler):
+HTTPEvent::HTTPEvent(struct event_base* base, bool _deleteWhenTriggered, const std::function<void()>& _handler):
deleteWhenTriggered(_deleteWhenTriggered), handler(_handler)
{
ev = event_new(base, -1, 0, httpevent_callback_fn, this);
@@ -536,7 +524,7 @@ HTTPRequest::~HTTPRequest()
// evhttpd cleans up the request, as long as a reply was sent.
}
-std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr)
+std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr) const
{
const struct evkeyvalq* headers = evhttp_request_get_input_headers(req);
assert(headers);
@@ -582,6 +570,9 @@ void HTTPRequest::WriteHeader(const std::string& hdr, const std::string& value)
void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
{
assert(!replySent && req);
+ if (ShutdownRequested()) {
+ WriteHeader("Connection", "close");
+ }
// Send event to main http thread to send reply message
struct evbuffer* evb = evhttp_request_get_output_buffer(req);
assert(evb);
@@ -606,7 +597,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
req = nullptr; // transferred back to main thread
}
-CService HTTPRequest::GetPeer()
+CService HTTPRequest::GetPeer() const
{
evhttp_connection* con = evhttp_request_get_connection(req);
CService peer;
@@ -620,12 +611,12 @@ CService HTTPRequest::GetPeer()
return peer;
}
-std::string HTTPRequest::GetURI()
+std::string HTTPRequest::GetURI() const
{
return evhttp_request_get_uri(req);
}
-HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod()
+HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod() const
{
switch (evhttp_request_get_command(req)) {
case EVHTTP_REQ_GET:
@@ -665,15 +656,3 @@ void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
pathHandlers.erase(i);
}
}
-
-std::string urlDecode(const std::string &urlEncoded) {
- std::string res;
- if (!urlEncoded.empty()) {
- char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, nullptr);
- if (decoded) {
- res = std::string(decoded);
- free(decoded);
- }
- }
- return res;
-}
diff --git a/src/httpserver.h b/src/httpserver.h
index 8a3adaf91f..7943f0094b 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -74,21 +74,21 @@ public:
/** Get requested URI.
*/
- std::string GetURI();
+ std::string GetURI() const;
/** Get CService (address:ip) for the origin of the http request.
*/
- CService GetPeer();
+ CService GetPeer() const;
/** Get request method.
*/
- RequestMethod GetRequestMethod();
+ RequestMethod GetRequestMethod() const;
/**
* Get the request header specified by hdr, or an empty string.
* Return a pair (isPresent,string).
*/
- std::pair<bool, std::string> GetHeader(const std::string& hdr);
+ std::pair<bool, std::string> GetHeader(const std::string& hdr) const;
/**
* Read request body.
@@ -134,7 +134,7 @@ public:
* deleteWhenTriggered deletes this event object after the event is triggered (and the handler called)
* handler is the handler to call when the event is triggered.
*/
- HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function<void(void)>& handler);
+ HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function<void()>& handler);
~HTTPEvent();
/** Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger it after
@@ -143,11 +143,9 @@ public:
void trigger(struct timeval* tv);
bool deleteWhenTriggered;
- std::function<void(void)> handler;
+ std::function<void()> handler;
private:
struct event* ev;
};
-std::string urlDecode(const std::string &urlEncoded);
-
#endif // BITCOIN_HTTPSERVER_H
diff --git a/src/index/base.cpp b/src/index/base.cpp
index 788f7adccd..bcc8e2ce7c 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -7,7 +7,7 @@
#include <shutdown.h>
#include <tinyformat.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <warnings.h>
@@ -41,9 +41,9 @@ bool BaseIndex::DB::ReadBestBlock(CBlockLocator& locator) const
return success;
}
-bool BaseIndex::DB::WriteBestBlock(const CBlockLocator& locator)
+void BaseIndex::DB::WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator)
{
- return Write(DB_BEST_BLOCK, locator);
+ batch.Write(DB_BEST_BLOCK, locator);
}
BaseIndex::~BaseIndex()
@@ -60,25 +60,29 @@ bool BaseIndex::Init()
}
LOCK(cs_main);
- m_best_block_index = FindForkInGlobalIndex(chainActive, locator);
- m_synced = m_best_block_index.load() == chainActive.Tip();
+ if (locator.IsNull()) {
+ m_best_block_index = nullptr;
+ } else {
+ m_best_block_index = FindForkInGlobalIndex(::ChainActive(), locator);
+ }
+ m_synced = m_best_block_index.load() == ::ChainActive().Tip();
return true;
}
-static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev)
+static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
if (!pindex_prev) {
- return chainActive.Genesis();
+ return ::ChainActive().Genesis();
}
- const CBlockIndex* pindex = chainActive.Next(pindex_prev);
+ const CBlockIndex* pindex = ::ChainActive().Next(pindex_prev);
if (pindex) {
return pindex;
}
- return chainActive.Next(chainActive.FindFork(pindex_prev));
+ return ::ChainActive().Next(::ChainActive().FindFork(pindex_prev));
}
void BaseIndex::ThreadSync()
@@ -91,7 +95,11 @@ void BaseIndex::ThreadSync()
int64_t last_locator_write_time = 0;
while (true) {
if (m_interrupt) {
- WriteBestBlock(pindex);
+ m_best_block_index = pindex;
+ // No need to handle errors in Commit. If it fails, the error will be already be
+ // logged. The best way to recover is to continue, as index cannot be corrupted by
+ // a missed commit to disk for an advanced index state.
+ Commit();
return;
}
@@ -99,11 +107,17 @@ void BaseIndex::ThreadSync()
LOCK(cs_main);
const CBlockIndex* pindex_next = NextSyncBlock(pindex);
if (!pindex_next) {
- WriteBestBlock(pindex);
m_best_block_index = pindex;
m_synced = true;
+ // No need to handle errors in Commit. See rationale above.
+ Commit();
break;
}
+ if (pindex_next->pprev != pindex && !Rewind(pindex, pindex_next->pprev)) {
+ FatalError("%s: Failed to rewind index %s to a previous chain tip",
+ __func__, GetName());
+ return;
+ }
pindex = pindex_next;
}
@@ -115,8 +129,10 @@ void BaseIndex::ThreadSync()
}
if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL < current_time) {
- WriteBestBlock(pindex);
+ m_best_block_index = pindex;
last_locator_write_time = current_time;
+ // No need to handle errors in Commit. See rationale above.
+ Commit();
}
CBlock block;
@@ -140,12 +156,35 @@ void BaseIndex::ThreadSync()
}
}
-bool BaseIndex::WriteBestBlock(const CBlockIndex* block_index)
+bool BaseIndex::Commit()
+{
+ CDBBatch batch(GetDB());
+ if (!CommitInternal(batch) || !GetDB().WriteBatch(batch)) {
+ return error("%s: Failed to commit latest %s state", __func__, GetName());
+ }
+ return true;
+}
+
+bool BaseIndex::CommitInternal(CDBBatch& batch)
{
LOCK(cs_main);
- if (!GetDB().WriteBestBlock(chainActive.GetLocator(block_index))) {
- return error("%s: Failed to write locator to disk", __func__);
+ GetDB().WriteBestBlock(batch, ::ChainActive().GetLocator(m_best_block_index));
+ return true;
+}
+
+bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
+{
+ assert(current_tip == m_best_block_index);
+ assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
+
+ // In the case of a reorg, ensure persisted block locator is not stale.
+ m_best_block_index = new_tip;
+ if (!Commit()) {
+ // If commit fails, revert the best block index to avoid corruption.
+ m_best_block_index = current_tip;
+ return false;
}
+
return true;
}
@@ -176,6 +215,11 @@ void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const
best_block_index->GetBlockHash().ToString());
return;
}
+ if (best_block_index != pindex->pprev && !Rewind(best_block_index, pindex->pprev)) {
+ FatalError("%s: Failed to rewind index %s to a previous chain tip",
+ __func__, GetName());
+ return;
+ }
}
if (WriteBlock(*block, pindex)) {
@@ -220,9 +264,10 @@ void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
return;
}
- if (!GetDB().WriteBestBlock(locator)) {
- error("%s: Failed to write locator to disk", __func__);
- }
+ // No need to handle errors in Commit. If it fails, the error will be already be logged. The
+ // best way to recover is to continue, as index cannot be corrupted by a missed commit to disk
+ // for an advanced index state.
+ Commit();
}
bool BaseIndex::BlockUntilSyncedToCurrentChain()
@@ -235,9 +280,9 @@ bool BaseIndex::BlockUntilSyncedToCurrentChain()
{
// Skip the queue-draining stuff if we know we're caught up with
- // chainActive.Tip().
+ // ::ChainActive().Tip().
LOCK(cs_main);
- const CBlockIndex* chain_tip = chainActive.Tip();
+ const CBlockIndex* chain_tip = ::ChainActive().Tip();
const CBlockIndex* best_block_index = m_best_block_index.load();
if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) {
return true;
diff --git a/src/index/base.h b/src/index/base.h
index 04ee6e6cc2..31acbed0c1 100644
--- a/src/index/base.h
+++ b/src/index/base.h
@@ -32,7 +32,7 @@ protected:
bool ReadBestBlock(CBlockLocator& locator) const;
/// Write block locator of the chain that the txindex is in sync with.
- bool WriteBestBlock(const CBlockLocator& locator);
+ void WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator);
};
private:
@@ -54,8 +54,15 @@ private:
/// over and the sync thread exits.
void ThreadSync();
- /// Write the current chain block locator to the DB.
- bool WriteBestBlock(const CBlockIndex* block_index);
+ /// Write the current index state (eg. chain block locator and subclass-specific items) to disk.
+ ///
+ /// Recommendations for error handling:
+ /// If called on a successor of the previous committed best block in the index, the index can
+ /// continue processing without risk of corruption, though the index state will need to catch up
+ /// from further behind on reboot. If the new state is not a successor of the previous state (due
+ /// to a chain reorganization), the index must halt until Commit succeeds or else it could end up
+ /// getting corrupted.
+ bool Commit();
protected:
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
@@ -69,6 +76,14 @@ protected:
/// Write update index entries for a newly connected block.
virtual bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) { return true; }
+ /// Virtual method called internally by Commit that can be overridden to atomically
+ /// commit more index state.
+ virtual bool CommitInternal(CDBBatch& batch);
+
+ /// Rewind index to an earlier chain tip during a chain reorg. The tip must
+ /// be an ancestor of the current best block.
+ virtual bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip);
+
virtual DB& GetDB() const = 0;
/// Get the name of the index for display in logs.
diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp
new file mode 100644
index 0000000000..20f33baf2c
--- /dev/null
+++ b/src/index/blockfilterindex.cpp
@@ -0,0 +1,467 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <map>
+
+#include <dbwrapper.h>
+#include <index/blockfilterindex.h>
+#include <util/system.h>
+#include <validation.h>
+
+/* The index database stores three items for each block: the disk location of the encoded filter,
+ * its dSHA256 hash, and the header. Those belonging to blocks on the active chain are indexed by
+ * height, and those belonging to blocks that have been reorganized out of the active chain are
+ * indexed by block hash. This ensures that filter data for any block that becomes part of the
+ * active chain can always be retrieved, alleviating timing concerns.
+ *
+ * The filters themselves are stored in flat files and referenced by the LevelDB entries. This
+ * minimizes the amount of data written to LevelDB and keeps the database values constant size. The
+ * disk location of the next block filter to be written (represented as a FlatFilePos) is stored
+ * under the DB_FILTER_POS key.
+ *
+ * Keys for the height index have the type [DB_BLOCK_HEIGHT, uint32 (BE)]. The height is represented
+ * as big-endian so that sequential reads of filters by height are fast.
+ * Keys for the hash index have the type [DB_BLOCK_HASH, uint256].
+ */
+constexpr char DB_BLOCK_HASH = 's';
+constexpr char DB_BLOCK_HEIGHT = 't';
+constexpr char DB_FILTER_POS = 'P';
+
+constexpr unsigned int MAX_FLTR_FILE_SIZE = 0x1000000; // 16 MiB
+/** The pre-allocation chunk size for fltr?????.dat files */
+constexpr unsigned int FLTR_FILE_CHUNK_SIZE = 0x100000; // 1 MiB
+
+namespace {
+
+struct DBVal {
+ uint256 hash;
+ uint256 header;
+ FlatFilePos pos;
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ READWRITE(hash);
+ READWRITE(header);
+ READWRITE(pos);
+ }
+};
+
+struct DBHeightKey {
+ int height;
+
+ DBHeightKey() : height(0) {}
+ DBHeightKey(int height_in) : height(height_in) {}
+
+ template<typename Stream>
+ void Serialize(Stream& s) const
+ {
+ ser_writedata8(s, DB_BLOCK_HEIGHT);
+ ser_writedata32be(s, height);
+ }
+
+ template<typename Stream>
+ void Unserialize(Stream& s)
+ {
+ char prefix = ser_readdata8(s);
+ if (prefix != DB_BLOCK_HEIGHT) {
+ throw std::ios_base::failure("Invalid format for block filter index DB height key");
+ }
+ height = ser_readdata32be(s);
+ }
+};
+
+struct DBHashKey {
+ uint256 hash;
+
+ DBHashKey(const uint256& hash_in) : hash(hash_in) {}
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ char prefix = DB_BLOCK_HASH;
+ READWRITE(prefix);
+ if (prefix != DB_BLOCK_HASH) {
+ throw std::ios_base::failure("Invalid format for block filter index DB hash key");
+ }
+
+ READWRITE(hash);
+ }
+};
+
+}; // namespace
+
+static std::map<BlockFilterType, BlockFilterIndex> g_filter_indexes;
+
+BlockFilterIndex::BlockFilterIndex(BlockFilterType filter_type,
+ size_t n_cache_size, bool f_memory, bool f_wipe)
+ : m_filter_type(filter_type)
+{
+ const std::string& filter_name = BlockFilterTypeName(filter_type);
+ if (filter_name.empty()) throw std::invalid_argument("unknown filter_type");
+
+ fs::path path = GetDataDir() / "indexes" / "blockfilter" / filter_name;
+ fs::create_directories(path);
+
+ m_name = filter_name + " block filter index";
+ m_db = MakeUnique<BaseIndex::DB>(path / "db", n_cache_size, f_memory, f_wipe);
+ m_filter_fileseq = MakeUnique<FlatFileSeq>(std::move(path), "fltr", FLTR_FILE_CHUNK_SIZE);
+}
+
+bool BlockFilterIndex::Init()
+{
+ if (!m_db->Read(DB_FILTER_POS, m_next_filter_pos)) {
+ // Check that the cause of the read failure is that the key does not exist. Any other errors
+ // indicate database corruption or a disk failure, and starting the index would cause
+ // further corruption.
+ if (m_db->Exists(DB_FILTER_POS)) {
+ return error("%s: Cannot read current %s state; index may be corrupted",
+ __func__, GetName());
+ }
+
+ // If the DB_FILTER_POS is not set, then initialize to the first location.
+ m_next_filter_pos.nFile = 0;
+ m_next_filter_pos.nPos = 0;
+ }
+ return BaseIndex::Init();
+}
+
+bool BlockFilterIndex::CommitInternal(CDBBatch& batch)
+{
+ const FlatFilePos& pos = m_next_filter_pos;
+
+ // Flush current filter file to disk.
+ CAutoFile file(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ if (file.IsNull()) {
+ return error("%s: Failed to open filter file %d", __func__, pos.nFile);
+ }
+ if (!FileCommit(file.Get())) {
+ return error("%s: Failed to commit filter file %d", __func__, pos.nFile);
+ }
+
+ batch.Write(DB_FILTER_POS, pos);
+ return BaseIndex::CommitInternal(batch);
+}
+
+bool BlockFilterIndex::ReadFilterFromDisk(const FlatFilePos& pos, BlockFilter& filter) const
+{
+ CAutoFile filein(m_filter_fileseq->Open(pos, true), SER_DISK, CLIENT_VERSION);
+ if (filein.IsNull()) {
+ return false;
+ }
+
+ uint256 block_hash;
+ std::vector<unsigned char> encoded_filter;
+ try {
+ filein >> block_hash >> encoded_filter;
+ filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter));
+ }
+ catch (const std::exception& e) {
+ return error("%s: Failed to deserialize block filter from disk: %s", __func__, e.what());
+ }
+
+ return true;
+}
+
+size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter)
+{
+ assert(filter.GetFilterType() == GetFilterType());
+
+ size_t data_size =
+ GetSerializeSize(filter.GetBlockHash(), CLIENT_VERSION) +
+ GetSerializeSize(filter.GetEncodedFilter(), CLIENT_VERSION);
+
+ // If writing the filter would overflow the file, flush and move to the next one.
+ if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) {
+ CAutoFile last_file(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ if (last_file.IsNull()) {
+ LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile);
+ return 0;
+ }
+ if (!TruncateFile(last_file.Get(), pos.nPos)) {
+ LogPrintf("%s: Failed to truncate filter file %d\n", __func__, pos.nFile);
+ return 0;
+ }
+ if (!FileCommit(last_file.Get())) {
+ LogPrintf("%s: Failed to commit filter file %d\n", __func__, pos.nFile);
+ return 0;
+ }
+
+ pos.nFile++;
+ pos.nPos = 0;
+ }
+
+ // Pre-allocate sufficient space for filter data.
+ bool out_of_space;
+ m_filter_fileseq->Allocate(pos, data_size, out_of_space);
+ if (out_of_space) {
+ LogPrintf("%s: out of disk space\n", __func__);
+ return 0;
+ }
+
+ CAutoFile fileout(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ if (fileout.IsNull()) {
+ LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile);
+ return 0;
+ }
+
+ fileout << filter.GetBlockHash() << filter.GetEncodedFilter();
+ return data_size;
+}
+
+bool BlockFilterIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
+{
+ CBlockUndo block_undo;
+ uint256 prev_header;
+
+ if (pindex->nHeight > 0) {
+ if (!UndoReadFromDisk(block_undo, pindex)) {
+ return false;
+ }
+
+ std::pair<uint256, DBVal> read_out;
+ if (!m_db->Read(DBHeightKey(pindex->nHeight - 1), read_out)) {
+ return false;
+ }
+
+ uint256 expected_block_hash = pindex->pprev->GetBlockHash();
+ if (read_out.first != expected_block_hash) {
+ return error("%s: previous block header belongs to unexpected block %s; expected %s",
+ __func__, read_out.first.ToString(), expected_block_hash.ToString());
+ }
+
+ prev_header = read_out.second.header;
+ }
+
+ BlockFilter filter(m_filter_type, block, block_undo);
+
+ size_t bytes_written = WriteFilterToDisk(m_next_filter_pos, filter);
+ if (bytes_written == 0) return false;
+
+ std::pair<uint256, DBVal> value;
+ value.first = pindex->GetBlockHash();
+ value.second.hash = filter.GetHash();
+ value.second.header = filter.ComputeHeader(prev_header);
+ value.second.pos = m_next_filter_pos;
+
+ if (!m_db->Write(DBHeightKey(pindex->nHeight), value)) {
+ return false;
+ }
+
+ m_next_filter_pos.nPos += bytes_written;
+ return true;
+}
+
+static bool CopyHeightIndexToHashIndex(CDBIterator& db_it, CDBBatch& batch,
+ const std::string& index_name,
+ int start_height, int stop_height)
+{
+ DBHeightKey key(start_height);
+ db_it.Seek(key);
+
+ for (int height = start_height; height <= stop_height; ++height) {
+ if (!db_it.GetKey(key) || key.height != height) {
+ return error("%s: unexpected key in %s: expected (%c, %d)",
+ __func__, index_name, DB_BLOCK_HEIGHT, height);
+ }
+
+ std::pair<uint256, DBVal> value;
+ if (!db_it.GetValue(value)) {
+ return error("%s: unable to read value in %s at key (%c, %d)",
+ __func__, index_name, DB_BLOCK_HEIGHT, height);
+ }
+
+ batch.Write(DBHashKey(value.first), std::move(value.second));
+
+ db_it.Next();
+ }
+ return true;
+}
+
+bool BlockFilterIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
+{
+ assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
+
+ CDBBatch batch(*m_db);
+ std::unique_ptr<CDBIterator> db_it(m_db->NewIterator());
+
+ // During a reorg, we need to copy all filters for blocks that are getting disconnected from the
+ // height index to the hash index so we can still find them when the height index entries are
+ // overwritten.
+ if (!CopyHeightIndexToHashIndex(*db_it, batch, m_name, new_tip->nHeight, current_tip->nHeight)) {
+ return false;
+ }
+
+ // The latest filter position gets written in Commit by the call to the BaseIndex::Rewind.
+ // But since this creates new references to the filter, the position should get updated here
+ // atomically as well in case Commit fails.
+ batch.Write(DB_FILTER_POS, m_next_filter_pos);
+ if (!m_db->WriteBatch(batch)) return false;
+
+ return BaseIndex::Rewind(current_tip, new_tip);
+}
+
+static bool LookupOne(const CDBWrapper& db, const CBlockIndex* block_index, DBVal& result)
+{
+ // First check if the result is stored under the height index and the value there matches the
+ // block hash. This should be the case if the block is on the active chain.
+ std::pair<uint256, DBVal> read_out;
+ if (!db.Read(DBHeightKey(block_index->nHeight), read_out)) {
+ return false;
+ }
+ if (read_out.first == block_index->GetBlockHash()) {
+ result = std::move(read_out.second);
+ return true;
+ }
+
+ // If value at the height index corresponds to an different block, the result will be stored in
+ // the hash index.
+ return db.Read(DBHashKey(block_index->GetBlockHash()), result);
+}
+
+static bool LookupRange(CDBWrapper& db, const std::string& index_name, int start_height,
+ const CBlockIndex* stop_index, std::vector<DBVal>& results)
+{
+ if (start_height < 0) {
+ return error("%s: start height (%d) is negative", __func__, start_height);
+ }
+ if (start_height > stop_index->nHeight) {
+ return error("%s: start height (%d) is greater than stop height (%d)",
+ __func__, start_height, stop_index->nHeight);
+ }
+
+ size_t results_size = static_cast<size_t>(stop_index->nHeight - start_height + 1);
+ std::vector<std::pair<uint256, DBVal>> values(results_size);
+
+ DBHeightKey key(start_height);
+ std::unique_ptr<CDBIterator> db_it(db.NewIterator());
+ db_it->Seek(DBHeightKey(start_height));
+ for (int height = start_height; height <= stop_index->nHeight; ++height) {
+ if (!db_it->Valid() || !db_it->GetKey(key) || key.height != height) {
+ return false;
+ }
+
+ size_t i = static_cast<size_t>(height - start_height);
+ if (!db_it->GetValue(values[i])) {
+ return error("%s: unable to read value in %s at key (%c, %d)",
+ __func__, index_name, DB_BLOCK_HEIGHT, height);
+ }
+
+ db_it->Next();
+ }
+
+ results.resize(results_size);
+
+ // Iterate backwards through block indexes collecting results in order to access the block hash
+ // of each entry in case we need to look it up in the hash index.
+ for (const CBlockIndex* block_index = stop_index;
+ block_index && block_index->nHeight >= start_height;
+ block_index = block_index->pprev) {
+ uint256 block_hash = block_index->GetBlockHash();
+
+ size_t i = static_cast<size_t>(block_index->nHeight - start_height);
+ if (block_hash == values[i].first) {
+ results[i] = std::move(values[i].second);
+ continue;
+ }
+
+ if (!db.Read(DBHashKey(block_hash), results[i])) {
+ return error("%s: unable to read value in %s at key (%c, %s)",
+ __func__, index_name, DB_BLOCK_HASH, block_hash.ToString());
+ }
+ }
+
+ return true;
+}
+
+bool BlockFilterIndex::LookupFilter(const CBlockIndex* block_index, BlockFilter& filter_out) const
+{
+ DBVal entry;
+ if (!LookupOne(*m_db, block_index, entry)) {
+ return false;
+ }
+
+ return ReadFilterFromDisk(entry.pos, filter_out);
+}
+
+bool BlockFilterIndex::LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out) const
+{
+ DBVal entry;
+ if (!LookupOne(*m_db, block_index, entry)) {
+ return false;
+ }
+
+ header_out = entry.header;
+ return true;
+}
+
+bool BlockFilterIndex::LookupFilterRange(int start_height, const CBlockIndex* stop_index,
+ std::vector<BlockFilter>& filters_out) const
+{
+ std::vector<DBVal> entries;
+ if (!LookupRange(*m_db, m_name, start_height, stop_index, entries)) {
+ return false;
+ }
+
+ filters_out.resize(entries.size());
+ auto filter_pos_it = filters_out.begin();
+ for (const auto& entry : entries) {
+ if (!ReadFilterFromDisk(entry.pos, *filter_pos_it)) {
+ return false;
+ }
+ ++filter_pos_it;
+ }
+
+ return true;
+}
+
+bool BlockFilterIndex::LookupFilterHashRange(int start_height, const CBlockIndex* stop_index,
+ std::vector<uint256>& hashes_out) const
+
+{
+ std::vector<DBVal> entries;
+ if (!LookupRange(*m_db, m_name, start_height, stop_index, entries)) {
+ return false;
+ }
+
+ hashes_out.clear();
+ hashes_out.reserve(entries.size());
+ for (const auto& entry : entries) {
+ hashes_out.push_back(entry.hash);
+ }
+ return true;
+}
+
+BlockFilterIndex* GetBlockFilterIndex(BlockFilterType filter_type)
+{
+ auto it = g_filter_indexes.find(filter_type);
+ return it != g_filter_indexes.end() ? &it->second : nullptr;
+}
+
+void ForEachBlockFilterIndex(std::function<void (BlockFilterIndex&)> fn)
+{
+ for (auto& entry : g_filter_indexes) fn(entry.second);
+}
+
+bool InitBlockFilterIndex(BlockFilterType filter_type,
+ size_t n_cache_size, bool f_memory, bool f_wipe)
+{
+ auto result = g_filter_indexes.emplace(std::piecewise_construct,
+ std::forward_as_tuple(filter_type),
+ std::forward_as_tuple(filter_type,
+ n_cache_size, f_memory, f_wipe));
+ return result.second;
+}
+
+bool DestroyBlockFilterIndex(BlockFilterType filter_type)
+{
+ return g_filter_indexes.erase(filter_type);
+}
+
+void DestroyAllBlockFilterIndexes()
+{
+ g_filter_indexes.clear();
+}
diff --git a/src/index/blockfilterindex.h b/src/index/blockfilterindex.h
new file mode 100644
index 0000000000..436d52515f
--- /dev/null
+++ b/src/index/blockfilterindex.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_INDEX_BLOCKFILTERINDEX_H
+#define BITCOIN_INDEX_BLOCKFILTERINDEX_H
+
+#include <blockfilter.h>
+#include <chain.h>
+#include <flatfile.h>
+#include <index/base.h>
+
+/**
+ * BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of
+ * blocks by height. An index is constructed for each supported filter type with its own database
+ * (ie. filter data for different types are stored in separate databases).
+ *
+ * This index is used to serve BIP 157 net requests.
+ */
+class BlockFilterIndex final : public BaseIndex
+{
+private:
+ BlockFilterType m_filter_type;
+ std::string m_name;
+ std::unique_ptr<BaseIndex::DB> m_db;
+
+ FlatFilePos m_next_filter_pos;
+ std::unique_ptr<FlatFileSeq> m_filter_fileseq;
+
+ bool ReadFilterFromDisk(const FlatFilePos& pos, BlockFilter& filter) const;
+ size_t WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter);
+
+protected:
+ bool Init() override;
+
+ bool CommitInternal(CDBBatch& batch) override;
+
+ bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) override;
+
+ bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip) override;
+
+ BaseIndex::DB& GetDB() const override { return *m_db; }
+
+ const char* GetName() const override { return m_name.c_str(); }
+
+public:
+ /** Constructs the index, which becomes available to be queried. */
+ explicit BlockFilterIndex(BlockFilterType filter_type,
+ size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
+
+ BlockFilterType GetFilterType() const { return m_filter_type; }
+
+ /** Get a single filter by block. */
+ bool LookupFilter(const CBlockIndex* block_index, BlockFilter& filter_out) const;
+
+ /** Get a single filter header by block. */
+ bool LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out) const;
+
+ /** Get a range of filters between two heights on a chain. */
+ bool LookupFilterRange(int start_height, const CBlockIndex* stop_index,
+ std::vector<BlockFilter>& filters_out) const;
+
+ /** Get a range of filter hashes between two heights on a chain. */
+ bool LookupFilterHashRange(int start_height, const CBlockIndex* stop_index,
+ std::vector<uint256>& hashes_out) const;
+};
+
+/**
+ * Get a block filter index by type. Returns nullptr if index has not been initialized or was
+ * already destroyed.
+ */
+BlockFilterIndex* GetBlockFilterIndex(BlockFilterType filter_type);
+
+/** Iterate over all running block filter indexes, invoking fn on each. */
+void ForEachBlockFilterIndex(std::function<void (BlockFilterIndex&)> fn);
+
+/**
+ * Initialize a block filter index for the given type if one does not already exist. Returns true if
+ * a new index is created and false if one has already been initialized.
+ */
+bool InitBlockFilterIndex(BlockFilterType filter_type,
+ size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
+
+/**
+ * Destroy the block filter index with the given type. Returns false if no such index exists. This
+ * just releases the allocated memory and closes the database connection, it does not delete the
+ * index data.
+ */
+bool DestroyBlockFilterIndex(BlockFilterType filter_type);
+
+/** Destroy all open block filter indexes. */
+void DestroyAllBlockFilterIndexes();
+
+#endif // BITCOIN_INDEX_BLOCKFILTERINDEX_H
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index c85030e18e..929b85bfb5 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -5,7 +5,7 @@
#include <index/txindex.h>
#include <shutdown.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <boost/thread.hpp>
@@ -16,7 +16,7 @@ constexpr char DB_TXINDEX_BLOCK = 'T';
std::unique_ptr<TxIndex> g_txindex;
-struct CDiskTxPos : public CDiskBlockPos
+struct CDiskTxPos : public FlatFilePos
{
unsigned int nTxOffset; // after header
@@ -24,11 +24,11 @@ struct CDiskTxPos : public CDiskBlockPos
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITEAS(CDiskBlockPos, *this);
+ READWRITEAS(FlatFilePos, *this);
READWRITE(VARINT(nTxOffset));
}
- CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
+ CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
}
CDiskTxPos() {
@@ -36,7 +36,7 @@ struct CDiskTxPos : public CDiskBlockPos
}
void SetNull() {
- CDiskBlockPos::SetNull();
+ FlatFilePos::SetNull();
nTxOffset = 0;
}
};
@@ -236,7 +236,7 @@ bool TxIndex::Init()
// Attempt to migrate txindex from the old database to the new one. Even if
// chain_tip is null, the node could be reindexing and we still want to
// delete txindex records in the old database.
- if (!m_db->MigrateData(*pblocktree, chainActive.GetLocator())) {
+ if (!m_db->MigrateData(*pblocktree, ::ChainActive().GetLocator())) {
return false;
}
@@ -245,12 +245,15 @@ bool TxIndex::Init()
bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
{
+ // Exclude genesis block transaction because outputs are not spendable.
+ if (pindex->nHeight == 0) return true;
+
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
std::vector<std::pair<uint256, CDiskTxPos>> vPos;
vPos.reserve(block.vtx.size());
for (const auto& tx : block.vtx) {
vPos.emplace_back(tx->GetHash(), pos);
- pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION);
+ pos.nTxOffset += ::GetSerializeSize(*tx, CLIENT_VERSION);
}
return m_db->WriteTxs(vPos);
}
diff --git a/src/init.cpp b/src/init.cpp
index feb5ff2c5e..b4b4ccb654 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -11,14 +11,17 @@
#include <addrman.h>
#include <amount.h>
+#include <banman.h>
+#include <blockfilter.h>
#include <chain.h>
#include <chainparams.h>
-#include <checkpoints.h>
#include <compat/sanity.h>
#include <consensus/validation.h>
#include <fs.h>
#include <httpserver.h>
#include <httprpc.h>
+#include <index/blockfilterindex.h>
+#include <interfaces/chain.h>
#include <index/txindex.h>
#include <key.h>
#include <validation.h>
@@ -29,20 +32,24 @@
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
+#include <policy/settings.h>
#include <rpc/server.h>
#include <rpc/register.h>
#include <rpc/blockchain.h>
+#include <rpc/util.h>
#include <script/standard.h>
#include <script/sigcache.h>
#include <scheduler.h>
#include <shutdown.h>
+#include <util/threadnames.h>
#include <timedata.h>
#include <txdb.h>
#include <txmempool.h>
#include <torcontrol.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/validation.h>
#include <validationinterface.h>
#include <warnings.h>
#include <walletinitinterface.h>
@@ -50,18 +57,19 @@
#include <stdio.h>
#ifndef WIN32
+#include <attributes.h>
+#include <cerrno>
#include <signal.h>
+#include <sys/stat.h>
#endif
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
-#include <boost/bind.hpp>
-#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/thread.hpp>
-#include <openssl/crypto.h>
#if ENABLE_ZMQ
+#include <zmq/zmqabstractnotifier.h>
#include <zmq/zmqnotificationinterface.h>
#include <zmq/zmqrpc.h>
#endif
@@ -71,35 +79,12 @@ static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
+// Dump addresses to banlist.dat every 15 minutes (900s)
+static constexpr int DUMP_BANS_INTERVAL = 60 * 15;
+
std::unique_ptr<CConnman> g_connman;
std::unique_ptr<PeerLogicValidation> peerLogic;
-
-#if !(ENABLE_WALLET)
-class DummyWalletInit : public WalletInitInterface {
-public:
-
- void AddWalletOptions() const override;
- bool ParameterInteraction() const override {return true;}
- void RegisterRPC(CRPCTable &) const override {}
- bool Verify() const override {return true;}
- bool Open() const override {LogPrintf("No wallet support compiled in!\n"); return true;}
- void Start(CScheduler& scheduler) const override {}
- void Flush() const override {}
- void Stop() const override {}
- void Close() const override {}
-};
-
-void DummyWalletInit::AddWalletOptions() const
-{
- std::vector<std::string> opts = {"-addresstype", "-changetype", "-disablewallet", "-discardfee=<amt>", "-fallbackfee=<amt>",
- "-keypool=<n>", "-mintxfee=<amt>", "-paytxfee=<amt>", "-rescan", "-salvagewallet", "-spendzeroconfchange", "-txconfirmtarget=<n>",
- "-upgradewallet", "-wallet=<path>", "-walletbroadcast", "-walletdir=<dir>", "-walletnotify=<cmd>", "-walletrbf", "-zapwallettxes=<mode>",
- "-dblogsize=<n>", "-flushwallet", "-privdb", "-walletrejectlongchains"};
- gArgs.AddHiddenArgs(opts);
-}
-
-const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
-#endif
+std::unique_ptr<BanMan> g_banman;
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
@@ -112,6 +97,32 @@ const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
+/**
+ * The PID file facilities.
+ */
+static const char* BITCOIN_PID_FILENAME = "bitcoind.pid";
+
+static fs::path GetPidFile()
+{
+ return AbsPathForConfigVal(fs::path(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME)));
+}
+
+NODISCARD static bool CreatePidFile()
+{
+ FILE* file = fsbridge::fopen(GetPidFile(), "w");
+ if (file) {
+#ifdef WIN32
+ fprintf(file, "%d\n", GetCurrentProcessId());
+#else
+ fprintf(file, "%d\n", getpid());
+#endif
+ fclose(file);
+ return true;
+ } else {
+ return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno)));
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////
//
// Shutdown
@@ -181,9 +192,10 @@ void Interrupt()
if (g_txindex) {
g_txindex->Interrupt();
}
+ ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Interrupt(); });
}
-void Shutdown()
+void Shutdown(InitInterfaces& interfaces)
{
LogPrintf("%s: In progress...\n", __func__);
static CCriticalSection cs_Shutdown;
@@ -195,25 +207,24 @@ void Shutdown()
/// for example if the data directory was found to be locked.
/// Be sure that anything that writes files or flushes caches only does this if the respective
/// module was initialized.
- RenameThread("bitcoin-shutoff");
+ util::ThreadRename("shutoff");
mempool.AddTransactionsUpdated(1);
StopHTTPRPC();
StopREST();
StopRPC();
StopHTTPServer();
- g_wallet_init_interface.Flush();
+ for (const auto& client : interfaces.chain_clients) {
+ client->flush();
+ }
StopMapPort();
// Because these depend on each-other, we make sure that neither can be
// using the other before destroying them.
if (peerLogic) UnregisterValidationInterface(peerLogic.get());
if (g_connman) g_connman->Stop();
- peerLogic.reset();
- g_connman.reset();
- if (g_txindex) {
- g_txindex.reset();
- }
+ if (g_txindex) g_txindex->Stop();
+ ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Stop(); });
StopTorControl();
@@ -222,8 +233,16 @@ void Shutdown()
threadGroup.interrupt_all();
threadGroup.join_all();
- if (g_is_mempool_loaded && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
- DumpMempool();
+ // After the threads that potentially access these pointers have been stopped,
+ // destruct and reset all to nullptr.
+ peerLogic.reset();
+ g_connman.reset();
+ g_banman.reset();
+ g_txindex.reset();
+ DestroyAllBlockFilterIndexes();
+
+ if (::mempool.IsLoaded() && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
+ DumpMempool(::mempool);
}
if (fFeeEstimatesInitialized)
@@ -263,7 +282,9 @@ void Shutdown()
pcoinsdbview.reset();
pblocktree.reset();
}
- g_wallet_init_interface.Stop();
+ for (const auto& client : interfaces.chain_clients) {
+ client->stop();
+ }
#if ENABLE_ZMQ
if (g_zmq_notification_interface) {
@@ -273,17 +294,17 @@ void Shutdown()
}
#endif
-#ifndef WIN32
try {
- fs::remove(GetPidFile());
+ if (!fs::remove(GetPidFile())) {
+ LogPrintf("%s: Unable to remove PID file: File does not exist\n", __func__);
+ }
} catch (const fs::filesystem_error& e) {
- LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what());
+ LogPrintf("%s: Unable to remove PID file: %s\n", __func__, fsbridge::get_filesystem_error_message(e));
}
-#endif
+ interfaces.chain_clients.clear();
UnregisterAllValidationInterfaces();
GetMainSignals().UnregisterBackgroundSignalScheduler();
GetMainSignals().UnregisterWithMempoolSignals(mempool);
- g_wallet_init_interface.Close();
globalVerifyHandle.reset();
ECC_Stop();
LogPrintf("%s: done\n", __func__);
@@ -302,7 +323,7 @@ static void HandleSIGTERM(int)
static void HandleSIGHUP(int)
{
- g_logger->m_reopen_file = true;
+ LogInstance().m_reopen_file = true;
}
#else
static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType)
@@ -324,14 +345,15 @@ static void registerSignalHandler(int signal, void(*handler)(int))
}
#endif
+static boost::signals2::connection rpc_notify_block_change_connection;
static void OnRPCStarted()
{
- uiInterface.NotifyBlockTip.connect(&RPCNotifyBlockChange);
+ rpc_notify_block_change_connection = uiInterface.NotifyBlockTip_connect(&RPCNotifyBlockChange);
}
static void OnRPCStopped()
{
- uiInterface.NotifyBlockTip.disconnect(&RPCNotifyBlockChange);
+ rpc_notify_block_change_connection.disconnect();
RPCNotifyBlockChange(false, nullptr);
g_best_block_cv.notify_all();
LogPrint(BCLog::RPC, "RPC stopped.\n");
@@ -339,32 +361,34 @@ static void OnRPCStopped()
void SetupServerArgs()
{
+ SetupHelpOptions(gArgs);
+ gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", false, OptionsCategory::DEBUG_TEST); // server-only for now
+
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
+ const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
const auto testnetChainParams = CreateChainParams(CBaseChainParams::TESTNET);
+ const auto regtestChainParams = CreateChainParams(CBaseChainParams::REGTEST);
// Hidden Options
- std::vector<std::string> hidden_args = {"-rpcssl", "-benchmark", "-h", "-help", "-socks", "-tor", "-debugnet", "-whitelistalwaysrelay",
- "-prematurewitness", "-walletprematurewitness", "-promiscuousmempoolflags", "-blockminsize", "-dbcrashratio", "-forcecompactdb", "-usehd",
+ std::vector<std::string> hidden_args = {
+ "-dbcrashratio", "-forcecompactdb",
// GUI args. These will be overwritten by SetupUIArgs for the GUI
"-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"};
- // Set all of the args and their help
- // When adding new options to the categories, please keep and ensure alphabetical ordering.
- gArgs.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-version", "Print version and exit", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-alertnotify=<cmd>", "Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-assumevalid=<hex>", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-blocksdir=<dir>", "Specify blocks directory (default: <datadir>/blocks)", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blocksdir=<dir>", "Specify directory to hold blocks subdirectory for *.dat files (default: <datadir>)", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-blockreconstructionextratxn=<n>", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-blocksonly", strprintf("Whether to operate in a blocks only mode (default: %u)", DEFAULT_BLOCKSONLY), true, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Transactions from the wallet or RPC are not affected. (default: %u)", DEFAULT_BLOCKSONLY), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), true, OptionsCategory::OPTIONS);
- gArgs.AddArg("-dbcache=<n>", strprintf("Set database cache size in megabytes (%d to %d, default: %d)", nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (0 to disable; default: %s)", DEFAULT_DEBUGLOGFILE), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (%d to %d, default: %d). In addition, unused mempool memory is shared for this cache (see -maxmempool).", nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (-nodebuglogfile to disable; default: %s)", DEFAULT_DEBUGLOGFILE), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER), true, OptionsCategory::OPTIONS);
gArgs.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-loadblock=<file>", "Imports blocks from external blk000??.dat file on startup", false, OptionsCategory::OPTIONS);
@@ -375,28 +399,28 @@ void SetupServerArgs()
gArgs.AddArg("-par=<n>", strprintf("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)",
-GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), false, OptionsCategory::OPTIONS);
-#ifndef WIN32
gArgs.AddArg("-pid=<file>", strprintf("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", BITCOIN_PID_FILENAME), false, OptionsCategory::OPTIONS);
-#else
- hidden_args.emplace_back("-pid");
-#endif
gArgs.AddArg("-prune=<n>", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. "
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
- "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), false, OptionsCategory::OPTIONS);
+ "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-reindex", "Rebuild chain state and block index from the blk*.dat files on disk", false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks. When in pruning mode or if blocks on disk might be corrupted, use full -reindex instead.", false, OptionsCategory::OPTIONS);
#ifndef WIN32
gArgs.AddArg("-sysperms", "Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)", false, OptionsCategory::OPTIONS);
#else
hidden_args.emplace_back("-sysperms");
#endif
gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blockfilterindex=<type>",
+ strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) +
+ " If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.",
+ false, OptionsCategory::OPTIONS);
gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-bantime=<n>", strprintf("Number of seconds to keep misbehaving peers from reconnecting (default: %u)", DEFAULT_MISBEHAVING_BANTIME), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6", false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-connect=<ip>", "Connect only to the specified node; -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-dnsseed", "Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)", false, OptionsCategory::CONNECTION);
@@ -410,15 +434,16 @@ void SetupServerArgs()
gArgs.AddArg("-maxsendbuffer=<n>", strprintf("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-maxtimeadjustment", strprintf("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)", DEFAULT_MAX_TIME_ADJUSTMENT), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)", DEFAULT_MAX_UPLOAD_TARGET), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor hidden services, set -noonion to disable (default: -proxy)", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-onlynet=<net>", "Make outgoing connections only through network <net> (ipv4, ipv6 or onion). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u or testnet: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-proxy=<ip:port>", "Connect through SOCKS5 proxy", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet: %u, regtest: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-proxy=<ip:port>", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled)", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-timeout=<n>", strprintf("Specify connection timeout in milliseconds (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-peertimeout=<n>", strprintf("Specify p2p connection timeout in seconds. This option determines the amount of time a peer may be inactive before the connection to it is dropped. (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), true, OptionsCategory::CONNECTION);
gArgs.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", false, OptionsCategory::CONNECTION);
#ifdef USE_UPNP
@@ -432,7 +457,7 @@ void SetupServerArgs()
#endif
gArgs.AddArg("-whitebind=<addr>", "Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-whitelist=<IP address or network>", "Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times."
- " Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway", false, OptionsCategory::CONNECTION);
+ " Whitelisted peers cannot be DoS banned", false, OptionsCategory::CONNECTION);
g_wallet_init_interface.AddWalletOptions();
@@ -441,17 +466,32 @@ void SetupServerArgs()
gArgs.AddArg("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>", false, OptionsCategory::ZMQ);
gArgs.AddArg("-zmqpubrawblock=<address>", "Enable publish raw block in <address>", false, OptionsCategory::ZMQ);
gArgs.AddArg("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>", false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubhashblockhwm=<n>", strprintf("Set publish hash block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubhashtxhwm=<n>", strprintf("Set publish hash transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubrawblockhwm=<n>", strprintf("Set publish raw block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubrawtxhwm=<n>", strprintf("Set publish raw transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), false, OptionsCategory::ZMQ);
#else
hidden_args.emplace_back("-zmqpubhashblock=<address>");
hidden_args.emplace_back("-zmqpubhashtx=<address>");
hidden_args.emplace_back("-zmqpubrawblock=<address>");
hidden_args.emplace_back("-zmqpubrawtx=<address>");
+ hidden_args.emplace_back("-zmqpubhashblockhwm=<n>");
+ hidden_args.emplace_back("-zmqpubhashtxhwm=<n>");
+ hidden_args.emplace_back("-zmqpubrawblockhwm=<n>");
+ hidden_args.emplace_back("-zmqpubrawtxhwm=<n>");
#endif
gArgs.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is (0-4, default: %u)", DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. (default: %u)", defaultChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is: "
+ "level 0 reads the blocks from disk, "
+ "level 1 verifies block validity, "
+ "level 2 verifies undo data, "
+ "level 3 checks disconnection of tip blocks, "
+ "and level 4 tries to reconnect the blocks, "
+ "each level includes the checks of the previous levels "
+ "(0-4, default: %u)", DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, ::ChainActive() and mapBlocksUnlinked occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages", true, OptionsCategory::DEBUG_TEST);
@@ -461,22 +501,19 @@ void SetupServerArgs()
gArgs.AddArg("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)", true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-addrmantest", "Allows to test address relay on localhost", true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-debug=<category>", strprintf("Output debugging information (default: %u, supplying <category> is optional)", 0) + ". " +
+ gArgs.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). "
"If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + ListLogCategories() + ".", false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."), false, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-help-debug", "Show all debugging options (usage: --help -help-debug)", false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-logthreadnames", strprintf("Prepend debug output with name of the originating thread (only available on platforms supporting thread_local) (default: %u)", DEFAULT_LOGTHREADNAMES), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-mocktime=<n>", "Replace actual time with <n> seconds since epoch (default: 0)", true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-maxtxfee=<amt>", strprintf("Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)",
- CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-printpriority", strprintf("Log transaction fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -daemon. To disable logging to file, set debuglogfile=0)", false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -daemon. To disable logging to file, set -nodebuglogfile)", false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-shrinkdebugfile", "Shrink debug.log file on client startup (default: 1 when no -debug)", false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", false, OptionsCategory::DEBUG_TEST);
@@ -484,14 +521,14 @@ void SetupServerArgs()
gArgs.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !testnetChainParams->RequireStandard()), true, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), true, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to defined dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), true, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), true, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), false, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), false, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), false, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-mempoolreplacement", strprintf("Enable transaction replacement in the memory pool (default: %u)", DEFAULT_ENABLE_REPLACEMENT), false, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), false, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-whitelistforcerelay", strprintf("Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)", DEFAULT_WHITELISTFORCERELAY), false, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-whitelistforcerelay", strprintf("Force relay of transactions from whitelisted peers even if the transactions were already in the mempool or violate local relay policy (default: %d)", DEFAULT_WHITELISTFORCERELAY), false, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-whitelistrelay", strprintf("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), false, OptionsCategory::NODE_RELAY);
@@ -501,11 +538,11 @@ void SetupServerArgs()
gArgs.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), false, OptionsCategory::RPC);
gArgs.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", false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcauth=<userpw>", "Username and 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", false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)", false, OptionsCategory::RPC);
+ gArgs.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", false, OptionsCategory::RPC);
+ gArgs.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)", false, OptionsCategory::RPC);
gArgs.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", false, OptionsCategory::RPC);
gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), false, OptionsCategory::RPC);
gArgs.AddArg("-rpcserialversion", strprintf("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)", DEFAULT_RPC_SERIALIZE_VERSION), false, OptionsCategory::RPC);
gArgs.AddArg("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT), true, OptionsCategory::RPC);
gArgs.AddArg("-rpcthreads=<n>", strprintf("Set the number of threads to service RPC calls (default: %d)", DEFAULT_HTTP_THREADS), false, OptionsCategory::RPC);
@@ -559,17 +596,17 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex
}
static bool fHaveGenesis = false;
-static CWaitableCriticalSection cs_GenesisWait;
-static CConditionVariable condvar_GenesisWait;
+static Mutex g_genesis_wait_mutex;
+static std::condition_variable g_genesis_wait_cv;
static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex)
{
if (pBlockIndex != nullptr) {
{
- WaitableLock lock_GenesisWait(cs_GenesisWait);
+ LOCK(g_genesis_wait_mutex);
fHaveGenesis = true;
}
- condvar_GenesisWait.notify_all();
+ g_genesis_wait_cv.notify_all();
}
}
@@ -631,7 +668,7 @@ static void CleanupBlockRevFiles()
static void ThreadImport(std::vector<fs::path> vImportFiles)
{
const CChainParams& chainparams = Params();
- RenameThread("bitcoin-loadblk");
+ util::ThreadRename("loadblk");
ScheduleBatchPriority();
{
@@ -641,8 +678,8 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
if (fReindex) {
int nFile = 0;
while (true) {
- CDiskBlockPos pos(nFile, 0);
- if (!fs::exists(GetBlockPosFilename(pos, "blk")))
+ FlatFilePos pos(nFile, 0);
+ if (!fs::exists(GetBlockPosFilename(pos)))
break; // No block files left to reindex
FILE *file = OpenBlockFile(pos, true);
if (!file)
@@ -698,16 +735,16 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
}
} // End scope of CImportingNow
if (gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
- LoadMempool();
+ LoadMempool(::mempool);
}
- g_is_mempool_loaded = !ShutdownRequested();
+ ::mempool.SetIsLoaded(!ShutdownRequested());
}
/** Sanity checks
* Ensure that Bitcoin is running in a usable environment with all
* necessary library support.
*/
-static bool InitSanityCheck(void)
+static bool InitSanityCheck()
{
if(!ECC_InitSanityCheck()) {
InitError("Elliptic curve cryptography sanity check failure. Aborting.");
@@ -734,8 +771,7 @@ static bool AppInitServers()
StartRPC();
if (!StartHTTPRPC())
return false;
- if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST())
- return false;
+ if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE)) StartREST();
StartHTTPServer();
return true;
}
@@ -802,11 +838,6 @@ void InitParameterInteraction()
if (gArgs.SoftSetBoolArg("-whitelistrelay", true))
LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__);
}
-
- // Warn if network-specific options (-addnode, -connect, etc) are
- // specified in default section of config file, but not overridden
- // on the command line or in this network's section of the config file.
- gArgs.WarnForSectionOnlyArgs();
}
static std::string ResolveErrMsg(const char * const optname, const std::string& strBind)
@@ -822,17 +853,18 @@ static std::string ResolveErrMsg(const char * const optname, const std::string&
*/
void InitLogging()
{
- g_logger->m_print_to_file = !gArgs.IsArgNegated("-debuglogfile");
- g_logger->m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
+ LogInstance().m_print_to_file = !gArgs.IsArgNegated("-debuglogfile");
+ LogInstance().m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
// Add newlines to the logfile to distinguish this execution from the last
// one; called before console logging is set up, so this is only sent to
// debug.log.
LogPrintf("\n\n\n\n\n");
- g_logger->m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
- g_logger->m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
- g_logger->m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
+ LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
+ LogInstance().m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
+ LogInstance().m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
+ LogInstance().m_log_threadnames = gArgs.GetBoolArg("-logthreadnames", DEFAULT_LOGTHREADNAMES);
fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);
@@ -851,6 +883,8 @@ int nMaxConnections;
int nUserMaxConnections;
int nFD;
ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED);
+int64_t peer_connect_timeout;
+std::vector<BlockFilterType> g_enabled_filter_types;
} // namespace
@@ -879,16 +913,7 @@ bool AppInitBasicSetup()
#endif
#ifdef WIN32
// Enable Data Execution Prevention (DEP)
- // Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008
- // A failure is non-critical and needs no further attention!
-#ifndef PROCESS_DEP_ENABLE
- // We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7),
- // which is not correct. Can be removed, when GCCs winbase.h is fixed!
-#define PROCESS_DEP_ENABLE 0x00000001
-#endif
- typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD);
- PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy");
- if (setProcDEPPol != nullptr) setProcDEPPol(PROCESS_DEP_ENABLE);
+ SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
#endif
if (!SetupNetworking())
@@ -924,14 +949,46 @@ bool AppInitParameterInteraction()
// also see: InitParameterInteraction()
- if (!fs::is_directory(GetBlocksDir(false))) {
+ // Warn if network-specific options (-addnode, -connect, etc) are
+ // specified in default section of config file, but not overridden
+ // on the command line or in this network's section of the config file.
+ std::string network = gArgs.GetChainName();
+ for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) {
+ return InitError(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network));
+ }
+
+ // Warn if unrecognized section name are present in the config file.
+ for (const auto& section : gArgs.GetUnrecognizedSections()) {
+ InitWarning(strprintf("%s:%i " + _("Section [%s] is not recognized."), section.m_file, section.m_line, section.m_name));
+ }
+
+ if (!fs::is_directory(GetBlocksDir())) {
return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str()));
}
+ // parse and validate enabled filter types
+ std::string blockfilterindex_value = gArgs.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX);
+ if (blockfilterindex_value == "" || blockfilterindex_value == "1") {
+ g_enabled_filter_types = AllBlockFilterTypes();
+ } else if (blockfilterindex_value != "0") {
+ const std::vector<std::string> names = gArgs.GetArgs("-blockfilterindex");
+ g_enabled_filter_types.reserve(names.size());
+ for (const auto& name : names) {
+ BlockFilterType filter_type;
+ if (!BlockFilterTypeByName(name, filter_type)) {
+ return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name));
+ }
+ g_enabled_filter_types.push_back(filter_type);
+ }
+ }
+
// if using block pruning, then disallow txindex
if (gArgs.GetArg("-prune", 0)) {
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX))
return InitError(_("Prune mode is incompatible with -txindex."));
+ if (!g_enabled_filter_types.empty()) {
+ return InitError(_("Prune mode is incompatible with -blockfilterindex."));
+ }
}
// -bind and -whitebind can't be set when not listening
@@ -947,8 +1004,13 @@ bool AppInitParameterInteraction()
// Trim requested connection counts, to fit into system limitations
// <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695
- nMaxConnections = std::max(std::min<int>(nMaxConnections, FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0);
nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS);
+#ifdef USE_POLL
+ int fd_max = nFD;
+#else
+ int fd_max = FD_SETSIZE;
+#endif
+ nMaxConnections = std::max(std::min<int>(nMaxConnections, fd_max - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0);
if (nFD < MIN_CORE_FILEDESCRIPTORS)
return InitError(_("Not enough file descriptors available."));
nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections);
@@ -964,7 +1026,7 @@ bool AppInitParameterInteraction()
if (std::none_of(categories.begin(), categories.end(),
[](std::string cat){return cat == "0" || cat == "none";})) {
for (const auto& cat : categories) {
- if (!g_logger->EnableCategory(cat)) {
+ if (!LogInstance().EnableCategory(cat)) {
InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat));
}
}
@@ -973,30 +1035,11 @@ bool AppInitParameterInteraction()
// Now remove the logging categories which were explicitly excluded
for (const std::string& cat : gArgs.GetArgs("-debugexclude")) {
- if (!g_logger->DisableCategory(cat)) {
+ if (!LogInstance().DisableCategory(cat)) {
InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat));
}
}
- // Check for -debugnet
- if (gArgs.GetBoolArg("-debugnet", false))
- InitWarning(_("Unsupported argument -debugnet ignored, use -debug=net."));
- // Check for -socks - as this is a privacy risk to continue, exit here
- if (gArgs.IsArgSet("-socks"))
- return InitError(_("Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
- // Check for -tor - as this is a privacy risk to continue, exit here
- if (gArgs.GetBoolArg("-tor", false))
- return InitError(_("Unsupported argument -tor found, use -onion."));
-
- if (gArgs.GetBoolArg("-benchmark", false))
- InitWarning(_("Unsupported argument -benchmark ignored, use -debug=bench."));
-
- if (gArgs.GetBoolArg("-whitelistalwaysrelay", false))
- InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay."));
-
- if (gArgs.IsArgSet("-blockminsize"))
- InitWarning("Unsupported argument -blockminsize ignored.");
-
// Checkmempool and checkblockindex default to true in regtest mode
int ratio = std::min<int>(std::max<int>(gArgs.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
if (ratio != 0) {
@@ -1063,13 +1106,19 @@ bool AppInitParameterInteraction()
if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) {
return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
}
- LogPrintf("Prune configured to target %uMiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);
+ LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);
fPruneMode = true;
}
nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
- if (nConnectTimeout <= 0)
+ if (nConnectTimeout <= 0) {
nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
+ }
+
+ peer_connect_timeout = gArgs.GetArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT);
+ if (peer_connect_timeout <= 0) {
+ return InitError("peertimeout cannot be configured with a negative value.");
+ }
if (gArgs.IsArgSet("-minrelaytxfee")) {
CAmount n = 0;
@@ -1137,39 +1186,6 @@ bool AppInitParameterInteraction()
fEnableReplacement = (std::find(vstrReplacementModes.begin(), vstrReplacementModes.end(), "fee") != vstrReplacementModes.end());
}
- if (gArgs.IsArgSet("-vbparams")) {
- // Allow overriding version bits parameters for testing
- if (!chainparams.MineBlocksOnDemand()) {
- return InitError("Version bits parameters may only be overridden on regtest.");
- }
- for (const std::string& strDeployment : gArgs.GetArgs("-vbparams")) {
- std::vector<std::string> vDeploymentParams;
- boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":"));
- if (vDeploymentParams.size() != 3) {
- return InitError("Version bits parameters malformed, expecting deployment:start:end");
- }
- int64_t nStartTime, nTimeout;
- if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
- return InitError(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
- }
- if (!ParseInt64(vDeploymentParams[2], &nTimeout)) {
- return InitError(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2]));
- }
- bool found = false;
- for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j)
- {
- if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) {
- UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
- found = true;
- LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
- break;
- }
- }
- if (!found) {
- return InitError(strprintf("Invalid deployment (%s)", vDeploymentParams[0]));
- }
- }
- }
return true;
}
@@ -1219,30 +1235,43 @@ bool AppInitLockDataDirectory()
return true;
}
-bool AppInitMain()
+bool AppInitMain(InitInterfaces& interfaces)
{
const CChainParams& chainparams = Params();
// ********************************************************* Step 4a: application initialization
-#ifndef WIN32
- CreatePidFile(GetPidFile(), getpid());
-#endif
- if (g_logger->m_print_to_file) {
- if (gArgs.GetBoolArg("-shrinkdebugfile", g_logger->DefaultShrinkDebugFile())) {
+ if (!CreatePidFile()) {
+ // Detailed error printed inside CreatePidFile().
+ return false;
+ }
+ if (LogInstance().m_print_to_file) {
+ if (gArgs.GetBoolArg("-shrinkdebugfile", LogInstance().DefaultShrinkDebugFile())) {
// Do this first since it both loads a bunch of debug.log into memory,
// and because this needs to happen before any other debug.log printing
- g_logger->ShrinkDebugFile();
+ LogInstance().ShrinkDebugFile();
}
- if (!g_logger->OpenDebugLog()) {
+ if (!LogInstance().OpenDebugLog()) {
return InitError(strprintf("Could not open debug log file %s",
- g_logger->m_file_path.string()));
+ LogInstance().m_file_path.string()));
}
}
- if (!g_logger->m_log_timestamps)
+ if (!LogInstance().m_log_timestamps)
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", GetDataDir().string());
- LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string());
+
+ // Only log conf file usage message if conf file actually exists.
+ fs::path config_file_path = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
+ if (fs::exists(config_file_path)) {
+ LogPrintf("Config file: %s\n", config_file_path.string());
+ } else if (gArgs.IsArgSet("-conf")) {
+ // Warn if no conf file exists at path provided by user
+ InitWarning(strprintf(_("The specified config file %s does not exist\n"), config_file_path.string()));
+ } else {
+ // Not categorizing as "Warning" because it's the default behavior
+ LogPrintf("Config file: %s (not found, skipping)\n", config_file_path.string());
+ }
+
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
// Warn about relative -datadir path.
@@ -1260,21 +1289,30 @@ bool AppInitMain()
LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
if (nScriptCheckThreads) {
for (int i=0; i<nScriptCheckThreads-1; i++)
- threadGroup.create_thread(&ThreadScriptCheck);
+ threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
}
// Start the lightweight task scheduler thread
- CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler);
- threadGroup.create_thread(boost::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
+ CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
+ threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
GetMainSignals().RegisterWithMempoolSignals(mempool);
+ // Create client interfaces for wallets that are supposed to be loaded
+ // according to -wallet and -disablewallet options. This only constructs
+ // the interfaces, it doesn't load wallet data. Wallets actually get loaded
+ // when load() and start() interface methods are called below.
+ g_wallet_init_interface.Construct(interfaces);
+
/* Register RPC commands regardless of -server setting so they will be
* available in the GUI RPC console even if external calls are disabled.
*/
RegisterAllCoreRPCCommands(tableRPC);
- g_wallet_init_interface.RegisterRPC(tableRPC);
+ for (const auto& client : interfaces.chain_clients) {
+ client->registerRpcs();
+ }
+ g_rpc_interfaces = &interfaces;
#if ENABLE_ZMQ
RegisterZMQRPCCommands(tableRPC);
#endif
@@ -1286,13 +1324,17 @@ bool AppInitMain()
*/
if (gArgs.GetBoolArg("-server", false))
{
- uiInterface.InitMessage.connect(SetRPCWarmupStatus);
+ uiInterface.InitMessage_connect(SetRPCWarmupStatus);
if (!AppInitServers())
return InitError(_("Unable to start HTTP server. See debug log for details."));
}
// ********************************************************* Step 5: verify wallet database integrity
- if (!g_wallet_init_interface.Verify()) return false;
+ for (const auto& client : interfaces.chain_clients) {
+ if (!client->verify()) {
+ return false;
+ }
+ }
// ********************************************************* Step 6: network initialization
// Note that we absolutely cannot open any actual connections
@@ -1300,11 +1342,12 @@ bool AppInitMain()
// is not yet setup and may end up being set up twice if we
// need to reindex later.
+ assert(!g_banman);
+ g_banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
assert(!g_connman);
g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));
- CConnman& connman = *g_connman;
- peerLogic.reset(new PeerLogicValidation(&connman, scheduler, gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61)));
+ peerLogic.reset(new PeerLogicValidation(g_connman.get(), g_banman.get(), scheduler, gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61)));
RegisterValidationInterface(peerLogic.get());
// sanitize comments per BIP-0014, format user agent and check total size
@@ -1331,7 +1374,7 @@ bool AppInitMain()
for (int n = 0; n < NET_MAX; n++) {
enum Network net = (enum Network)n;
if (!nets.count(net))
- SetLimited(net);
+ SetReachable(net, false);
}
}
@@ -1342,7 +1385,7 @@ bool AppInitMain()
// -proxy sets a proxy for all outgoing network traffic
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
std::string proxyArg = gArgs.GetArg("-proxy", "");
- SetLimited(NET_ONION);
+ SetReachable(NET_ONION, false);
if (proxyArg != "" && proxyArg != "0") {
CService proxyAddr;
if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) {
@@ -1357,7 +1400,7 @@ bool AppInitMain()
SetProxy(NET_IPV6, addrProxy);
SetProxy(NET_ONION, addrProxy);
SetNameProxy(addrProxy);
- SetLimited(NET_ONION, false); // by default, -proxy sets onion as reachable, unless -noonion later
+ SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
}
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
@@ -1366,7 +1409,7 @@ bool AppInitMain()
std::string onionArg = gArgs.GetArg("-onion", "");
if (onionArg != "") {
if (onionArg == "0") { // Handle -noonion/-onion=0
- SetLimited(NET_ONION); // set onions as unreachable
+ SetReachable(NET_ONION, false);
} else {
CService onionProxy;
if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) {
@@ -1376,14 +1419,14 @@ bool AppInitMain()
if (!addrOnion.IsValid())
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
SetProxy(NET_ONION, addrOnion);
- SetLimited(NET_ONION, false);
+ SetReachable(NET_ONION, true);
}
}
// see Step 2: parameter interactions for more information about these
fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN);
fDiscover = gArgs.GetBoolArg("-discover", true);
- fRelayTxes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
+ g_relay_txes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
for (const std::string& strAddr : gArgs.GetArgs("-externalip")) {
CService addrLocal;
@@ -1420,18 +1463,29 @@ bool AppInitMain()
nTotalCache -= nBlockTreeDBCache;
int64_t nTxIndexCache = std::min(nTotalCache / 8, gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxTxIndexCache << 20 : 0);
nTotalCache -= nTxIndexCache;
+ int64_t filter_index_cache = 0;
+ if (!g_enabled_filter_types.empty()) {
+ size_t n_indexes = g_enabled_filter_types.size();
+ int64_t max_cache = std::min(nTotalCache / 8, max_filter_index_cache << 20);
+ filter_index_cache = max_cache / n_indexes;
+ nTotalCache -= filter_index_cache * n_indexes;
+ }
int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache
nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache
nTotalCache -= nCoinDBCache;
nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
LogPrintf("Cache configuration:\n");
- LogPrintf("* Using %.1fMiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024));
+ LogPrintf("* Using %.1f MiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024));
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
- LogPrintf("* Using %.1fMiB for transaction index database\n", nTxIndexCache * (1.0 / 1024 / 1024));
+ LogPrintf("* Using %.1f MiB for transaction index database\n", nTxIndexCache * (1.0 / 1024 / 1024));
+ }
+ for (BlockFilterType filter_type : g_enabled_filter_types) {
+ LogPrintf("* Using %.1f MiB for %s block filter index database\n",
+ filter_index_cache * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
}
- LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
- LogPrintf("* Using %.1fMiB for in-memory UTXO set (plus up to %.1fMiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
+ LogPrintf("* Using %.1f MiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
+ LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
bool fLoaded = false;
while (!fLoaded && !ShutdownRequested()) {
@@ -1440,11 +1494,11 @@ bool AppInitMain()
uiInterface.InitMessage(_("Loading block index..."));
- LOCK(cs_main);
-
do {
const int64_t load_block_index_start_time = GetTimeMillis();
+ bool is_coinsview_empty;
try {
+ LOCK(cs_main);
UnloadBlockIndex();
pcoinsTip.reset();
pcoinsdbview.reset();
@@ -1517,27 +1571,34 @@ bool AppInitMain()
// The on-disk coinsdb is now in a good state, create the cache
pcoinsTip.reset(new CCoinsViewCache(pcoinscatcher.get()));
- bool is_coinsview_empty = fReset || fReindexChainState || pcoinsTip->GetBestBlock().IsNull();
+ is_coinsview_empty = fReset || fReindexChainState || pcoinsTip->GetBestBlock().IsNull();
if (!is_coinsview_empty) {
- // LoadChainTip sets chainActive based on pcoinsTip's best block
+ // LoadChainTip sets ::ChainActive() based on pcoinsTip's best block
if (!LoadChainTip(chainparams)) {
strLoadError = _("Error initializing block database");
break;
}
- assert(chainActive.Tip() != nullptr);
+ assert(::ChainActive().Tip() != nullptr);
}
+ } catch (const std::exception& e) {
+ LogPrintf("%s\n", e.what());
+ strLoadError = _("Error opening block database");
+ break;
+ }
- if (!fReset) {
- // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
- // It both disconnects blocks based on chainActive, and drops block data in
- // mapBlockIndex based on lack of available witness data.
- uiInterface.InitMessage(_("Rewinding blocks..."));
- if (!RewindBlockIndex(chainparams)) {
- strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain");
- break;
- }
+ if (!fReset) {
+ // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
+ // It both disconnects blocks based on ::ChainActive(), and drops block data in
+ // mapBlockIndex based on lack of available witness data.
+ uiInterface.InitMessage(_("Rewinding blocks..."));
+ if (!RewindBlockIndex(chainparams)) {
+ strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain");
+ break;
}
+ }
+ try {
+ LOCK(cs_main);
if (!is_coinsview_empty) {
uiInterface.InitMessage(_("Verifying blocks..."));
if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
@@ -1545,7 +1606,7 @@ bool AppInitMain()
MIN_BLOCKS_TO_KEEP);
}
- CBlockIndex* tip = chainActive.Tip();
+ CBlockIndex* tip = ::ChainActive().Tip();
RPCNotifyBlockChange(true, tip);
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
strLoadError = _("The block database contains a block which appears to be from the future. "
@@ -1611,8 +1672,17 @@ bool AppInitMain()
g_txindex->Start();
}
+ for (const auto& filter_type : g_enabled_filter_types) {
+ InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex);
+ GetBlockFilterIndex(filter_type)->Start();
+ }
+
// ********************************************************* Step 9: load wallet
- if (!g_wallet_init_interface.Open()) return false;
+ for (const auto& client : interfaces.chain_clients) {
+ if (!client->load()) {
+ return false;
+ }
+ }
// ********************************************************* Step 10: data directory maintenance
@@ -1638,37 +1708,44 @@ bool AppInitMain()
// ********************************************************* Step 11: import blocks
- if (!CheckDiskSpace() && !CheckDiskSpace(0, true))
+ if (!CheckDiskSpace(GetDataDir())) {
+ InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir()));
+ return false;
+ }
+ if (!CheckDiskSpace(GetBlocksDir())) {
+ InitError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir()));
return false;
+ }
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
// No locking, as this happens before any background thread is started.
- if (chainActive.Tip() == nullptr) {
- uiInterface.NotifyBlockTip.connect(BlockNotifyGenesisWait);
+ boost::signals2::connection block_notify_genesis_wait_connection;
+ if (::ChainActive().Tip() == nullptr) {
+ block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(BlockNotifyGenesisWait);
} else {
fHaveGenesis = true;
}
if (gArgs.IsArgSet("-blocknotify"))
- uiInterface.NotifyBlockTip.connect(BlockNotifyCallback);
+ uiInterface.NotifyBlockTip_connect(BlockNotifyCallback);
std::vector<fs::path> vImportFiles;
for (const std::string& strFile : gArgs.GetArgs("-loadblock")) {
vImportFiles.push_back(strFile);
}
- threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
+ threadGroup.create_thread(std::bind(&ThreadImport, vImportFiles));
// Wait for genesis block to be processed
{
- WaitableLock lock(cs_GenesisWait);
+ WAIT_LOCK(g_genesis_wait_mutex, lock);
// We previously could hang here if StartShutdown() is called prior to
// ThreadImport getting started, so instead we just wait on a timer to
// check ShutdownRequested() regularly.
while (!fHaveGenesis && !ShutdownRequested()) {
- condvar_GenesisWait.wait_for(lock, std::chrono::milliseconds(500));
+ g_genesis_wait_cv.wait_for(lock, std::chrono::milliseconds(500));
}
- uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait);
+ block_notify_genesis_wait_connection.disconnect();
}
if (ShutdownRequested()) {
@@ -1683,7 +1760,7 @@ bool AppInitMain()
{
LOCK(cs_main);
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
- chain_active_height = chainActive.Height();
+ chain_active_height = ::ChainActive().Height();
}
LogPrintf("nBestHeight = %d\n", chain_active_height);
@@ -1705,6 +1782,7 @@ bool AppInitMain()
connOptions.nMaxFeeler = 1;
connOptions.nBestHeight = chain_active_height;
connOptions.uiInterface = &uiInterface;
+ connOptions.m_banman = g_banman.get();
connOptions.m_msgproc = peerLogic.get();
connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
@@ -1712,6 +1790,7 @@ bool AppInitMain()
connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe;
connOptions.nMaxOutboundLimit = nMaxOutboundLimit;
+ connOptions.m_peer_connect_timeout = peer_connect_timeout;
for (const std::string& strBind : gArgs.GetArgs("-bind")) {
CService addrBind;
@@ -1749,7 +1828,7 @@ bool AppInitMain()
connOptions.m_specified_outgoing = connect;
}
}
- if (!connman.Start(scheduler, connOptions)) {
+ if (!g_connman->Start(scheduler, connOptions)) {
return false;
}
@@ -1758,7 +1837,13 @@ bool AppInitMain()
SetRPCWarmupFinished();
uiInterface.InitMessage(_("Done loading"));
- g_wallet_init_interface.Start(scheduler);
+ for (const auto& client : interfaces.chain_clients) {
+ client->start(scheduler);
+ }
+
+ scheduler.scheduleEvery([]{
+ g_banman->DumpBanlist();
+ }, DUMP_BANS_INTERVAL * 1000);
return true;
}
diff --git a/src/init.h b/src/init.h
index 0c85d3c9dc..1c59ca069e 100644
--- a/src/init.h
+++ b/src/init.h
@@ -8,13 +8,19 @@
#include <memory>
#include <string>
-#include <util.h>
+#include <util/system.h>
-class CScheduler;
-class CWallet;
+namespace interfaces {
+class Chain;
+class ChainClient;
+} // namespace interfaces
-class WalletInitInterface;
-extern const WalletInitInterface& g_wallet_init_interface;
+//! Pointers to interfaces used during init and destroyed on shutdown.
+struct InitInterfaces
+{
+ std::unique_ptr<interfaces::Chain> chain;
+ std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
+};
namespace boost
{
@@ -23,7 +29,7 @@ class thread_group;
/** Interrupt threads */
void Interrupt();
-void Shutdown();
+void Shutdown(InitInterfaces& interfaces);
//!Initialize the logging infrastructure
void InitLogging();
//!Parameter interaction: change current parameters depending on various rules
@@ -57,7 +63,7 @@ bool AppInitLockDataDirectory();
* @note This should only be done after daemonization. Call Shutdown() if this function fails.
* @pre Parameters should be parsed and config file should be read, AppInitLockDataDirectory should have been called.
*/
-bool AppInitMain();
+bool AppInitMain(InitInterfaces& interfaces);
/**
* Setup the arguments for gArgs
diff --git a/src/interfaces/README.md b/src/interfaces/README.md
index e93b91d23c..f77d172153 100644
--- a/src/interfaces/README.md
+++ b/src/interfaces/README.md
@@ -2,9 +2,9 @@
The following interfaces are defined here:
-* [`Chain`](chain.h) — used by wallet to access blockchain and mempool state. Added in [#10973](https://github.com/bitcoin/bitcoin/pull/10973).
+* [`Chain`](chain.h) — used by wallet to access blockchain and mempool state. Added in [#14437](https://github.com/bitcoin/bitcoin/pull/14437), [#14711](https://github.com/bitcoin/bitcoin/pull/14711), [#15288](https://github.com/bitcoin/bitcoin/pull/15288), and [#10973](https://github.com/bitcoin/bitcoin/pull/10973).
-* [`Chain::Client`](chain.h) — used by node to start & stop `Chain` clients. Added in [#10973](https://github.com/bitcoin/bitcoin/pull/10973).
+* [`ChainClient`](chain.h) — used by node to start & stop `Chain` clients. Added in [#14437](https://github.com/bitcoin/bitcoin/pull/14437).
* [`Node`](node.h) — used by GUI to start & stop bitcoin node. Added in [#10244](https://github.com/bitcoin/bitcoin/pull/10244).
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
new file mode 100644
index 0000000000..6097d80931
--- /dev/null
+++ b/src/interfaces/chain.cpp
@@ -0,0 +1,385 @@
+// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <interfaces/chain.h>
+
+#include <chain.h>
+#include <chainparams.h>
+#include <interfaces/handler.h>
+#include <interfaces/wallet.h>
+#include <net.h>
+#include <node/coin.h>
+#include <policy/fees.h>
+#include <policy/policy.h>
+#include <policy/rbf.h>
+#include <policy/settings.h>
+#include <primitives/block.h>
+#include <primitives/transaction.h>
+#include <protocol.h>
+#include <rpc/protocol.h>
+#include <rpc/server.h>
+#include <shutdown.h>
+#include <sync.h>
+#include <threadsafety.h>
+#include <timedata.h>
+#include <txmempool.h>
+#include <ui_interface.h>
+#include <uint256.h>
+#include <univalue.h>
+#include <util/system.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+#include <memory>
+#include <utility>
+
+namespace interfaces {
+namespace {
+
+class LockImpl : public Chain::Lock, public UniqueLock<CCriticalSection>
+{
+ Optional<int> getHeight() override
+ {
+ LockAnnotation lock(::cs_main);
+ int height = ::ChainActive().Height();
+ if (height >= 0) {
+ return height;
+ }
+ return nullopt;
+ }
+ Optional<int> getBlockHeight(const uint256& hash) override
+ {
+ LockAnnotation lock(::cs_main);
+ CBlockIndex* block = LookupBlockIndex(hash);
+ if (block && ::ChainActive().Contains(block)) {
+ return block->nHeight;
+ }
+ return nullopt;
+ }
+ int getBlockDepth(const uint256& hash) override
+ {
+ const Optional<int> tip_height = getHeight();
+ const Optional<int> height = getBlockHeight(hash);
+ return tip_height && height ? *tip_height - *height + 1 : 0;
+ }
+ uint256 getBlockHash(int height) override
+ {
+ LockAnnotation lock(::cs_main);
+ CBlockIndex* block = ::ChainActive()[height];
+ assert(block != nullptr);
+ return block->GetBlockHash();
+ }
+ int64_t getBlockTime(int height) override
+ {
+ LockAnnotation lock(::cs_main);
+ CBlockIndex* block = ::ChainActive()[height];
+ assert(block != nullptr);
+ return block->GetBlockTime();
+ }
+ int64_t getBlockMedianTimePast(int height) override
+ {
+ LockAnnotation lock(::cs_main);
+ CBlockIndex* block = ::ChainActive()[height];
+ assert(block != nullptr);
+ return block->GetMedianTimePast();
+ }
+ bool haveBlockOnDisk(int height) override
+ {
+ LockAnnotation lock(::cs_main);
+ CBlockIndex* block = ::ChainActive()[height];
+ return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
+ }
+ Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
+ {
+ LockAnnotation lock(::cs_main);
+ CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
+ if (block) {
+ if (hash) *hash = block->GetBlockHash();
+ return block->nHeight;
+ }
+ return nullopt;
+ }
+ Optional<int> findPruned(int start_height, Optional<int> stop_height) override
+ {
+ LockAnnotation lock(::cs_main);
+ if (::fPruneMode) {
+ CBlockIndex* block = stop_height ? ::ChainActive()[*stop_height] : ::ChainActive().Tip();
+ while (block && block->nHeight >= start_height) {
+ if ((block->nStatus & BLOCK_HAVE_DATA) == 0) {
+ return block->nHeight;
+ }
+ block = block->pprev;
+ }
+ }
+ return nullopt;
+ }
+ Optional<int> findFork(const uint256& hash, Optional<int>* height) override
+ {
+ LockAnnotation lock(::cs_main);
+ const CBlockIndex* block = LookupBlockIndex(hash);
+ const CBlockIndex* fork = block ? ::ChainActive().FindFork(block) : nullptr;
+ if (height) {
+ if (block) {
+ *height = block->nHeight;
+ } else {
+ height->reset();
+ }
+ }
+ if (fork) {
+ return fork->nHeight;
+ }
+ return nullopt;
+ }
+ CBlockLocator getTipLocator() override
+ {
+ LockAnnotation lock(::cs_main);
+ return ::ChainActive().GetLocator();
+ }
+ Optional<int> findLocatorFork(const CBlockLocator& locator) override
+ {
+ LockAnnotation lock(::cs_main);
+ if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
+ return fork->nHeight;
+ }
+ return nullopt;
+ }
+ bool checkFinalTx(const CTransaction& tx) override
+ {
+ LockAnnotation lock(::cs_main);
+ return CheckFinalTx(tx);
+ }
+ bool submitToMemoryPool(const CTransactionRef& tx, CAmount absurd_fee, CValidationState& state) override
+ {
+ LockAnnotation lock(::cs_main);
+ return AcceptToMemoryPool(::mempool, state, tx, nullptr /* missing inputs */, nullptr /* txn replaced */,
+ false /* bypass limits */, absurd_fee);
+ }
+
+ using UniqueLock::UniqueLock;
+};
+
+class NotificationsHandlerImpl : public Handler, CValidationInterface
+{
+public:
+ explicit NotificationsHandlerImpl(Chain& chain, Chain::Notifications& notifications)
+ : m_chain(chain), m_notifications(&notifications)
+ {
+ RegisterValidationInterface(this);
+ }
+ ~NotificationsHandlerImpl() override { disconnect(); }
+ void disconnect() override
+ {
+ if (m_notifications) {
+ m_notifications = nullptr;
+ UnregisterValidationInterface(this);
+ }
+ }
+ void TransactionAddedToMempool(const CTransactionRef& tx) override
+ {
+ m_notifications->TransactionAddedToMempool(tx);
+ }
+ void TransactionRemovedFromMempool(const CTransactionRef& tx) override
+ {
+ m_notifications->TransactionRemovedFromMempool(tx);
+ }
+ void BlockConnected(const std::shared_ptr<const CBlock>& block,
+ const CBlockIndex* index,
+ const std::vector<CTransactionRef>& tx_conflicted) override
+ {
+ m_notifications->BlockConnected(*block, tx_conflicted);
+ }
+ void BlockDisconnected(const std::shared_ptr<const CBlock>& block) override
+ {
+ m_notifications->BlockDisconnected(*block);
+ }
+ void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
+ {
+ m_notifications->UpdatedBlockTip();
+ }
+ void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->ChainStateFlushed(locator); }
+ Chain& m_chain;
+ Chain::Notifications* m_notifications;
+};
+
+class RpcHandlerImpl : public Handler
+{
+public:
+ RpcHandlerImpl(const CRPCCommand& command) : m_command(command), m_wrapped_command(&command)
+ {
+ m_command.actor = [this](const JSONRPCRequest& request, UniValue& result, bool last_handler) {
+ if (!m_wrapped_command) return false;
+ try {
+ return m_wrapped_command->actor(request, result, last_handler);
+ } catch (const UniValue& e) {
+ // If this is not the last handler and a wallet not found
+ // exception was thrown, return false so the next handler can
+ // try to handle the request. Otherwise, reraise the exception.
+ if (!last_handler) {
+ const UniValue& code = e["code"];
+ if (code.isNum() && code.get_int() == RPC_WALLET_NOT_FOUND) {
+ return false;
+ }
+ }
+ throw;
+ }
+ };
+ ::tableRPC.appendCommand(m_command.name, &m_command);
+ }
+
+ void disconnect() override final
+ {
+ if (m_wrapped_command) {
+ m_wrapped_command = nullptr;
+ ::tableRPC.removeCommand(m_command.name, &m_command);
+ }
+ }
+
+ ~RpcHandlerImpl() override { disconnect(); }
+
+ CRPCCommand m_command;
+ const CRPCCommand* m_wrapped_command;
+};
+
+class ChainImpl : public Chain
+{
+public:
+ std::unique_ptr<Chain::Lock> lock(bool try_lock) override
+ {
+ auto result = MakeUnique<LockImpl>(::cs_main, "cs_main", __FILE__, __LINE__, try_lock);
+ if (try_lock && result && !*result) return {};
+ // std::move necessary on some compilers due to conversion from
+ // LockImpl to Lock pointer
+ return std::move(result);
+ }
+ bool findBlock(const uint256& hash, CBlock* block, int64_t* time, int64_t* time_max) override
+ {
+ CBlockIndex* index;
+ {
+ LOCK(cs_main);
+ index = LookupBlockIndex(hash);
+ if (!index) {
+ return false;
+ }
+ if (time) {
+ *time = index->GetBlockTime();
+ }
+ if (time_max) {
+ *time_max = index->GetBlockTimeMax();
+ }
+ }
+ if (block && !ReadBlockFromDisk(*block, index, Params().GetConsensus())) {
+ block->SetNull();
+ }
+ return true;
+ }
+ void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(coins); }
+ double guessVerificationProgress(const uint256& block_hash) override
+ {
+ LOCK(cs_main);
+ return GuessVerificationProgress(Params().TxData(), LookupBlockIndex(block_hash));
+ }
+ RBFTransactionState isRBFOptIn(const CTransaction& tx) override
+ {
+ LOCK(::mempool.cs);
+ return IsRBFOptIn(tx, ::mempool);
+ }
+ bool hasDescendantsInMempool(const uint256& txid) override
+ {
+ LOCK(::mempool.cs);
+ auto it = ::mempool.GetIter(txid);
+ return it && (*it)->GetCountWithDescendants() > 1;
+ }
+ void relayTransaction(const uint256& txid) override
+ {
+ CInv inv(MSG_TX, txid);
+ g_connman->ForEachNode([&inv](CNode* node) { node->PushInventory(inv); });
+ }
+ void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) override
+ {
+ ::mempool.GetTransactionAncestry(txid, ancestors, descendants);
+ }
+ bool checkChainLimits(const CTransactionRef& tx) override
+ {
+ LockPoints lp;
+ CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp);
+ CTxMemPool::setEntries ancestors;
+ auto limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
+ auto limit_ancestor_size = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000;
+ auto limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
+ auto limit_descendant_size = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000;
+ std::string unused_error_string;
+ LOCK(::mempool.cs);
+ return ::mempool.CalculateMemPoolAncestors(entry, ancestors, limit_ancestor_count, limit_ancestor_size,
+ limit_descendant_count, limit_descendant_size, unused_error_string);
+ }
+ CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
+ {
+ return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative);
+ }
+ unsigned int estimateMaxBlocks() override
+ {
+ return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+ }
+ CFeeRate mempoolMinFee() override
+ {
+ return ::mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
+ }
+ CFeeRate relayMinFee() override { return ::minRelayTxFee; }
+ CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
+ CFeeRate relayDustFee() override { return ::dustRelayFee; }
+ bool havePruned() override
+ {
+ LOCK(cs_main);
+ return ::fHavePruned;
+ }
+ bool p2pEnabled() override { return g_connman != nullptr; }
+ bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !IsInitialBlockDownload(); }
+ bool isInitialBlockDownload() override { return IsInitialBlockDownload(); }
+ bool shutdownRequested() override { return ShutdownRequested(); }
+ int64_t getAdjustedTime() override { return GetAdjustedTime(); }
+ void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
+ void initWarning(const std::string& message) override { InitWarning(message); }
+ void initError(const std::string& message) override { InitError(message); }
+ void loadWallet(std::unique_ptr<Wallet> wallet) override { ::uiInterface.LoadWallet(wallet); }
+ void showProgress(const std::string& title, int progress, bool resume_possible) override
+ {
+ ::uiInterface.ShowProgress(title, progress, resume_possible);
+ }
+ std::unique_ptr<Handler> handleNotifications(Notifications& notifications) override
+ {
+ return MakeUnique<NotificationsHandlerImpl>(*this, notifications);
+ }
+ void waitForNotificationsIfNewBlocksConnected(const uint256& old_tip) override
+ {
+ if (!old_tip.IsNull()) {
+ LOCK(::cs_main);
+ if (old_tip == ::ChainActive().Tip()->GetBlockHash()) return;
+ CBlockIndex* block = LookupBlockIndex(old_tip);
+ if (block && block->GetAncestor(::ChainActive().Height()) == ::ChainActive().Tip()) return;
+ }
+ SyncWithValidationInterfaceQueue();
+ }
+ std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
+ {
+ return MakeUnique<RpcHandlerImpl>(command);
+ }
+ bool rpcEnableDeprecated(const std::string& method) override { return IsDeprecatedRPCEnabled(method); }
+ void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) override
+ {
+ RPCRunLater(name, std::move(fn), seconds);
+ }
+ int rpcSerializationFlags() override { return RPCSerializationFlags(); }
+ void requestMempoolTransactions(Notifications& notifications) override
+ {
+ LOCK2(::cs_main, ::mempool.cs);
+ for (const CTxMemPoolEntry& entry : ::mempool.mapTx) {
+ notifications.TransactionAddedToMempool(entry.GetSharedTx());
+ }
+ }
+};
+} // namespace
+
+std::unique_ptr<Chain> MakeChain() { return MakeUnique<ChainImpl>(); }
+
+} // namespace interfaces
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
new file mode 100644
index 0000000000..e675defd47
--- /dev/null
+++ b/src/interfaces/chain.h
@@ -0,0 +1,313 @@
+// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_INTERFACES_CHAIN_H
+#define BITCOIN_INTERFACES_CHAIN_H
+
+#include <optional.h> // For Optional and nullopt
+#include <primitives/transaction.h> // For CTransactionRef
+
+#include <memory>
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+class CBlock;
+class CFeeRate;
+class CRPCCommand;
+class CScheduler;
+class CValidationState;
+class Coin;
+class uint256;
+enum class RBFTransactionState;
+struct CBlockLocator;
+struct FeeCalculation;
+
+namespace interfaces {
+
+class Handler;
+class Wallet;
+
+//! Interface giving clients (wallet processes, maybe other analysis tools in
+//! the future) ability to access to the chain state, receive notifications,
+//! estimate fees, and submit transactions.
+//!
+//! TODO: Current chain methods are too low level, exposing too much of the
+//! internal workings of the bitcoin node, and not being very convenient to use.
+//! Chain methods should be cleaned up and simplified over time. Examples:
+//!
+//! * The Chain::lock() method, which lets clients delay chain tip updates
+//! should be removed when clients are able to respond to updates
+//! asynchronously
+//! (https://github.com/bitcoin/bitcoin/pull/10973#issuecomment-380101269).
+//!
+//! * The relayTransactions() and submitToMemoryPool() methods could be replaced
+//! with a higher-level broadcastTransaction method
+//! (https://github.com/bitcoin/bitcoin/pull/14978#issuecomment-459373984).
+//!
+//! * The initMessages() and loadWallet() methods which the wallet uses to send
+//! notifications to the GUI should go away when GUI and wallet can directly
+//! communicate with each other without going through the node
+//! (https://github.com/bitcoin/bitcoin/pull/15288#discussion_r253321096).
+//!
+//! * The handleRpc, registerRpcs, rpcEnableDeprecated methods and other RPC
+//! methods can go away if wallets listen for HTTP requests on their own
+//! ports instead of registering to handle requests on the node HTTP port.
+class Chain
+{
+public:
+ virtual ~Chain() {}
+
+ //! Interface for querying locked chain state, used by legacy code that
+ //! assumes state won't change between calls. New code should avoid using
+ //! the Lock interface and instead call higher-level Chain methods
+ //! that return more information so the chain doesn't need to stay locked
+ //! between calls.
+ class Lock
+ {
+ public:
+ virtual ~Lock() {}
+
+ //! Get current chain height, not including genesis block (returns 0 if
+ //! chain only contains genesis block, nullopt if chain does not contain
+ //! any blocks).
+ virtual Optional<int> getHeight() = 0;
+
+ //! Get block height above genesis block. Returns 0 for genesis block,
+ //! 1 for following block, and so on. Returns nullopt for a block not
+ //! included in the current chain.
+ virtual Optional<int> getBlockHeight(const uint256& hash) = 0;
+
+ //! Get block depth. Returns 1 for chain tip, 2 for preceding block, and
+ //! so on. Returns 0 for a block not included in the current chain.
+ virtual int getBlockDepth(const uint256& hash) = 0;
+
+ //! Get block hash. Height must be valid or this function will abort.
+ virtual uint256 getBlockHash(int height) = 0;
+
+ //! Get block time. Height must be valid or this function will abort.
+ virtual int64_t getBlockTime(int height) = 0;
+
+ //! Get block median time past. Height must be valid or this function
+ //! will abort.
+ virtual int64_t getBlockMedianTimePast(int height) = 0;
+
+ //! Check that the block is available on disk (i.e. has not been
+ //! pruned), and contains transactions.
+ virtual bool haveBlockOnDisk(int height) = 0;
+
+ //! Return height of the first block in the chain with timestamp equal
+ //! or greater than the given time and height equal or greater than the
+ //! given height, or nullopt if there is no block with a high enough
+ //! timestamp and height. Also return the block hash as an optional output parameter
+ //! (to avoid the cost of a second lookup in case this information is needed.)
+ virtual Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 0;
+
+ //! Return height of last block in the specified range which is pruned, or
+ //! nullopt if no block in the range is pruned. Range is inclusive.
+ virtual Optional<int> findPruned(int start_height = 0, Optional<int> stop_height = nullopt) = 0;
+
+ //! Return height of the specified block if it is on the chain, otherwise
+ //! return the height of the highest block on chain that's an ancestor
+ //! of the specified block, or nullopt if there is no common ancestor.
+ //! Also return the height of the specified block as an optional output
+ //! parameter (to avoid the cost of a second hash lookup in case this
+ //! information is desired).
+ virtual Optional<int> findFork(const uint256& hash, Optional<int>* height) = 0;
+
+ //! Get locator for the current chain tip.
+ virtual CBlockLocator getTipLocator() = 0;
+
+ //! Return height of the highest block on chain in common with the locator,
+ //! which will either be the original block used to create the locator,
+ //! or one of its ancestors.
+ virtual Optional<int> findLocatorFork(const CBlockLocator& locator) = 0;
+
+ //! Check if transaction will be final given chain height current time.
+ virtual bool checkFinalTx(const CTransaction& tx) = 0;
+
+ //! Add transaction to memory pool if the transaction fee is below the
+ //! amount specified by absurd_fee. Returns false if the transaction
+ //! could not be added due to the fee or for another reason.
+ virtual bool submitToMemoryPool(const CTransactionRef& tx, CAmount absurd_fee, CValidationState& state) = 0;
+ };
+
+ //! Return Lock interface. Chain is locked when this is called, and
+ //! unlocked when the returned interface is freed.
+ virtual std::unique_ptr<Lock> lock(bool try_lock = false) = 0;
+
+ //! Return whether node has the block and optionally return block metadata
+ //! or contents.
+ //!
+ //! If a block pointer is provided to retrieve the block contents, and the
+ //! block exists but doesn't have data (for example due to pruning), the
+ //! block will be empty and all fields set to null.
+ virtual bool findBlock(const uint256& hash,
+ CBlock* block = nullptr,
+ int64_t* time = nullptr,
+ int64_t* max_time = nullptr) = 0;
+
+ //! Look up unspent output information. Returns coins in the mempool and in
+ //! the current chain UTXO set. Iterates through all the keys in the map and
+ //! populates the values.
+ virtual void findCoins(std::map<COutPoint, Coin>& coins) = 0;
+
+ //! Estimate fraction of total transactions verified if blocks up to
+ //! the specified block hash are verified.
+ virtual double guessVerificationProgress(const uint256& block_hash) = 0;
+
+ //! Check if transaction is RBF opt in.
+ virtual RBFTransactionState isRBFOptIn(const CTransaction& tx) = 0;
+
+ //! Check if transaction has descendants in mempool.
+ virtual bool hasDescendantsInMempool(const uint256& txid) = 0;
+
+ //! Relay transaction.
+ virtual void relayTransaction(const uint256& txid) = 0;
+
+ //! Calculate mempool ancestor and descendant counts for the given transaction.
+ virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0;
+
+ //! Check if transaction will pass the mempool's chain limits.
+ virtual bool checkChainLimits(const CTransactionRef& tx) = 0;
+
+ //! Estimate smart fee.
+ virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc = nullptr) = 0;
+
+ //! Fee estimator max target.
+ virtual unsigned int estimateMaxBlocks() = 0;
+
+ //! Mempool minimum fee.
+ virtual CFeeRate mempoolMinFee() = 0;
+
+ //! Relay current minimum fee (from -minrelaytxfee and -incrementalrelayfee settings).
+ virtual CFeeRate relayMinFee() = 0;
+
+ //! Relay incremental fee setting (-incrementalrelayfee), reflecting cost of relay.
+ virtual CFeeRate relayIncrementalFee() = 0;
+
+ //! Relay dust fee setting (-dustrelayfee), reflecting lowest rate it's economical to spend.
+ virtual CFeeRate relayDustFee() = 0;
+
+ //! Check if any block has been pruned.
+ virtual bool havePruned() = 0;
+
+ //! Check if p2p enabled.
+ virtual bool p2pEnabled() = 0;
+
+ //! Check if the node is ready to broadcast transactions.
+ virtual bool isReadyToBroadcast() = 0;
+
+ //! Check if in IBD.
+ virtual bool isInitialBlockDownload() = 0;
+
+ //! Check if shutdown requested.
+ virtual bool shutdownRequested() = 0;
+
+ //! Get adjusted time.
+ virtual int64_t getAdjustedTime() = 0;
+
+ //! Send init message.
+ virtual void initMessage(const std::string& message) = 0;
+
+ //! Send init warning.
+ virtual void initWarning(const std::string& message) = 0;
+
+ //! Send init error.
+ virtual void initError(const std::string& message) = 0;
+
+ //! Send wallet load notification to the GUI.
+ virtual void loadWallet(std::unique_ptr<Wallet> wallet) = 0;
+
+ //! Send progress indicator.
+ virtual void showProgress(const std::string& title, int progress, bool resume_possible) = 0;
+
+ //! Chain notifications.
+ class Notifications
+ {
+ public:
+ virtual ~Notifications() {}
+ virtual void TransactionAddedToMempool(const CTransactionRef& tx) {}
+ virtual void TransactionRemovedFromMempool(const CTransactionRef& ptx) {}
+ virtual void BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& tx_conflicted) {}
+ virtual void BlockDisconnected(const CBlock& block) {}
+ virtual void UpdatedBlockTip() {}
+ virtual void ChainStateFlushed(const CBlockLocator& locator) {}
+ };
+
+ //! Register handler for notifications.
+ virtual std::unique_ptr<Handler> handleNotifications(Notifications& notifications) = 0;
+
+ //! Wait for pending notifications to be processed unless block hash points to the current
+ //! chain tip, or to a possible descendant of the current chain tip that isn't currently
+ //! connected.
+ virtual void waitForNotificationsIfNewBlocksConnected(const uint256& old_tip) = 0;
+
+ //! Register handler for RPC. Command is not copied, so reference
+ //! needs to remain valid until Handler is disconnected.
+ virtual std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) = 0;
+
+ //! Check if deprecated RPC is enabled.
+ virtual bool rpcEnableDeprecated(const std::string& method) = 0;
+
+ //! Run function after given number of seconds. Cancel any previous calls with same name.
+ virtual void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) = 0;
+
+ //! Current RPC serialization flags.
+ virtual int rpcSerializationFlags() = 0;
+
+ //! Synchronously send TransactionAddedToMempool notifications about all
+ //! current mempool transactions to the specified handler and return after
+ //! the last one is sent. These notifications aren't coordinated with async
+ //! notifications sent by handleNotifications, so out of date async
+ //! notifications from handleNotifications can arrive during and after
+ //! synchronous notifications from requestMempoolTransactions. Clients need
+ //! to be prepared to handle this by ignoring notifications about unknown
+ //! removed transactions and already added new transactions.
+ virtual void requestMempoolTransactions(Notifications& notifications) = 0;
+};
+
+//! Interface to let node manage chain clients (wallets, or maybe tools for
+//! monitoring and analysis in the future).
+class ChainClient
+{
+public:
+ virtual ~ChainClient() {}
+
+ //! Register rpcs.
+ virtual void registerRpcs() = 0;
+
+ //! Check for errors before loading.
+ virtual bool verify() = 0;
+
+ //! Load saved state.
+ virtual bool load() = 0;
+
+ //! Start client execution and provide a scheduler.
+ virtual void start(CScheduler& scheduler) = 0;
+
+ //! Save state to disk.
+ virtual void flush() = 0;
+
+ //! Shut down client.
+ virtual void stop() = 0;
+};
+
+//! Return implementation of Chain interface.
+std::unique_ptr<Chain> MakeChain();
+
+//! Return implementation of ChainClient interface for a wallet client. This
+//! function will be undefined in builds where ENABLE_WALLET is false.
+//!
+//! Currently, wallets are the only chain clients. But in the future, other
+//! types of chain clients could be added, such as tools for monitoring,
+//! analysis, or fee estimation. These clients need to expose their own
+//! MakeXXXClient functions returning their implementations of the ChainClient
+//! interface.
+std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, std::vector<std::string> wallet_filenames);
+
+} // namespace interfaces
+
+#endif // BITCOIN_INTERFACES_CHAIN_H
diff --git a/src/interfaces/handler.cpp b/src/interfaces/handler.cpp
index 80f461f4d3..92601fc4e9 100644
--- a/src/interfaces/handler.cpp
+++ b/src/interfaces/handler.cpp
@@ -4,7 +4,7 @@
#include <interfaces/handler.h>
-#include <utilmemory.h>
+#include <util/memory.h>
#include <boost/signals2/connection.hpp>
#include <utility>
@@ -15,7 +15,7 @@ namespace {
class HandlerImpl : public Handler
{
public:
- HandlerImpl(boost::signals2::connection connection) : m_connection(std::move(connection)) {}
+ explicit HandlerImpl(boost::signals2::connection connection) : m_connection(std::move(connection)) {}
void disconnect() override { m_connection.disconnect(); }
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 106dd38f60..618cd02ea6 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -6,9 +6,11 @@
#include <addrdb.h>
#include <amount.h>
+#include <banman.h>
#include <chain.h>
#include <chainparams.h>
#include <init.h>
+#include <interfaces/chain.h>
#include <interfaces/handler.h>
#include <interfaces/wallet.h>
#include <net.h>
@@ -18,6 +20,7 @@
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
+#include <policy/settings.h>
#include <primitives/block.h>
#include <rpc/server.h>
#include <scheduler.h>
@@ -25,30 +28,33 @@
#include <sync.h>
#include <txmempool.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <warnings.h>
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif
-#ifdef ENABLE_WALLET
-#include <wallet/fees.h>
-#include <wallet/wallet.h>
-#define CHECK_WALLET(x) x
-#else
-#define CHECK_WALLET(x) throw std::logic_error("Wallet function called in non-wallet build.")
-#endif
#include <atomic>
-#include <boost/thread/thread.hpp>
#include <univalue.h>
+class CWallet;
+fs::path GetWalletDir();
+std::vector<fs::path> ListWalletDir();
+std::vector<std::shared_ptr<CWallet>> GetWallets();
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning);
+
namespace interfaces {
+
+class Wallet;
+
namespace {
class NodeImpl : public Node
{
+public:
+ NodeImpl() { m_interfaces.chain = MakeChain(); }
bool parseParameters(int argc, const char* const argv[], std::string& error) override
{
return gArgs.ParseParameters(argc, argv, error);
@@ -57,21 +63,23 @@ class NodeImpl : public Node
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
void selectParams(const std::string& network) override { SelectParams(network); }
+ uint64_t getAssumedBlockchainSize() override { return Params().AssumedBlockchainSize(); }
+ uint64_t getAssumedChainStateSize() override { return Params().AssumedChainStateSize(); }
std::string getNetwork() override { return Params().NetworkIDString(); }
void initLogging() override { InitLogging(); }
void initParameterInteraction() override { InitParameterInteraction(); }
std::string getWarnings(const std::string& type) override { return GetWarnings(type); }
- uint32_t getLogCategories() override { return g_logger->GetCategoryMask(); }
+ uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); }
bool baseInitialize() override
{
return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
AppInitLockDataDirectory();
}
- bool appInitMain() override { return AppInitMain(); }
+ bool appInitMain() override { return AppInitMain(m_interfaces); }
void appShutdown() override
{
Interrupt();
- Shutdown();
+ Shutdown(m_interfaces);
}
void startShutdown() override { StartShutdown(); }
bool shutdownRequested() override { return ShutdownRequested(); }
@@ -117,28 +125,35 @@ class NodeImpl : public Node
}
bool getBanned(banmap_t& banmap) override
{
- if (g_connman) {
- g_connman->GetBanned(banmap);
+ if (g_banman) {
+ g_banman->GetBanned(banmap);
return true;
}
return false;
}
bool ban(const CNetAddr& net_addr, BanReason reason, int64_t ban_time_offset) override
{
- if (g_connman) {
- g_connman->Ban(net_addr, reason, ban_time_offset);
+ if (g_banman) {
+ g_banman->Ban(net_addr, reason, ban_time_offset);
return true;
}
return false;
}
bool unban(const CSubNet& ip) override
{
- if (g_connman) {
- g_connman->Unban(ip);
+ if (g_banman) {
+ g_banman->Unban(ip);
return true;
}
return false;
}
+ bool disconnect(const CNetAddr& net_addr) override
+ {
+ if (g_connman) {
+ return g_connman->DisconnectNode(net_addr);
+ }
+ return false;
+ }
bool disconnect(NodeId id) override
{
if (g_connman) {
@@ -163,13 +178,13 @@ class NodeImpl : public Node
int getNumBlocks() override
{
LOCK(::cs_main);
- return ::chainActive.Height();
+ return ::ChainActive().Height();
}
int64_t getLastBlockTime() override
{
LOCK(::cs_main);
- if (::chainActive.Tip()) {
- return ::chainActive.Tip()->GetBlockTime();
+ if (::ChainActive().Tip()) {
+ return ::ChainActive().Tip()->GetBlockTime();
}
return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network
}
@@ -178,7 +193,7 @@ class NodeImpl : public Node
const CBlockIndex* tip;
{
LOCK(::cs_main);
- tip = ::chainActive.Tip();
+ tip = ::ChainActive().Tip();
}
return GuessVerificationProgress(Params().TxData(), tip);
}
@@ -192,7 +207,6 @@ class NodeImpl : public Node
}
}
bool getNetworkActive() override { return g_connman && g_connman->GetNetworkActive(); }
- CAmount getMaxTxFee() override { return ::maxTxFee; }
CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
{
FeeCalculation fee_calc;
@@ -219,58 +233,69 @@ class NodeImpl : public Node
LOCK(::cs_main);
return ::pcoinsTip->GetCoin(output, coin);
}
+ std::string getWalletDir() override
+ {
+ return GetWalletDir().string();
+ }
+ std::vector<std::string> listWalletDir() override
+ {
+ std::vector<std::string> paths;
+ for (auto& path : ListWalletDir()) {
+ paths.push_back(path.string());
+ }
+ return paths;
+ }
std::vector<std::unique_ptr<Wallet>> getWallets() override
{
-#ifdef ENABLE_WALLET
std::vector<std::unique_ptr<Wallet>> wallets;
for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
wallets.emplace_back(MakeWallet(wallet));
}
return wallets;
-#else
- throw std::logic_error("Node::getWallets() called in non-wallet build.");
-#endif
+ }
+ std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) override
+ {
+ return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warning));
}
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
{
- return MakeHandler(::uiInterface.InitMessage.connect(fn));
+ return MakeHandler(::uiInterface.InitMessage_connect(fn));
}
std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override
{
- return MakeHandler(::uiInterface.ThreadSafeMessageBox.connect(fn));
+ return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn));
}
std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override
{
- return MakeHandler(::uiInterface.ThreadSafeQuestion.connect(fn));
+ return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn));
}
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
{
- return MakeHandler(::uiInterface.ShowProgress.connect(fn));
+ return MakeHandler(::uiInterface.ShowProgress_connect(fn));
}
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
{
- CHECK_WALLET(
- return MakeHandler(::uiInterface.LoadWallet.connect([fn](std::shared_ptr<CWallet> wallet) { fn(MakeWallet(wallet)); })));
+ return MakeHandler(::uiInterface.LoadWallet_connect([fn](std::unique_ptr<Wallet>& wallet) { fn(std::move(wallet)); }));
}
std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
{
- return MakeHandler(::uiInterface.NotifyNumConnectionsChanged.connect(fn));
+ return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn));
}
std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override
{
- return MakeHandler(::uiInterface.NotifyNetworkActiveChanged.connect(fn));
+ return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn));
}
std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override
{
- return MakeHandler(::uiInterface.NotifyAlertChanged.connect(fn));
+ return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn));
}
std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override
{
- return MakeHandler(::uiInterface.BannedListChanged.connect(fn));
+ return MakeHandler(::uiInterface.BannedListChanged_connect(fn));
}
std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
{
- return MakeHandler(::uiInterface.NotifyBlockTip.connect([fn](bool initial_download, const CBlockIndex* block) {
+ return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](bool initial_download, const CBlockIndex* block) {
fn(initial_download, block->nHeight, block->GetBlockTime(),
GuessVerificationProgress(Params().TxData(), block));
}));
@@ -278,11 +303,12 @@ class NodeImpl : public Node
std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override
{
return MakeHandler(
- ::uiInterface.NotifyHeaderTip.connect([fn](bool initial_download, const CBlockIndex* block) {
+ ::uiInterface.NotifyHeaderTip_connect([fn](bool initial_download, const CBlockIndex* block) {
fn(initial_download, block->nHeight, block->GetBlockTime(),
GuessVerificationProgress(Params().TxData(), block));
}));
}
+ InitInterfaces m_interfaces;
};
} // namespace
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 8185c015a9..1ccd2a31b7 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -18,6 +18,7 @@
#include <tuple>
#include <vector>
+class BanMan;
class CCoinControl;
class CFeeRate;
class CNodeStats;
@@ -52,6 +53,12 @@ public:
//! Choose network parameters.
virtual void selectParams(const std::string& network) = 0;
+ //! Get the (assumed) blockchain size.
+ virtual uint64_t getAssumedBlockchainSize() = 0;
+
+ //! Get the (assumed) chain state size.
+ virtual uint64_t getAssumedChainStateSize() = 0;
+
//! Get network name.
virtual std::string getNetwork() = 0;
@@ -107,7 +114,10 @@ public:
//! Unban node.
virtual bool unban(const CSubNet& ip) = 0;
- //! Disconnect node.
+ //! Disconnect node by address.
+ virtual bool disconnect(const CNetAddr& net_addr) = 0;
+
+ //! Disconnect node by id.
virtual bool disconnect(NodeId id) = 0;
//! Get total bytes recv.
@@ -149,9 +159,6 @@ public:
//! Get network active.
virtual bool getNetworkActive() = 0;
- //! Get max tx fee.
- virtual CAmount getMaxTxFee() = 0;
-
//! Estimate smart fee.
virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) = 0;
@@ -173,9 +180,20 @@ public:
//! Get unspent outputs associated with a transaction.
virtual bool getUnspentOutput(const COutPoint& output, Coin& coin) = 0;
+ //! Return default wallet directory.
+ virtual std::string getWalletDir() = 0;
+
+ //! Return available wallets in wallet directory.
+ virtual std::vector<std::string> listWalletDir() = 0;
+
//! Return interfaces for accessing wallets (if any).
virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
+ //! Attempts to load a wallet from file or directory.
+ //! The loaded wallet is also notified to handlers previously registered
+ //! with handleLoadWallet.
+ virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) = 0;
+
//! Register handler for init messages.
using InitMessageFn = std::function<void(const std::string& message)>;
virtual std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) = 0;
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 55a6f771e5..b57299d78d 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -7,12 +7,16 @@
#include <amount.h>
#include <chain.h>
#include <consensus/validation.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <interfaces/handler.h>
#include <net.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
+#include <rpc/server.h>
+#include <scheduler.h>
#include <script/ismine.h>
#include <script/standard.h>
#include <support/allocators/secure.h>
@@ -20,10 +24,19 @@
#include <timedata.h>
#include <ui_interface.h>
#include <uint256.h>
+#include <util/system.h>
#include <validation.h>
#include <wallet/feebumper.h>
#include <wallet/fees.h>
+#include <wallet/rpcwallet.h>
+#include <wallet/load.h>
#include <wallet/wallet.h>
+#include <wallet/walletutil.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
namespace interfaces {
namespace {
@@ -31,20 +44,18 @@ namespace {
class PendingWalletTxImpl : public PendingWalletTx
{
public:
- PendingWalletTxImpl(CWallet& wallet) : m_wallet(wallet), m_key(&wallet) {}
+ explicit PendingWalletTxImpl(CWallet& wallet) : m_wallet(wallet), m_key(&wallet) {}
const CTransaction& get() override { return *m_tx; }
- int64_t getVirtualSize() override { return GetVirtualTransactionSize(*m_tx); }
-
bool commit(WalletValueMap value_map,
WalletOrderForm order_form,
- std::string from_account,
std::string& reject_reason) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet.chain().lock();
+ LOCK(m_wallet.cs_wallet);
CValidationState state;
- if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), std::move(from_account), m_key, g_connman.get(), state)) {
+ if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), m_key, state)) {
reject_reason = state.GetRejectReason();
return false;
}
@@ -57,7 +68,7 @@ public:
};
//! Construct wallet tx struct.
-WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
+WalletTx MakeWalletTx(interfaces::Chain::Lock& locked_chain, CWallet& wallet, const CWalletTx& wtx)
{
WalletTx result;
result.tx = wtx.tx;
@@ -75,7 +86,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
IsMine(wallet, result.txout_address.back()) :
ISMINE_NO);
}
- result.credit = wtx.GetCredit(ISMINE_ALL);
+ result.credit = wtx.GetCredit(locked_chain, ISMINE_ALL);
result.debit = wtx.GetDebit(ISMINE_ALL);
result.change = wtx.GetChange();
result.time = wtx.GetTxTime();
@@ -85,87 +96,89 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
}
//! Construct wallet tx status struct.
-WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx)
+WalletTxStatus MakeWalletTxStatus(interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx)
{
WalletTxStatus result;
- auto mi = ::mapBlockIndex.find(wtx.hashBlock);
- CBlockIndex* block = mi != ::mapBlockIndex.end() ? mi->second : nullptr;
- result.block_height = (block ? block->nHeight : std::numeric_limits<int>::max());
- result.blocks_to_maturity = wtx.GetBlocksToMaturity();
- result.depth_in_main_chain = wtx.GetDepthInMainChain();
+ result.block_height = locked_chain.getBlockHeight(wtx.hashBlock).get_value_or(std::numeric_limits<int>::max());
+ result.blocks_to_maturity = wtx.GetBlocksToMaturity(locked_chain);
+ result.depth_in_main_chain = wtx.GetDepthInMainChain(locked_chain);
result.time_received = wtx.nTimeReceived;
result.lock_time = wtx.tx->nLockTime;
- result.is_final = CheckFinalTx(*wtx.tx);
- result.is_trusted = wtx.IsTrusted();
+ result.is_final = locked_chain.checkFinalTx(*wtx.tx);
+ result.is_trusted = wtx.IsTrusted(locked_chain);
result.is_abandoned = wtx.isAbandoned();
result.is_coinbase = wtx.IsCoinBase();
- result.is_in_main_chain = wtx.IsInMainChain();
+ result.is_in_main_chain = wtx.IsInMainChain(locked_chain);
return result;
}
//! Construct wallet TxOut struct.
-WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth)
+WalletTxOut MakeWalletTxOut(interfaces::Chain::Lock& locked_chain,
+ CWallet& wallet,
+ const CWalletTx& wtx,
+ int n,
+ int depth) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
WalletTxOut result;
result.txout = wtx.tx->vout[n];
result.time = wtx.GetTxTime();
result.depth_in_main_chain = depth;
- result.is_spent = wallet.IsSpent(wtx.GetHash(), n);
+ result.is_spent = wallet.IsSpent(locked_chain, wtx.GetHash(), n);
return result;
}
class WalletImpl : public Wallet
{
public:
- WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_shared_wallet(wallet), m_wallet(*wallet.get()) {}
+ explicit WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_wallet(wallet) {}
bool encryptWallet(const SecureString& wallet_passphrase) override
{
- return m_wallet.EncryptWallet(wallet_passphrase);
+ return m_wallet->EncryptWallet(wallet_passphrase);
}
- bool isCrypted() override { return m_wallet.IsCrypted(); }
- bool lock() override { return m_wallet.Lock(); }
- bool unlock(const SecureString& wallet_passphrase) override { return m_wallet.Unlock(wallet_passphrase); }
- bool isLocked() override { return m_wallet.IsLocked(); }
+ bool isCrypted() override { return m_wallet->IsCrypted(); }
+ bool lock() override { return m_wallet->Lock(); }
+ bool unlock(const SecureString& wallet_passphrase) override { return m_wallet->Unlock(wallet_passphrase); }
+ bool isLocked() override { return m_wallet->IsLocked(); }
bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
const SecureString& new_wallet_passphrase) override
{
- return m_wallet.ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase);
+ return m_wallet->ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase);
}
- void abortRescan() override { m_wallet.AbortRescan(); }
- bool backupWallet(const std::string& filename) override { return m_wallet.BackupWallet(filename); }
- std::string getWalletName() override { return m_wallet.GetName(); }
+ void abortRescan() override { m_wallet->AbortRescan(); }
+ bool backupWallet(const std::string& filename) override { return m_wallet->BackupWallet(filename); }
+ std::string getWalletName() override { return m_wallet->GetName(); }
bool getKeyFromPool(bool internal, CPubKey& pub_key) override
{
- return m_wallet.GetKeyFromPool(pub_key, internal);
+ return m_wallet->GetKeyFromPool(pub_key, internal);
}
- bool getPubKey(const CKeyID& address, CPubKey& pub_key) override { return m_wallet.GetPubKey(address, pub_key); }
- bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet.GetKey(address, key); }
- bool isSpendable(const CTxDestination& dest) override { return IsMine(m_wallet, dest) & ISMINE_SPENDABLE; }
- bool haveWatchOnly() override { return m_wallet.HaveWatchOnly(); };
+ bool getPubKey(const CKeyID& address, CPubKey& pub_key) override { return m_wallet->GetPubKey(address, pub_key); }
+ bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet->GetKey(address, key); }
+ bool isSpendable(const CTxDestination& dest) override { return IsMine(*m_wallet, dest) & ISMINE_SPENDABLE; }
+ bool haveWatchOnly() override { return m_wallet->HaveWatchOnly(); };
bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::string& purpose) override
{
- return m_wallet.SetAddressBook(dest, name, purpose);
+ return m_wallet->SetAddressBook(dest, name, purpose);
}
bool delAddressBook(const CTxDestination& dest) override
{
- return m_wallet.DelAddressBook(dest);
+ return m_wallet->DelAddressBook(dest);
}
bool getAddress(const CTxDestination& dest,
std::string* name,
isminetype* is_mine,
std::string* purpose) override
{
- LOCK(m_wallet.cs_wallet);
- auto it = m_wallet.mapAddressBook.find(dest);
- if (it == m_wallet.mapAddressBook.end()) {
+ LOCK(m_wallet->cs_wallet);
+ auto it = m_wallet->mapAddressBook.find(dest);
+ if (it == m_wallet->mapAddressBook.end()) {
return false;
}
if (name) {
*name = it->second.name;
}
if (is_mine) {
- *is_mine = IsMine(m_wallet, dest);
+ *is_mine = IsMine(*m_wallet, dest);
}
if (purpose) {
*purpose = it->second.purpose;
@@ -174,47 +187,52 @@ public:
}
std::vector<WalletAddress> getAddresses() override
{
- LOCK(m_wallet.cs_wallet);
+ LOCK(m_wallet->cs_wallet);
std::vector<WalletAddress> result;
- for (const auto& item : m_wallet.mapAddressBook) {
- result.emplace_back(item.first, IsMine(m_wallet, item.first), item.second.name, item.second.purpose);
+ for (const auto& item : m_wallet->mapAddressBook) {
+ result.emplace_back(item.first, IsMine(*m_wallet, item.first), item.second.name, item.second.purpose);
}
return result;
}
- void learnRelatedScripts(const CPubKey& key, OutputType type) override { m_wallet.LearnRelatedScripts(key, type); }
+ void learnRelatedScripts(const CPubKey& key, OutputType type) override { m_wallet->LearnRelatedScripts(key, type); }
bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) override
{
- LOCK(m_wallet.cs_wallet);
- return m_wallet.AddDestData(dest, key, value);
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->AddDestData(dest, key, value);
}
bool eraseDestData(const CTxDestination& dest, const std::string& key) override
{
- LOCK(m_wallet.cs_wallet);
- return m_wallet.EraseDestData(dest, key);
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->EraseDestData(dest, key);
}
std::vector<std::string> getDestValues(const std::string& prefix) override
{
- return m_wallet.GetDestValues(prefix);
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->GetDestValues(prefix);
}
void lockCoin(const COutPoint& output) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
- return m_wallet.LockCoin(output);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->LockCoin(output);
}
void unlockCoin(const COutPoint& output) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
- return m_wallet.UnlockCoin(output);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->UnlockCoin(output);
}
bool isLockedCoin(const COutPoint& output) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
- return m_wallet.IsLockedCoin(output.hash, output.n);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->IsLockedCoin(output.hash, output.n);
}
void listLockedCoins(std::vector<COutPoint>& outputs) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
- return m_wallet.ListLockedCoins(outputs);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->ListLockedCoins(outputs);
}
std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
const CCoinControl& coin_control,
@@ -223,23 +241,25 @@ public:
CAmount& fee,
std::string& fail_reason) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
- auto pending = MakeUnique<PendingWalletTxImpl>(m_wallet);
- if (!m_wallet.CreateTransaction(recipients, pending->m_tx, pending->m_key, fee, change_pos,
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ auto pending = MakeUnique<PendingWalletTxImpl>(*m_wallet);
+ if (!m_wallet->CreateTransaction(*locked_chain, recipients, pending->m_tx, pending->m_key, fee, change_pos,
fail_reason, coin_control, sign)) {
return {};
}
return std::move(pending);
}
- bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet.TransactionCanBeAbandoned(txid); }
+ bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); }
bool abandonTransaction(const uint256& txid) override
{
- LOCK2(cs_main, m_wallet.cs_wallet);
- return m_wallet.AbandonTransaction(txid);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->AbandonTransaction(*locked_chain, txid);
}
bool transactionCanBeBumped(const uint256& txid) override
{
- return feebumper::TransactionCanBeBumped(&m_wallet, txid);
+ return feebumper::TransactionCanBeBumped(m_wallet.get(), txid);
}
bool createBumpTransaction(const uint256& txid,
const CCoinControl& coin_control,
@@ -249,169 +269,188 @@ public:
CAmount& new_fee,
CMutableTransaction& mtx) override
{
- return feebumper::CreateTransaction(&m_wallet, txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) ==
- feebumper::Result::OK;
+ if (total_fee > 0) {
+ return feebumper::CreateTotalBumpTransaction(m_wallet.get(), txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) ==
+ feebumper::Result::OK;
+ } else {
+ return feebumper::CreateRateBumpTransaction(m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) ==
+ feebumper::Result::OK;
+ }
}
- bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(&m_wallet, mtx); }
+ bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(m_wallet.get(), mtx); }
bool commitBumpTransaction(const uint256& txid,
CMutableTransaction&& mtx,
std::vector<std::string>& errors,
uint256& bumped_txid) override
{
- return feebumper::CommitTransaction(&m_wallet, txid, std::move(mtx), errors, bumped_txid) ==
+ return feebumper::CommitTransaction(m_wallet.get(), txid, std::move(mtx), errors, bumped_txid) ==
feebumper::Result::OK;
}
CTransactionRef getTx(const uint256& txid) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
- auto mi = m_wallet.mapWallet.find(txid);
- if (mi != m_wallet.mapWallet.end()) {
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ auto mi = m_wallet->mapWallet.find(txid);
+ if (mi != m_wallet->mapWallet.end()) {
return mi->second.tx;
}
return {};
}
WalletTx getWalletTx(const uint256& txid) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
- auto mi = m_wallet.mapWallet.find(txid);
- if (mi != m_wallet.mapWallet.end()) {
- return MakeWalletTx(m_wallet, mi->second);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ auto mi = m_wallet->mapWallet.find(txid);
+ if (mi != m_wallet->mapWallet.end()) {
+ return MakeWalletTx(*locked_chain, *m_wallet, mi->second);
}
return {};
}
std::vector<WalletTx> getWalletTxs() override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
std::vector<WalletTx> result;
- result.reserve(m_wallet.mapWallet.size());
- for (const auto& entry : m_wallet.mapWallet) {
- result.emplace_back(MakeWalletTx(m_wallet, entry.second));
+ result.reserve(m_wallet->mapWallet.size());
+ for (const auto& entry : m_wallet->mapWallet) {
+ result.emplace_back(MakeWalletTx(*locked_chain, *m_wallet, entry.second));
}
return result;
}
bool tryGetTxStatus(const uint256& txid,
interfaces::WalletTxStatus& tx_status,
int& num_blocks,
- int64_t& adjusted_time) override
+ int64_t& block_time) override
{
- TRY_LOCK(::cs_main, locked_chain);
+ auto locked_chain = m_wallet->chain().lock(true /* try_lock */);
if (!locked_chain) {
return false;
}
- TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
+ TRY_LOCK(m_wallet->cs_wallet, locked_wallet);
if (!locked_wallet) {
return false;
}
- auto mi = m_wallet.mapWallet.find(txid);
- if (mi == m_wallet.mapWallet.end()) {
+ auto mi = m_wallet->mapWallet.find(txid);
+ if (mi == m_wallet->mapWallet.end()) {
return false;
}
- num_blocks = ::chainActive.Height();
- adjusted_time = GetAdjustedTime();
- tx_status = MakeWalletTxStatus(mi->second);
+ if (Optional<int> height = locked_chain->getHeight()) {
+ num_blocks = *height;
+ block_time = locked_chain->getBlockTime(*height);
+ } else {
+ num_blocks = -1;
+ block_time = -1;
+ }
+ tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
return true;
}
WalletTx getWalletTxDetails(const uint256& txid,
WalletTxStatus& tx_status,
WalletOrderForm& order_form,
bool& in_mempool,
- int& num_blocks,
- int64_t& adjusted_time) override
+ int& num_blocks) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
- auto mi = m_wallet.mapWallet.find(txid);
- if (mi != m_wallet.mapWallet.end()) {
- num_blocks = ::chainActive.Height();
- adjusted_time = GetAdjustedTime();
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ auto mi = m_wallet->mapWallet.find(txid);
+ if (mi != m_wallet->mapWallet.end()) {
+ num_blocks = locked_chain->getHeight().get_value_or(-1);
in_mempool = mi->second.InMempool();
order_form = mi->second.vOrderForm;
- tx_status = MakeWalletTxStatus(mi->second);
- return MakeWalletTx(m_wallet, mi->second);
+ tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
+ return MakeWalletTx(*locked_chain, *m_wallet, mi->second);
}
return {};
}
WalletBalances getBalances() override
{
+ const auto bal = m_wallet->GetBalance();
WalletBalances result;
- result.balance = m_wallet.GetBalance();
- result.unconfirmed_balance = m_wallet.GetUnconfirmedBalance();
- result.immature_balance = m_wallet.GetImmatureBalance();
- result.have_watch_only = m_wallet.HaveWatchOnly();
+ result.balance = bal.m_mine_trusted;
+ result.unconfirmed_balance = bal.m_mine_untrusted_pending;
+ result.immature_balance = bal.m_mine_immature;
+ result.have_watch_only = m_wallet->HaveWatchOnly();
if (result.have_watch_only) {
- result.watch_only_balance = m_wallet.GetBalance(ISMINE_WATCH_ONLY);
- result.unconfirmed_watch_only_balance = m_wallet.GetUnconfirmedWatchOnlyBalance();
- result.immature_watch_only_balance = m_wallet.GetImmatureWatchOnlyBalance();
+ result.watch_only_balance = bal.m_watchonly_trusted;
+ result.unconfirmed_watch_only_balance = bal.m_watchonly_untrusted_pending;
+ result.immature_watch_only_balance = bal.m_watchonly_immature;
}
return result;
}
bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
{
- TRY_LOCK(cs_main, locked_chain);
+ auto locked_chain = m_wallet->chain().lock(true /* try_lock */);
if (!locked_chain) return false;
- TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
+ TRY_LOCK(m_wallet->cs_wallet, locked_wallet);
if (!locked_wallet) {
return false;
}
balances = getBalances();
- num_blocks = ::chainActive.Height();
+ num_blocks = locked_chain->getHeight().get_value_or(-1);
return true;
}
- CAmount getBalance() override { return m_wallet.GetBalance(); }
+ CAmount getBalance() override { return m_wallet->GetBalance().m_mine_trusted; }
CAmount getAvailableBalance(const CCoinControl& coin_control) override
{
- return m_wallet.GetAvailableBalance(&coin_control);
+ return m_wallet->GetAvailableBalance(&coin_control);
}
isminetype txinIsMine(const CTxIn& txin) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
- return m_wallet.IsMine(txin);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->IsMine(txin);
}
isminetype txoutIsMine(const CTxOut& txout) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
- return m_wallet.IsMine(txout);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->IsMine(txout);
}
CAmount getDebit(const CTxIn& txin, isminefilter filter) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
- return m_wallet.GetDebit(txin, filter);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->GetDebit(txin, filter);
}
CAmount getCredit(const CTxOut& txout, isminefilter filter) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
- return m_wallet.GetCredit(txout, filter);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ return m_wallet->GetCredit(txout, filter);
}
CoinsList listCoins() override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
CoinsList result;
- for (const auto& entry : m_wallet.ListCoins()) {
+ for (const auto& entry : m_wallet->ListCoins(*locked_chain)) {
auto& group = result[entry.first];
for (const auto& coin : entry.second) {
- group.emplace_back(
- COutPoint(coin.tx->GetHash(), coin.i), MakeWalletTxOut(m_wallet, *coin.tx, coin.i, coin.nDepth));
+ group.emplace_back(COutPoint(coin.tx->GetHash(), coin.i),
+ MakeWalletTxOut(*locked_chain, *m_wallet, *coin.tx, coin.i, coin.nDepth));
}
}
return result;
}
std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override
{
- LOCK2(::cs_main, m_wallet.cs_wallet);
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
std::vector<WalletTxOut> result;
result.reserve(outputs.size());
for (const auto& output : outputs) {
result.emplace_back();
- auto it = m_wallet.mapWallet.find(output.hash);
- if (it != m_wallet.mapWallet.end()) {
- int depth = it->second.GetDepthInMainChain();
+ auto it = m_wallet->mapWallet.find(output.hash);
+ if (it != m_wallet->mapWallet.end()) {
+ int depth = it->second.GetDepthInMainChain(*locked_chain);
if (depth >= 0) {
- result.back() = MakeWalletTxOut(m_wallet, it->second, output.n, depth);
+ result.back() = MakeWalletTxOut(*locked_chain, *m_wallet, it->second, output.n, depth);
}
}
}
return result;
}
- CAmount getRequiredFee(unsigned int tx_bytes) override { return GetRequiredFee(m_wallet, tx_bytes); }
+ CAmount getRequiredFee(unsigned int tx_bytes) override { return GetRequiredFee(*m_wallet, tx_bytes); }
CAmount getMinimumFee(unsigned int tx_bytes,
const CCoinControl& coin_control,
int* returned_target,
@@ -419,50 +458,84 @@ public:
{
FeeCalculation fee_calc;
CAmount result;
- result = GetMinimumFee(m_wallet, tx_bytes, coin_control, ::mempool, ::feeEstimator, &fee_calc);
+ result = GetMinimumFee(*m_wallet, tx_bytes, coin_control, &fee_calc);
if (returned_target) *returned_target = fee_calc.returnedTarget;
if (reason) *reason = fee_calc.reason;
return result;
}
- unsigned int getConfirmTarget() override { return m_wallet.m_confirm_target; }
- bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
- bool IsWalletFlagSet(uint64_t flag) override { return m_wallet.IsWalletFlagSet(flag); }
- OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
- OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
+ unsigned int getConfirmTarget() override { return m_wallet->m_confirm_target; }
+ bool hdEnabled() override { return m_wallet->IsHDEnabled(); }
+ bool canGetAddresses() override { return m_wallet->CanGetAddresses(); }
+ bool IsWalletFlagSet(uint64_t flag) override { return m_wallet->IsWalletFlagSet(flag); }
+ OutputType getDefaultAddressType() override { return m_wallet->m_default_address_type; }
+ OutputType getDefaultChangeType() override { return m_wallet->m_default_change_type; }
+ CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; }
+ void remove() override
+ {
+ RemoveWallet(m_wallet);
+ }
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
{
- return MakeHandler(m_wallet.NotifyUnload.connect(fn));
+ return MakeHandler(m_wallet->NotifyUnload.connect(fn));
}
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
{
- return MakeHandler(m_wallet.ShowProgress.connect(fn));
+ return MakeHandler(m_wallet->ShowProgress.connect(fn));
}
std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) override
{
- return MakeHandler(m_wallet.NotifyStatusChanged.connect([fn](CCryptoKeyStore*) { fn(); }));
+ return MakeHandler(m_wallet->NotifyStatusChanged.connect([fn](CCryptoKeyStore*) { fn(); }));
}
std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) override
{
- return MakeHandler(m_wallet.NotifyAddressBookChanged.connect(
+ return MakeHandler(m_wallet->NotifyAddressBookChanged.connect(
[fn](CWallet*, const CTxDestination& address, const std::string& label, bool is_mine,
const std::string& purpose, ChangeType status) { fn(address, label, is_mine, purpose, status); }));
}
std::unique_ptr<Handler> handleTransactionChanged(TransactionChangedFn fn) override
{
- return MakeHandler(m_wallet.NotifyTransactionChanged.connect(
+ return MakeHandler(m_wallet->NotifyTransactionChanged.connect(
[fn](CWallet*, const uint256& txid, ChangeType status) { fn(txid, status); }));
}
std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) override
{
- return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
+ return MakeHandler(m_wallet->NotifyWatchonlyChanged.connect(fn));
+ }
+ std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) override
+ {
+ return MakeHandler(m_wallet->NotifyCanGetAddressesChanged.connect(fn));
}
- std::shared_ptr<CWallet> m_shared_wallet;
- CWallet& m_wallet;
+ std::shared_ptr<CWallet> m_wallet;
+};
+
+class WalletClientImpl : public ChainClient
+{
+public:
+ WalletClientImpl(Chain& chain, std::vector<std::string> wallet_filenames)
+ : m_chain(chain), m_wallet_filenames(std::move(wallet_filenames))
+ {
+ }
+ void registerRpcs() override { return RegisterWalletRPCCommands(m_chain, m_rpc_handlers); }
+ bool verify() override { return VerifyWallets(m_chain, m_wallet_filenames); }
+ bool load() override { return LoadWallets(m_chain, m_wallet_filenames); }
+ void start(CScheduler& scheduler) override { return StartWallets(scheduler); }
+ void flush() override { return FlushWallets(); }
+ void stop() override { return StopWallets(); }
+ ~WalletClientImpl() override { UnloadWallets(); }
+
+ Chain& m_chain;
+ std::vector<std::string> m_wallet_filenames;
+ std::vector<std::unique_ptr<Handler>> m_rpc_handlers;
};
} // namespace
-std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return MakeUnique<WalletImpl>(wallet); }
+std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? MakeUnique<WalletImpl>(wallet) : nullptr; }
+
+std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, std::vector<std::string> wallet_filenames)
+{
+ return MakeUnique<WalletClientImpl>(chain, std::move(wallet_filenames));
+}
} // namespace interfaces
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index ae54d42442..7096f54047 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -179,15 +179,14 @@ public:
virtual bool tryGetTxStatus(const uint256& txid,
WalletTxStatus& tx_status,
int& num_blocks,
- int64_t& adjusted_time) = 0;
+ int64_t& block_time) = 0;
//! Get transaction details.
virtual WalletTx getWalletTxDetails(const uint256& txid,
WalletTxStatus& tx_status,
WalletOrderForm& order_form,
bool& in_mempool,
- int& num_blocks,
- int64_t& adjusted_time) = 0;
+ int& num_blocks) = 0;
//! Get balances.
virtual WalletBalances getBalances() = 0;
@@ -236,6 +235,9 @@ public:
// Return whether HD enabled.
virtual bool hdEnabled() = 0;
+ // Return whether the wallet is blank.
+ virtual bool canGetAddresses() = 0;
+
// check if a certain wallet flag is set.
virtual bool IsWalletFlagSet(uint64_t flag) = 0;
@@ -245,6 +247,12 @@ public:
// Get default change type.
virtual OutputType getDefaultChangeType() = 0;
+ //! Get max tx fee.
+ virtual CAmount getDefaultMaxTxFee() = 0;
+
+ // Remove wallet.
+ virtual void remove() = 0;
+
//! Register handler for unload message.
using UnloadFn = std::function<void()>;
virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
@@ -272,6 +280,10 @@ public:
//! Register handler for watchonly changed messages.
using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
virtual std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;
+
+ //! Register handler for keypool changed messages.
+ using CanGetAddressesChangedFn = std::function<void()>;
+ virtual std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) = 0;
};
//! Tracking object returned by CreateTransaction and passed to CommitTransaction.
@@ -283,13 +295,9 @@ public:
//! Get transaction data.
virtual const CTransaction& get() = 0;
- //! Get virtual transaction size.
- virtual int64_t getVirtualSize() = 0;
-
//! Send pending transaction and commit to wallet.
virtual bool commit(WalletValueMap value_map,
WalletOrderForm order_form,
- std::string from_account,
std::string& reject_reason) = 0;
};
@@ -367,8 +375,8 @@ struct WalletTxOut
bool is_spent = false;
};
-//! Return implementation of Wallet interface. This function will be undefined
-//! in builds where ENABLE_WALLET is false.
+//! Return implementation of Wallet interface. This function is defined in
+//! dummywallet.cpp and throws if the wallet component is not compiled.
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
} // namespace interfaces
diff --git a/src/key.cpp b/src/key.cpp
index 94be179bfb..c17f6a0ae2 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 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.
@@ -89,7 +89,7 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou
* will be set to the number of bytes used in the buffer.
* key32 must point to a 32-byte raw private key.
*/
-static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) {
+static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, bool compressed) {
assert(*privkeylen >= CKey::PRIVATE_KEY_SIZE);
secp256k1_pubkey pubkey;
size_t pubkeylen = 0;
@@ -163,6 +163,12 @@ void CKey::MakeNewKey(bool fCompressedIn) {
fCompressed = fCompressedIn;
}
+bool CKey::Negate()
+{
+ assert(fValid);
+ return secp256k1_ec_privkey_negate(secp256k1_context_sign, keydata.data());
+}
+
CPrivKey CKey::GetPrivKey() const {
assert(fValid);
CPrivKey privkey;
@@ -170,7 +176,7 @@ CPrivKey CKey::GetPrivKey() const {
size_t privkeylen;
privkey.resize(PRIVATE_KEY_SIZE);
privkeylen = PRIVATE_KEY_SIZE;
- ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
+ ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed);
assert(ret);
privkey.resize(privkeylen);
return privkey;
@@ -189,7 +195,20 @@ CPubKey CKey::GetPubKey() const {
return result;
}
-bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
+// Check that the sig has a low R value and will be less than 71 bytes
+bool SigHasLowR(const secp256k1_ecdsa_signature* sig)
+{
+ unsigned char compact_sig[64];
+ secp256k1_ecdsa_signature_serialize_compact(secp256k1_context_sign, compact_sig, sig);
+
+ // In DER serialization, all values are interpreted as big-endian, signed integers. The highest bit in the integer indicates
+ // its signed-ness; 0 is positive, 1 is negative. When the value is interpreted as a negative integer, it must be converted
+ // to a positive value by prepending a 0x00 byte so that the highest bit is 0. We can avoid this prepending by ensuring that
+ // our highest bit is always 0, and thus we must check that the first byte is less than 0x80.
+ return compact_sig[0] < 0x80;
+}
+
+bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, bool grind, uint32_t test_case) const {
if (!fValid)
return false;
vchSig.resize(CPubKey::SIGNATURE_SIZE);
@@ -197,7 +216,14 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_
unsigned char extra_entropy[32] = {0};
WriteLE32(extra_entropy, test_case);
secp256k1_ecdsa_signature sig;
- int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, test_case ? extra_entropy : nullptr);
+ uint32_t counter = 0;
+ int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, (!grind && test_case) ? extra_entropy : nullptr);
+
+ // Grind for low R
+ while (ret && !SigHasLowR(&sig) && grind) {
+ WriteLE32(extra_entropy, ++counter);
+ ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, extra_entropy);
+ }
assert(ret);
secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, vchSig.data(), &nSigLen, &sig);
vchSig.resize(nSigLen);
@@ -226,7 +252,7 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
secp256k1_ecdsa_recoverable_signature sig;
int ret = secp256k1_ecdsa_sign_recoverable(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, nullptr);
assert(ret);
- secp256k1_ecdsa_recoverable_signature_serialize_compact(secp256k1_context_sign, &vchSig[1], &rec, &sig);
+ ret = secp256k1_ecdsa_recoverable_signature_serialize_compact(secp256k1_context_sign, &vchSig[1], &rec, &sig);
assert(ret);
assert(rec != -1);
vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
diff --git a/src/key.h b/src/key.h
index f573a18a4e..67e2cfc094 100644
--- a/src/key.h
+++ b/src/key.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 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.
@@ -98,6 +98,9 @@ public:
//! Generate a new private key using a cryptographic PRNG.
void MakeNewKey(bool fCompressed);
+ //! Negate private key
+ bool Negate();
+
/**
* Convert the private key to a CPrivKey (serialized OpenSSL private key data).
* This is expensive.
@@ -114,7 +117,7 @@ public:
* Create a DER-serialized signature.
* The test_case parameter tweaks the deterministic nonce.
*/
- bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const;
+ bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, bool grind = true, uint32_t test_case = 0) const;
/**
* Create a compact signature (65 bytes), which allows reconstructing the used public key.
@@ -181,12 +184,12 @@ struct CExtKey {
};
/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */
-void ECC_Start(void);
+void ECC_Start();
/** Deinitialize the elliptic curve support. No-op if ECC_Start wasn't called first. */
-void ECC_Stop(void);
+void ECC_Stop();
/** Check that required EC support is available at runtime. */
-bool ECC_InitSanityCheck(void);
+bool ECC_InitSanityCheck();
#endif // BITCOIN_KEY_H
diff --git a/src/key_io.cpp b/src/key_io.cpp
index c2dc511989..cd41a93549 100644
--- a/src/key_io.cpp
+++ b/src/key_io.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2016 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,7 +7,7 @@
#include <base58.h>
#include <bech32.h>
#include <script/script.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
@@ -24,16 +24,16 @@ private:
const CChainParams& m_params;
public:
- DestinationEncoder(const CChainParams& params) : m_params(params) {}
+ explicit DestinationEncoder(const CChainParams& params) : m_params(params) {}
- std::string operator()(const CKeyID& id) const
+ std::string operator()(const PKHash& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}
- std::string operator()(const CScriptID& id) const
+ std::string operator()(const ScriptHash& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
@@ -81,14 +81,14 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
- return CKeyID(hash);
+ return PKHash(hash);
}
// Script-hash-addresses have version 5 (or 196 testnet).
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
- return CScriptID(hash);
+ return ScriptHash(hash);
}
}
data.clear();
@@ -142,7 +142,9 @@ CKey DecodeSecret(const std::string& str)
key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
}
}
- memory_cleanse(data.data(), data.size());
+ if (!data.empty()) {
+ memory_cleanse(data.data(), data.size());
+ }
return key;
}
diff --git a/src/key_io.h b/src/key_io.h
index d75b5b31c8..d80c08f49c 100644
--- a/src/key_io.h
+++ b/src/key_io.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/keystore.cpp b/src/keystore.cpp
index ea93ed69fa..f6d19416ce 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -1,11 +1,11 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <keystore.h>
-#include <util.h>
+#include <util/system.h>
void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
{
@@ -178,16 +178,17 @@ CKeyID GetKeyForDestination(const CKeyStore& store, const CTxDestination& dest)
{
// Only supports destinations which map to single public keys, i.e. P2PKH,
// P2WPKH, and P2SH-P2WPKH.
- if (auto id = boost::get<CKeyID>(&dest)) {
- return *id;
+ if (auto id = boost::get<PKHash>(&dest)) {
+ return CKeyID(*id);
}
if (auto witness_id = boost::get<WitnessV0KeyHash>(&dest)) {
return CKeyID(*witness_id);
}
- if (auto script_id = boost::get<CScriptID>(&dest)) {
+ if (auto script_hash = boost::get<ScriptHash>(&dest)) {
CScript script;
+ CScriptID script_id(*script_hash);
CTxDestination inner_dest;
- if (store.GetCScript(*script_id, script) && ExtractDestination(script, inner_dest)) {
+ if (store.GetCScript(script_id, script) && ExtractDestination(script, inner_dest)) {
if (auto inner_witness_id = boost::get<WitnessV0KeyHash>(&inner_dest)) {
return CKeyID(*inner_witness_id);
}
diff --git a/src/keystore.h b/src/keystore.h
index f64024c7e7..4bd99e255d 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/leveldb/db/c.cc b/src/leveldb/db/c.cc
index 08ff0ad90a..b23e3dcc9d 100644
--- a/src/leveldb/db/c.cc
+++ b/src/leveldb/db/c.cc
@@ -5,7 +5,9 @@
#include "leveldb/c.h"
#include <stdlib.h>
+#ifndef WIN32
#include <unistd.h>
+#endif
#include "leveldb/cache.h"
#include "leveldb/comparator.h"
#include "leveldb/db.h"
diff --git a/src/leveldb/port/port_win.h b/src/leveldb/port/port_win.h
index e8bf46ef27..989c15cd91 100644
--- a/src/leveldb/port/port_win.h
+++ b/src/leveldb/port/port_win.h
@@ -32,9 +32,16 @@
#define STORAGE_LEVELDB_PORT_PORT_WIN_H_
#ifdef _MSC_VER
+#if !(_MSC_VER >= 1900)
#define snprintf _snprintf
+#endif
#define close _close
#define fread_unlocked _fread_nolock
+#ifdef _WIN64
+#define ssize_t int64_t
+#else
+#define ssize_t int32_t
+#endif
#endif
#include <string>
diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc
index 4676bc2240..f77918313e 100644
--- a/src/leveldb/util/env_posix.cc
+++ b/src/leveldb/util/env_posix.cc
@@ -585,8 +585,8 @@ static int MaxMmaps() {
if (mmap_limit >= 0) {
return mmap_limit;
}
- // Up to 1000 mmaps for 64-bit binaries; none for smaller pointer sizes.
- mmap_limit = sizeof(void*) >= 8 ? 1000 : 0;
+ // Up to 4096 mmaps for 64-bit binaries; none for smaller pointer sizes.
+ mmap_limit = sizeof(void*) >= 8 ? 4096 : 0;
return mmap_limit;
}
diff --git a/src/leveldb/util/env_win.cc b/src/leveldb/util/env_win.cc
index 81380216bb..830332abe9 100644
--- a/src/leveldb/util/env_win.cc
+++ b/src/leveldb/util/env_win.cc
@@ -203,24 +203,16 @@ public:
void ToWidePath(const std::string& value, std::wstring& target) {
wchar_t buffer[MAX_PATH];
- MultiByteToWideChar(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH);
+ MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, buffer, MAX_PATH);
target = buffer;
}
void ToNarrowPath(const std::wstring& value, std::string& target) {
char buffer[MAX_PATH];
- WideCharToMultiByte(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, value.c_str(), -1, buffer, MAX_PATH, NULL, NULL);
target = buffer;
}
-std::string GetCurrentDir()
-{
- CHAR path[MAX_PATH];
- ::GetModuleFileNameA(::GetModuleHandleA(NULL),path,MAX_PATH);
- *strrchr(path,'\\') = 0;
- return std::string(path);
-}
-
std::wstring GetCurrentDirW()
{
WCHAR path[MAX_PATH];
@@ -229,6 +221,13 @@ std::wstring GetCurrentDirW()
return std::wstring(path);
}
+std::string GetCurrentDir()
+{
+ std::string path;
+ ToNarrowPath(GetCurrentDirW(), path);
+ return path;
+}
+
std::string& ModifyPath(std::string& path)
{
if(path[0] == '/' || path[0] == '\\'){
@@ -764,14 +763,16 @@ uint64_t Win32Env::NowMicros()
static Status CreateDirInner( const std::string& dirname )
{
Status sRet;
- DWORD attr = ::GetFileAttributes(dirname.c_str());
+ std::wstring dirnameW;
+ ToWidePath(dirname, dirnameW);
+ DWORD attr = ::GetFileAttributesW(dirnameW.c_str());
if (attr == INVALID_FILE_ATTRIBUTES) { // doesn't exist:
std::size_t slash = dirname.find_last_of("\\");
if (slash != std::string::npos){
sRet = CreateDirInner(dirname.substr(0, slash));
if (!sRet.ok()) return sRet;
}
- BOOL result = ::CreateDirectory(dirname.c_str(), NULL);
+ BOOL result = ::CreateDirectoryW(dirnameW.c_str(), NULL);
if (result == FALSE) {
sRet = Status::IOError(dirname, "Could not create directory.");
return sRet;
diff --git a/src/limitedmap.h b/src/limitedmap.h
index 22dde5ec36..7d66964e36 100644
--- a/src/limitedmap.h
+++ b/src/limitedmap.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/logging.cpp b/src/logging.cpp
index e8e22cbf97..3eda4995db 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -4,10 +4,15 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <logging.h>
-#include <utiltime.h>
+#include <util/threadnames.h>
+#include <util/time.h>
+
+#include <mutex>
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
+BCLog::Logger& LogInstance()
+{
/**
* NOTE: the logger instances is leaked on exit. This is ugly, but will be
* cleaned up by the OS/libc. Defining a logger as a global object doesn't work
@@ -17,11 +22,15 @@ const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
* access the logger. When the shutdown sequence is fully audited and tested,
* explicit destruction of these objects can be implemented by changing this
* from a raw pointer to a std::unique_ptr.
+ * Since the destructor is never called, the logger and all its members must
+ * have a trivial destructor.
*
* This method of initialization was originally introduced in
* ee3374234c60aba2cc4c5cd5cac1c0aefc2d817c.
*/
-BCLog::Logger* const g_logger = new BCLog::Logger();
+ static BCLog::Logger* g_logger{new BCLog::Logger()};
+ return *g_logger;
+}
bool fLogIPs = DEFAULT_LOGIPS;
@@ -168,7 +177,7 @@ std::vector<CLogCategoryActive> ListActiveLogCategories()
return ret;
}
-std::string BCLog::Logger::LogTimestampStr(const std::string &str)
+std::string BCLog::Logger::LogTimestampStr(const std::string& str)
{
std::string strStamped;
@@ -190,21 +199,24 @@ std::string BCLog::Logger::LogTimestampStr(const std::string &str)
} else
strStamped = str;
- if (!str.empty() && str[str.size()-1] == '\n')
- m_started_new_line = true;
- else
- m_started_new_line = false;
-
return strStamped;
}
void BCLog::Logger::LogPrintStr(const std::string &str)
{
- std::string strTimestamped = LogTimestampStr(str);
+ std::string str_prefixed = str;
+
+ if (m_log_threadnames && m_started_new_line) {
+ str_prefixed.insert(0, "[" + util::ThreadGetInternalName() + "] ");
+ }
+
+ str_prefixed = LogTimestampStr(str_prefixed);
+
+ m_started_new_line = !str.empty() && str[str.size()-1] == '\n';
if (m_print_to_console) {
// print to console
- fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
+ fwrite(str_prefixed.data(), 1, str_prefixed.size(), stdout);
fflush(stdout);
}
if (m_print_to_file) {
@@ -212,21 +224,21 @@ void BCLog::Logger::LogPrintStr(const std::string &str)
// buffer if we haven't opened the log yet
if (m_fileout == nullptr) {
- m_msgs_before_open.push_back(strTimestamped);
+ m_msgs_before_open.push_back(str_prefixed);
}
else
{
// reopen the log file, if requested
if (m_reopen_file) {
m_reopen_file = false;
- m_fileout = fsbridge::freopen(m_file_path, "a", m_fileout);
- if (!m_fileout) {
- return;
+ FILE* new_fileout = fsbridge::fopen(m_file_path, "a");
+ if (new_fileout) {
+ setbuf(new_fileout, nullptr); // unbuffered
+ fclose(m_fileout);
+ m_fileout = new_fileout;
}
- setbuf(m_fileout, nullptr); // unbuffered
}
-
- FileWriteStr(strTimestamped, m_fileout);
+ FileWriteStr(str_prefixed, m_fileout);
}
}
}
@@ -245,7 +257,7 @@ void BCLog::Logger::ShrinkDebugFile()
size_t log_size = 0;
try {
log_size = fs::file_size(m_file_path);
- } catch (boost::filesystem::filesystem_error &) {}
+ } catch (const fs::filesystem_error&) {}
// If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE
// trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes
diff --git a/src/logging.h b/src/logging.h
index 6400b131c2..e399d4c307 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -19,6 +19,7 @@
static const bool DEFAULT_LOGTIMEMICROS = false;
static const bool DEFAULT_LOGIPS = false;
static const bool DEFAULT_LOGTIMESTAMPS = true;
+static const bool DEFAULT_LOGTHREADNAMES = false;
extern const char * const DEFAULT_DEBUGLOGFILE;
extern bool fLogIPs;
@@ -81,6 +82,7 @@ namespace BCLog {
bool m_log_timestamps = DEFAULT_LOGTIMESTAMPS;
bool m_log_time_micros = DEFAULT_LOGTIMEMICROS;
+ bool m_log_threadnames = DEFAULT_LOGTHREADNAMES;
fs::path m_file_path;
std::atomic<bool> m_reopen_file{false};
@@ -108,12 +110,12 @@ namespace BCLog {
} // namespace BCLog
-extern BCLog::Logger* const g_logger;
+BCLog::Logger& LogInstance();
/** Return true if log accepts specified category */
static inline bool LogAcceptCategory(BCLog::LogFlags category)
{
- return g_logger->WillLogCategory(category);
+ return LogInstance().WillLogCategory(category);
}
/** Returns a string with the log categories. */
@@ -125,42 +127,31 @@ std::vector<CLogCategoryActive> ListActiveLogCategories();
/** Return true if str parses as a log category and set the flag */
bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str);
-/** Get format string from VA_ARGS for error reporting */
-template<typename... Args> std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; }
-
-static inline void MarkUsed() {}
-template<typename T, typename... Args> static inline void MarkUsed(const T& t, const Args&... args)
-{
- (void)t;
- MarkUsed(args...);
-}
-
// Be conservative when using LogPrintf/error or other things which
// unconditionally log to debug.log! It should not be the case that an inbound
// peer can fill up a user's disk with debug.log entries.
-#ifdef USE_COVERAGE
-#define LogPrintf(...) do { MarkUsed(__VA_ARGS__); } while(0)
-#define LogPrint(category, ...) do { MarkUsed(__VA_ARGS__); } while(0)
-#else
-#define LogPrintf(...) do { \
- if (g_logger->Enabled()) { \
- std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \
- try { \
- _log_msg_ = tfm::format(__VA_ARGS__); \
- } catch (tinyformat::format_error &fmterr) { \
- /* Original format string will have newline so don't add one here */ \
- _log_msg_ = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \
- } \
- g_logger->LogPrintStr(_log_msg_); \
- } \
-} while(0)
-
-#define LogPrint(category, ...) do { \
- if (LogAcceptCategory((category))) { \
- LogPrintf(__VA_ARGS__); \
- } \
-} while(0)
-#endif
+template <typename... Args>
+static inline void LogPrintf(const char* fmt, const Args&... args)
+{
+ if (LogInstance().Enabled()) {
+ std::string log_msg;
+ try {
+ log_msg = tfm::format(fmt, args...);
+ } catch (tinyformat::format_error& fmterr) {
+ /* Original format string will have newline so don't add one here */
+ log_msg = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + fmt;
+ }
+ LogInstance().LogPrintStr(log_msg);
+ }
+}
+
+template <typename... Args>
+static inline void LogPrint(const BCLog::LogFlags& category, const Args&... args)
+{
+ if (LogAcceptCategory((category))) {
+ LogPrintf(args...);
+ }
+}
#endif // BITCOIN_LOGGING_H
diff --git a/src/memusage.h b/src/memusage.h
index 0b92e53b48..3ae9face15 100644
--- a/src/memusage.h
+++ b/src/memusage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index de3519c1da..a54268d655 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,7 +7,7 @@
#include <hash.h>
#include <consensus/consensus.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids)
@@ -53,7 +53,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
else
right = left;
// combine subhashes
- return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
+ return Hash(left.begin(), left.end(), right.begin(), right.end());
}
}
@@ -109,7 +109,7 @@ uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, uns
right = left;
}
// and combine them before returning
- return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
+ return Hash(left.begin(), left.end(), right.begin(), right.end());
}
}
diff --git a/src/merkleblock.h b/src/merkleblock.h
index 984e33a961..e641c8aa94 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/miner.cpp b/src/miner.cpp
index c32dc26f86..3d53515435 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,8 +10,8 @@
#include <chainparams.h>
#include <coins.h>
#include <consensus/consensus.h>
-#include <consensus/tx_verify.h>
#include <consensus/merkle.h>
+#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <hash.h>
#include <net.h>
@@ -21,22 +21,15 @@
#include <primitives/transaction.h>
#include <script/standard.h>
#include <timedata.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/moneystr.h>
+#include <util/system.h>
+#include <util/validation.h>
#include <validationinterface.h>
#include <algorithm>
#include <queue>
#include <utility>
-// Unconfirmed transactions in the memory pool often depend on other
-// transactions in the memory pool. When we select transactions from the
-// pool, we select by highest fee rate of a transaction combined with all
-// its ancestors.
-
-uint64_t nLastBlockTx = 0;
-uint64_t nLastBlockWeight = 0;
-
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
{
int64_t nOldTime = pblock->nTime;
@@ -70,9 +63,8 @@ static BlockAssembler::Options DefaultOptions()
// If -blockmaxweight is not given, limit to DEFAULT_BLOCK_MAX_WEIGHT
BlockAssembler::Options options;
options.nBlockMaxWeight = gArgs.GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
- if (gArgs.IsArgSet("-blockmintxfee")) {
- CAmount n = 0;
- ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n);
+ CAmount n = 0;
+ if (gArgs.IsArgSet("-blockmintxfee") && ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) {
options.blockMinFeeRate = CFeeRate(n);
} else {
options.blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
@@ -96,7 +88,10 @@ void BlockAssembler::resetBlock()
nFees = 0;
}
-std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx)
+Optional<int64_t> BlockAssembler::m_last_block_num_txs{nullopt};
+Optional<int64_t> BlockAssembler::m_last_block_weight{nullopt};
+
+std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
{
int64_t nTimeStart = GetTimeMicros();
@@ -114,7 +109,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end
LOCK2(cs_main, mempool.cs);
- CBlockIndex* pindexPrev = chainActive.Tip();
+ CBlockIndex* pindexPrev = ::ChainActive().Tip();
assert(pindexPrev != nullptr);
nHeight = pindexPrev->nHeight + 1;
@@ -133,11 +128,14 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
// Decide whether to include witness transactions
// This is only needed in case the witness softfork activation is reverted
- // (which would require a very deep reorganization) or when
- // -promiscuousmempoolflags is used.
+ // (which would require a very deep reorganization).
+ // Note that the mempool would accept transactions with witness data before
+ // IsWitnessEnabled, but we would only ever mine blocks after IsWitnessEnabled
+ // unless there is a massive block reorganization with the witness softfork
+ // not activated.
// TODO: replace this with a call to main to assess validity of a mempool
// transaction (which in most cases can be a no-op).
- fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()) && fMineWitnessTx;
+ fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus());
int nPackagesSelected = 0;
int nDescendantsUpdated = 0;
@@ -145,8 +143,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
int64_t nTime1 = GetTimeMicros();
- nLastBlockTx = nBlockTx;
- nLastBlockWeight = nBlockWeight;
+ m_last_block_num_txs = nBlockTx;
+ m_last_block_weight = nBlockWeight;
// Create coinbase transaction.
CMutableTransaction coinbaseTx;
diff --git a/src/miner.h b/src/miner.h
index ed1b4434f9..7c4c455072 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -1,17 +1,19 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MINER_H
#define BITCOIN_MINER_H
+#include <optional.h>
#include <primitives/block.h>
#include <txmempool.h>
#include <validation.h>
-#include <stdint.h>
#include <memory>
+#include <stdint.h>
+
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
@@ -157,7 +159,10 @@ public:
BlockAssembler(const CChainParams& params, const Options& options);
/** Construct a new block template with coinbase to scriptPubKeyIn */
- std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx=true);
+ std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
+
+ static Optional<int64_t> m_last_block_num_txs;
+ static Optional<int64_t> m_last_block_weight;
private:
// utility functions
diff --git a/src/net.cpp b/src/net.cpp
index 0ebfefa757..3c6f5a05f3 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,6 +9,7 @@
#include <net.h>
+#include <banman.h>
#include <chainparams.h>
#include <clientversion.h>
#include <consensus/consensus.h>
@@ -18,7 +19,7 @@
#include <netbase.h>
#include <scheduler.h>
#include <ui_interface.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#ifdef WIN32
#include <string.h>
@@ -26,6 +27,10 @@
#include <fcntl.h>
#endif
+#ifdef USE_POLL
+#include <poll.h>
+#endif
+
#ifdef USE_UPNP
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/miniwget.h>
@@ -33,11 +38,12 @@
#include <miniupnpc/upnperrors.h>
#endif
+#include <unordered_map>
#include <math.h>
-// Dump addresses to peers.dat and banlist.dat every 15 minutes (900s)
-#define DUMP_ADDRESSES_INTERVAL 900
+// Dump addresses to peers.dat every 15 minutes (900s)
+static constexpr int DUMP_PEERS_INTERVAL = 15 * 60;
// We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
#define FEELER_SLEEP_WINDOW 1
@@ -52,17 +58,6 @@
#define MSG_DONTWAIT 0
#endif
-// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
-// Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
-#ifdef WIN32
-#ifndef PROTECTION_LEVEL_UNRESTRICTED
-#define PROTECTION_LEVEL_UNRESTRICTED 10
-#endif
-#ifndef IPV6_PROTECTION_LEVEL
-#define IPV6_PROTECTION_LEVEL 23
-#endif
-#endif
-
/** Used to pass flags to the Bind() function */
enum BindFlags {
BF_NONE = 0,
@@ -71,7 +66,11 @@ enum BindFlags {
BF_WHITELIST = (1U << 2),
};
-const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
+// The set of sockets cannot be modified while waiting
+// The sleep time needs to be small to avoid new sockets stalling
+static const uint64_t SELECT_TIMEOUT_MILLISECONDS = 50;
+
+const std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
@@ -80,14 +79,12 @@ static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // S
//
bool fDiscover = true;
bool fListen = true;
-bool fRelayTxes = true;
+bool g_relay_txes = !DEFAULT_BLOCKSONLY;
CCriticalSection cs_mapLocalHost;
-std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
-static bool vfLimited[NET_MAX] = {};
+std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(cs_mapLocalHost);
+static bool vfLimited[NET_MAX] GUARDED_BY(cs_mapLocalHost) = {};
std::string strSubVersion;
-limitedmap<uint256, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
-
void CConnman::AddOneShot(const std::string& strDest)
{
LOCK(cs_vOneShots);
@@ -134,11 +131,12 @@ static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn
const int64_t nOneWeek = 7*24*60*60;
std::vector<CAddress> vSeedsOut;
vSeedsOut.reserve(vSeedsIn.size());
+ FastRandomContext rng;
for (const auto& seed_in : vSeedsIn) {
struct in6_addr ip;
memcpy(&ip, seed_in.addr, sizeof(ip));
CAddress addr(CService(ip, seed_in.port), GetDesirableServiceFlags(NODE_NONE));
- addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
+ addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek;
vSeedsOut.push_back(addr);
}
return vSeedsOut;
@@ -163,8 +161,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
static int GetnScore(const CService& addr)
{
LOCK(cs_mapLocalHost);
- if (mapLocalHost.count(addr) == LOCAL_NONE)
- return 0;
+ if (mapLocalHost.count(addr) == 0) return 0;
return mapLocalHost[addr].nScore;
}
@@ -173,7 +170,7 @@ bool IsPeerAddrLocalGood(CNode *pnode)
{
CService addrLocal = pnode->GetAddrLocal();
return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
- !IsLimited(addrLocal.GetNetwork());
+ IsReachable(addrLocal.GetNetwork());
}
// pushes our own address to a peer
@@ -189,16 +186,16 @@ void AdvertiseLocal(CNode *pnode)
// If discovery is enabled, sometimes give our peer the address it
// tells us that it sees us as in case it has a better idea of our
// address than we do.
+ FastRandomContext rng;
if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
- GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
+ rng.randbits((GetnScore(addrLocal) > LOCAL_MANUAL) ? 3 : 1) == 0))
{
addrLocal.SetIP(pnode->GetAddrLocal());
}
if (addrLocal.IsRoutable() || gArgs.GetBoolArg("-addrmantest", false))
{
LogPrint(BCLog::NET, "AdvertiseLocal: advertising address %s\n", addrLocal.ToString());
- FastRandomContext insecure_rand;
- pnode->PushAddress(addrLocal, insecure_rand);
+ pnode->PushAddress(addrLocal, rng);
}
}
}
@@ -212,7 +209,7 @@ bool AddLocal(const CService& addr, int nScore)
if (!fDiscover && nScore < LOCAL_MANUAL)
return false;
- if (IsLimited(addr))
+ if (!IsReachable(addr))
return false;
LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
@@ -242,24 +239,23 @@ void RemoveLocal(const CService& addr)
mapLocalHost.erase(addr);
}
-/** Make a particular network entirely off-limits (no automatic connects to it) */
-void SetLimited(enum Network net, bool fLimited)
+void SetReachable(enum Network net, bool reachable)
{
if (net == NET_UNROUTABLE || net == NET_INTERNAL)
return;
LOCK(cs_mapLocalHost);
- vfLimited[net] = fLimited;
+ vfLimited[net] = !reachable;
}
-bool IsLimited(enum Network net)
+bool IsReachable(enum Network net)
{
LOCK(cs_mapLocalHost);
- return vfLimited[net];
+ return !vfLimited[net];
}
-bool IsLimited(const CNetAddr &addr)
+bool IsReachable(const CNetAddr &addr)
{
- return IsLimited(addr.GetNetwork());
+ return IsReachable(addr.GetNetwork());
}
/** vote for a local address */
@@ -282,21 +278,6 @@ bool IsLocal(const CService& addr)
return mapLocalHost.count(addr) > 0;
}
-/** check whether a given network is one we can probably connect to */
-bool IsReachable(enum Network net)
-{
- LOCK(cs_mapLocalHost);
- return !vfLimited[net];
-}
-
-/** check whether a given address is in a network we can probably connect to */
-bool IsReachable(const CNetAddr& addr)
-{
- enum Network net = addr.GetNetwork();
- return IsReachable(net);
-}
-
-
CNode* CConnman::FindNode(const CNetAddr& ip)
{
LOCK(cs_vNodes);
@@ -344,7 +325,7 @@ CNode* CConnman::FindNode(const CService& addr)
bool CConnman::CheckIncomingNonce(uint64_t nonce)
{
LOCK(cs_vNodes);
- for (CNode* pnode : vNodes) {
+ for (const CNode* pnode : vNodes) {
if (!pnode->fSuccessfullyConnected && !pnode->fInbound && pnode->GetLocalNonce() == nonce)
return false;
}
@@ -463,26 +444,6 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
return pnode;
}
-void CConnman::DumpBanlist()
-{
- SweepBanned(); // clean unused entries (if bantime has expired)
-
- if (!BannedSetIsDirty())
- return;
-
- int64_t nStart = GetTimeMillis();
-
- CBanDB bandb;
- banmap_t banmap;
- GetBanned(banmap);
- if (bandb.Write(banmap)) {
- SetBannedSetDirty(false);
- }
-
- LogPrint(BCLog::NET, "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
- banmap.size(), GetTimeMillis() - nStart);
-}
-
void CNode::CloseSocketDisconnect()
{
fDisconnect = true;
@@ -494,157 +455,6 @@ void CNode::CloseSocketDisconnect()
}
}
-void CConnman::ClearBanned()
-{
- {
- LOCK(cs_setBanned);
- setBanned.clear();
- setBannedIsDirty = true;
- }
- DumpBanlist(); //store banlist to disk
- if(clientInterface)
- clientInterface->BannedListChanged();
-}
-
-bool CConnman::IsBanned(CNetAddr ip)
-{
- LOCK(cs_setBanned);
- for (const auto& it : setBanned) {
- CSubNet subNet = it.first;
- CBanEntry banEntry = it.second;
-
- if (subNet.Match(ip) && GetTime() < banEntry.nBanUntil) {
- return true;
- }
- }
- return false;
-}
-
-bool CConnman::IsBanned(CSubNet subnet)
-{
- LOCK(cs_setBanned);
- banmap_t::iterator i = setBanned.find(subnet);
- if (i != setBanned.end())
- {
- CBanEntry banEntry = (*i).second;
- if (GetTime() < banEntry.nBanUntil) {
- return true;
- }
- }
- return false;
-}
-
-void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
- CSubNet subNet(addr);
- Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch);
-}
-
-void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
- CBanEntry banEntry(GetTime());
- banEntry.banReason = banReason;
- if (bantimeoffset <= 0)
- {
- bantimeoffset = gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME);
- sinceUnixEpoch = false;
- }
- banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
-
- {
- LOCK(cs_setBanned);
- if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) {
- setBanned[subNet] = banEntry;
- setBannedIsDirty = true;
- }
- else
- return;
- }
- if(clientInterface)
- clientInterface->BannedListChanged();
- {
- LOCK(cs_vNodes);
- for (CNode* pnode : vNodes) {
- if (subNet.Match(static_cast<CNetAddr>(pnode->addr)))
- pnode->fDisconnect = true;
- }
- }
- if(banReason == BanReasonManuallyAdded)
- DumpBanlist(); //store banlist to disk immediately if user requested ban
-}
-
-bool CConnman::Unban(const CNetAddr &addr) {
- CSubNet subNet(addr);
- return Unban(subNet);
-}
-
-bool CConnman::Unban(const CSubNet &subNet) {
- {
- LOCK(cs_setBanned);
- if (!setBanned.erase(subNet))
- return false;
- setBannedIsDirty = true;
- }
- if(clientInterface)
- clientInterface->BannedListChanged();
- DumpBanlist(); //store banlist to disk immediately
- return true;
-}
-
-void CConnman::GetBanned(banmap_t &banMap)
-{
- LOCK(cs_setBanned);
- // Sweep the banlist so expired bans are not returned
- SweepBanned();
- banMap = setBanned; //create a thread safe copy
-}
-
-void CConnman::SetBanned(const banmap_t &banMap)
-{
- LOCK(cs_setBanned);
- setBanned = banMap;
- setBannedIsDirty = true;
-}
-
-void CConnman::SweepBanned()
-{
- int64_t now = GetTime();
- bool notifyUI = false;
- {
- LOCK(cs_setBanned);
- banmap_t::iterator it = setBanned.begin();
- while(it != setBanned.end())
- {
- CSubNet subNet = (*it).first;
- CBanEntry banEntry = (*it).second;
- if(now > banEntry.nBanUntil)
- {
- setBanned.erase(it++);
- setBannedIsDirty = true;
- notifyUI = true;
- LogPrint(BCLog::NET, "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, subNet.ToString());
- }
- else
- ++it;
- }
- }
- // update UI
- if(notifyUI && clientInterface) {
- clientInterface->BannedListChanged();
- }
-}
-
-bool CConnman::BannedSetIsDirty()
-{
- LOCK(cs_setBanned);
- return setBannedIsDirty;
-}
-
-void CConnman::SetBannedSetDirty(bool dirty)
-{
- LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag
- setBannedIsDirty = dirty;
-}
-
-
bool CConnman::IsWhitelistedRange(const CNetAddr &addr) {
for (const CSubNet& subnet : vWhitelistedRange) {
if (subnet.Match(addr))
@@ -715,6 +525,10 @@ void CNode::copyStats(CNodeStats &stats)
X(nRecvBytes);
}
X(fWhitelisted);
+ {
+ LOCK(cs_feeFilter);
+ X(minFeeFilter);
+ }
// It is common for nodes with good ping times to suddenly become lagged,
// due to a new block arriving or other large transfer.
@@ -773,7 +587,6 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete
nBytes -= handled;
if (msg.complete()) {
-
//store received bytes per message command
//to prevent a memory DOS, only allow valid commands
mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.hdr.pchCommand);
@@ -873,16 +686,7 @@ const uint256& CNetMessage::GetMessageHash() const
return data_hash;
}
-
-
-
-
-
-
-
-
-// requires LOCK(cs_vSend)
-size_t CConnman::SocketSendData(CNode *pnode) const
+size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_vSend)
{
auto it = pnode->vSendMsg.begin();
size_t nSentSize = 0;
@@ -946,6 +750,7 @@ struct NodeEvictionCandidate
bool fBloomFilter;
CAddress addr;
uint64_t nKeyedNetGroup;
+ bool prefer_evict;
};
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
@@ -1010,10 +815,12 @@ bool CConnman::AttemptToEvictConnection()
continue;
if (node->fDisconnect)
continue;
+ LOCK(node->cs_filter);
NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
node->nLastBlockTime, node->nLastTXTime,
HasAllDesirableServiceFlags(node->nServices),
- node->fRelayTxes, node->pfilter != nullptr, node->addr, node->nKeyedNetGroup};
+ node->fRelayTxes, node->pfilter != nullptr, node->addr, node->nKeyedNetGroup,
+ node->m_prefer_evict};
vEvictionCandidates.push_back(candidate);
}
}
@@ -1038,6 +845,14 @@ bool CConnman::AttemptToEvictConnection()
if (vEvictionCandidates.empty()) return false;
+ // If any remaining peers are preferred for eviction consider only them.
+ // This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
+ // then we probably don't want to evict it no matter what.
+ if (std::any_of(vEvictionCandidates.begin(),vEvictionCandidates.end(),[](NodeEvictionCandidate const &n){return n.prefer_evict;})) {
+ vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.begin(),vEvictionCandidates.end(),
+ [](NodeEvictionCandidate const &n){return !n.prefer_evict;}),vEvictionCandidates.end());
+ }
+
// Identify the network group with the most connections and youngest member.
// (vEvictionCandidates is already sorted by reverse connect time)
uint64_t naMostConnections;
@@ -1118,7 +933,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
// on all platforms. Set it again here just to be sure.
SetSocketNoDelay(hSocket);
- if (IsBanned(addr) && !whitelisted)
+ int bannedlevel = m_banman ? m_banman->IsBannedLevel(addr) : 0;
+
+ // Don't accept connections from banned peers, but if our inbound slots aren't almost full, accept
+ // if the only banning reason was an automatic misbehavior ban.
+ if (!whitelisted && bannedlevel > ((nInbound + 1 < nMaxInbound) ? 1 : 0))
{
LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString());
CloseSocket(hSocket);
@@ -1142,6 +961,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true);
pnode->AddRef();
pnode->fWhitelisted = whitelisted;
+ pnode->m_prefer_evict = bannedlevel > 0;
m_msgproc->InitializeNode(pnode);
LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString());
@@ -1152,310 +972,409 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
}
}
-void CConnman::ThreadSocketHandler()
+void CConnman::DisconnectNodes()
{
- unsigned int nPrevNodeCount = 0;
- while (!interruptNet)
{
- //
- // Disconnect nodes
- //
- {
- LOCK(cs_vNodes);
+ LOCK(cs_vNodes);
- if (!fNetworkActive) {
- // Disconnect any connected nodes
- for (CNode* pnode : vNodes) {
- if (!pnode->fDisconnect) {
- LogPrint(BCLog::NET, "Network not active, dropping peer=%d\n", pnode->GetId());
- pnode->fDisconnect = true;
- }
+ if (!fNetworkActive) {
+ // Disconnect any connected nodes
+ for (CNode* pnode : vNodes) {
+ if (!pnode->fDisconnect) {
+ LogPrint(BCLog::NET, "Network not active, dropping peer=%d\n", pnode->GetId());
+ pnode->fDisconnect = true;
}
}
+ }
- // Disconnect unused nodes
- std::vector<CNode*> vNodesCopy = vNodes;
- for (CNode* pnode : vNodesCopy)
+ // Disconnect unused nodes
+ std::vector<CNode*> vNodesCopy = vNodes;
+ for (CNode* pnode : vNodesCopy)
+ {
+ if (pnode->fDisconnect)
{
- if (pnode->fDisconnect)
- {
- // remove from vNodes
- vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
+ // remove from vNodes
+ vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
- // release outbound grant (if any)
- pnode->grantOutbound.Release();
+ // release outbound grant (if any)
+ pnode->grantOutbound.Release();
- // close socket and cleanup
- pnode->CloseSocketDisconnect();
+ // close socket and cleanup
+ pnode->CloseSocketDisconnect();
- // hold in disconnected pool until all refs are released
- pnode->Release();
- vNodesDisconnected.push_back(pnode);
- }
+ // hold in disconnected pool until all refs are released
+ pnode->Release();
+ vNodesDisconnected.push_back(pnode);
}
}
+ }
+ {
+ // Delete disconnected nodes
+ std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
+ for (CNode* pnode : vNodesDisconnectedCopy)
{
- // Delete disconnected nodes
- std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
- for (CNode* pnode : vNodesDisconnectedCopy)
- {
- // wait until threads are done using it
- if (pnode->GetRefCount() <= 0) {
- bool fDelete = false;
- {
- TRY_LOCK(pnode->cs_inventory, lockInv);
- if (lockInv) {
- TRY_LOCK(pnode->cs_vSend, lockSend);
- if (lockSend) {
- fDelete = true;
- }
+ // wait until threads are done using it
+ if (pnode->GetRefCount() <= 0) {
+ bool fDelete = false;
+ {
+ TRY_LOCK(pnode->cs_inventory, lockInv);
+ if (lockInv) {
+ TRY_LOCK(pnode->cs_vSend, lockSend);
+ if (lockSend) {
+ fDelete = true;
}
}
- if (fDelete) {
- vNodesDisconnected.remove(pnode);
- DeleteNode(pnode);
- }
+ }
+ if (fDelete) {
+ vNodesDisconnected.remove(pnode);
+ DeleteNode(pnode);
}
}
}
- size_t vNodesSize;
+ }
+}
+
+void CConnman::NotifyNumConnectionsChanged()
+{
+ size_t vNodesSize;
+ {
+ LOCK(cs_vNodes);
+ vNodesSize = vNodes.size();
+ }
+ if(vNodesSize != nPrevNodeCount) {
+ nPrevNodeCount = vNodesSize;
+ if(clientInterface)
+ clientInterface->NotifyNumConnectionsChanged(vNodesSize);
+ }
+}
+
+void CConnman::InactivityCheck(CNode *pnode)
+{
+ int64_t nTime = GetSystemTimeInSeconds();
+ if (nTime - pnode->nTimeConnected > m_peer_connect_timeout)
+ {
+ if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
{
- LOCK(cs_vNodes);
- vNodesSize = vNodes.size();
+ LogPrint(BCLog::NET, "socket no message in first %i seconds, %d %d from %d\n", m_peer_connect_timeout, pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId());
+ pnode->fDisconnect = true;
}
- if(vNodesSize != nPrevNodeCount) {
- nPrevNodeCount = vNodesSize;
- if(clientInterface)
- clientInterface->NotifyNumConnectionsChanged(nPrevNodeCount);
+ else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
+ {
+ LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
+ pnode->fDisconnect = true;
}
-
- //
- // Find which sockets have data to receive
- //
- struct timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 50000; // frequency to poll pnode->vSend
-
- fd_set fdsetRecv;
- fd_set fdsetSend;
- fd_set fdsetError;
- FD_ZERO(&fdsetRecv);
- FD_ZERO(&fdsetSend);
- FD_ZERO(&fdsetError);
- SOCKET hSocketMax = 0;
- bool have_fds = false;
-
- for (const ListenSocket& hListenSocket : vhListenSocket) {
- FD_SET(hListenSocket.socket, &fdsetRecv);
- hSocketMax = std::max(hSocketMax, hListenSocket.socket);
- have_fds = true;
+ else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
+ {
+ LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
+ pnode->fDisconnect = true;
+ }
+ else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
+ {
+ LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
+ pnode->fDisconnect = true;
}
+ else if (!pnode->fSuccessfullyConnected)
+ {
+ LogPrint(BCLog::NET, "version handshake timeout from %d\n", pnode->GetId());
+ pnode->fDisconnect = true;
+ }
+ }
+}
+bool CConnman::GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
+{
+ for (const ListenSocket& hListenSocket : vhListenSocket) {
+ recv_set.insert(hListenSocket.socket);
+ }
+
+ {
+ LOCK(cs_vNodes);
+ for (CNode* pnode : vNodes)
{
- LOCK(cs_vNodes);
- for (CNode* pnode : vNodes)
+ // Implement the following logic:
+ // * If there is data to send, select() for sending data. As this only
+ // happens when optimistic write failed, we choose to first drain the
+ // write buffer in this case before receiving more. This avoids
+ // needlessly queueing received data, if the remote peer is not themselves
+ // receiving data. This means properly utilizing TCP flow control signalling.
+ // * Otherwise, if there is space left in the receive buffer, select() for
+ // receiving data.
+ // * Hand off all complete messages to the processor, to be handled without
+ // blocking here.
+
+ bool select_recv = !pnode->fPauseRecv;
+ bool select_send;
{
- // Implement the following logic:
- // * If there is data to send, select() for sending data. As this only
- // happens when optimistic write failed, we choose to first drain the
- // write buffer in this case before receiving more. This avoids
- // needlessly queueing received data, if the remote peer is not themselves
- // receiving data. This means properly utilizing TCP flow control signalling.
- // * Otherwise, if there is space left in the receive buffer, select() for
- // receiving data.
- // * Hand off all complete messages to the processor, to be handled without
- // blocking here.
-
- bool select_recv = !pnode->fPauseRecv;
- bool select_send;
- {
- LOCK(pnode->cs_vSend);
- select_send = !pnode->vSendMsg.empty();
- }
-
- LOCK(pnode->cs_hSocket);
- if (pnode->hSocket == INVALID_SOCKET)
- continue;
+ LOCK(pnode->cs_vSend);
+ select_send = !pnode->vSendMsg.empty();
+ }
- FD_SET(pnode->hSocket, &fdsetError);
- hSocketMax = std::max(hSocketMax, pnode->hSocket);
- have_fds = true;
+ LOCK(pnode->cs_hSocket);
+ if (pnode->hSocket == INVALID_SOCKET)
+ continue;
- if (select_send) {
- FD_SET(pnode->hSocket, &fdsetSend);
- continue;
- }
- if (select_recv) {
- FD_SET(pnode->hSocket, &fdsetRecv);
- }
+ error_set.insert(pnode->hSocket);
+ if (select_send) {
+ send_set.insert(pnode->hSocket);
+ continue;
+ }
+ if (select_recv) {
+ recv_set.insert(pnode->hSocket);
}
}
+ }
- int nSelect = select(have_fds ? hSocketMax + 1 : 0,
- &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
- if (interruptNet)
+ return !recv_set.empty() || !send_set.empty() || !error_set.empty();
+}
+
+#ifdef USE_POLL
+void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
+{
+ std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
+ if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
+ interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
+ return;
+ }
+
+ std::unordered_map<SOCKET, struct pollfd> pollfds;
+ for (SOCKET socket_id : recv_select_set) {
+ pollfds[socket_id].fd = socket_id;
+ pollfds[socket_id].events |= POLLIN;
+ }
+
+ for (SOCKET socket_id : send_select_set) {
+ pollfds[socket_id].fd = socket_id;
+ pollfds[socket_id].events |= POLLOUT;
+ }
+
+ for (SOCKET socket_id : error_select_set) {
+ pollfds[socket_id].fd = socket_id;
+ // These flags are ignored, but we set them for clarity
+ pollfds[socket_id].events |= POLLERR|POLLHUP;
+ }
+
+ std::vector<struct pollfd> vpollfds;
+ vpollfds.reserve(pollfds.size());
+ for (auto it : pollfds) {
+ vpollfds.push_back(std::move(it.second));
+ }
+
+ if (poll(vpollfds.data(), vpollfds.size(), SELECT_TIMEOUT_MILLISECONDS) < 0) return;
+
+ if (interruptNet) return;
+
+ for (struct pollfd pollfd_entry : vpollfds) {
+ if (pollfd_entry.revents & POLLIN) recv_set.insert(pollfd_entry.fd);
+ if (pollfd_entry.revents & POLLOUT) send_set.insert(pollfd_entry.fd);
+ if (pollfd_entry.revents & (POLLERR|POLLHUP)) error_set.insert(pollfd_entry.fd);
+ }
+}
+#else
+void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
+{
+ std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
+ if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
+ interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
+ return;
+ }
+
+ //
+ // Find which sockets have data to receive
+ //
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = SELECT_TIMEOUT_MILLISECONDS * 1000; // frequency to poll pnode->vSend
+
+ fd_set fdsetRecv;
+ fd_set fdsetSend;
+ fd_set fdsetError;
+ FD_ZERO(&fdsetRecv);
+ FD_ZERO(&fdsetSend);
+ FD_ZERO(&fdsetError);
+ SOCKET hSocketMax = 0;
+
+ for (SOCKET hSocket : recv_select_set) {
+ FD_SET(hSocket, &fdsetRecv);
+ hSocketMax = std::max(hSocketMax, hSocket);
+ }
+
+ for (SOCKET hSocket : send_select_set) {
+ FD_SET(hSocket, &fdsetSend);
+ hSocketMax = std::max(hSocketMax, hSocket);
+ }
+
+ for (SOCKET hSocket : error_select_set) {
+ FD_SET(hSocket, &fdsetError);
+ hSocketMax = std::max(hSocketMax, hSocket);
+ }
+
+ int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
+
+ if (interruptNet)
+ return;
+
+ if (nSelect == SOCKET_ERROR)
+ {
+ int nErr = WSAGetLastError();
+ LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
+ for (unsigned int i = 0; i <= hSocketMax; i++)
+ FD_SET(i, &fdsetRecv);
+ FD_ZERO(&fdsetSend);
+ FD_ZERO(&fdsetError);
+ if (!interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS)))
return;
+ }
- if (nSelect == SOCKET_ERROR)
- {
- if (have_fds)
- {
- int nErr = WSAGetLastError();
- LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
- for (unsigned int i = 0; i <= hSocketMax; i++)
- FD_SET(i, &fdsetRecv);
- }
- FD_ZERO(&fdsetSend);
- FD_ZERO(&fdsetError);
- if (!interruptNet.sleep_for(std::chrono::milliseconds(timeout.tv_usec/1000)))
- return;
+ for (SOCKET hSocket : recv_select_set) {
+ if (FD_ISSET(hSocket, &fdsetRecv)) {
+ recv_set.insert(hSocket);
}
+ }
- //
- // Accept new connections
- //
- for (const ListenSocket& hListenSocket : vhListenSocket)
+ for (SOCKET hSocket : send_select_set) {
+ if (FD_ISSET(hSocket, &fdsetSend)) {
+ send_set.insert(hSocket);
+ }
+ }
+
+ for (SOCKET hSocket : error_select_set) {
+ if (FD_ISSET(hSocket, &fdsetError)) {
+ error_set.insert(hSocket);
+ }
+ }
+}
+#endif
+
+void CConnman::SocketHandler()
+{
+ std::set<SOCKET> recv_set, send_set, error_set;
+ SocketEvents(recv_set, send_set, error_set);
+
+ if (interruptNet) return;
+
+ //
+ // Accept new connections
+ //
+ for (const ListenSocket& hListenSocket : vhListenSocket)
+ {
+ if (hListenSocket.socket != INVALID_SOCKET && recv_set.count(hListenSocket.socket) > 0)
{
- if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
- {
- AcceptConnection(hListenSocket);
- }
+ AcceptConnection(hListenSocket);
}
+ }
+
+ //
+ // Service each socket
+ //
+ std::vector<CNode*> vNodesCopy;
+ {
+ LOCK(cs_vNodes);
+ vNodesCopy = vNodes;
+ for (CNode* pnode : vNodesCopy)
+ pnode->AddRef();
+ }
+ for (CNode* pnode : vNodesCopy)
+ {
+ if (interruptNet)
+ return;
//
- // Service each socket
+ // Receive
//
- std::vector<CNode*> vNodesCopy;
+ bool recvSet = false;
+ bool sendSet = false;
+ bool errorSet = false;
{
- LOCK(cs_vNodes);
- vNodesCopy = vNodes;
- for (CNode* pnode : vNodesCopy)
- pnode->AddRef();
+ LOCK(pnode->cs_hSocket);
+ if (pnode->hSocket == INVALID_SOCKET)
+ continue;
+ recvSet = recv_set.count(pnode->hSocket) > 0;
+ sendSet = send_set.count(pnode->hSocket) > 0;
+ errorSet = error_set.count(pnode->hSocket) > 0;
}
- for (CNode* pnode : vNodesCopy)
+ if (recvSet || errorSet)
{
- if (interruptNet)
- return;
-
- //
- // Receive
- //
- bool recvSet = false;
- bool sendSet = false;
- bool errorSet = false;
+ // typical socket buffer is 8K-64K
+ char pchBuf[0x10000];
+ int nBytes = 0;
{
LOCK(pnode->cs_hSocket);
if (pnode->hSocket == INVALID_SOCKET)
continue;
- recvSet = FD_ISSET(pnode->hSocket, &fdsetRecv);
- sendSet = FD_ISSET(pnode->hSocket, &fdsetSend);
- errorSet = FD_ISSET(pnode->hSocket, &fdsetError);
+ nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
}
- if (recvSet || errorSet)
+ if (nBytes > 0)
{
- // typical socket buffer is 8K-64K
- char pchBuf[0x10000];
- int nBytes = 0;
- {
- LOCK(pnode->cs_hSocket);
- if (pnode->hSocket == INVALID_SOCKET)
- continue;
- nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
- }
- if (nBytes > 0)
- {
- bool notify = false;
- if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify))
- pnode->CloseSocketDisconnect();
- RecordBytesRecv(nBytes);
- if (notify) {
- size_t nSizeAdded = 0;
- auto it(pnode->vRecvMsg.begin());
- for (; it != pnode->vRecvMsg.end(); ++it) {
- if (!it->complete())
- break;
- nSizeAdded += it->vRecv.size() + CMessageHeader::HEADER_SIZE;
- }
- {
- LOCK(pnode->cs_vProcessMsg);
- pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
- pnode->nProcessQueueSize += nSizeAdded;
- pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize;
- }
- WakeMessageHandler();
- }
- }
- else if (nBytes == 0)
- {
- // socket closed gracefully
- if (!pnode->fDisconnect) {
- LogPrint(BCLog::NET, "socket closed\n");
- }
+ bool notify = false;
+ if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify))
pnode->CloseSocketDisconnect();
- }
- else if (nBytes < 0)
- {
- // error
- int nErr = WSAGetLastError();
- if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
+ RecordBytesRecv(nBytes);
+ if (notify) {
+ size_t nSizeAdded = 0;
+ auto it(pnode->vRecvMsg.begin());
+ for (; it != pnode->vRecvMsg.end(); ++it) {
+ if (!it->complete())
+ break;
+ nSizeAdded += it->vRecv.size() + CMessageHeader::HEADER_SIZE;
+ }
{
- if (!pnode->fDisconnect)
- LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
- pnode->CloseSocketDisconnect();
+ LOCK(pnode->cs_vProcessMsg);
+ pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
+ pnode->nProcessQueueSize += nSizeAdded;
+ pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize;
}
+ WakeMessageHandler();
}
}
-
- //
- // Send
- //
- if (sendSet)
+ else if (nBytes == 0)
{
- LOCK(pnode->cs_vSend);
- size_t nBytes = SocketSendData(pnode);
- if (nBytes) {
- RecordBytesSent(nBytes);
+ // socket closed gracefully
+ if (!pnode->fDisconnect) {
+ LogPrint(BCLog::NET, "socket closed\n");
}
+ pnode->CloseSocketDisconnect();
}
-
- //
- // Inactivity checking
- //
- int64_t nTime = GetSystemTimeInSeconds();
- if (nTime - pnode->nTimeConnected > 60)
+ else if (nBytes < 0)
{
- if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
- {
- LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId());
- pnode->fDisconnect = true;
- }
- else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
- {
- LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
- pnode->fDisconnect = true;
- }
- else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
- {
- LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
- pnode->fDisconnect = true;
- }
- else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
- {
- LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
- pnode->fDisconnect = true;
- }
- else if (!pnode->fSuccessfullyConnected)
+ // error
+ int nErr = WSAGetLastError();
+ if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
- LogPrint(BCLog::NET, "version handshake timeout from %d\n", pnode->GetId());
- pnode->fDisconnect = true;
+ if (!pnode->fDisconnect)
+ LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
+ pnode->CloseSocketDisconnect();
}
}
}
+
+ //
+ // Send
+ //
+ if (sendSet)
{
- LOCK(cs_vNodes);
- for (CNode* pnode : vNodesCopy)
- pnode->Release();
+ LOCK(pnode->cs_vSend);
+ size_t nBytes = SocketSendData(pnode);
+ if (nBytes) {
+ RecordBytesSent(nBytes);
+ }
}
+
+ InactivityCheck(pnode);
+ }
+ {
+ LOCK(cs_vNodes);
+ for (CNode* pnode : vNodesCopy)
+ pnode->Release();
+ }
+}
+
+void CConnman::ThreadSocketHandler()
+{
+ while (!interruptNet)
+ {
+ DisconnectNodes();
+ NotifyNumConnectionsChanged();
+ SocketHandler();
}
}
@@ -1613,7 +1532,7 @@ void CConnman::ThreadDNSAddressSeed()
LOCK(cs_vNodes);
int nRelevant = 0;
- for (auto pnode : vNodes) {
+ for (const CNode* pnode : vNodes) {
nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound;
}
if (nRelevant >= 2) {
@@ -1687,12 +1606,6 @@ void CConnman::DumpAddresses()
addrman.size(), GetTimeMillis() - nStart);
}
-void CConnman::DumpData()
-{
- DumpAddresses();
- DumpBanlist();
-}
-
void CConnman::ProcessOneShot()
{
std::string strDest;
@@ -1732,7 +1645,7 @@ int CConnman::GetExtraOutboundCount()
int nOutbound = 0;
{
LOCK(cs_vNodes);
- for (CNode* pnode : vNodes) {
+ for (const CNode* pnode : vNodes) {
if (!pnode->fInbound && !pnode->m_manual_connection && !pnode->fFeeler && !pnode->fDisconnect && !pnode->fOneShot && pnode->fSuccessfullyConnected) {
++nOutbound;
}
@@ -1798,12 +1711,11 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
CAddress addrConnect;
// Only connect out to one peer per network group (/16 for IPv4).
- // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
int nOutbound = 0;
std::set<std::vector<unsigned char> > setConnected;
{
LOCK(cs_vNodes);
- for (CNode* pnode : vNodes) {
+ for (const CNode* pnode : vNodes) {
if (!pnode->fInbound && !pnode->m_manual_connection) {
// Netgroups for inbound and addnode peers are not excluded because our goal here
// is to not use multiple of our limited outbound slots on a single netgroup
@@ -1853,9 +1765,15 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
addr = addrman.Select(fFeeler);
}
- // if we selected an invalid address, restart
- if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
+ // Require outbound connections, other than feelers, to be to distinct network groups
+ if (!fFeeler && setConnected.count(addr.GetGroup())) {
break;
+ }
+
+ // if we selected an invalid or local address, restart
+ if (!addr.IsValid() || IsLocal(addr)) {
+ break;
+ }
// If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
// stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
@@ -1864,7 +1782,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
if (nTries > 100)
break;
- if (IsLimited(addr))
+ if (!IsReachable(addr))
continue;
// only consider very recently tried nodes after 30 failed attempts
@@ -1998,7 +1916,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
}
if (!pszDest) {
if (IsLocal(addrConnect) ||
- FindNode(static_cast<CNetAddr>(addrConnect)) || IsBanned(addrConnect) ||
+ FindNode(static_cast<CNetAddr>(addrConnect)) || (m_banman && m_banman->IsBanned(addrConnect)) ||
FindNode(addrConnect.ToStringIPPort()))
return;
} else if (FindNode(std::string(pszDest)))
@@ -2065,7 +1983,7 @@ void CConnman::ThreadMessageHandler()
pnode->Release();
}
- std::unique_lock<std::mutex> lock(mutexMsgProc);
+ WAIT_LOCK(mutexMsgProc, lock);
if (!fMoreWork) {
condMsgProc.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(100), [this] { return fMsgProcWake; });
}
@@ -2167,7 +2085,7 @@ void Discover()
}
}
}
-#else
+#elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
// Get local host ip
struct ifaddrs* myaddrs;
if (getifaddrs(&myaddrs) == 0)
@@ -2213,13 +2131,6 @@ void CConnman::SetNetworkActive(bool active)
CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSeed1(nSeed1In)
{
- fNetworkActive = true;
- setBannedIsDirty = false;
- fAddressesInitialized = false;
- nLastNodeId = 0;
- nSendBufferMaxSize = 0;
- nReceiveFloodSize = 0;
- flagInterruptMsgProc = false;
SetTryNewOutboundPeer(false);
Options connOptions;
@@ -2233,7 +2144,7 @@ NodeId CConnman::GetNewNodeId()
bool CConnman::Bind(const CService &addr, unsigned int flags) {
- if (!(flags & BF_EXPLICIT) && IsLimited(addr))
+ if (!(flags & BF_EXPLICIT) && !IsReachable(addr))
return false;
std::string strError;
if (!BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) {
@@ -2306,24 +2217,6 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
DumpAddresses();
}
}
- if (clientInterface)
- clientInterface->InitMessage(_("Loading banlist..."));
- // Load addresses from banlist.dat
- nStart = GetTimeMillis();
- CBanDB bandb;
- banmap_t banmap;
- if (bandb.Read(banmap)) {
- SetBanned(banmap); // thread save setter
- SetBannedSetDirty(false); // no need to write down, just read data
- SweepBanned(); // sweep out unused entries
-
- LogPrint(BCLog::NET, "Loaded %d banned node ips/subnets from banlist.dat %dms\n",
- banmap.size(), GetTimeMillis() - nStart);
- } else {
- LogPrintf("Invalid or missing banlist.dat; recreating\n");
- SetBannedSetDirty(true); // force write
- DumpBanlist();
- }
uiInterface.InitMessage(_("Starting network threads..."));
@@ -2347,7 +2240,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
flagInterruptMsgProc = false;
{
- std::unique_lock<std::mutex> lock(mutexMsgProc);
+ LOCK(mutexMsgProc);
fMsgProcWake = false;
}
@@ -2377,7 +2270,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
threadMessageHandler = std::thread(&TraceThread<std::function<void()> >, "msghand", std::function<void()>(std::bind(&CConnman::ThreadMessageHandler, this)));
// Dump network addresses
- scheduler.scheduleEvery(std::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL * 1000);
+ scheduler.scheduleEvery(std::bind(&CConnman::DumpAddresses, this), DUMP_PEERS_INTERVAL * 1000);
return true;
}
@@ -2436,7 +2329,7 @@ void CConnman::Stop()
if (fAddressesInitialized)
{
- DumpData();
+ DumpAddresses();
fAddressesInitialized = false;
}
@@ -2563,6 +2456,25 @@ bool CConnman::DisconnectNode(const std::string& strNode)
}
return false;
}
+
+bool CConnman::DisconnectNode(const CSubNet& subnet)
+{
+ bool disconnected = false;
+ LOCK(cs_vNodes);
+ for (CNode* pnode : vNodes) {
+ if (subnet.Match(pnode->addr)) {
+ pnode->fDisconnect = true;
+ disconnected = true;
+ }
+ }
+ return disconnected;
+}
+
+bool CConnman::DisconnectNode(const CNetAddr& addr)
+{
+ return DisconnectNode(CSubNet(addr));
+}
+
bool CConnman::DisconnectNode(NodeId id)
{
LOCK(cs_vNodes);
@@ -2700,8 +2612,8 @@ int CConnman::GetBestHeight() const
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
-CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string& addrNameIn, bool fInboundIn) :
- nTimeConnected(GetSystemTimeInSeconds()),
+CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, bool fInboundIn)
+ : nTimeConnected(GetSystemTimeInSeconds()),
addr(addrIn),
addrBind(addrBindIn),
fInbound(fInboundIn),
@@ -2711,56 +2623,13 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
id(idIn),
nLocalHostNonce(nLocalHostNonceIn),
nLocalServices(nLocalServicesIn),
- nMyStartingHeight(nMyStartingHeightIn),
- nSendVersion(0)
+ nMyStartingHeight(nMyStartingHeightIn)
{
- nServices = NODE_NONE;
hSocket = hSocketIn;
- nRecvVersion = INIT_PROTO_VERSION;
- nLastSend = 0;
- nLastRecv = 0;
- nSendBytes = 0;
- nRecvBytes = 0;
- nTimeOffset = 0;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
- nVersion = 0;
- strSubVer = "";
- fWhitelisted = false;
- fOneShot = false;
- m_manual_connection = false;
- fClient = false; // set by version message
- m_limited_node = false; // set by version message
- fFeeler = false;
- fSuccessfullyConnected = false;
- fDisconnect = false;
- nRefCount = 0;
- nSendSize = 0;
- nSendOffset = 0;
hashContinue = uint256();
- nStartingHeight = -1;
filterInventoryKnown.reset();
- fSendMempool = false;
- fGetAddr = false;
- nNextLocalAddrSend = 0;
- nNextAddrSend = 0;
- nNextInvSend = 0;
- fRelayTxes = false;
- fSentAddr = false;
pfilter = MakeUnique<CBloomFilter>();
- timeLastMempoolReq = 0;
- nLastBlockTime = 0;
- nLastTXTime = 0;
- nPingNonceSent = 0;
- nPingUsecStart = 0;
- nPingUsecTime = 0;
- fPingQueued = false;
- nMinPingUsecTime = std::numeric_limits<int64_t>::max();
- minFeeFilter = 0;
- lastSentFeeFilter = 0;
- nextSendTimeFeeFilter = 0;
- fPauseRecv = false;
- fPauseSend = false;
- nProcessQueueSize = 0;
for (const std::string &msg : getAllNetMessageTypes())
mapRecvBytesPerMsgCmd[msg] = 0;
@@ -2778,40 +2647,6 @@ CNode::~CNode()
CloseSocket(hSocket);
}
-void CNode::AskFor(const CInv& inv)
-{
- if (mapAskFor.size() > MAPASKFOR_MAX_SZ || setAskFor.size() > SETASKFOR_MAX_SZ)
- return;
- // a peer may not have multiple non-responded queue positions for a single inv item
- if (!setAskFor.insert(inv.hash).second)
- return;
-
- // We're using mapAskFor as a priority queue,
- // the key is the earliest time the request can be sent
- int64_t nRequestTime;
- limitedmap<uint256, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv.hash);
- if (it != mapAlreadyAskedFor.end())
- nRequestTime = it->second;
- else
- nRequestTime = 0;
- LogPrint(BCLog::NET, "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, FormatISO8601Time(nRequestTime/1000000), id);
-
- // Make sure not to reuse time indexes to keep things in the same order
- int64_t nNow = GetTimeMicros() - 1000000;
- static int64_t nLastTime;
- ++nLastTime;
- nNow = std::max(nNow, nLastTime);
- nLastTime = nNow;
-
- // Each retry is 2 minutes after the last
- nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
- if (it != mapAlreadyAskedFor.end())
- mapAlreadyAskedFor.update(it, nRequestTime);
- else
- mapAlreadyAskedFor.insert(std::make_pair(inv.hash, nRequestTime));
- mapAskFor.insert(std::make_pair(nRequestTime, inv));
-}
-
bool CConnman::NodeFullyConnected(const CNode* pnode)
{
return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect;
diff --git a/src/net.h b/src/net.h
index 36c2a4b8f5..37aaf1a63b 100644
--- a/src/net.h
+++ b/src/net.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,6 +11,7 @@
#include <amount.h>
#include <bloom.h>
#include <compat.h>
+#include <crypto/siphash.h>
#include <hash.h>
#include <limitedmap.h>
#include <netaddress.h>
@@ -36,6 +37,7 @@
class CScheduler;
class CNode;
+class BanMan;
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
static const int PING_INTERVAL = 2 * 60;
@@ -45,11 +47,13 @@ static const int TIMEOUT_INTERVAL = 20 * 60;
static const int FEELER_INTERVAL = 120;
/** The maximum number of entries in an 'inv' protocol message */
static const unsigned int MAX_INV_SZ = 50000;
+/** The maximum number of entries in a locator */
+static const unsigned int MAX_LOCATOR_SZ = 101;
/** The maximum number of new addresses to accumulate before announcing. */
static const unsigned int MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable). */
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1000 * 1000;
-/** Maximum length of strSubVer in `version` message */
+/** Maximum length of the user agent string in `version` message */
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
/** Maximum number of automatic outgoing nodes */
static const int MAX_OUTBOUND_CONNECTIONS = 8;
@@ -63,10 +67,6 @@ static const bool DEFAULT_UPNP = USE_UPNP;
#else
static const bool DEFAULT_UPNP = false;
#endif
-/** The maximum number of entries in mapAskFor */
-static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ;
-/** The maximum number of entries in setAskFor (larger due to getdata latency)*/
-static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ;
/** The maximum number of peer connections to maintain. */
static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125;
/** The default for -maxuploadtarget. 0 = Unlimited */
@@ -75,14 +75,13 @@ static const uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0;
static const uint64_t MAX_UPLOAD_TIMEFRAME = 60 * 60 * 24;
/** Default for blocks only*/
static const bool DEFAULT_BLOCKSONLY = false;
+/** -peertimeout default */
+static const int64_t DEFAULT_PEER_CONNECT_TIMEOUT = 60;
static const bool DEFAULT_FORCEDNSSEED = false;
static const size_t DEFAULT_MAXRECEIVEBUFFER = 5 * 1000;
static const size_t DEFAULT_MAXSENDBUFFER = 1 * 1000;
-// NOTE: When adjusting this, update rpcnet:setban's help ("24h")
-static const unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Default 24-hour ban
-
typedef int64_t NodeId;
struct AddedNodeInfo
@@ -109,6 +108,7 @@ struct CSerializedNetMsg
std::string command;
};
+
class NetEventsInterface;
class CConnman
{
@@ -131,10 +131,12 @@ public:
int nBestHeight = 0;
CClientUIInterface* uiInterface = nullptr;
NetEventsInterface* m_msgproc = nullptr;
+ BanMan* m_banman = nullptr;
unsigned int nSendBufferMaxSize = 0;
unsigned int nReceiveFloodSize = 0;
uint64_t nMaxOutboundTimeframe = 0;
uint64_t nMaxOutboundLimit = 0;
+ int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT;
std::vector<std::string> vSeedNodes;
std::vector<CSubNet> vWhitelistedRange;
std::vector<CService> vBinds, vWhiteBinds;
@@ -147,13 +149,16 @@ public:
nLocalServices = connOptions.nLocalServices;
nMaxConnections = connOptions.nMaxConnections;
nMaxOutbound = std::min(connOptions.nMaxOutbound, connOptions.nMaxConnections);
+ m_use_addrman_outgoing = connOptions.m_use_addrman_outgoing;
nMaxAddnode = connOptions.nMaxAddnode;
nMaxFeeler = connOptions.nMaxFeeler;
nBestHeight = connOptions.nBestHeight;
clientInterface = connOptions.uiInterface;
+ m_banman = connOptions.m_banman;
m_msgproc = connOptions.m_msgproc;
nSendBufferMaxSize = connOptions.nSendBufferMaxSize;
nReceiveFloodSize = connOptions.nReceiveFloodSize;
+ m_peer_connect_timeout = connOptions.m_peer_connect_timeout;
{
LOCK(cs_totalBytesSent);
nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe;
@@ -169,9 +174,21 @@ public:
CConnman(uint64_t seed0, uint64_t seed1);
~CConnman();
bool Start(CScheduler& scheduler, const Options& options);
- void Stop();
+
+ // TODO: Remove NO_THREAD_SAFETY_ANALYSIS. Lock cs_vNodes before reading the variable vNodes.
+ //
+ // When removing NO_THREAD_SAFETY_ANALYSIS be aware of the following lock order requirements:
+ // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount
+ // which locks cs_vNodes.
+ // * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which
+ // locks cs_vNodes.
+ //
+ // Thus the implicit locking order requirement is: (1) cs_main, (2) g_cs_orphans, (3) cs_vNodes.
+ void Stop() NO_THREAD_SAFETY_ANALYSIS;
+
void Interrupt();
bool GetNetworkActive() const { return fNetworkActive; };
+ bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };
void SetNetworkActive(bool active);
void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = nullptr, const char *strDest = nullptr, bool fOneShot = false, bool fFeeler = false, bool manual_connection = false);
bool CheckIncomingNonce(uint64_t nonce);
@@ -229,30 +246,6 @@ public:
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
std::vector<CAddress> GetAddresses();
- // Denial-of-service detection/prevention
- // The idea is to detect peers that are behaving
- // badly and disconnect/ban them, but do it in a
- // one-coding-mistake-won't-shatter-the-entire-network
- // way.
- // IMPORTANT: There should be nothing I can give a
- // node that it will forward on that will make that
- // node's peers drop it. If there is, an attacker
- // can isolate a node and/or try to split the network.
- // Dropping a node for sending stuff that is invalid
- // now but might be valid in a later version is also
- // dangerous, because it can cause a network split
- // between nodes running old code and nodes running
- // new code.
- void Ban(const CNetAddr& netAddr, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
- void Ban(const CSubNet& subNet, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
- void ClearBanned(); // needed for unit testing
- bool IsBanned(CNetAddr ip);
- bool IsBanned(CSubNet subnet);
- bool Unban(const CNetAddr &ip);
- bool Unban(const CSubNet &ip);
- void GetBanned(banmap_t &banmap);
- void SetBanned(const banmap_t &banmap);
-
// This allows temporarily exceeding nMaxOutbound, with the goal of finding
// a peer that is better than all our current peers.
void SetTryNewOutboundPeer(bool flag);
@@ -273,6 +266,8 @@ public:
size_t GetNodeCount(NumConnections num);
void GetNodeStats(std::vector<CNodeStats>& vstats);
bool DisconnectNode(const std::string& node);
+ bool DisconnectNode(const CSubNet& subnet);
+ bool DisconnectNode(const CNetAddr& addr);
bool DisconnectNode(NodeId id);
ServiceFlags GetLocalServices() const;
@@ -285,17 +280,17 @@ public:
void SetMaxOutboundTimeframe(uint64_t timeframe);
uint64_t GetMaxOutboundTimeframe();
- //!check if the outbound target is reached
- // if param historicalBlockServingLimit is set true, the function will
- // response true if the limit for serving historical blocks has been reached
+ //! check if the outbound target is reached
+ //! if param historicalBlockServingLimit is set true, the function will
+ //! response true if the limit for serving historical blocks has been reached
bool OutboundTargetReached(bool historicalBlockServingLimit);
- //!response the bytes left in the current max outbound cycle
- // in case of no limit, it will always response 0
+ //! response the bytes left in the current max outbound cycle
+ //! in case of no limit, it will always response 0
uint64_t GetOutboundTargetBytesLeft();
- //!response the time in second left in the current max outbound cycle
- // in case of no limit, it will always response 0
+ //! response the time in second left in the current max outbound cycle
+ //! in case of no limit, it will always response 0
uint64_t GetMaxOutboundTimeLeftInCycle();
uint64_t GetTotalBytesRecv();
@@ -334,6 +329,12 @@ private:
void ThreadOpenConnections(std::vector<std::string> connect);
void ThreadMessageHandler();
void AcceptConnection(const ListenSocket& hListenSocket);
+ void DisconnectNodes();
+ void NotifyNumConnectionsChanged();
+ void InactivityCheck(CNode *pnode);
+ bool GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
+ void SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
+ void SocketHandler();
void ThreadSocketHandler();
void ThreadDNSAddressSeed();
@@ -353,15 +354,7 @@ private:
NodeId GetNewNodeId();
size_t SocketSendData(CNode *pnode) const;
- //!check is the banlist has unwritten changes
- bool BannedSetIsDirty();
- //!set the "dirty" flag for the banlist
- void SetBannedSetDirty(bool dirty=true);
- //!clean unused entries (if bantime has expired)
- void SweepBanned();
void DumpAddresses();
- void DumpData();
- void DumpBanlist();
// Network stats
void RecordBytesRecv(uint64_t bytes);
@@ -382,28 +375,29 @@ private:
uint64_t nMaxOutboundLimit GUARDED_BY(cs_totalBytesSent);
uint64_t nMaxOutboundTimeframe GUARDED_BY(cs_totalBytesSent);
+ // P2P timeout in seconds
+ int64_t m_peer_connect_timeout;
+
// Whitelisted ranges. Any node connecting from these is automatically
// whitelisted (as well as those connecting to whitelisted binds).
std::vector<CSubNet> vWhitelistedRange;
- unsigned int nSendBufferMaxSize;
- unsigned int nReceiveFloodSize;
+ unsigned int nSendBufferMaxSize{0};
+ unsigned int nReceiveFloodSize{0};
std::vector<ListenSocket> vhListenSocket;
- std::atomic<bool> fNetworkActive;
- banmap_t setBanned;
- CCriticalSection cs_setBanned;
- bool setBannedIsDirty;
- bool fAddressesInitialized;
+ std::atomic<bool> fNetworkActive{true};
+ bool fAddressesInitialized{false};
CAddrMan addrman;
- std::deque<std::string> vOneShots;
+ std::deque<std::string> vOneShots GUARDED_BY(cs_vOneShots);
CCriticalSection cs_vOneShots;
std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes);
CCriticalSection cs_vAddedNodes;
- std::vector<CNode*> vNodes;
+ std::vector<CNode*> vNodes GUARDED_BY(cs_vNodes);
std::list<CNode*> vNodesDisconnected;
mutable CCriticalSection cs_vNodes;
- std::atomic<NodeId> nLastNodeId;
+ std::atomic<NodeId> nLastNodeId{0};
+ unsigned int nPrevNodeCount{0};
/** Services this instance offers */
ServiceFlags nLocalServices;
@@ -414,9 +408,11 @@ private:
int nMaxOutbound;
int nMaxAddnode;
int nMaxFeeler;
+ bool m_use_addrman_outgoing;
std::atomic<int> nBestHeight;
CClientUIInterface* clientInterface;
NetEventsInterface* m_msgproc;
+ BanMan* m_banman;
/** SipHasher seeds for deterministic randomness */
const uint64_t nSeed0, nSeed1;
@@ -425,8 +421,8 @@ private:
bool fMsgProcWake;
std::condition_variable condMsgProc;
- std::mutex mutexMsgProc;
- std::atomic<bool> flagInterruptMsgProc;
+ Mutex mutexMsgProc;
+ std::atomic<bool> flagInterruptMsgProc{false};
CThreadInterrupt interruptNet;
@@ -446,6 +442,7 @@ private:
friend struct CConnmanTest;
};
extern std::unique_ptr<CConnman> g_connman;
+extern std::unique_ptr<BanMan> g_banman;
void Discover();
void StartMapPort();
void InterruptMapPort();
@@ -500,25 +497,29 @@ enum
bool IsPeerAddrLocalGood(CNode *pnode);
void AdvertiseLocal(CNode *pnode);
-void SetLimited(enum Network net, bool fLimited = true);
-bool IsLimited(enum Network net);
-bool IsLimited(const CNetAddr& addr);
+
+/**
+ * Mark a network as reachable or unreachable (no automatic connects to it)
+ * @note Networks are reachable by default
+ */
+void SetReachable(enum Network net, bool reachable);
+/** @returns true if the network is reachable, false otherwise */
+bool IsReachable(enum Network net);
+/** @returns true if the address is in a reachable network, false otherwise */
+bool IsReachable(const CNetAddr& addr);
+
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
void RemoveLocal(const CService& addr);
bool SeenLocal(const CService& addr);
bool IsLocal(const CService& addr);
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = nullptr);
-bool IsReachable(enum Network net);
-bool IsReachable(const CNetAddr &addr);
CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices);
extern bool fDiscover;
extern bool fListen;
-extern bool fRelayTxes;
-
-extern limitedmap<uint256, int64_t> mapAlreadyAskedFor;
+extern bool g_relay_txes;
/** Subversion as sent to the P2P network in `version` messages */
extern std::string strSubVersion;
@@ -529,7 +530,9 @@ struct LocalServiceInfo {
};
extern CCriticalSection cs_mapLocalHost;
-extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
+extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(cs_mapLocalHost);
+
+extern const std::string NET_MESSAGE_COMMAND_OTHER;
typedef std::map<std::string, uint64_t> mapMsgCmdSize; //command, total bytes
class CNodeStats
@@ -556,6 +559,7 @@ public:
double dPingTime;
double dPingWait;
double dMinPing;
+ CAmount minFeeFilter;
// Our address, as reported by the peer
std::string addrLocal;
// Address of this peer
@@ -617,123 +621,125 @@ class CNode
friend class CConnman;
public:
// socket
- std::atomic<ServiceFlags> nServices;
- SOCKET hSocket;
- size_t nSendSize; // total size of all vSendMsg entries
- size_t nSendOffset; // offset inside the first vSendMsg already sent
- uint64_t nSendBytes;
- std::deque<std::vector<unsigned char>> vSendMsg;
+ std::atomic<ServiceFlags> nServices{NODE_NONE};
+ SOCKET hSocket GUARDED_BY(cs_hSocket);
+ size_t nSendSize{0}; // total size of all vSendMsg entries
+ size_t nSendOffset{0}; // offset inside the first vSendMsg already sent
+ uint64_t nSendBytes GUARDED_BY(cs_vSend){0};
+ std::deque<std::vector<unsigned char>> vSendMsg GUARDED_BY(cs_vSend);
CCriticalSection cs_vSend;
CCriticalSection cs_hSocket;
CCriticalSection cs_vRecv;
CCriticalSection cs_vProcessMsg;
- std::list<CNetMessage> vProcessMsg;
- size_t nProcessQueueSize;
+ std::list<CNetMessage> vProcessMsg GUARDED_BY(cs_vProcessMsg);
+ size_t nProcessQueueSize{0};
CCriticalSection cs_sendProcessing;
std::deque<CInv> vRecvGetData;
- uint64_t nRecvBytes;
- std::atomic<int> nRecvVersion;
+ uint64_t nRecvBytes GUARDED_BY(cs_vRecv){0};
+ std::atomic<int> nRecvVersion{INIT_PROTO_VERSION};
- std::atomic<int64_t> nLastSend;
- std::atomic<int64_t> nLastRecv;
+ std::atomic<int64_t> nLastSend{0};
+ std::atomic<int64_t> nLastRecv{0};
const int64_t nTimeConnected;
- std::atomic<int64_t> nTimeOffset;
+ std::atomic<int64_t> nTimeOffset{0};
// Address of this peer
const CAddress addr;
// Bind address of our side of the connection
const CAddress addrBind;
- std::atomic<int> nVersion;
- // strSubVer is whatever byte array we read from the wire. However, this field is intended
- // to be printed out, displayed to humans in various forms and so on. So we sanitize it and
- // store the sanitized version in cleanSubVer. The original should be used when dealing with
- // the network or wire types and the cleaned string used when displayed or logged.
- std::string strSubVer, cleanSubVer;
- CCriticalSection cs_SubVer; // used for both cleanSubVer and strSubVer
- bool fWhitelisted; // This peer can bypass DoS banning.
- bool fFeeler; // If true this node is being used as a short lived feeler.
- bool fOneShot;
- bool m_manual_connection;
- bool fClient;
- bool m_limited_node; //after BIP159
+ std::atomic<int> nVersion{0};
+ RecursiveMutex cs_SubVer;
+ /**
+ * cleanSubVer is a sanitized string of the user agent byte array we read
+ * from the wire. This cleaned string can safely be logged or displayed.
+ */
+ std::string cleanSubVer GUARDED_BY(cs_SubVer){};
+ bool m_prefer_evict{false}; // This peer is preferred for eviction.
+ bool fWhitelisted{false}; // This peer can bypass DoS banning.
+ bool fFeeler{false}; // If true this node is being used as a short lived feeler.
+ bool fOneShot{false};
+ bool m_manual_connection{false};
+ bool fClient{false}; // set by version message
+ bool m_limited_node{false}; //after BIP159, set by version message
const bool fInbound;
- std::atomic_bool fSuccessfullyConnected;
- std::atomic_bool fDisconnect;
+ std::atomic_bool fSuccessfullyConnected{false};
+ // Setting fDisconnect to true will cause the node to be disconnected the
+ // next time DisconnectNodes() runs
+ std::atomic_bool fDisconnect{false};
// We use fRelayTxes for two purposes -
// a) it allows us to not relay tx invs before receiving the peer's version message
// b) the peer may tell us in its version message that we should not relay tx invs
// unless it loads a bloom filter.
- bool fRelayTxes; //protected by cs_filter
- bool fSentAddr;
+ bool fRelayTxes GUARDED_BY(cs_filter){false};
+ bool fSentAddr{false};
CSemaphoreGrant grantOutbound;
- CCriticalSection cs_filter;
- std::unique_ptr<CBloomFilter> pfilter;
- std::atomic<int> nRefCount;
+ mutable CCriticalSection cs_filter;
+ std::unique_ptr<CBloomFilter> pfilter PT_GUARDED_BY(cs_filter);
+ std::atomic<int> nRefCount{0};
const uint64_t nKeyedNetGroup;
- std::atomic_bool fPauseRecv;
- std::atomic_bool fPauseSend;
-protected:
+ std::atomic_bool fPauseRecv{false};
+ std::atomic_bool fPauseSend{false};
+protected:
mapMsgCmdSize mapSendBytesPerMsgCmd;
- mapMsgCmdSize mapRecvBytesPerMsgCmd;
+ mapMsgCmdSize mapRecvBytesPerMsgCmd GUARDED_BY(cs_vRecv);
public:
uint256 hashContinue;
- std::atomic<int> nStartingHeight;
+ std::atomic<int> nStartingHeight{-1};
// flood relay
std::vector<CAddress> vAddrToSend;
CRollingBloomFilter addrKnown;
- bool fGetAddr;
+ bool fGetAddr{false};
std::set<uint256> setKnown;
- int64_t nNextAddrSend;
- int64_t nNextLocalAddrSend;
+ int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0};
+ int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0};
// inventory based relay
- CRollingBloomFilter filterInventoryKnown;
+ CRollingBloomFilter filterInventoryKnown GUARDED_BY(cs_inventory);
// Set of transaction ids we still have to announce.
// They are sorted by the mempool before relay, so the order is not important.
std::set<uint256> setInventoryTxToSend;
// List of block ids we still have announce.
// There is no final sorting before sending, as they are always sent immediately
// and in the order requested.
- std::vector<uint256> vInventoryBlockToSend;
+ std::vector<uint256> vInventoryBlockToSend GUARDED_BY(cs_inventory);
CCriticalSection cs_inventory;
- std::set<uint256> setAskFor;
- std::multimap<int64_t, CInv> mapAskFor;
- int64_t nNextInvSend;
+ int64_t nNextInvSend{0};
// Used for headers announcements - unfiltered blocks to relay
- // Also protected by cs_inventory
- std::vector<uint256> vBlockHashesToAnnounce;
- // Used for BIP35 mempool sending, also protected by cs_inventory
- bool fSendMempool;
+ std::vector<uint256> vBlockHashesToAnnounce GUARDED_BY(cs_inventory);
+ // Used for BIP35 mempool sending
+ bool fSendMempool GUARDED_BY(cs_inventory){false};
// Last time a "MEMPOOL" request was serviced.
- std::atomic<int64_t> timeLastMempoolReq;
+ std::atomic<int64_t> timeLastMempoolReq{0};
// Block and TXN accept times
- std::atomic<int64_t> nLastBlockTime;
- std::atomic<int64_t> nLastTXTime;
+ std::atomic<int64_t> nLastBlockTime{0};
+ std::atomic<int64_t> nLastTXTime{0};
// Ping time measurement:
// The pong reply we're expecting, or 0 if no pong expected.
- std::atomic<uint64_t> nPingNonceSent;
+ std::atomic<uint64_t> nPingNonceSent{0};
// Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
- std::atomic<int64_t> nPingUsecStart;
+ std::atomic<int64_t> nPingUsecStart{0};
// Last measured round-trip time.
- std::atomic<int64_t> nPingUsecTime;
+ std::atomic<int64_t> nPingUsecTime{0};
// Best measured round-trip time.
- std::atomic<int64_t> nMinPingUsecTime;
+ std::atomic<int64_t> nMinPingUsecTime{std::numeric_limits<int64_t>::max()};
// Whether a ping is requested.
- std::atomic<bool> fPingQueued;
+ std::atomic<bool> fPingQueued{false};
// Minimum fee rate with which to filter inv's to this node
- CAmount minFeeFilter;
+ CAmount minFeeFilter GUARDED_BY(cs_feeFilter){0};
CCriticalSection cs_feeFilter;
- CAmount lastSentFeeFilter;
- int64_t nextSendTimeFeeFilter;
+ CAmount lastSentFeeFilter{0};
+ int64_t nextSendTimeFeeFilter{0};
+
+ std::set<uint256> orphan_work_set;
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn = "", bool fInboundIn = false);
~CNode();
@@ -746,14 +752,14 @@ private:
// Services offered to this peer
const ServiceFlags nLocalServices;
const int nMyStartingHeight;
- int nSendVersion;
+ int nSendVersion{0};
std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread
mutable CCriticalSection cs_addrName;
- std::string addrName;
+ std::string addrName GUARDED_BY(cs_addrName);
// Our address, as reported by the peer
- CService addrLocal;
+ CService addrLocal GUARDED_BY(cs_addrLocal);
mutable CCriticalSection cs_addrLocal;
public:
@@ -851,8 +857,6 @@ public:
vBlockHashesToAnnounce.push_back(hash);
}
- void AskFor(const CInv& inv);
-
void CloseSocketDisconnect();
void copyStats(CNodeStats &stats);
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index d5d664b27e..cb2b9f8c03 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1,11 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <net_processing.h>
#include <addrman.h>
+#include <banman.h>
#include <arith_uint256.h>
#include <blockencodings.h>
#include <chainparams.h>
@@ -25,9 +26,10 @@
#include <tinyformat.h>
#include <txmempool.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
+#include <util/validation.h>
#include <memory>
@@ -63,14 +65,30 @@ static constexpr int STALE_RELAY_AGE_LIMIT = 30 * 24 * 60 * 60;
/// Age after which a block is considered historical for purposes of rate
/// limiting block relay. Set to one week, denominated in seconds.
static constexpr int HISTORICAL_BLOCK_AGE = 7 * 24 * 60 * 60;
+/** Maximum number of in-flight transactions from a peer */
+static constexpr int32_t MAX_PEER_TX_IN_FLIGHT = 100;
+/** Maximum number of announced transactions from a peer */
+static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS = 2 * MAX_INV_SZ;
+/** How many microseconds to delay requesting transactions from inbound peers */
+static constexpr int64_t INBOUND_PEER_TX_DELAY = 2 * 1000000;
+/** How long to wait (in microseconds) before downloading a transaction from an additional peer */
+static constexpr int64_t GETDATA_TX_INTERVAL = 60 * 1000000;
+/** Maximum delay (in microseconds) for transaction requests to avoid biasing some peers over others. */
+static constexpr int64_t MAX_GETDATA_RANDOM_DELAY = 2 * 1000000;
+static_assert(INBOUND_PEER_TX_DELAY >= MAX_GETDATA_RANDOM_DELAY,
+"To preserve security, MAX_GETDATA_RANDOM_DELAY should not exceed INBOUND_PEER_DELAY");
+/** Limit to avoid sending big packets. Not used in processing incoming GETDATA for compatibility */
+static const unsigned int MAX_GETDATA_SZ = 1000;
+
struct COrphanTx {
// When modifying, adapt the copy of this definition in tests/DoS_tests.
CTransactionRef tx;
NodeId fromPeer;
int64_t nTimeExpire;
+ size_t list_pos;
};
-static CCriticalSection g_cs_orphans;
+CCriticalSection g_cs_orphans;
std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans);
void EraseOrphansFor(NodeId peer);
@@ -158,8 +176,6 @@ namespace {
/** Expiration-time ordered list of (expire time, relay map entry) pairs. */
std::deque<std::pair<int64_t, MapRelay::iterator>> vRelayExpiration GUARDED_BY(cs_main);
- std::atomic<int64_t> nTimeBestReceived(0); // Used only to inform the wallet of when we last received a block
-
struct IteratorComparator
{
template<typename I>
@@ -170,6 +186,8 @@ namespace {
};
std::map<COutPoint, std::set<std::map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans);
+ std::vector<std::map<uint256, COrphanTx>::iterator> g_orphan_list GUARDED_BY(g_cs_orphans); //! For random eviction
+
static size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0;
static std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY(g_cs_orphans);
} // namespace
@@ -273,7 +291,76 @@ struct CNodeState {
//! Time of last new block announcement
int64_t m_last_block_announcement;
- CNodeState(CAddress addrIn, std::string addrNameIn) : address(addrIn), name(addrNameIn) {
+ /*
+ * State associated with transaction download.
+ *
+ * Tx download algorithm:
+ *
+ * When inv comes in, queue up (process_time, txid) inside the peer's
+ * CNodeState (m_tx_process_time) as long as m_tx_announced for the peer
+ * isn't too big (MAX_PEER_TX_ANNOUNCEMENTS).
+ *
+ * The process_time for a transaction is set to nNow for outbound peers,
+ * nNow + 2 seconds for inbound peers. This is the time at which we'll
+ * consider trying to request the transaction from the peer in
+ * SendMessages(). The delay for inbound peers is to allow outbound peers
+ * a chance to announce before we request from inbound peers, to prevent
+ * an adversary from using inbound connections to blind us to a
+ * transaction (InvBlock).
+ *
+ * When we call SendMessages() for a given peer,
+ * we will loop over the transactions in m_tx_process_time, looking
+ * at the transactions whose process_time <= nNow. We'll request each
+ * such transaction that we don't have already and that hasn't been
+ * requested from another peer recently, up until we hit the
+ * MAX_PEER_TX_IN_FLIGHT limit for the peer. Then we'll update
+ * g_already_asked_for for each requested txid, storing the time of the
+ * GETDATA request. We use g_already_asked_for to coordinate transaction
+ * requests amongst our peers.
+ *
+ * For transactions that we still need but we have already recently
+ * requested from some other peer, we'll reinsert (process_time, txid)
+ * back into the peer's m_tx_process_time at the point in the future at
+ * which the most recent GETDATA request would time out (ie
+ * GETDATA_TX_INTERVAL + the request time stored in g_already_asked_for).
+ * We add an additional delay for inbound peers, again to prefer
+ * attempting download from outbound peers first.
+ * We also add an extra small random delay up to 2 seconds
+ * to avoid biasing some peers over others. (e.g., due to fixed ordering
+ * of peer processing in ThreadMessageHandler).
+ *
+ * When we receive a transaction from a peer, we remove the txid from the
+ * peer's m_tx_in_flight set and from their recently announced set
+ * (m_tx_announced). We also clear g_already_asked_for for that entry, so
+ * that if somehow the transaction is not accepted but also not added to
+ * the reject filter, then we will eventually redownload from other
+ * peers.
+ */
+ struct TxDownloadState {
+ /* Track when to attempt download of announced transactions (process
+ * time in micros -> txid)
+ */
+ std::multimap<int64_t, uint256> m_tx_process_time;
+
+ //! Store all the transactions a peer has recently announced
+ std::set<uint256> m_tx_announced;
+
+ //! Store transactions which were requested by us
+ std::set<uint256> m_tx_in_flight;
+ };
+
+ TxDownloadState m_tx_download;
+
+ //! Whether this peer is an inbound connection
+ bool m_is_inbound;
+
+ //! Whether this peer is a manual connection
+ bool m_is_manual_connection;
+
+ CNodeState(CAddress addrIn, std::string addrNameIn, bool is_inbound, bool is_manual) :
+ address(addrIn), name(std::move(addrNameIn)), m_is_inbound(is_inbound),
+ m_is_manual_connection (is_manual)
+ {
fCurrentlyConnected = false;
nMisbehavior = 0;
fShouldBan = false;
@@ -300,6 +387,9 @@ struct CNodeState {
}
};
+// Keeps track of the time (in microseconds) when transactions were requested last time
+limitedmap<uint256, int64_t> g_already_asked_for GUARDED_BY(cs_main)(MAX_INV_SZ);
+
/** Map maintaining per-node state. */
static std::map<NodeId, CNodeState> mapNodeState GUARDED_BY(cs_main);
@@ -332,7 +422,7 @@ static void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
CAddress addrMe = CAddress(CService(), nLocalNodeServices);
connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
- nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes));
+ nonce, strSubVersion, nNodeStartingHeight, ::g_relay_txes));
if (fLogIPs) {
LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
@@ -442,7 +532,7 @@ static void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIV
* lNodesAnnouncingHeaderAndIDs, and keeping that list under a certain size by
* removing the first element if necessary.
*/
-static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman)
+static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
CNodeState* nodestate = State(nodeid);
@@ -489,7 +579,7 @@ static bool TipMayBeStale(const Consensus::Params &consensusParams) EXCLUSIVE_LO
static bool CanDirectFetch(const Consensus::Params &consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- return chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20;
+ return ::ChainActive().Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20;
}
static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -515,7 +605,7 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec
// Make sure pindexBestKnownBlock is up to date, we'll need it.
ProcessBlockAvailability(nodeid);
- if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
+ if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < ::ChainActive().Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
// This peer has nothing interesting.
return;
}
@@ -523,7 +613,7 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec
if (state->pindexLastCommonBlock == nullptr) {
// Bootstrap quickly by guessing a parent of our best tip is the forking point.
// Guessing wrong in either direction is not a problem.
- state->pindexLastCommonBlock = chainActive[std::min(state->pindexBestKnownBlock->nHeight, chainActive.Height())];
+ state->pindexLastCommonBlock = ::ChainActive()[std::min(state->pindexBestKnownBlock->nHeight, ::ChainActive().Height())];
}
// If the peer reorganized, our previous pindexLastCommonBlock may not be an ancestor
@@ -565,8 +655,8 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec
// We wouldn't download this block or its descendants from this peer.
return;
}
- if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains(pindex)) {
- if (pindex->nChainTx)
+ if (pindex->nStatus & BLOCK_HAVE_DATA || ::ChainActive().Contains(pindex)) {
+ if (pindex->HaveTxsDownloaded())
state->pindexLastCommonBlock = pindex;
} else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) {
// The block is not already downloaded, and not yet in flight.
@@ -590,6 +680,58 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec
}
}
+void EraseTxRequest(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+{
+ g_already_asked_for.erase(txid);
+}
+
+int64_t GetTxRequestTime(const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+{
+ auto it = g_already_asked_for.find(txid);
+ if (it != g_already_asked_for.end()) {
+ return it->second;
+ }
+ return 0;
+}
+
+void UpdateTxRequestTime(const uint256& txid, int64_t request_time) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+{
+ auto it = g_already_asked_for.find(txid);
+ if (it == g_already_asked_for.end()) {
+ g_already_asked_for.insert(std::make_pair(txid, request_time));
+ } else {
+ g_already_asked_for.update(it, request_time);
+ }
+}
+
+
+void RequestTx(CNodeState* state, const uint256& txid, int64_t nNow) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+{
+ CNodeState::TxDownloadState& peer_download_state = state->m_tx_download;
+ if (peer_download_state.m_tx_announced.size() >= MAX_PEER_TX_ANNOUNCEMENTS || peer_download_state.m_tx_announced.count(txid)) {
+ // Too many queued announcements from this peer, or we already have
+ // this announcement
+ return;
+ }
+ peer_download_state.m_tx_announced.insert(txid);
+
+ int64_t process_time;
+ int64_t last_request_time = GetTxRequestTime(txid);
+ // First time requesting this tx
+ if (last_request_time == 0) {
+ process_time = nNow;
+ } else {
+ // Randomize the delay to avoid biasing some peers over others (such as due to
+ // fixed ordering of peer processing in ThreadMessageHandler)
+ process_time = last_request_time + GETDATA_TX_INTERVAL + GetRand(MAX_GETDATA_RANDOM_DELAY);
+ }
+
+ // We delay processing announcements from non-preferred (eg inbound) peers
+ if (!state->fPreferredDownload) process_time += INBOUND_PEER_TX_DELAY;
+
+ peer_download_state.m_tx_process_time.emplace(process_time, txid);
+}
+
} // namespace
// This function is used for testing the stale tip eviction logic, see
@@ -614,7 +756,7 @@ void PeerLogicValidation::InitializeNode(CNode *pnode) {
NodeId nodeid = pnode->GetId();
{
LOCK(cs_main);
- mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, std::move(addrName)));
+ mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, std::move(addrName), pnode->fInbound, pnode->m_manual_connection));
}
if(!pnode->fInbound)
PushNodeVersion(pnode, connman, GetTime());
@@ -706,8 +848,9 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE
return false;
}
- auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME});
+ auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME, g_orphan_list.size()});
assert(ret.second);
+ g_orphan_list.push_back(ret.first);
for (const CTxIn& txin : tx->vin) {
mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first);
}
@@ -733,6 +876,18 @@ int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
if (itPrev->second.empty())
mapOrphanTransactionsByPrev.erase(itPrev);
}
+
+ size_t old_pos = it->second.list_pos;
+ assert(g_orphan_list[old_pos] == it);
+ if (old_pos + 1 != g_orphan_list.size()) {
+ // Unless we're deleting the last entry in g_orphan_list, move the last
+ // entry to the position we're deleting.
+ auto it_last = g_orphan_list.back();
+ g_orphan_list[old_pos] = it_last;
+ it_last->second.list_pos = old_pos;
+ }
+ g_orphan_list.pop_back();
+
mapOrphanTransactions.erase(it);
return 1;
}
@@ -779,14 +934,12 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL;
if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx due to expiration\n", nErased);
}
+ FastRandomContext rng;
while (mapOrphanTransactions.size() > nMaxOrphans)
{
// Evict a random orphan:
- uint256 randomhash = GetRandHash();
- std::map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
- if (it == mapOrphanTransactions.end())
- it = mapOrphanTransactions.begin();
- EraseOrphanTx(it->first);
+ size_t randompos = rng.randrange(g_orphan_list.size());
+ EraseOrphanTx(g_orphan_list[randompos]->first);
++nEvicted;
}
return nEvicted;
@@ -815,6 +968,90 @@ void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIV
LogPrint(BCLog::NET, "%s: %s peer=%d (%d -> %d)%s\n", __func__, state->name, pnode, state->nMisbehavior-howmuch, state->nMisbehavior, message_prefixed);
}
+/**
+ * Returns true if the given validation state result may result in a peer
+ * banning/disconnecting us. We use this to determine which unaccepted
+ * transactions from a whitelisted peer that we can safely relay.
+ */
+static bool TxRelayMayResultInDisconnect(const CValidationState& state)
+{
+ assert(IsTransactionReason(state.GetReason()));
+ return state.GetReason() == ValidationInvalidReason::CONSENSUS;
+}
+
+/**
+ * Potentially ban a node based on the contents of a CValidationState object
+ *
+ * @param[in] via_compact_block: this bool is passed in because net_processing should
+ * punish peers differently depending on whether the data was provided in a compact
+ * block message or not. If the compact block had a valid header, but contained invalid
+ * txs, the peer should not be punished. See BIP 152.
+ *
+ * @return Returns true if the peer was punished (probably disconnected)
+ *
+ * Changes here may need to be reflected in TxRelayMayResultInDisconnect().
+ */
+static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool via_compact_block, const std::string& message = "") {
+ switch (state.GetReason()) {
+ case ValidationInvalidReason::NONE:
+ break;
+ // The node is providing invalid data:
+ case ValidationInvalidReason::CONSENSUS:
+ case ValidationInvalidReason::BLOCK_MUTATED:
+ if (!via_compact_block) {
+ LOCK(cs_main);
+ Misbehaving(nodeid, 100, message);
+ return true;
+ }
+ break;
+ case ValidationInvalidReason::CACHED_INVALID:
+ {
+ LOCK(cs_main);
+ CNodeState *node_state = State(nodeid);
+ if (node_state == nullptr) {
+ break;
+ }
+
+ // Ban outbound (but not inbound) peers if on an invalid chain.
+ // Exempt HB compact block peers and manual connections.
+ if (!via_compact_block && !node_state->m_is_inbound && !node_state->m_is_manual_connection) {
+ Misbehaving(nodeid, 100, message);
+ return true;
+ }
+ break;
+ }
+ case ValidationInvalidReason::BLOCK_INVALID_HEADER:
+ case ValidationInvalidReason::BLOCK_CHECKPOINT:
+ case ValidationInvalidReason::BLOCK_INVALID_PREV:
+ {
+ LOCK(cs_main);
+ Misbehaving(nodeid, 100, message);
+ }
+ return true;
+ // Conflicting (but not necessarily invalid) data or different policy:
+ case ValidationInvalidReason::BLOCK_MISSING_PREV:
+ {
+ // TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
+ LOCK(cs_main);
+ Misbehaving(nodeid, 10, message);
+ }
+ return true;
+ case ValidationInvalidReason::RECENT_CONSENSUS_CHANGE:
+ case ValidationInvalidReason::BLOCK_TIME_FUTURE:
+ case ValidationInvalidReason::TX_NOT_STANDARD:
+ case ValidationInvalidReason::TX_MISSING_INPUTS:
+ case ValidationInvalidReason::TX_PREMATURE_SPEND:
+ case ValidationInvalidReason::TX_WITNESS_MUTATED:
+ case ValidationInvalidReason::TX_CONFLICT:
+ case ValidationInvalidReason::TX_MEMPOOL_POLICY:
+ break;
+ }
+ if (message != "") {
+ LogPrint(BCLog::NET, "peer=%d: %s\n", nodeid, message);
+ }
+ return false;
+}
+
@@ -831,18 +1068,17 @@ void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIV
// active chain if they are no more than a month older (both in time, and in
// best equivalent proof of work) than the best header chain we know about and
// we fully-validated them at some point.
-static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams)
+static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
- if (chainActive.Contains(pindex)) return true;
+ if (::ChainActive().Contains(pindex)) return true;
return pindex->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != nullptr) &&
(pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
}
-PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, CScheduler &scheduler, bool enable_bip61)
- : connman(connmanIn), m_stale_tip_check_time(0), m_enable_bip61(enable_bip61) {
-
+PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler &scheduler, bool enable_bip61)
+ : connman(connmanIn), m_banman(banman), m_stale_tip_check_time(0), m_enable_bip61(enable_bip61) {
// Initialize global variables that cannot be constructed at startup.
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
@@ -882,7 +1118,7 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pb
// Erase orphan transactions included or precluded by this block
if (vOrphanErase.size()) {
int nErased = 0;
- for (uint256 &orphanHash : vOrphanErase) {
+ for (const uint256& orphanHash : vOrphanErase) {
nErased += EraseOrphanTx(orphanHash);
}
LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased);
@@ -947,7 +1183,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std:
/**
* Update our best height and announce any block hashes which weren't previously
- * in chainActive to our peers.
+ * in ::ChainActive() to our peers.
*/
void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
const int nNewHeight = pindexNew->nHeight;
@@ -977,8 +1213,6 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CB
});
connman->WakeMessageHandler();
}
-
- nTimeBestReceived = GetTime();
}
/**
@@ -991,14 +1225,12 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
const uint256 hash(block.GetHash());
std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
- int nDoS = 0;
- if (state.IsInvalid(nDoS)) {
+ if (state.IsInvalid()) {
// Don't send reject message with code 0 or an internal reject code.
if (it != mapBlockSource.end() && State(it->second.first) && state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) {
CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), hash};
State(it->second.first)->rejects.push_back(reject);
- if (nDoS > 0 && it->second.second)
- Misbehaving(it->second.first, nDoS);
+ MaybePunishNode(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second);
}
}
// Check that:
@@ -1032,13 +1264,13 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
case MSG_WITNESS_TX:
{
assert(recentRejects);
- if (chainActive.Tip()->GetBlockHash() != hashRecentRejectsChainTip)
+ if (::ChainActive().Tip()->GetBlockHash() != hashRecentRejectsChainTip)
{
// If the chain tip has changed previously rejected transactions
// might be now valid, e.g. due to a nLockTime'd tx becoming valid,
// or a double-spend. Reset the rejects filter and give those
// txs a second chance.
- hashRecentRejectsChainTip = chainActive.Tip()->GetBlockHash();
+ hashRecentRejectsChainTip = ::ChainActive().Tip()->GetBlockHash();
recentRejects->reset();
}
@@ -1124,7 +1356,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
LOCK(cs_main);
const CBlockIndex* pindex = LookupBlockIndex(inv.hash);
if (pindex) {
- if (pindex->nChainTx && !pindex->IsValid(BLOCK_VALID_SCRIPTS) &&
+ if (pindex->HaveTxsDownloaded() && !pindex->IsValid(BLOCK_VALID_SCRIPTS) &&
pindex->IsValid(BLOCK_VALID_TREE)) {
// If we have the block and all of its parents, but have not yet validated it,
// we might be in the middle of connecting it (ie in the unlock of cs_main
@@ -1163,7 +1395,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
}
// Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold
if (send && !pfrom->fWhitelisted && (
- (((pfrom->GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom->GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (chainActive.Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) )
+ (((pfrom->GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom->GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (::ChainActive().Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) )
)) {
LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold from peer=%d\n", pfrom->GetId());
@@ -1233,7 +1465,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
// instead we respond with the full, non-compact block.
bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness;
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
- if (CanDirectFetch(consensusParams) && pindex->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
+ if (CanDirectFetch(consensusParams) && pindex->nHeight >= ::ChainActive().Height() - MAX_CMPCTBLOCK_DEPTH) {
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
} else {
@@ -1253,14 +1485,14 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
// and we want it right after the last block so they don't
// wait for other stuff first.
std::vector<CInv> vInv;
- vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
+ vInv.push_back(CInv(MSG_BLOCK, ::ChainActive().Tip()->GetBlockHash()));
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv));
pfrom->hashContinue.SetNull();
}
}
}
-void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
+void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
{
AssertLockNotHeld(cs_main);
@@ -1348,7 +1580,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCKTXN, resp));
}
-bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::vector<CBlockHeader>& headers, const CChainParams& chainparams, bool punish_duplicate_invalid)
+bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::vector<CBlockHeader>& headers, const CChainParams& chainparams, bool via_compact_block)
{
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
size_t nCount = headers.size();
@@ -1374,7 +1606,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
// nUnconnectingHeaders gets reset back to 0.
if (!LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
nodestate->nUnconnectingHeaders++;
- connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), uint256()));
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
headers[0].GetHash().ToString(),
headers[0].hashPrevBlock.ToString(),
@@ -1410,48 +1642,8 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
CValidationState state;
CBlockHeader first_invalid_header;
if (!ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast, &first_invalid_header)) {
- int nDoS;
- if (state.IsInvalid(nDoS)) {
- LOCK(cs_main);
- if (nDoS > 0) {
- Misbehaving(pfrom->GetId(), nDoS, "invalid header received");
- } else {
- LogPrint(BCLog::NET, "peer=%d: invalid header received\n", pfrom->GetId());
- }
- if (punish_duplicate_invalid && LookupBlockIndex(first_invalid_header.GetHash())) {
- // Goal: don't allow outbound peers to use up our outbound
- // connection slots if they are on incompatible chains.
- //
- // We ask the caller to set punish_invalid appropriately based
- // on the peer and the method of header delivery (compact
- // blocks are allowed to be invalid in some circumstances,
- // under BIP 152).
- // Here, we try to detect the narrow situation that we have a
- // valid block header (ie it was valid at the time the header
- // was received, and hence stored in mapBlockIndex) but know the
- // block is invalid, and that a peer has announced that same
- // block as being on its active chain.
- // Disconnect the peer in such a situation.
- //
- // Note: if the header that is invalid was not accepted to our
- // mapBlockIndex at all, that may also be grounds for
- // disconnecting the peer, as the chain they are on is likely
- // to be incompatible. However, there is a circumstance where
- // that does not hold: if the header's timestamp is more than
- // 2 hours ahead of our current time. In that case, the header
- // may become valid in the future, and we don't want to
- // disconnect a peer merely for serving us one too-far-ahead
- // block header, to prevent an attacker from splitting the
- // network by mining a block right at the 2 hour boundary.
- //
- // TODO: update the DoS logic (or, rather, rewrite the
- // DoS-interface between validation and net_processing) so that
- // the interface is cleaner, and so that we disconnect on all the
- // reasons that a peer's headers chain is incompatible
- // with ours (eg block->nVersion softforks, MTP violations,
- // etc), and not just the duplicate-invalid case.
- pfrom->fDisconnect = true;
- }
+ if (state.IsInvalid()) {
+ MaybePunishNode(pfrom->GetId(), state, via_compact_block, "invalid header received");
return false;
}
}
@@ -1471,26 +1663,26 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
// because it is set in UpdateBlockAvailability. Some nullptr checks
// are still present, however, as belt-and-suspenders.
- if (received_new_header && pindexLast->nChainWork > chainActive.Tip()->nChainWork) {
+ if (received_new_header && pindexLast->nChainWork > ::ChainActive().Tip()->nChainWork) {
nodestate->m_last_block_announcement = GetTime();
}
if (nCount == MAX_HEADERS_RESULTS) {
// Headers message had its maximum size; the peer may have more headers.
- // TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
+ // TODO: optimize: if pindexLast is an ancestor of ::ChainActive().Tip or pindexBestHeader, continue
// from there instead.
LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->GetId(), pfrom->nStartingHeight);
- connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256()));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexLast), uint256()));
}
bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus());
// If this set of headers is valid and ends in a block with at least as
// much work as our tip, download as much as possible.
- if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainWork <= pindexLast->nChainWork) {
+ if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && ::ChainActive().Tip()->nChainWork <= pindexLast->nChainWork) {
std::vector<const CBlockIndex*> vToFetch;
const CBlockIndex *pindexWalk = pindexLast;
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
- while (pindexWalk && !chainActive.Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
+ while (pindexWalk && !::ChainActive().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
!mapBlocksInFlight.count(pindexWalk->GetBlockHash()) &&
(!IsWitnessEnabled(pindexWalk->pprev, chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) {
@@ -1503,7 +1695,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
// very large reorg at a time we think we're close to caught up to
// the main chain -- this shouldn't really happen. Bail out on the
// direct fetch and rely on parallel download instead.
- if (!chainActive.Contains(pindexWalk)) {
+ if (!::ChainActive().Contains(pindexWalk)) {
LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
pindexLast->GetBlockHash().ToString(),
pindexLast->nHeight);
@@ -1544,7 +1736,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
// us sync -- disconnect if using an outbound slot (unless
// whitelisted or addnode).
// Note: We compare their tip to nMinimumChainWork (rather than
- // chainActive.Tip()) because we won't start block download
+ // ::ChainActive().Tip()) because we won't start block download
// until we have a headers chain that has at least
// nMinimumChainWork, even if a peer has a chain past our tip,
// as an anti-DoS measure.
@@ -1558,7 +1750,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
if (!pfrom->fDisconnect && IsOutboundDisconnectionCandidate(pfrom) && nodestate->pindexBestKnownBlock != nullptr) {
// If this is an outbound peer, check to see if we should protect
// it from the bad/lagging chain logic.
- if (g_outbound_peers_with_protect_from_disconnect < MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT && nodestate->pindexBestKnownBlock->nChainWork >= chainActive.Tip()->nChainWork && !nodestate->m_chain_sync.m_protect) {
+ if (g_outbound_peers_with_protect_from_disconnect < MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT && nodestate->pindexBestKnownBlock->nChainWork >= ::ChainActive().Tip()->nChainWork && !nodestate->m_chain_sync.m_protect) {
LogPrint(BCLog::NET, "Protecting outbound peer=%d from eviction\n", pfrom->GetId());
nodestate->m_chain_sync.m_protect = true;
++g_outbound_peers_with_protect_from_disconnect;
@@ -1569,6 +1761,68 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
return true;
}
+void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_set, std::list<CTransactionRef>& removed_txn) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
+{
+ AssertLockHeld(cs_main);
+ AssertLockHeld(g_cs_orphans);
+ std::set<NodeId> setMisbehaving;
+ bool done = false;
+ while (!done && !orphan_work_set.empty()) {
+ const uint256 orphanHash = *orphan_work_set.begin();
+ orphan_work_set.erase(orphan_work_set.begin());
+
+ auto orphan_it = mapOrphanTransactions.find(orphanHash);
+ if (orphan_it == mapOrphanTransactions.end()) continue;
+
+ const CTransactionRef porphanTx = orphan_it->second.tx;
+ const CTransaction& orphanTx = *porphanTx;
+ NodeId fromPeer = orphan_it->second.fromPeer;
+ bool fMissingInputs2 = false;
+ // Use a new CValidationState because orphans come from different peers (and we call
+ // MaybePunishNode based on the source peer from the orphan map, not based on the peer
+ // that relayed the previous transaction).
+ CValidationState orphan_state;
+
+ if (setMisbehaving.count(fromPeer)) continue;
+ if (AcceptToMemoryPool(mempool, orphan_state, porphanTx, &fMissingInputs2, &removed_txn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
+ LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
+ RelayTransaction(orphanTx, connman);
+ for (unsigned int i = 0; i < orphanTx.vout.size(); i++) {
+ auto it_by_prev = mapOrphanTransactionsByPrev.find(COutPoint(orphanHash, i));
+ if (it_by_prev != mapOrphanTransactionsByPrev.end()) {
+ for (const auto& elem : it_by_prev->second) {
+ orphan_work_set.insert(elem->first);
+ }
+ }
+ }
+ EraseOrphanTx(orphanHash);
+ done = true;
+ } else if (!fMissingInputs2) {
+ if (orphan_state.IsInvalid()) {
+ // Punish peer that gave us an invalid orphan tx
+ if (MaybePunishNode(fromPeer, orphan_state, /*via_compact_block*/ false)) {
+ setMisbehaving.insert(fromPeer);
+ }
+ LogPrint(BCLog::MEMPOOL, " invalid orphan tx %s\n", orphanHash.ToString());
+ }
+ // Has inputs but not accepted to mempool
+ // Probably non-standard or insufficient fee
+ LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString());
+ assert(IsTransactionReason(orphan_state.GetReason()));
+ if (!orphanTx.HasWitness() && orphan_state.GetReason() != ValidationInvalidReason::TX_WITNESS_MUTATED) {
+ // Do not use rejection cache for witness transactions or
+ // witness-stripped transactions, as they can have been malleated.
+ // See https://github.com/bitcoin/bitcoin/issues/8279 for details.
+ assert(recentRejects);
+ recentRejects->insert(orphanHash);
+ }
+ EraseOrphanTx(orphanHash);
+ done = true;
+ }
+ mempool.check(pcoinsTip.get());
+ }
+}
+
bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc, bool enable_bip61)
{
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
@@ -1618,8 +1872,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- else if (strCommand == NetMsgType::VERSION)
- {
+ if (strCommand == NetMsgType::VERSION) {
// Each connection can only send one version message
if (pfrom->nVersion != 0)
{
@@ -1639,7 +1892,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
ServiceFlags nServices;
int nVersion;
int nSendVersion;
- std::string strSubVer;
std::string cleanSubVer;
int nStartingHeight = -1;
bool fRelay = true;
@@ -1662,8 +1914,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return false;
}
- if (nVersion < MIN_PEER_PROTO_VERSION)
- {
+ if (nVersion < MIN_PEER_PROTO_VERSION) {
// disconnect from peers older than this proto version
LogPrint(BCLog::NET, "peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion);
if (enable_bip61) {
@@ -1674,11 +1925,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return false;
}
- if (nVersion == 10300)
- nVersion = 300;
if (!vRecv.empty())
vRecv >> addrFrom >> nNonce;
if (!vRecv.empty()) {
+ std::string strSubVer;
vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);
cleanSubVer = SanitizeString(strSubVer);
}
@@ -1710,7 +1960,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->SetAddrLocal(addrMe);
{
LOCK(pfrom->cs_SubVer);
- pfrom->strSubVer = strSubVer;
pfrom->cleanSubVer = cleanSubVer;
}
pfrom->nStartingHeight = nStartingHeight;
@@ -1796,9 +2045,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
-
- else if (pfrom->nVersion == 0)
- {
+ if (pfrom->nVersion == 0) {
// Must have a version message before anything else
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 1);
@@ -1842,18 +2089,17 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
}
pfrom->fSuccessfullyConnected = true;
+ return true;
}
- else if (!pfrom->fSuccessfullyConnected)
- {
+ if (!pfrom->fSuccessfullyConnected) {
// Must have a verack message before anything else
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 1);
return false;
}
- else if (strCommand == NetMsgType::ADDR)
- {
+ if (strCommand == NetMsgType::ADDR) {
std::vector<CAddress> vAddr;
vRecv >> vAddr;
@@ -1885,6 +2131,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
addr.nTime = nNow - 5 * 24 * 60 * 60;
pfrom->AddAddressKnown(addr);
+ if (g_banman->IsBanned(addr)) continue; // Do not process banned addresses beyond remembering we received them
bool fReachable = IsReachable(addr);
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
{
@@ -1900,16 +2147,16 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->fGetAddr = false;
if (pfrom->fOneShot)
pfrom->fDisconnect = true;
+ return true;
}
- else if (strCommand == NetMsgType::SENDHEADERS)
- {
+ if (strCommand == NetMsgType::SENDHEADERS) {
LOCK(cs_main);
State(pfrom->GetId())->fPreferHeaders = true;
+ return true;
}
- else if (strCommand == NetMsgType::SENDCMPCT)
- {
+ if (strCommand == NetMsgType::SENDCMPCT) {
bool fAnnounceUsingCMPCTBLOCK = false;
uint64_t nCMPCTBLOCKVersion = 0;
vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
@@ -1929,11 +2176,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
State(pfrom->GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
}
}
+ return true;
}
-
- else if (strCommand == NetMsgType::INV)
- {
+ if (strCommand == NetMsgType::INV) {
std::vector<CInv> vInv;
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ)
@@ -1943,7 +2189,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return false;
}
- bool fBlocksOnly = !fRelayTxes;
+ bool fBlocksOnly = !g_relay_txes;
// Allow whitelisted peers to send data other than blocks in blocks only mode if whitelistrelay is true
if (pfrom->fWhitelisted && gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))
@@ -1952,6 +2198,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
uint32_t nFetchFlags = GetFetchFlags(pfrom);
+ int64_t nNow = GetTimeMicros();
for (CInv &inv : vInv)
{
@@ -1973,7 +2220,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// fell back to inv we probably have a reorg which we should get the headers for first,
// we now only provide a getheaders response here. When we receive the headers, we will
// then ask for the blocks we need.
- connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), inv.hash));
LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->GetId());
}
}
@@ -1983,15 +2230,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (fBlocksOnly) {
LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->GetId());
} else if (!fAlreadyHave && !fImporting && !fReindex && !IsInitialBlockDownload()) {
- pfrom->AskFor(inv);
+ RequestTx(State(pfrom->GetId()), inv.hash, nNow);
}
}
}
+ return true;
}
-
- else if (strCommand == NetMsgType::GETDATA)
- {
+ if (strCommand == NetMsgType::GETDATA) {
std::vector<CInv> vInv;
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ)
@@ -2009,15 +2255,20 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
+ return true;
}
-
- else if (strCommand == NetMsgType::GETBLOCKS)
- {
+ if (strCommand == NetMsgType::GETBLOCKS) {
CBlockLocator locator;
uint256 hashStop;
vRecv >> locator >> hashStop;
+ if (locator.vHave.size() > MAX_LOCATOR_SZ) {
+ LogPrint(BCLog::NET, "getblocks locator size %lld > %d, disconnect peer=%d\n", locator.vHave.size(), MAX_LOCATOR_SZ, pfrom->GetId());
+ pfrom->fDisconnect = true;
+ return true;
+ }
+
// We might have announced the currently-being-connected tip using a
// compact block, which resulted in the peer sending a getblocks
// request, which we would otherwise respond to without the new block.
@@ -2040,14 +2291,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
// Find the last block the caller has in the main chain
- const CBlockIndex* pindex = FindForkInGlobalIndex(chainActive, locator);
+ const CBlockIndex* pindex = FindForkInGlobalIndex(::ChainActive(), locator);
// Send the rest of the chain
if (pindex)
- pindex = chainActive.Next(pindex);
+ pindex = ::ChainActive().Next(pindex);
int nLimit = 500;
LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->GetId());
- for (; pindex; pindex = chainActive.Next(pindex))
+ for (; pindex; pindex = ::ChainActive().Next(pindex))
{
if (pindex->GetBlockHash() == hashStop)
{
@@ -2057,7 +2308,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// 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 / chainparams.GetConsensus().nPowTargetSpacing;
- if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= chainActive.Tip()->nHeight - nPrunedBlocksLikelyToHave))
+ if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= ::ChainActive().Tip()->nHeight - nPrunedBlocksLikelyToHave))
{
LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
break;
@@ -2072,11 +2323,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
break;
}
}
+ return true;
}
-
- else if (strCommand == NetMsgType::GETBLOCKTXN)
- {
+ if (strCommand == NetMsgType::GETBLOCKTXN) {
BlockTransactionsRequest req;
vRecv >> req;
@@ -2100,7 +2350,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
}
- if (pindex->nHeight < chainActive.Height() - MAX_BLOCKTXN_DEPTH) {
+ if (pindex->nHeight < ::ChainActive().Height() - MAX_BLOCKTXN_DEPTH) {
// If an older block is requested (should never happen in practice,
// but can happen in tests) send a block response instead of a
// blocktxn response. Sending a full block response instead of a
@@ -2122,15 +2372,20 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
assert(ret);
SendBlockTransactions(block, req, pfrom, connman);
+ return true;
}
-
- else if (strCommand == NetMsgType::GETHEADERS)
- {
+ if (strCommand == NetMsgType::GETHEADERS) {
CBlockLocator locator;
uint256 hashStop;
vRecv >> locator >> hashStop;
+ if (locator.vHave.size() > MAX_LOCATOR_SZ) {
+ LogPrint(BCLog::NET, "getheaders locator size %lld > %d, disconnect peer=%d\n", locator.vHave.size(), MAX_LOCATOR_SZ, pfrom->GetId());
+ pfrom->fDisconnect = true;
+ return true;
+ }
+
LOCK(cs_main);
if (IsInitialBlockDownload() && !pfrom->fWhitelisted) {
LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->GetId());
@@ -2155,23 +2410,23 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
else
{
// Find the last block the caller has in the main chain
- pindex = FindForkInGlobalIndex(chainActive, locator);
+ pindex = FindForkInGlobalIndex(::ChainActive(), locator);
if (pindex)
- pindex = chainActive.Next(pindex);
+ pindex = ::ChainActive().Next(pindex);
}
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
std::vector<CBlock> vHeaders;
int nLimit = MAX_HEADERS_RESULTS;
LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->GetId());
- for (; pindex; pindex = chainActive.Next(pindex))
+ for (; pindex; pindex = ::ChainActive().Next(pindex))
{
vHeaders.push_back(pindex->GetBlockHeader());
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
break;
}
- // pindex can be nullptr either if we sent chainActive.Tip() OR
- // if our peer has chainActive.Tip() (and thus we are sending an empty
+ // pindex can be nullptr either if we sent ::ChainActive().Tip() OR
+ // if our peer has ::ChainActive().Tip() (and thus we are sending an empty
// headers message). In both cases it's safe to update
// pindexBestHeaderSent to be our tip.
//
@@ -2182,23 +2437,20 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// without the new block. By resetting the BestHeaderSent, we ensure we
// will re-announce the new block via headers (or compact blocks again)
// in the SendMessages logic.
- nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
+ nodestate->pindexBestHeaderSent = pindex ? pindex : ::ChainActive().Tip();
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
+ return true;
}
-
- else if (strCommand == NetMsgType::TX)
- {
+ if (strCommand == NetMsgType::TX) {
// Stop processing the transaction early if
// We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off
- if (!fRelayTxes && (!pfrom->fWhitelisted || !gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)))
+ if (!g_relay_txes && (!pfrom->fWhitelisted || !gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)))
{
LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->GetId());
return true;
}
- std::deque<COutPoint> vWorkQueue;
- std::vector<uint256> vEraseQueue;
CTransactionRef ptx;
vRecv >> ptx;
const CTransaction& tx = *ptx;
@@ -2211,8 +2463,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
bool fMissingInputs = false;
CValidationState state;
- pfrom->setAskFor.erase(inv.hash);
- mapAlreadyAskedFor.erase(inv.hash);
+ CNodeState* nodestate = State(pfrom->GetId());
+ nodestate->m_tx_download.m_tx_announced.erase(inv.hash);
+ nodestate->m_tx_download.m_tx_in_flight.erase(inv.hash);
+ EraseTxRequest(inv.hash);
std::list<CTransactionRef> lRemovedTxn;
@@ -2221,7 +2475,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
mempool.check(pcoinsTip.get());
RelayTransaction(tx, connman);
for (unsigned int i = 0; i < tx.vout.size(); i++) {
- vWorkQueue.emplace_back(inv.hash, i);
+ auto it_by_prev = mapOrphanTransactionsByPrev.find(COutPoint(inv.hash, i));
+ if (it_by_prev != mapOrphanTransactionsByPrev.end()) {
+ for (const auto& elem : it_by_prev->second) {
+ pfrom->orphan_work_set.insert(elem->first);
+ }
+ }
}
pfrom->nLastTXTime = GetTime();
@@ -2232,65 +2491,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
mempool.size(), mempool.DynamicMemoryUsage() / 1000);
// Recursively process any orphan transactions that depended on this one
- std::set<NodeId> setMisbehaving;
- while (!vWorkQueue.empty()) {
- auto itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue.front());
- vWorkQueue.pop_front();
- if (itByPrev == mapOrphanTransactionsByPrev.end())
- continue;
- for (auto mi = itByPrev->second.begin();
- mi != itByPrev->second.end();
- ++mi)
- {
- const CTransactionRef& porphanTx = (*mi)->second.tx;
- const CTransaction& orphanTx = *porphanTx;
- const uint256& orphanHash = orphanTx.GetHash();
- NodeId fromPeer = (*mi)->second.fromPeer;
- bool fMissingInputs2 = false;
- // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
- // resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get
- // anyone relaying LegitTxX banned)
- CValidationState stateDummy;
-
-
- if (setMisbehaving.count(fromPeer))
- continue;
- if (AcceptToMemoryPool(mempool, stateDummy, porphanTx, &fMissingInputs2, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
- LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
- RelayTransaction(orphanTx, connman);
- for (unsigned int i = 0; i < orphanTx.vout.size(); i++) {
- vWorkQueue.emplace_back(orphanHash, i);
- }
- vEraseQueue.push_back(orphanHash);
- }
- else if (!fMissingInputs2)
- {
- int nDos = 0;
- if (stateDummy.IsInvalid(nDos) && nDos > 0)
- {
- // Punish peer that gave us an invalid orphan tx
- Misbehaving(fromPeer, nDos);
- setMisbehaving.insert(fromPeer);
- LogPrint(BCLog::MEMPOOL, " invalid orphan tx %s\n", orphanHash.ToString());
- }
- // Has inputs but not accepted to mempool
- // Probably non-standard or insufficient fee
- LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString());
- vEraseQueue.push_back(orphanHash);
- if (!orphanTx.HasWitness() && !stateDummy.CorruptionPossible()) {
- // Do not use rejection cache for witness transactions or
- // witness-stripped transactions, as they can have been malleated.
- // See https://github.com/bitcoin/bitcoin/issues/8279 for details.
- assert(recentRejects);
- recentRejects->insert(orphanHash);
- }
- }
- mempool.check(pcoinsTip.get());
- }
- }
-
- for (uint256 hash : vEraseQueue)
- EraseOrphanTx(hash);
+ ProcessOrphanTx(connman, pfrom->orphan_work_set, lRemovedTxn);
}
else if (fMissingInputs)
{
@@ -2303,10 +2504,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
if (!fRejectedParents) {
uint32_t nFetchFlags = GetFetchFlags(pfrom);
+ int64_t nNow = GetTimeMicros();
+
for (const CTxIn& txin : tx.vin) {
CInv _inv(MSG_TX | nFetchFlags, txin.prevout.hash);
pfrom->AddInventoryKnown(_inv);
- if (!AlreadyHave(_inv)) pfrom->AskFor(_inv);
+ if (!AlreadyHave(_inv)) RequestTx(State(pfrom->GetId()), _inv.hash, nNow);
}
AddOrphanTx(ptx, pfrom->GetId());
@@ -2323,7 +2526,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
recentRejects->insert(tx.GetHash());
}
} else {
- if (!tx.HasWitness() && !state.CorruptionPossible()) {
+ assert(IsTransactionReason(state.GetReason()));
+ if (!tx.HasWitness() && state.GetReason() != ValidationInvalidReason::TX_WITNESS_MUTATED) {
// Do not use rejection cache for witness transactions or
// witness-stripped transactions, as they can have been malleated.
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
@@ -2342,15 +2546,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// to policy, allowing the node to function as a gateway for
// nodes hidden behind it.
//
- // Never relay transactions that we would assign a non-zero DoS
- // score for, as we expect peers to do the same with us in that
- // case.
- int nDoS = 0;
- if (!state.IsInvalid(nDoS) || nDoS == 0) {
+ // Never relay transactions that might result in being
+ // disconnected (or banned).
+ if (state.IsInvalid() && TxRelayMayResultInDisconnect(state)) {
+ LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->GetId(), FormatStateMessage(state));
+ } else {
LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->GetId());
RelayTransaction(tx, connman);
- } else {
- LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->GetId(), FormatStateMessage(state));
}
}
}
@@ -2358,8 +2560,24 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
for (const CTransactionRef& removedTx : lRemovedTxn)
AddToCompactExtraTransactions(removedTx);
- int nDoS = 0;
- if (state.IsInvalid(nDoS))
+ // If a tx has been detected by recentRejects, we will have reached
+ // this point and the tx will have been ignored. Because we haven't run
+ // the tx through AcceptToMemoryPool, we won't have computed a DoS
+ // score for it or determined exactly why we consider it invalid.
+ //
+ // This means we won't penalize any peer subsequently relaying a DoSy
+ // tx (even if we penalized the first peer who gave it to us) because
+ // we have to account for recentRejects showing false positives. In
+ // other words, we shouldn't penalize a peer if we aren't *sure* they
+ // submitted a DoSy tx.
+ //
+ // Note that recentRejects doesn't just record DoSy or invalid
+ // transactions, but any tx not accepted by the mempool, which may be
+ // due to node policy (vs. consensus). So we can't blanket penalize a
+ // peer simply for relaying a tx that our recentRejects has caught,
+ // regardless of false positives.
+
+ if (state.IsInvalid())
{
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
pfrom->GetId(),
@@ -2368,15 +2586,19 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash));
}
- if (nDoS > 0) {
- Misbehaving(pfrom->GetId(), nDoS);
- }
+ MaybePunishNode(pfrom->GetId(), state, /*via_compact_block*/ false);
}
+ return true;
}
-
- else if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
+ if (strCommand == NetMsgType::CMPCTBLOCK)
{
+ // Ignore cmpctblock received while importing
+ if (fImporting || fReindex) {
+ LogPrint(BCLog::NET, "Unexpected cmpctblock message received from peer %d\n", pfrom->GetId());
+ return true;
+ }
+
CBlockHeaderAndShortTxIDs cmpctblock;
vRecv >> cmpctblock;
@@ -2388,7 +2610,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
if (!IsInitialBlockDownload())
- connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), uint256()));
return true;
}
@@ -2400,14 +2622,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
const CBlockIndex *pindex = nullptr;
CValidationState state;
if (!ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) {
- int nDoS;
- if (state.IsInvalid(nDoS)) {
- if (nDoS > 0) {
- LOCK(cs_main);
- Misbehaving(pfrom->GetId(), nDoS, strprintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId()));
- } else {
- LogPrint(BCLog::NET, "Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId());
- }
+ if (state.IsInvalid()) {
+ MaybePunishNode(pfrom->GetId(), state, /*via_compact_block*/ true, "invalid header via cmpctblock");
return true;
}
}
@@ -2438,7 +2654,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// If this was a new header with more work than our tip, update the
// peer's last block announcement time
- if (received_new_header && pindex->nChainWork > chainActive.Tip()->nChainWork) {
+ if (received_new_header && pindex->nChainWork > ::ChainActive().Tip()->nChainWork) {
nodestate->m_last_block_announcement = GetTime();
}
@@ -2448,7 +2664,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here
return true;
- if (pindex->nChainWork <= chainActive.Tip()->nChainWork || // We know something better
+ if (pindex->nChainWork <= ::ChainActive().Tip()->nChainWork || // We know something better
pindex->nTx != 0) { // We had this block at some point, but pruned it
if (fAlreadyInFlight) {
// We requested this block for some reason, but our mempool will probably be useless
@@ -2472,7 +2688,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// We want to be a bit conservative just to be extra careful about DoS
// possibilities in compact block processing...
- if (pindex->nHeight <= chainActive.Height() + 2) {
+ if (pindex->nHeight <= ::ChainActive().Height() + 2) {
if ((!fAlreadyInFlight && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
(fAlreadyInFlight && blockInFlightIt->second.first == pfrom->GetId())) {
std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr;
@@ -2557,7 +2773,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// the peer if the header turns out to be for an invalid block.
// Note that if a peer tries to build on an invalid chain, that
// will be detected and the peer will be banned.
- return ProcessHeadersMessage(pfrom, connman, {cmpctblock.header}, chainparams, /*punish_duplicate_invalid=*/false);
+ return ProcessHeadersMessage(pfrom, connman, {cmpctblock.header}, chainparams, /*via_compact_block=*/true);
}
if (fBlockReconstructed) {
@@ -2593,11 +2809,17 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
MarkBlockAsReceived(pblock->GetHash());
}
}
-
+ return true;
}
- else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex) // Ignore blocks received while importing
+ if (strCommand == NetMsgType::BLOCKTXN)
{
+ // Ignore blocktxn received while importing
+ if (fImporting || fReindex) {
+ LogPrint(BCLog::NET, "Unexpected blocktxn message received from peer %d\n", pfrom->GetId());
+ return true;
+ }
+
BlockTransactions resp;
vRecv >> resp;
@@ -2668,11 +2890,17 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
mapBlockSource.erase(pblock->GetHash());
}
}
+ return true;
}
-
- else if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) // Ignore headers received while importing
+ if (strCommand == NetMsgType::HEADERS)
{
+ // Ignore headers received while importing
+ if (fImporting || fReindex) {
+ LogPrint(BCLog::NET, "Unexpected headers message received from peer %d\n", pfrom->GetId());
+ return true;
+ }
+
std::vector<CBlockHeader> headers;
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
@@ -2688,16 +2916,17 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
}
- // Headers received via a HEADERS message should be valid, and reflect
- // the chain the peer is on. If we receive a known-invalid header,
- // disconnect the peer if it is using one of our outbound connection
- // slots.
- bool should_punish = !pfrom->fInbound && !pfrom->m_manual_connection;
- return ProcessHeadersMessage(pfrom, connman, headers, chainparams, should_punish);
+ return ProcessHeadersMessage(pfrom, connman, headers, chainparams, /*via_compact_block=*/false);
}
- else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
+ if (strCommand == NetMsgType::BLOCK)
{
+ // Ignore block received while importing
+ if (fImporting || fReindex) {
+ LogPrint(BCLog::NET, "Unexpected block message received from peer %d\n", pfrom->GetId());
+ return true;
+ }
+
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
vRecv >> *pblock;
@@ -2722,11 +2951,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
mapBlockSource.erase(pblock->GetHash());
}
+ return true;
}
-
- else if (strCommand == NetMsgType::GETADDR)
- {
+ if (strCommand == NetMsgType::GETADDR) {
// This asymmetric behavior for inbound and outbound connections was introduced
// to prevent a fingerprinting attack: an attacker can send specific fake addresses
// to users' AddrMan and later request them by sending getaddr messages.
@@ -2748,13 +2976,15 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->vAddrToSend.clear();
std::vector<CAddress> vAddr = connman->GetAddresses();
FastRandomContext insecure_rand;
- for (const CAddress &addr : vAddr)
- pfrom->PushAddress(addr, insecure_rand);
+ for (const CAddress &addr : vAddr) {
+ if (!g_banman->IsBanned(addr)) {
+ pfrom->PushAddress(addr, insecure_rand);
+ }
+ }
+ return true;
}
-
- else if (strCommand == NetMsgType::MEMPOOL)
- {
+ if (strCommand == NetMsgType::MEMPOOL) {
if (!(pfrom->GetLocalServices() & NODE_BLOOM) && !pfrom->fWhitelisted)
{
LogPrint(BCLog::NET, "mempool request with bloom filters disabled, disconnect peer=%d\n", pfrom->GetId());
@@ -2771,11 +3001,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(pfrom->cs_inventory);
pfrom->fSendMempool = true;
+ return true;
}
-
- else if (strCommand == NetMsgType::PING)
- {
+ if (strCommand == NetMsgType::PING) {
if (pfrom->nVersion > BIP0031_VERSION)
{
uint64_t nonce = 0;
@@ -2793,11 +3022,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// return very quickly.
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::PONG, nonce));
}
+ return true;
}
-
- else if (strCommand == NetMsgType::PONG)
- {
+ if (strCommand == NetMsgType::PONG) {
int64_t pingUsecEnd = nTimeReceived;
uint64_t nonce = 0;
size_t nAvail = vRecv.in_avail();
@@ -2850,11 +3078,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (bPingFinished) {
pfrom->nPingNonceSent = 0;
}
+ return true;
}
-
- else if (strCommand == NetMsgType::FILTERLOAD)
- {
+ if (strCommand == NetMsgType::FILTERLOAD) {
CBloomFilter filter;
vRecv >> filter;
@@ -2871,11 +3098,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->pfilter->UpdateEmptyFull();
pfrom->fRelayTxes = true;
}
+ return true;
}
-
- else if (strCommand == NetMsgType::FILTERADD)
- {
+ if (strCommand == NetMsgType::FILTERADD) {
std::vector<unsigned char> vData;
vRecv >> vData;
@@ -2896,19 +3122,19 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 100);
}
+ return true;
}
-
- else if (strCommand == NetMsgType::FILTERCLEAR)
- {
+ if (strCommand == NetMsgType::FILTERCLEAR) {
LOCK(pfrom->cs_filter);
if (pfrom->GetLocalServices() & NODE_BLOOM) {
pfrom->pfilter.reset(new CBloomFilter());
}
pfrom->fRelayTxes = true;
+ return true;
}
- else if (strCommand == NetMsgType::FEEFILTER) {
+ if (strCommand == NetMsgType::FEEFILTER) {
CAmount newFeeFilter = 0;
vRecv >> newFeeFilter;
if (MoneyRange(newFeeFilter)) {
@@ -2918,24 +3144,21 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->GetId());
}
+ return true;
}
- else if (strCommand == NetMsgType::NOTFOUND) {
+ if (strCommand == NetMsgType::NOTFOUND) {
// We do not care about the NOTFOUND message, but logging an Unknown Command
// message would be undesirable as we transmit it ourselves.
+ return true;
}
- else {
- // Ignore unknown commands for extensibility
- LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());
- }
-
-
-
+ // Ignore unknown commands for extensibility
+ LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());
return true;
}
-static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman, bool enable_bip61)
+bool PeerLogicValidation::SendRejectsAndCheckIfBanned(CNode* pnode, bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
CNodeState &state = *State(pnode->GetId());
@@ -2953,14 +3176,16 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman, bool en
LogPrintf("Warning: not punishing whitelisted peer %s!\n", pnode->addr.ToString());
else if (pnode->m_manual_connection)
LogPrintf("Warning: not punishing manually-connected peer %s!\n", pnode->addr.ToString());
- else {
+ else if (pnode->addr.IsLocal()) {
+ // Disconnect but don't ban _this_ local node
+ LogPrintf("Warning: disconnecting but not banning local peer %s!\n", pnode->addr.ToString());
pnode->fDisconnect = true;
- if (pnode->addr.IsLocal())
- LogPrintf("Warning: not banning local peer %s!\n", pnode->addr.ToString());
- else
- {
- connman->Ban(pnode->addr, BanReasonNodeMisbehaving);
+ } else {
+ // Disconnect and ban all nodes sharing the address
+ if (m_banman) {
+ m_banman->Ban(pnode->addr, BanReasonNodeMisbehaving);
}
+ connman->DisconnectNode(pnode->addr);
}
return true;
}
@@ -2983,11 +3208,21 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
if (!pfrom->vRecvGetData.empty())
ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
+ if (!pfrom->orphan_work_set.empty()) {
+ std::list<CTransactionRef> removed_txn;
+ LOCK2(cs_main, g_cs_orphans);
+ ProcessOrphanTx(connman, pfrom->orphan_work_set, removed_txn);
+ for (const CTransactionRef& removedTx : removed_txn) {
+ AddToCompactExtraTransactions(removedTx);
+ }
+ }
+
if (pfrom->fDisconnect)
return false;
// this maintains the order of responses
if (!pfrom->vRecvGetData.empty()) return true;
+ if (!pfrom->orphan_work_set.empty()) return true;
// Don't bother if send buffer is too full to respond anyway
if (pfrom->fPauseSend)
@@ -3084,7 +3319,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
}
LOCK(cs_main);
- SendRejectsAndCheckIfBanned(pfrom, connman, m_enable_bip61);
+ SendRejectsAndCheckIfBanned(pfrom, m_enable_bip61);
return fMoreWork;
}
@@ -3103,7 +3338,7 @@ void PeerLogicValidation::ConsiderEviction(CNode *pto, int64_t time_in_seconds)
// their chain has more work than ours, we should sync to it,
// unless it's invalid, in which case we should find that out and
// disconnect from them elsewhere).
- if (state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= chainActive.Tip()->nChainWork) {
+ if (state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= ::ChainActive().Tip()->nChainWork) {
if (state.m_chain_sync.m_timeout != 0) {
state.m_chain_sync.m_timeout = 0;
state.m_chain_sync.m_work_header = nullptr;
@@ -3115,7 +3350,7 @@ void PeerLogicValidation::ConsiderEviction(CNode *pto, int64_t time_in_seconds)
// where we checked against our tip.
// Either way, set a new timeout based on current tip.
state.m_chain_sync.m_timeout = time_in_seconds + CHAIN_SYNC_TIMEOUT;
- state.m_chain_sync.m_work_header = chainActive.Tip();
+ state.m_chain_sync.m_work_header = ::ChainActive().Tip();
state.m_chain_sync.m_sent_getheaders = false;
} else if (state.m_chain_sync.m_timeout > 0 && time_in_seconds > state.m_chain_sync.m_timeout) {
// No evidence yet that our peer has synced to a chain with work equal to that
@@ -3128,7 +3363,7 @@ void PeerLogicValidation::ConsiderEviction(CNode *pto, int64_t time_in_seconds)
} else {
assert(state.m_chain_sync.m_work_header);
LogPrint(BCLog::NET, "sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto->GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString());
- connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(state.m_chain_sync.m_work_header->pprev), uint256()));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(state.m_chain_sync.m_work_header->pprev), uint256()));
state.m_chain_sync.m_sent_getheaders = true;
constexpr int64_t HEADERS_RESPONSE_TIME = 120; // 2 minutes
// Bump the timeout to allow a response, which could clear the timeout
@@ -3154,8 +3389,6 @@ void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds)
NodeId worst_peer = -1;
int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
- LOCK(cs_main);
-
connman->ForEachNode([&](CNode* pnode) {
AssertLockHeld(cs_main);
@@ -3203,6 +3436,8 @@ void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds)
void PeerLogicValidation::CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams)
{
+ LOCK(cs_main);
+
if (connman == nullptr) return;
int64_t time_in_seconds = GetTime();
@@ -3210,10 +3445,9 @@ void PeerLogicValidation::CheckForStaleTipAndEvictPeers(const Consensus::Params
EvictExtraOutboundPeers(time_in_seconds);
if (time_in_seconds > m_stale_tip_check_time) {
- LOCK(cs_main);
// Check whether our tip is stale, and if so, allow using an extra
// outbound peer
- if (TipMayBeStale(consensusParams)) {
+ if (!fImporting && !fReindex && connman->GetNetworkActive() && connman->GetUseAddrmanOutgoing() && TipMayBeStale(consensusParams)) {
LogPrintf("Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n", time_in_seconds - g_last_tip_update);
connman->SetTryNewOutboundPeer(true);
} else if (connman->GetTryNewOutboundPeer()) {
@@ -3286,8 +3520,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
if (!lockMain)
return true;
- if (SendRejectsAndCheckIfBanned(pto, connman, m_enable_bip61))
- return true;
+ if (SendRejectsAndCheckIfBanned(pto, m_enable_bip61)) return true;
CNodeState &state = *State(pto->GetId());
// Address refresh broadcast
@@ -3328,7 +3561,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
// Start block sync
if (pindexBestHeader == nullptr)
- pindexBestHeader = chainActive.Tip();
+ pindexBestHeader = ::ChainActive().Tip();
bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do.
if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) {
// Only actively request headers from a single peer, unless we're close to today.
@@ -3347,18 +3580,10 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), pto->nStartingHeight);
- connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256()));
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexStart), uint256()));
}
}
- // Resend wallet transactions that haven't gotten in a block yet
- // Except during reindex, importing and IBD, when old wallet
- // transactions become unconfirmed and spams other nodes.
- if (!fReindex && !fImporting && !IsInitialBlockDownload())
- {
- GetMainSignals().Broadcast(nTimeBestReceived, connman);
- }
-
//
// Try sending block announcements via headers
//
@@ -3382,11 +3607,11 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
bool fFoundStartingHeader = false;
// Try to find first header that our peer doesn't have, and
// then send all headers past that one. If we come across any
- // headers that aren't on chainActive, give up.
+ // headers that aren't on ::ChainActive(), give up.
for (const uint256 &hash : pto->vBlockHashesToAnnounce) {
const CBlockIndex* pindex = LookupBlockIndex(hash);
assert(pindex);
- if (chainActive[pindex->nHeight] != pindex) {
+ if (::ChainActive()[pindex->nHeight] != pindex) {
// Bail out if we reorged away from this block
fRevertToInv = true;
break;
@@ -3482,9 +3707,9 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
// Warn if we're announcing a block that is not on the main chain.
// This should be very rare and could be optimized out.
// Just log for now.
- if (chainActive[pindex->nHeight] != pindex) {
+ if (::ChainActive()[pindex->nHeight] != pindex) {
LogPrint(BCLog::NET, "Announcing block %s not on main chain (tip=%s)\n",
- hashToAnnounce.ToString(), chainActive.Tip()->GetBlockHash().ToString());
+ hashToAnnounce.ToString(), ::ChainActive().Tip()->GetBlockHash().ToString());
}
// If the peer's chain has this block, don't inv it back.
@@ -3723,24 +3948,39 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
//
// Message: getdata (non-blocks)
//
- while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
- {
- const CInv& inv = (*pto->mapAskFor.begin()).second;
- if (!AlreadyHave(inv))
- {
- LogPrint(BCLog::NET, "Requesting %s peer=%d\n", inv.ToString(), pto->GetId());
- vGetData.push_back(inv);
- if (vGetData.size() >= 1000)
- {
- connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
- vGetData.clear();
+ auto& tx_process_time = state.m_tx_download.m_tx_process_time;
+ while (!tx_process_time.empty() && tx_process_time.begin()->first <= nNow && state.m_tx_download.m_tx_in_flight.size() < MAX_PEER_TX_IN_FLIGHT) {
+ const uint256& txid = tx_process_time.begin()->second;
+ CInv inv(MSG_TX | GetFetchFlags(pto), txid);
+ if (!AlreadyHave(inv)) {
+ // If this transaction was last requested more than 1 minute ago,
+ // then request.
+ int64_t last_request_time = GetTxRequestTime(inv.hash);
+ if (last_request_time <= nNow - GETDATA_TX_INTERVAL) {
+ LogPrint(BCLog::NET, "Requesting %s peer=%d\n", inv.ToString(), pto->GetId());
+ vGetData.push_back(inv);
+ if (vGetData.size() >= MAX_GETDATA_SZ) {
+ connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
+ vGetData.clear();
+ }
+ UpdateTxRequestTime(inv.hash, nNow);
+ state.m_tx_download.m_tx_in_flight.insert(inv.hash);
+ } else {
+ // This transaction is in flight from someone else; queue
+ // up processing to happen after the download times out
+ // (with a slight delay for inbound peers, to prefer
+ // requests to outbound peers).
+ RequestTx(&state, txid, nNow);
}
} else {
- //If we're not going to ask, don't expect a response.
- pto->setAskFor.erase(inv.hash);
+ // We have already seen this transaction, no need to download.
+ state.m_tx_download.m_tx_announced.erase(inv.hash);
+ state.m_tx_download.m_tx_in_flight.erase(inv.hash);
}
- pto->mapAskFor.erase(pto->mapAskFor.begin());
+ tx_process_time.erase(tx_process_time.begin());
}
+
+
if (!vGetData.empty())
connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
diff --git a/src/net_processing.h b/src/net_processing.h
index 4dab0ada2b..39c22d7118 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,20 +9,25 @@
#include <net.h>
#include <validationinterface.h>
#include <consensus/params.h>
+#include <sync.h>
+
+extern CCriticalSection cs_main;
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
/** Default number of orphan+recently-replaced txn to keep around for block reconstruction */
static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100;
/** Default for BIP61 (sending reject messages) */
-static constexpr bool DEFAULT_ENABLE_BIP61 = true;
+static constexpr bool DEFAULT_ENABLE_BIP61{false};
class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface {
private:
CConnman* const connman;
+ BanMan* const m_banman;
+ bool SendRejectsAndCheckIfBanned(CNode* pnode, bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
public:
- explicit PeerLogicValidation(CConnman* connman, CScheduler &scheduler, bool enable_bip61);
+ PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler &scheduler, bool enable_bip61);
/**
* Overridden from CValidationInterface.
@@ -61,14 +66,14 @@ public:
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
- void ConsiderEviction(CNode *pto, int64_t time_in_seconds);
+ void ConsiderEviction(CNode *pto, int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound */
void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams);
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */
- void EvictExtraOutboundPeers(int64_t time_in_seconds);
+ void EvictExtraOutboundPeers(int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
private:
- int64_t m_stale_tip_check_time; //! Next time to check for stale tip
+ int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
/** Enable BIP61 (sending reject messages) */
const bool m_enable_bip61;
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 193582d14e..6ee2d8a4b3 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -1,11 +1,11 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <netaddress.h>
#include <hash.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <tinyformat.h>
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
@@ -14,10 +14,14 @@ static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
// 0xFD + sha256("bitcoin")[0:5]
static const unsigned char g_internal_prefix[] = { 0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 };
+/**
+ * Construct an unspecified IPv6 network address (::/128).
+ *
+ * @note This address is considered invalid by CNetAddr::IsValid()
+ */
CNetAddr::CNetAddr()
{
memset(ip, 0, sizeof(ip));
- scopeId = 0;
}
void CNetAddr::SetIP(const CNetAddr& ipIn)
@@ -41,6 +45,20 @@ void CNetAddr::SetRaw(Network network, const uint8_t *ip_in)
}
}
+/**
+ * Try to make this a dummy address that maps the specified name into IPv6 like
+ * so: (0xFD + %sha256("bitcoin")[0:5]) + %sha256(name)[0:10]. Such dummy
+ * addresses have a prefix of fd6b:88c0:8724::/48 and are guaranteed to not be
+ * publicly routable as it falls under RFC4193's fc00::/7 subnet allocated to
+ * unique-local addresses.
+ *
+ * CAddrMan uses these fake addresses to keep track of which DNS seeds were
+ * used.
+ *
+ * @returns Whether or not the operation was successful.
+ *
+ * @see CNetAddr::IsInternal(), CNetAddr::IsRFC4193()
+ */
bool CNetAddr::SetInternal(const std::string &name)
{
if (name.empty()) {
@@ -53,6 +71,16 @@ bool CNetAddr::SetInternal(const std::string &name)
return true;
}
+/**
+ * Try to make this a dummy address that maps the specified onion address into
+ * IPv6 using OnionCat's range and encoding. Such dummy addresses have a prefix
+ * of fd87:d87e:eb43::/48 and are guaranteed to not be publicly routable as they
+ * fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses.
+ *
+ * @returns Whether or not the operation was successful.
+ *
+ * @see CNetAddr::IsTor(), CNetAddr::IsRFC4193()
+ */
bool CNetAddr::SetSpecial(const std::string &strName)
{
if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
@@ -83,6 +111,16 @@ unsigned int CNetAddr::GetByte(int n) const
return ip[15-n];
}
+bool CNetAddr::IsBindAny() const
+{
+ const int cmplen = IsIPv4() ? 4 : 16;
+ for (int i = 0; i < cmplen; ++i) {
+ if (GetByte(i)) return false;
+ }
+
+ return true;
+}
+
bool CNetAddr::IsIPv4() const
{
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
@@ -166,6 +204,12 @@ bool CNetAddr::IsRFC4843() const
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
}
+/**
+ * @returns Whether or not this is a dummy address that maps an onion address
+ * into IPv6.
+ *
+ * @see CNetAddr::SetSpecial(const std::string &)
+ */
bool CNetAddr::IsTor() const
{
return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
@@ -173,18 +217,28 @@ bool CNetAddr::IsTor() const
bool CNetAddr::IsLocal() const
{
- // IPv4 loopback
- if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
- return true;
+ // IPv4 loopback (127.0.0.0/8 or 0.0.0.0/8)
+ if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
+ return true;
- // IPv6 loopback (::1/128)
- static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
- if (memcmp(ip, pchLocal, 16) == 0)
- return true;
+ // IPv6 loopback (::1/128)
+ static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+ if (memcmp(ip, pchLocal, 16) == 0)
+ return true;
- return false;
+ return false;
}
+/**
+ * @returns Whether or not this network address is a valid address that @a could
+ * be used to refer to an actual host.
+ *
+ * @note A valid address may or may not be publicly routable on the global
+ * internet. As in, the set of valid addreses is a superset of the set of
+ * publicly routable addresses.
+ *
+ * @see CNetAddr::IsRoutable()
+ */
bool CNetAddr::IsValid() const
{
// Cleanup 3-byte shifted addresses caused by garbage in size field
@@ -224,11 +278,25 @@ bool CNetAddr::IsValid() const
return true;
}
+/**
+ * @returns Whether or not this network address is publicly routable on the
+ * global internet.
+ *
+ * @note A routable address is always valid. As in, the set of routable addreses
+ * is a subset of the set of valid addresses.
+ *
+ * @see CNetAddr::IsValid()
+ */
bool CNetAddr::IsRoutable() const
{
return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal() || IsInternal());
}
+/**
+ * @returns Whether or not this is a dummy address that maps a name into IPv6.
+ *
+ * @see CNetAddr::SetInternal(const std::string &)
+ */
bool CNetAddr::IsInternal() const
{
return memcmp(ip, g_internal_prefix, sizeof(g_internal_prefix)) == 0;
@@ -290,6 +358,16 @@ bool operator<(const CNetAddr& a, const CNetAddr& b)
return (memcmp(a.ip, b.ip, 16) < 0);
}
+/**
+ * Try to get our IPv4 address.
+ *
+ * @param[out] pipv4Addr The in_addr struct to which to copy.
+ *
+ * @returns Whether or not the operation was successful, in particular, whether
+ * or not our address was an IPv4 address.
+ *
+ * @see CNetAddr::IsIPv4()
+ */
bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
{
if (!IsIPv4())
@@ -298,6 +376,16 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
return true;
}
+/**
+ * Try to get our IPv6 address.
+ *
+ * @param[out] pipv6Addr The in6_addr struct to which to copy.
+ *
+ * @returns Whether or not the operation was successful, in particular, whether
+ * or not our address was an IPv6 address.
+ *
+ * @see CNetAddr::IsIPv6()
+ */
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
{
if (!IsIPv6()) {
@@ -307,8 +395,16 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
return true;
}
-// get canonical identifier of an address' group
-// no two connections will be attempted to addresses with the same group
+/**
+ * Get the canonical identifier of our network group
+ *
+ * The groups are assigned in a way where it should be costly for an attacker to
+ * obtain addresses with many different group identifiers, even if it is cheap
+ * to obtain addresses with the same identifier.
+ *
+ * @note No two connections will be attempted to addresses with the same network
+ * group.
+ */
std::vector<unsigned char> CNetAddr::GetGroup() const
{
std::vector<unsigned char> vchRet;
@@ -370,12 +466,15 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
nBits = 32;
vchRet.push_back(nClass);
+
+ // push our ip onto vchRet byte by byte...
while (nBits >= 8)
{
vchRet.push_back(GetByte(15 - nStartByte));
nStartByte++;
nBits -= 8;
}
+ // ...for the last byte, push nBits and for the rest of the byte push 1's
if (nBits > 0)
vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1));
@@ -517,6 +616,18 @@ bool operator<(const CService& a, const CService& b)
return static_cast<CNetAddr>(a) < static_cast<CNetAddr>(b) || (static_cast<CNetAddr>(a) == static_cast<CNetAddr>(b) && a.port < b.port);
}
+/**
+ * Obtain the IPv4/6 socket address this represents.
+ *
+ * @param[out] paddr The obtained socket address.
+ * @param[in,out] addrlen The size, in bytes, of the address structure pointed
+ * to by paddr. The value that's pointed to by this
+ * parameter might change after calling this function if
+ * the size of the corresponding address structure
+ * changed.
+ *
+ * @returns Whether or not the operation was successful.
+ */
bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
{
if (IsIPv4()) {
@@ -547,13 +658,16 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
return false;
}
+/**
+ * @returns An identifier unique to this service's address and port number.
+ */
std::vector<unsigned char> CService::GetKey() const
{
std::vector<unsigned char> vKey;
vKey.resize(18);
memcpy(vKey.data(), ip, 16);
- vKey[16] = port / 0x100;
- vKey[17] = port & 0x0FF;
+ vKey[16] = port / 0x100; // most significant byte of our port
+ vKey[17] = port & 0x0FF; // least significant byte of our port
return vKey;
}
@@ -632,6 +746,10 @@ CSubNet::CSubNet(const CNetAddr &addr):
network = addr;
}
+/**
+ * @returns True if this subnet is valid, the specified address is valid, and
+ * the specified address belongs in this subnet.
+ */
bool CSubNet::Match(const CNetAddr &addr) const
{
if (!valid || !addr.IsValid())
@@ -642,6 +760,10 @@ bool CSubNet::Match(const CNetAddr &addr) const
return true;
}
+/**
+ * @returns The number of 1-bits in the prefix of the specified subnet mask. If
+ * the specified subnet mask is not a valid one, -1.
+ */
static inline int NetmaskBits(uint8_t x)
{
switch(x) {
diff --git a/src/netaddress.h b/src/netaddress.h
index 966bef8cdf..8230e40606 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -33,7 +33,7 @@ class CNetAddr
{
protected:
unsigned char ip[16]; // in network byte order
- uint32_t scopeId; // for scoped/link-local ipv6 addresses
+ uint32_t scopeId{0}; // for scoped/link-local ipv6 addresses
public:
CNetAddr();
@@ -48,13 +48,10 @@ class CNetAddr
void SetRaw(Network network, const uint8_t *data);
public:
- /**
- * Transform an arbitrary string into a non-routable ipv6 address.
- * Useful for mapping resolved addresses back to their source.
- */
bool SetInternal(const std::string& name);
bool SetSpecial(const std::string &strName); // for Tor addresses
+ bool IsBindAny() const; // INADDR_ANY equivalent
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor)
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
@@ -68,8 +65,8 @@ class CNetAddr
bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
- bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
- bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
+ bool IsRFC6052() const; // IPv6 well-known prefix for IPv4-embedded address (64:FF9B::/96)
+ bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765)
bool IsTor() const;
bool IsLocal() const;
bool IsRoutable() const;
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 607eb89573..6c386a9ade 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,25 +10,29 @@
#include <uint256.h>
#include <random.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <atomic>
#ifndef WIN32
#include <fcntl.h>
+#else
+#include <codecvt>
#endif
-#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
+#ifdef USE_POLL
+#include <poll.h>
+#endif
#if !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL 0
#endif
// Settings
-static proxyType proxyInfo[NET_MAX];
-static proxyType nameProxy;
static CCriticalSection cs_proxyInfos;
+static proxyType proxyInfo[NET_MAX] GUARDED_BY(cs_proxyInfos);
+static proxyType nameProxy GUARDED_BY(cs_proxyInfos);
int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
bool fNameLookup = DEFAULT_NAME_LOOKUP;
@@ -37,7 +41,7 @@ static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
static std::atomic<bool> interruptSocks5Recv(false);
enum Network ParseNetwork(std::string net) {
- boost::to_lower(net);
+ Downcase(net);
if (net == "ipv4") return NET_IPV4;
if (net == "ipv6") return NET_IPV6;
if (net == "onion") return NET_ONION;
@@ -76,11 +80,7 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
aiHint.ai_socktype = SOCK_STREAM;
aiHint.ai_protocol = IPPROTO_TCP;
aiHint.ai_family = AF_UNSPEC;
-#ifdef WIN32
- aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
-#else
aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
-#endif
struct addrinfo *aiRes = nullptr;
int nErr = getaddrinfo(pszName, nullptr, &aiHint, &aiRes);
if (nErr)
@@ -191,10 +191,10 @@ enum SOCKSVersion: uint8_t {
/** Values defined for METHOD in RFC1928 */
enum SOCKS5Method: uint8_t {
- NOAUTH = 0x00, //! No authentication required
- GSSAPI = 0x01, //! GSSAPI
- USER_PASS = 0x02, //! Username/password
- NO_ACCEPTABLE = 0xff, //! No acceptable methods
+ NOAUTH = 0x00, //!< No authentication required
+ GSSAPI = 0x01, //!< GSSAPI
+ USER_PASS = 0x02, //!< Username/password
+ NO_ACCEPTABLE = 0xff, //!< No acceptable methods
};
/** Values defined for CMD in RFC1928 */
@@ -206,15 +206,15 @@ enum SOCKS5Command: uint8_t {
/** Values defined for REP in RFC1928 */
enum SOCKS5Reply: uint8_t {
- SUCCEEDED = 0x00, //! Succeeded
- GENFAILURE = 0x01, //! General failure
- NOTALLOWED = 0x02, //! Connection not allowed by ruleset
- NETUNREACHABLE = 0x03, //! Network unreachable
- HOSTUNREACHABLE = 0x04, //! Network unreachable
- CONNREFUSED = 0x05, //! Connection refused
- TTLEXPIRED = 0x06, //! TTL expired
- CMDUNSUPPORTED = 0x07, //! Command not supported
- ATYPEUNSUPPORTED = 0x08, //! Address type not supported
+ SUCCEEDED = 0x00, //!< Succeeded
+ GENFAILURE = 0x01, //!< General failure
+ NOTALLOWED = 0x02, //!< Connection not allowed by ruleset
+ NETUNREACHABLE = 0x03, //!< Network unreachable
+ HOSTUNREACHABLE = 0x04, //!< Network unreachable
+ CONNREFUSED = 0x05, //!< Connection refused
+ TTLEXPIRED = 0x06, //!< TTL expired
+ CMDUNSUPPORTED = 0x07, //!< Command not supported
+ ATYPEUNSUPPORTED = 0x08, //!< Address type not supported
};
/** Values defined for ATYPE in RFC1928 */
@@ -264,11 +264,19 @@ static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, c
if (!IsSelectableSocket(hSocket)) {
return IntrRecvError::NetworkError;
}
- struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait));
+ int timeout_ms = std::min(endTime - curTime, maxWait);
+#ifdef USE_POLL
+ struct pollfd pollfd = {};
+ pollfd.fd = hSocket;
+ pollfd.events = POLLIN | POLLOUT;
+ int nRet = poll(&pollfd, 1, timeout_ms);
+#else
+ struct timeval tval = MillisToTimeval(timeout_ms);
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(hSocket, &fdset);
int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
+#endif
if (nRet == SOCKET_ERROR) {
return IntrRecvError::NetworkError;
}
@@ -499,11 +507,18 @@ bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, i
// WSAEINVAL is here because some legacy version of winsock uses it
if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
{
+#ifdef USE_POLL
+ struct pollfd pollfd = {};
+ pollfd.fd = hSocket;
+ pollfd.events = POLLIN | POLLOUT;
+ int nRet = poll(&pollfd, 1, nTimeout);
+#else
struct timeval timeout = MillisToTimeval(nTimeout);
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(hSocket, &fdset);
int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
+#endif
if (nRet == 0)
{
LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
@@ -651,13 +666,13 @@ bool LookupSubNet(const char* pszName, CSubNet& ret)
#ifdef WIN32
std::string NetworkErrorString(int err)
{
- char buf[256];
+ wchar_t buf[256];
buf[0] = 0;
- if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- buf, sizeof(buf), nullptr))
+ buf, ARRAYSIZE(buf), nullptr))
{
- return strprintf("%s (%d)", buf, err);
+ return strprintf("%s (%d)", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf), err);
}
else
{
diff --git a/src/netbase.h b/src/netbase.h
index 50d4bc54fa..708df5b8e2 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/netmessagemaker.h b/src/netmessagemaker.h
index 975be460b3..2efb384a7b 100644
--- a/src/netmessagemaker.h
+++ b/src/netmessagemaker.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/node/README.md b/src/node/README.md
new file mode 100644
index 0000000000..e99a717534
--- /dev/null
+++ b/src/node/README.md
@@ -0,0 +1,22 @@
+# src/node/
+
+The [`src/node/`](./) directory contains code that needs to access node state
+(state in `CChain`, `CBlockIndex`, `CCoinsView`, `CTxMemPool`, and similar
+classes).
+
+Code in [`src/node/`](./) is meant to be segregated from code in
+[`src/wallet/`](../wallet/) and [`src/qt/`](../qt/), to ensure wallet and GUI
+code changes don't interfere with node operation, to allow wallet and GUI code
+to run in separate processes, and to perhaps eventually allow wallet and GUI
+code to be maintained in separate source repositories.
+
+As a rule of thumb, code in one of the [`src/node/`](./),
+[`src/wallet/`](../wallet/), or [`src/qt/`](../qt/) directories should avoid
+calling code in the other directories directly, and only invoke it indirectly
+through the more limited [`src/interfaces/`](../interfaces/) classes.
+
+The [`src/node/`](./) directory is a new directory introduced in
+[#14978](https://github.com/bitcoin/bitcoin/pull/14978) and at the moment is
+sparsely populated. Eventually more substantial files like
+[`src/validation.cpp`](../validation.cpp) and
+[`src/txmempool.cpp`](../txmempool.cpp) might be moved there.
diff --git a/src/node/coin.cpp b/src/node/coin.cpp
new file mode 100644
index 0000000000..bb98e63f3a
--- /dev/null
+++ b/src/node/coin.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <node/coin.h>
+
+#include <txmempool.h>
+#include <validation.h>
+
+void FindCoins(std::map<COutPoint, Coin>& coins)
+{
+ LOCK2(cs_main, ::mempool.cs);
+ assert(pcoinsTip);
+ CCoinsViewCache& chain_view = *::pcoinsTip;
+ CCoinsViewMemPool mempool_view(&chain_view, ::mempool);
+ for (auto& coin : coins) {
+ if (!mempool_view.GetCoin(coin.first, coin.second)) {
+ // Either the coin is not in the CCoinsViewCache or is spent. Clear it.
+ coin.second.Clear();
+ }
+ }
+}
diff --git a/src/node/coin.h b/src/node/coin.h
new file mode 100644
index 0000000000..eb95b75cfb
--- /dev/null
+++ b/src/node/coin.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_COIN_H
+#define BITCOIN_NODE_COIN_H
+
+#include <map>
+
+class COutPoint;
+class Coin;
+
+/**
+ * Look up unspent output information. Returns coins in the mempool and in the
+ * current chain UTXO set. Iterates through all the keys in the map and
+ * populates the values.
+ *
+ * @param[in,out] coins map to fill
+ */
+void FindCoins(std::map<COutPoint, Coin>& coins);
+
+#endif // BITCOIN_NODE_COIN_H
diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp
new file mode 100644
index 0000000000..12559c5a5f
--- /dev/null
+++ b/src/node/psbt.cpp
@@ -0,0 +1,134 @@
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <coins.h>
+#include <consensus/tx_verify.h>
+#include <node/psbt.h>
+#include <policy/policy.h>
+#include <policy/settings.h>
+
+#include <numeric>
+
+PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
+{
+ // Go through each input and build status
+ PSBTAnalysis result;
+
+ bool calc_fee = true;
+ bool all_final = true;
+ bool only_missing_sigs = true;
+ bool only_missing_final = false;
+ CAmount in_amt = 0;
+
+ result.inputs.resize(psbtx.tx->vin.size());
+
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ PSBTInput& input = psbtx.inputs[i];
+ PSBTInputAnalysis& input_analysis = result.inputs[i];
+
+ // Check for a UTXO
+ CTxOut utxo;
+ if (psbtx.GetInputUTXO(utxo, i)) {
+ in_amt += utxo.nValue;
+ input_analysis.has_utxo = true;
+ } else {
+ input_analysis.has_utxo = false;
+ input_analysis.is_final = false;
+ input_analysis.next = PSBTRole::UPDATER;
+ calc_fee = false;
+ }
+
+ // Check if it is final
+ if (!utxo.IsNull() && !PSBTInputSigned(input)) {
+ input_analysis.is_final = false;
+ all_final = false;
+
+ // Figure out what is missing
+ SignatureData outdata;
+ bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, &outdata);
+
+ // Things are missing
+ if (!complete) {
+ input_analysis.missing_pubkeys = outdata.missing_pubkeys;
+ input_analysis.missing_redeem_script = outdata.missing_redeem_script;
+ input_analysis.missing_witness_script = outdata.missing_witness_script;
+ input_analysis.missing_sigs = outdata.missing_sigs;
+
+ // If we are only missing signatures and nothing else, then next is signer
+ if (outdata.missing_pubkeys.empty() && outdata.missing_redeem_script.IsNull() && outdata.missing_witness_script.IsNull() && !outdata.missing_sigs.empty()) {
+ input_analysis.next = PSBTRole::SIGNER;
+ } else {
+ only_missing_sigs = false;
+ input_analysis.next = PSBTRole::UPDATER;
+ }
+ } else {
+ only_missing_final = true;
+ input_analysis.next = PSBTRole::FINALIZER;
+ }
+ } else if (!utxo.IsNull()){
+ input_analysis.is_final = true;
+ }
+ }
+
+ if (all_final) {
+ only_missing_sigs = false;
+ result.next = PSBTRole::EXTRACTOR;
+ }
+ if (calc_fee) {
+ // Get the output amount
+ CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmount(0),
+ [](CAmount a, const CTxOut& b) {
+ return a += b.nValue;
+ }
+ );
+
+ // Get the fee
+ CAmount fee = in_amt - out_amt;
+ result.fee = fee;
+
+ // Estimate the size
+ CMutableTransaction mtx(*psbtx.tx);
+ CCoinsView view_dummy;
+ CCoinsViewCache view(&view_dummy);
+ bool success = true;
+
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ PSBTInput& input = psbtx.inputs[i];
+ Coin newcoin;
+
+ if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, 1, nullptr, true) || !psbtx.GetInputUTXO(newcoin.out, i)) {
+ success = false;
+ break;
+ } else {
+ mtx.vin[i].scriptSig = input.final_script_sig;
+ mtx.vin[i].scriptWitness = input.final_script_witness;
+ newcoin.nHeight = 1;
+ view.AddCoin(psbtx.tx->vin[i].prevout, std::move(newcoin), true);
+ }
+ }
+
+ if (success) {
+ CTransaction ctx = CTransaction(mtx);
+ size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
+ result.estimated_vsize = size;
+ // Estimate fee rate
+ CFeeRate feerate(fee, size);
+ result.estimated_feerate = feerate;
+ }
+
+ if (only_missing_sigs) {
+ result.next = PSBTRole::SIGNER;
+ } else if (only_missing_final) {
+ result.next = PSBTRole::FINALIZER;
+ } else if (all_final) {
+ result.next = PSBTRole::EXTRACTOR;
+ } else {
+ result.next = PSBTRole::UPDATER;
+ }
+ } else {
+ result.next = PSBTRole::UPDATER;
+ }
+
+ return result;
+}
diff --git a/src/node/psbt.h b/src/node/psbt.h
new file mode 100644
index 0000000000..e04366a20f
--- /dev/null
+++ b/src/node/psbt.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_PSBT_H
+#define BITCOIN_NODE_PSBT_H
+
+#include <psbt.h>
+
+/**
+ * Holds an analysis of one input from a PSBT
+ */
+struct PSBTInputAnalysis {
+ bool has_utxo; //!< Whether we have UTXO information for this input
+ bool is_final; //!< Whether the input has all required information including signatures
+ PSBTRole next; //!< Which of the BIP 174 roles needs to handle this input next
+
+ std::vector<CKeyID> missing_pubkeys; //!< Pubkeys whose BIP32 derivation path is missing
+ std::vector<CKeyID> missing_sigs; //!< Pubkeys whose signatures are missing
+ uint160 missing_redeem_script; //!< Hash160 of redeem script, if missing
+ uint256 missing_witness_script; //!< SHA256 of witness script, if missing
+};
+
+/**
+ * Holds the results of AnalyzePSBT (miscellaneous information about a PSBT)
+ */
+struct PSBTAnalysis {
+ Optional<size_t> estimated_vsize; //!< Estimated weight of the transaction
+ Optional<CFeeRate> estimated_feerate; //!< Estimated feerate (fee / weight) of the transaction
+ Optional<CAmount> fee; //!< Amount of fee being paid by the transaction
+ std::vector<PSBTInputAnalysis> inputs; //!< More information about the individual inputs of the transaction
+ PSBTRole next; //!< Which of the BIP 174 roles needs to handle the transaction next
+};
+
+/**
+ * Provides helpful miscellaneous information about where a PSBT is in the signing workflow.
+ *
+ * @param[in] psbtx the PSBT to analyze
+ * @return A PSBTAnalysis with information about the provided PSBT.
+ */
+PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx);
+
+#endif // BITCOIN_NODE_PSBT_H
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
new file mode 100644
index 0000000000..5ffb15ed3c
--- /dev/null
+++ b/src/node/transaction.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/validation.h>
+#include <net.h>
+#include <txmempool.h>
+#include <util/validation.h>
+#include <validation.h>
+#include <validationinterface.h>
+#include <node/transaction.h>
+
+#include <future>
+
+TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, std::string& err_string, const CAmount& highfee)
+{
+ std::promise<void> promise;
+ hashTx = tx->GetHash();
+
+ { // cs_main scope
+ LOCK(cs_main);
+ CCoinsViewCache &view = *pcoinsTip;
+ bool fHaveChain = false;
+ for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
+ const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
+ fHaveChain = !existingCoin.IsSpent();
+ }
+ bool fHaveMempool = mempool.exists(hashTx);
+ if (!fHaveMempool && !fHaveChain) {
+ // push to local node and sync with wallets
+ CValidationState state;
+ bool fMissingInputs;
+ if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
+ nullptr /* plTxnReplaced */, false /* bypass_limits */, highfee)) {
+ if (state.IsInvalid()) {
+ err_string = FormatStateMessage(state);
+ return TransactionError::MEMPOOL_REJECTED;
+ } else {
+ if (fMissingInputs) {
+ return TransactionError::MISSING_INPUTS;
+ }
+ err_string = FormatStateMessage(state);
+ return TransactionError::MEMPOOL_ERROR;
+ }
+ } else {
+ // If wallet is enabled, ensure that the wallet has been made aware
+ // of the new transaction prior to returning. This prevents a race
+ // where a user might call sendrawtransaction with a transaction
+ // to/from their wallet, immediately call some wallet RPC, and get
+ // a stale result because callbacks have not yet been processed.
+ CallFunctionInValidationInterfaceQueue([&promise] {
+ promise.set_value();
+ });
+ }
+ } else if (fHaveChain) {
+ return TransactionError::ALREADY_IN_CHAIN;
+ } else {
+ // Make sure we don't block forever if re-sending
+ // a transaction already in mempool.
+ promise.set_value();
+ }
+
+ } // cs_main
+
+ promise.get_future().wait();
+
+ if (!g_connman) {
+ return TransactionError::P2P_DISABLED;
+ }
+
+ CInv inv(MSG_TX, hashTx);
+ g_connman->ForEachNode([&inv](CNode* pnode) {
+ pnode->PushInventory(inv);
+ });
+
+ return TransactionError::OK;
+}
diff --git a/src/node/transaction.h b/src/node/transaction.h
new file mode 100644
index 0000000000..51033f94e5
--- /dev/null
+++ b/src/node/transaction.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_TRANSACTION_H
+#define BITCOIN_NODE_TRANSACTION_H
+
+#include <attributes.h>
+#include <primitives/transaction.h>
+#include <uint256.h>
+#include <util/error.h>
+
+/**
+ * Broadcast a transaction
+ *
+ * @param[in] tx the transaction to broadcast
+ * @param[out] &txid the txid of the transaction, if successfully broadcast
+ * @param[out] &err_string reference to std::string to fill with error string if available
+ * @param[in] highfee Reject txs with fees higher than this (if 0, accept any fee)
+ * return error
+ */
+NODISCARD TransactionError BroadcastTransaction(CTransactionRef tx, uint256& txid, std::string& err_string, const CAmount& highfee);
+
+#endif // BITCOIN_NODE_TRANSACTION_H
diff --git a/src/noui.cpp b/src/noui.cpp
index efe6f28246..c7d8fee0ba 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -1,18 +1,20 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <noui.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <cstdio>
#include <stdint.h>
#include <string>
-static bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
+#include <boost/signals2/connection.hpp>
+
+bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
{
bool fSecure = style & CClientUIInterface::SECURE;
style &= ~CClientUIInterface::SECURE;
@@ -39,20 +41,19 @@ static bool noui_ThreadSafeMessageBox(const std::string& message, const std::str
return false;
}
-static bool noui_ThreadSafeQuestion(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style)
+bool noui_ThreadSafeQuestion(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style)
{
return noui_ThreadSafeMessageBox(message, caption, style);
}
-static void noui_InitMessage(const std::string& message)
+void noui_InitMessage(const std::string& message)
{
LogPrintf("init message: %s\n", message);
}
void noui_connect()
{
- // Connect bitcoind signal handlers
- uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox);
- uiInterface.ThreadSafeQuestion.connect(noui_ThreadSafeQuestion);
- uiInterface.InitMessage.connect(noui_InitMessage);
+ uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox);
+ uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion);
+ uiInterface.InitMessage_connect(noui_InitMessage);
}
diff --git a/src/noui.h b/src/noui.h
index ff16cc9aa8..79a79a9af2 100644
--- a/src/noui.h
+++ b/src/noui.h
@@ -1,10 +1,20 @@
-// Copyright (c) 2013-2014 The Bitcoin Core developers
+// Copyright (c) 2013-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_NOUI_H
#define BITCOIN_NOUI_H
-extern void noui_connect();
+#include <string>
+
+/** Non-GUI handler, which logs and prints messages. */
+bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style);
+/** Non-GUI handler, which logs and prints questions. */
+bool noui_ThreadSafeQuestion(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style);
+/** Non-GUI handler, which only logs a message. */
+void noui_InitMessage(const std::string& message);
+
+/** Connect all bitcoind signal handlers */
+void noui_connect();
#endif // BITCOIN_NOUI_H
diff --git a/src/optional.h b/src/optional.h
new file mode 100644
index 0000000000..95a3b24d0a
--- /dev/null
+++ b/src/optional.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2017 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_OPTIONAL_H
+#define BITCOIN_OPTIONAL_H
+
+#include <utility>
+
+#include <boost/optional.hpp>
+
+//! Substitute for C++17 std::optional
+template <typename T>
+using Optional = boost::optional<T>;
+
+//! Substitute for C++17 std::make_optional
+template <typename T>
+Optional<T> MakeOptional(bool condition, T&& value)
+{
+ return boost::make_optional(condition, std::forward<T>(value));
+}
+
+//! Substitute for C++17 std::nullopt
+static auto& nullopt = boost::none;
+
+#endif // BITCOIN_OPTIONAL_H
diff --git a/src/outputtype.cpp b/src/outputtype.cpp
index 3ff28bf9c2..73ffb801f2 100644
--- a/src/outputtype.cpp
+++ b/src/outputtype.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -45,14 +45,14 @@ const std::string& FormatOutputType(OutputType type)
CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type)
{
switch (type) {
- case OutputType::LEGACY: return key.GetID();
+ case OutputType::LEGACY: return PKHash(key);
case OutputType::P2SH_SEGWIT:
case OutputType::BECH32: {
- if (!key.IsCompressed()) return key.GetID();
- CTxDestination witdest = WitnessV0KeyHash(key.GetID());
+ if (!key.IsCompressed()) return PKHash(key);
+ CTxDestination witdest = WitnessV0KeyHash(PKHash(key));
CScript witprog = GetScriptForDestination(witdest);
if (type == OutputType::P2SH_SEGWIT) {
- return CScriptID(witprog);
+ return ScriptHash(witprog);
} else {
return witdest;
}
@@ -63,10 +63,10 @@ CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type)
std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key)
{
- CKeyID keyid = key.GetID();
+ PKHash keyid(key);
if (key.IsCompressed()) {
CTxDestination segwit = WitnessV0KeyHash(keyid);
- CTxDestination p2sh = CScriptID(GetScriptForDestination(segwit));
+ CTxDestination p2sh = ScriptHash(GetScriptForDestination(segwit));
return std::vector<CTxDestination>{std::move(keyid), std::move(p2sh), std::move(segwit)};
} else {
return std::vector<CTxDestination>{std::move(keyid)};
@@ -80,19 +80,19 @@ CTxDestination AddAndGetDestinationForScript(CKeyStore& keystore, const CScript&
// Note that scripts over 520 bytes are not yet supported.
switch (type) {
case OutputType::LEGACY:
- return CScriptID(script);
+ return ScriptHash(script);
case OutputType::P2SH_SEGWIT:
case OutputType::BECH32: {
CTxDestination witdest = WitnessV0ScriptHash(script);
CScript witprog = GetScriptForDestination(witdest);
// Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
- if (!IsSolvable(keystore, witprog)) return CScriptID(script);
+ if (!IsSolvable(keystore, witprog)) return ScriptHash(script);
// Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
keystore.AddCScript(witprog);
if (type == OutputType::BECH32) {
return witdest;
} else {
- return CScriptID(witprog);
+ return ScriptHash(witprog);
}
}
default: assert(false);
diff --git a/src/outputtype.h b/src/outputtype.h
index 21623e3b49..6c30fd1950 100644
--- a/src/outputtype.h
+++ b/src/outputtype.h
@@ -1,11 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_OUTPUTTYPE_H
#define BITCOIN_OUTPUTTYPE_H
+#include <attributes.h>
#include <keystore.h>
#include <script/standard.h>
@@ -26,7 +27,7 @@ enum class OutputType {
CHANGE_AUTO,
};
-bool ParseOutputType(const std::string& str, OutputType& output_type);
+NODISCARD bool ParseOutputType(const std::string& str, OutputType& output_type);
const std::string& FormatOutputType(OutputType type);
/**
diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp
index a560815491..14be6192fe 100644
--- a/src/policy/feerate.cpp
+++ b/src/policy/feerate.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
index eed77d5030..85d7d22b4f 100644
--- a/src/policy/feerate.h
+++ b/src/policy/feerate.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 79b450e3e6..6456eec016 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
#include <primitives/transaction.h>
#include <streams.h>
#include <txmempool.h>
-#include <util.h>
+#include <util/system.h>
static constexpr double INF_FEERATE = 1e99;
@@ -27,40 +27,6 @@ std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon) {
return horizon_string->second;
}
-std::string StringForFeeReason(FeeReason reason) {
- static const std::map<FeeReason, std::string> fee_reason_strings = {
- {FeeReason::NONE, "None"},
- {FeeReason::HALF_ESTIMATE, "Half Target 60% Threshold"},
- {FeeReason::FULL_ESTIMATE, "Target 85% Threshold"},
- {FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"},
- {FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"},
- {FeeReason::MEMPOOL_MIN, "Mempool Min Fee"},
- {FeeReason::PAYTXFEE, "PayTxFee set"},
- {FeeReason::FALLBACK, "Fallback fee"},
- {FeeReason::REQUIRED, "Minimum Required Fee"},
- {FeeReason::MAXTXFEE, "MaxTxFee limit"}
- };
- auto reason_string = fee_reason_strings.find(reason);
-
- if (reason_string == fee_reason_strings.end()) return "Unknown";
-
- return reason_string->second;
-}
-
-bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
- static const std::map<std::string, FeeEstimateMode> fee_modes = {
- {"UNSET", FeeEstimateMode::UNSET},
- {"ECONOMICAL", FeeEstimateMode::ECONOMICAL},
- {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
- };
- auto mode = fee_modes.find(mode_string);
-
- if (mode == fee_modes.end()) return false;
-
- fee_estimate_mode = mode->second;
- return true;
-}
-
/**
* We will instantiate an instance of this class to track transactions that were
* included in a block. We will lump transactions into a bucket according to their
@@ -511,7 +477,7 @@ void TxConfirmStats::removeTx(unsigned int entryHeight, unsigned int nBestSeenHe
// of no harm to try to remove them again.
bool CBlockPolicyEstimator::removeTx(uint256 hash, bool inBlock)
{
- LOCK(cs_feeEstimator);
+ LOCK(m_cs_fee_estimator);
std::map<uint256, TxStatsInfo>::iterator pos = mapMemPoolTxs.find(hash);
if (pos != mapMemPoolTxs.end()) {
feeStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex, inBlock);
@@ -548,7 +514,7 @@ CBlockPolicyEstimator::~CBlockPolicyEstimator()
void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, bool validFeeEstimate)
{
- LOCK(cs_feeEstimator);
+ LOCK(m_cs_fee_estimator);
unsigned int txHeight = entry.GetHeight();
uint256 hash = entry.GetTx().GetHash();
if (mapMemPoolTxs.count(hash)) {
@@ -560,7 +526,7 @@ void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, boo
if (txHeight != nBestSeenHeight) {
// Ignore side chains and re-orgs; assuming they are random they don't
// affect the estimate. We'll potentially double count transactions in 1-block reorgs.
- // Ignore txs if BlockPolicyEstimator is not in sync with chainActive.Tip().
+ // Ignore txs if BlockPolicyEstimator is not in sync with ::ChainActive().Tip().
// It will be synced next time a block is processed.
return;
}
@@ -615,7 +581,7 @@ bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxM
void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight,
std::vector<const CTxMemPoolEntry*>& entries)
{
- LOCK(cs_feeEstimator);
+ LOCK(m_cs_fee_estimator);
if (nBlockHeight <= nBestSeenHeight) {
// Ignore side chains and re-orgs; assuming they are random
// they don't affect the estimate.
@@ -693,7 +659,7 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr
}
}
- LOCK(cs_feeEstimator);
+ LOCK(m_cs_fee_estimator);
// Return failure if trying to analyze a target we're not tracking
if (confTarget <= 0 || (unsigned int)confTarget > stats->GetMaxConfirms())
return CFeeRate(0);
@@ -710,6 +676,7 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr
unsigned int CBlockPolicyEstimator::HighestTargetTracked(FeeEstimateHorizon horizon) const
{
+ LOCK(m_cs_fee_estimator);
switch (horizon) {
case FeeEstimateHorizon::SHORT_HALFLIFE: {
return shortStats->GetMaxConfirms();
@@ -819,7 +786,7 @@ double CBlockPolicyEstimator::estimateConservativeFee(unsigned int doubleTarget,
*/
CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const
{
- LOCK(cs_feeEstimator);
+ LOCK(m_cs_fee_estimator);
if (feeCalc) {
feeCalc->desiredTarget = confTarget;
@@ -899,7 +866,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
{
try {
- LOCK(cs_feeEstimator);
+ LOCK(m_cs_fee_estimator);
fileout << 149900; // version required to read: 0.14.99 or later
fileout << CLIENT_VERSION; // version that wrote the file
fileout << nBestSeenHeight;
@@ -924,7 +891,7 @@ bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
bool CBlockPolicyEstimator::Read(CAutoFile& filein)
{
try {
- LOCK(cs_feeEstimator);
+ LOCK(m_cs_fee_estimator);
int nVersionRequired, nVersionThatWrote;
filein >> nVersionRequired >> nVersionThatWrote;
if (nVersionRequired > CLIENT_VERSION)
@@ -983,7 +950,7 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
void CBlockPolicyEstimator::FlushUnconfirmed() {
int64_t startclear = GetTimeMicros();
- LOCK(cs_feeEstimator);
+ LOCK(m_cs_fee_estimator);
size_t num_entries = mapMemPoolTxs.size();
// Remove every entry in mapMemPoolTxs
while (!mapMemPoolTxs.empty()) {
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 8c34bee237..6e61f76178 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_POLICY_FEES_H
@@ -22,51 +22,6 @@ class CTxMemPoolEntry;
class CTxMemPool;
class TxConfirmStats;
-/** \class CBlockPolicyEstimator
- * The BlockPolicyEstimator is used for estimating the feerate needed
- * for a transaction to be included in a block within a certain number of
- * blocks.
- *
- * At a high level the algorithm works by grouping transactions into buckets
- * based on having similar feerates and then tracking how long it
- * takes transactions in the various buckets to be mined. It operates under
- * the assumption that in general transactions of higher feerate will be
- * included in blocks before transactions of lower feerate. So for
- * example if you wanted to know what feerate you should put on a transaction to
- * be included in a block within the next 5 blocks, you would start by looking
- * at the bucket with the highest feerate transactions and verifying that a
- * sufficiently high percentage of them were confirmed within 5 blocks and
- * then you would look at the next highest feerate bucket, and so on, stopping at
- * the last bucket to pass the test. The average feerate of transactions in this
- * bucket will give you an indication of the lowest feerate you can put on a
- * transaction and still have a sufficiently high chance of being confirmed
- * within your desired 5 blocks.
- *
- * Here is a brief description of the implementation:
- * When a transaction enters the mempool, we track the height of the block chain
- * at entry. All further calculations are conducted only on this set of "seen"
- * transactions. Whenever a block comes in, we count the number of transactions
- * in each bucket and the total amount of feerate paid in each bucket. Then we
- * calculate how many blocks Y it took each transaction to be mined. We convert
- * from a number of blocks to a number of periods Y' each encompassing "scale"
- * blocks. This is tracked in 3 different data sets each up to a maximum
- * number of periods. Within each data set we have an array of counters in each
- * feerate bucket and we increment all the counters from Y' up to max periods
- * representing that a tx was successfully confirmed in less than or equal to
- * that many periods. We want to save a history of this information, so at any
- * time we have a counter of the total number of transactions that happened in a
- * given feerate bucket and the total number that were confirmed in each of the
- * periods or less for any bucket. We save this history by keeping an
- * exponentially decaying moving average of each one of these stats. This is
- * done for a different decay in each of the 3 data sets to keep relevant data
- * from different time horizons. Furthermore we also keep track of the number
- * unmined (in mempool or left mempool without being included in a block)
- * transactions in each bucket and for how many blocks they have been
- * outstanding and use both of these numbers to increase the number of transactions
- * we've seen in that feerate bucket when calculating an estimate for any number
- * of confirmations below the number of blocks they've been outstanding.
- */
-
/* Identifier for each of the 3 different TxConfirmStats which will track
* history over different time horizons. */
enum class FeeEstimateHorizon {
@@ -91,17 +46,13 @@ enum class FeeReason {
MAXTXFEE,
};
-std::string StringForFeeReason(FeeReason reason);
-
/* Used to determine type of fee estimation requested */
enum class FeeEstimateMode {
- UNSET, //! Use default settings based on other criteria
- ECONOMICAL, //! Force estimateSmartFee to use non-conservative estimates
- CONSERVATIVE, //! Force estimateSmartFee to use conservative estimates
+ UNSET, //!< Use default settings based on other criteria
+ ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates
+ CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
};
-bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode);
-
/* Used to return detailed information about a feerate bucket */
struct EstimatorBucket
{
@@ -130,7 +81,50 @@ struct FeeCalculation
int returnedTarget = 0;
};
-/**
+/** \class CBlockPolicyEstimator
+ * The BlockPolicyEstimator is used for estimating the feerate needed
+ * for a transaction to be included in a block within a certain number of
+ * blocks.
+ *
+ * At a high level the algorithm works by grouping transactions into buckets
+ * based on having similar feerates and then tracking how long it
+ * takes transactions in the various buckets to be mined. It operates under
+ * the assumption that in general transactions of higher feerate will be
+ * included in blocks before transactions of lower feerate. So for
+ * example if you wanted to know what feerate you should put on a transaction to
+ * be included in a block within the next 5 blocks, you would start by looking
+ * at the bucket with the highest feerate transactions and verifying that a
+ * sufficiently high percentage of them were confirmed within 5 blocks and
+ * then you would look at the next highest feerate bucket, and so on, stopping at
+ * the last bucket to pass the test. The average feerate of transactions in this
+ * bucket will give you an indication of the lowest feerate you can put on a
+ * transaction and still have a sufficiently high chance of being confirmed
+ * within your desired 5 blocks.
+ *
+ * Here is a brief description of the implementation:
+ * When a transaction enters the mempool, we track the height of the block chain
+ * at entry. All further calculations are conducted only on this set of "seen"
+ * transactions. Whenever a block comes in, we count the number of transactions
+ * in each bucket and the total amount of feerate paid in each bucket. Then we
+ * calculate how many blocks Y it took each transaction to be mined. We convert
+ * from a number of blocks to a number of periods Y' each encompassing "scale"
+ * blocks. This is tracked in 3 different data sets each up to a maximum
+ * number of periods. Within each data set we have an array of counters in each
+ * feerate bucket and we increment all the counters from Y' up to max periods
+ * representing that a tx was successfully confirmed in less than or equal to
+ * that many periods. We want to save a history of this information, so at any
+ * time we have a counter of the total number of transactions that happened in a
+ * given feerate bucket and the total number that were confirmed in each of the
+ * periods or less for any bucket. We save this history by keeping an
+ * exponentially decaying moving average of each one of these stats. This is
+ * done for a different decay in each of the 3 data sets to keep relevant data
+ * from different time horizons. Furthermore we also keep track of the number
+ * unmined (in mempool or left mempool without being included in a block)
+ * transactions in each bucket and for how many blocks they have been
+ * outstanding and use both of these numbers to increase the number of transactions
+ * we've seen in that feerate bucket when calculating an estimate for any number
+ * of confirmations below the number of blocks they've been outstanding.
+ *
* We want to be able to estimate feerates that are needed on tx's to be included in
* a certain number of blocks. Every time a block is added to the best chain, this class records
* stats on the transactions included in that block
@@ -230,10 +224,12 @@ public:
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const;
private:
- unsigned int nBestSeenHeight;
- unsigned int firstRecordedHeight;
- unsigned int historicalFirst;
- unsigned int historicalBest;
+ mutable CCriticalSection 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);
struct TxStatsInfo
{
@@ -243,34 +239,32 @@ private:
};
// map of txids to information about that transaction
- std::map<uint256, TxStatsInfo> mapMemPoolTxs;
+ std::map<uint256, TxStatsInfo> mapMemPoolTxs GUARDED_BY(m_cs_fee_estimator);
/** Classes to track historical data on transaction confirmations */
- std::unique_ptr<TxConfirmStats> feeStats;
- std::unique_ptr<TxConfirmStats> shortStats;
- std::unique_ptr<TxConfirmStats> longStats;
-
- unsigned int trackedTxs;
- unsigned int untrackedTxs;
+ std::unique_ptr<TxConfirmStats> feeStats PT_GUARDED_BY(m_cs_fee_estimator);
+ std::unique_ptr<TxConfirmStats> shortStats PT_GUARDED_BY(m_cs_fee_estimator);
+ std::unique_ptr<TxConfirmStats> longStats PT_GUARDED_BY(m_cs_fee_estimator);
- std::vector<double> buckets; // The upper-bound of the range for the bucket (inclusive)
- std::map<double, unsigned int> bucketMap; // Map of bucket upper-bound to index into all vectors by bucket
+ unsigned int trackedTxs GUARDED_BY(m_cs_fee_estimator);
+ unsigned int untrackedTxs GUARDED_BY(m_cs_fee_estimator);
- mutable CCriticalSection cs_feeEstimator;
+ 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
/** Process a transaction confirmed in a block*/
- bool processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry* entry);
+ bool processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry* entry) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
/** Helper for estimateSmartFee */
- double estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const;
+ double estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
/** Helper for estimateSmartFee */
- double estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const;
+ double estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
/** Number of blocks of data recorded while fee estimates have been running */
- unsigned int BlockSpan() const;
+ unsigned int BlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
/** Number of blocks of recorded fee estimate data represented in saved data file */
- unsigned int HistoricalBlockSpan() const;
+ unsigned int HistoricalBlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
/** Calculation of highest target that reasonable estimate can be provided for */
- unsigned int MaxUsableEstimate() const;
+ unsigned int MaxUsableEstimate() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
};
class FeeFilterRounder
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 3a592e40d3..63a3d06267 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,11 +8,11 @@
#include <policy/policy.h>
#include <consensus/validation.h>
-#include <validation.h>
#include <coins.h>
+#include <policy/settings.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
@@ -34,7 +34,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
if (txout.scriptPubKey.IsUnspendable())
return 0;
- size_t nSize = GetSerializeSize(txout, SER_DISK, 0);
+ size_t nSize = GetSerializeSize(txout);
int witnessversion = 0;
std::vector<unsigned char> witnessprogram;
@@ -57,11 +57,11 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
{
std::vector<std::vector<unsigned char> > vSolutions;
- if (!Solver(scriptPubKey, whichType, vSolutions))
- return false;
+ whichType = Solver(scriptPubKey, vSolutions);
- if (whichType == TX_MULTISIG)
- {
+ if (whichType == TX_NONSTANDARD) {
+ return false;
+ } else if (whichType == TX_MULTISIG) {
unsigned char m = vSolutions.front()[0];
unsigned char n = vSolutions.back()[0];
// Support up to x-of-3 multisig txns as standard
@@ -70,13 +70,14 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
if (m < 1 || m > n)
return false;
} else if (whichType == TX_NULL_DATA &&
- (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
+ (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
return false;
+ }
- return whichType != TX_NONSTANDARD && whichType != TX_WITNESS_UNKNOWN;
+ return true;
}
-bool IsStandardTx(const CTransaction& tx, std::string& reason)
+bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
{
if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version";
@@ -122,10 +123,10 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
if (whichType == TX_NULL_DATA)
nDataOut++;
- else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
+ else if ((whichType == TX_MULTISIG) && (!permit_bare_multisig)) {
reason = "bare-multisig";
return false;
- } else if (IsDust(txout, ::dustRelayFee)) {
+ } else if (IsDust(txout, dust_relay_fee)) {
reason = "dust";
return false;
}
@@ -166,14 +167,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
std::vector<std::vector<unsigned char> > vSolutions;
- txnouttype whichType;
- // get the scriptPubKey corresponding to this input:
- const CScript& prevScript = prev.scriptPubKey;
- if (!Solver(prevScript, whichType, vSolutions))
+ txnouttype whichType = Solver(prev.scriptPubKey, vSolutions);
+ if (whichType == TX_NONSTANDARD) {
return false;
-
- if (whichType == TX_SCRIPTHASH)
- {
+ } else if (whichType == TX_SCRIPTHASH) {
std::vector<std::vector<unsigned char> > stack;
// convert the scriptSig into a stack, so we can inspect the redeemScript
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
@@ -242,21 +239,17 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
return true;
}
-CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
-CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
-unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
-
-int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)
+int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{
- return (std::max(nWeight, nSigOpCost * nBytesPerSigOp) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
+ return (std::max(nWeight, nSigOpCost * bytes_per_sigop) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
}
-int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost)
+int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{
- return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost);
+ return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost, bytes_per_sigop);
}
-int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost)
+int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{
- return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost);
+ return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost, bytes_per_sigop);
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 035627bd60..ebe040f0ea 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -34,6 +34,8 @@ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
static const unsigned int DEFAULT_INCREMENTAL_RELAY_FEE = 1000;
/** Default for -bytespersigop */
static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
+/** Default for -permitbaremultisig */
+static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
/** The maximum number of witness stack items in a standard P2WSH script */
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100;
/** The maximum size of each witness stack item in a standard P2WSH script */
@@ -84,7 +86,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
* Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
-bool IsStandardTx(const CTransaction& tx, std::string& reason);
+bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
/**
* Check for standard transaction types
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
@@ -98,13 +100,19 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
*/
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
-extern CFeeRate incrementalRelayFee;
-extern CFeeRate dustRelayFee;
-extern unsigned int nBytesPerSigOp;
-
/** Compute the virtual transaction size (weight reinterpreted as bytes). */
-int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost);
-int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0);
-int64_t GetVirtualTransactionInputSize(const CTxIn& tx, int64_t nSigOpCost = 0);
+int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop);
+int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
+int64_t GetVirtualTransactionInputSize(const CTxIn& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
+
+static inline int64_t GetVirtualTransactionSize(const CTransaction& tx)
+{
+ return GetVirtualTransactionSize(tx, 0, 0);
+}
+
+static inline int64_t GetVirtualTransactionInputSize(const CTxIn& tx)
+{
+ return GetVirtualTransactionInputSize(tx, 0, 0);
+}
#endif // BITCOIN_POLICY_POLICY_H
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index 81b2a7fadc..b4b8341d77 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -1,20 +1,11 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <policy/rbf.h>
+#include <util/rbf.h>
-bool SignalsOptInRBF(const CTransaction &tx)
-{
- for (const CTxIn &txin : tx.vin) {
- if (txin.nSequence < std::numeric_limits<unsigned int>::max()-1) {
- return true;
- }
- }
- return false;
-}
-
-RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool)
+RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
{
AssertLockHeld(pool.cs);
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index c0a25f75b5..0707b0044f 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,22 +7,16 @@
#include <txmempool.h>
-static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd;
-
enum class RBFTransactionState {
UNKNOWN,
REPLACEABLE_BIP125,
FINAL
};
-// Check whether the sequence numbers on this transaction are signaling
-// opt-in to replace-by-fee, according to BIP 125
-bool SignalsOptInRBF(const CTransaction &tx);
-
// Determine whether an in-mempool transaction is signaling opt-in to RBF
// according to BIP 125
// This involves checking sequence numbers of the transaction, as well
// as the sequence numbers of all in-mempool ancestors.
-RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
+RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
#endif // BITCOIN_POLICY_RBF_H
diff --git a/src/policy/settings.cpp b/src/policy/settings.cpp
new file mode 100644
index 0000000000..e8e1559407
--- /dev/null
+++ b/src/policy/settings.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <policy/settings.h>
+
+#include <policy/feerate.h>
+#include <policy/policy.h>
+
+bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
+CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
+CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
+unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
diff --git a/src/policy/settings.h b/src/policy/settings.h
new file mode 100644
index 0000000000..30a7189c93
--- /dev/null
+++ b/src/policy/settings.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_POLICY_SETTINGS_H
+#define BITCOIN_POLICY_SETTINGS_H
+
+#include <policy/policy.h>
+
+class CFeeRate;
+class CTransaction;
+
+// Policy settings which are configurable at runtime.
+extern CFeeRate incrementalRelayFee;
+extern CFeeRate dustRelayFee;
+extern unsigned int nBytesPerSigOp;
+extern bool fIsBareMultisigStd;
+
+static inline bool IsStandardTx(const CTransaction& tx, std::string& reason)
+{
+ return IsStandardTx(tx, ::fIsBareMultisigStd, ::dustRelayFee, reason);
+}
+
+static inline int64_t GetVirtualTransactionSize(int64_t weight, int64_t sigop_cost)
+{
+ return GetVirtualTransactionSize(weight, sigop_cost, ::nBytesPerSigOp);
+}
+
+static inline int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t sigop_cost)
+{
+ return GetVirtualTransactionSize(tx, sigop_cost, ::nBytesPerSigOp);
+}
+
+#endif // BITCOIN_POLICY_SETTINGS_H
diff --git a/src/pow.cpp b/src/pow.cpp
index 929ea26a02..1414d37564 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/pow.h b/src/pow.h
index b8cc349263..1d802cd01e 100644
--- a/src/pow.h
+++ b/src/pow.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/prevector.h b/src/prevector.h
index 103ead82cc..ea8707389a 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,12 +10,11 @@
#include <stdint.h>
#include <string.h>
+#include <algorithm>
#include <cstddef>
#include <iterator>
#include <type_traits>
-#include <compat.h>
-
#pragma pack(push, 1)
/** Implements a drop-in replacement for std::vector<T> which stores up to N
* elements directly (without heap allocation). The types Size and Diff are
@@ -148,14 +147,14 @@ public:
};
private:
- size_type _size;
+ size_type _size = 0;
union direct_or_indirect {
char direct[sizeof(T) * N];
struct {
size_type capacity;
char* indirect;
};
- } _union;
+ } _union = {};
T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
@@ -197,23 +196,8 @@ private:
T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
- void fill(T* dst, ptrdiff_t count) {
- if (IS_TRIVIALLY_CONSTRUCTIBLE<T>::value) {
- // The most common use of prevector is where T=unsigned char. For
- // trivially constructible types, we can use memset() to avoid
- // looping.
- ::memset(dst, 0, count * sizeof(T));
- } else {
- for (auto i = 0; i < count; ++i) {
- new(static_cast<void*>(dst + i)) T();
- }
- }
- }
-
- void fill(T* dst, ptrdiff_t count, const T& value) {
- for (auto i = 0; i < count; ++i) {
- new(static_cast<void*>(dst + i)) T(value);
- }
+ void fill(T* dst, ptrdiff_t count, const T& value = T{}) {
+ std::fill_n(dst, count, value);
}
template<typename InputIterator>
@@ -246,34 +230,34 @@ public:
fill(item_ptr(0), first, last);
}
- prevector() : _size(0), _union{{}} {}
+ prevector() {}
- explicit prevector(size_type n) : _size(0) {
+ explicit prevector(size_type n) {
resize(n);
}
- explicit prevector(size_type n, const T& val = T()) : _size(0) {
+ explicit prevector(size_type n, const T& val) {
change_capacity(n);
_size += n;
fill(item_ptr(0), n, val);
}
template<typename InputIterator>
- prevector(InputIterator first, InputIterator last) : _size(0) {
+ prevector(InputIterator first, InputIterator last) {
size_type n = last - first;
change_capacity(n);
_size += n;
fill(item_ptr(0), first, last);
}
- prevector(const prevector<N, T, Size, Diff>& other) : _size(0) {
+ prevector(const prevector<N, T, Size, Diff>& other) {
size_type n = other.size();
change_capacity(n);
_size += n;
fill(item_ptr(0), other.begin(), other.end());
}
- prevector(prevector<N, T, Size, Diff>&& other) : _size(0) {
+ prevector(prevector<N, T, Size, Diff>&& other) {
swap(other);
}
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index 21f880bccb..a0c2e3f125 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,7 +7,7 @@
#include <hash.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <crypto/common.h>
uint256 CBlockHeader::GetHash() const
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 1fca55d910..750d42efbc 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 230f762a1b..28c145f71d 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,7 +7,7 @@
#include <hash.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
std::string COutPoint::ToString() const
{
@@ -93,7 +93,7 @@ CAmount CTransaction::GetValueOut() const
unsigned int CTransaction::GetTotalSize() const
{
- return ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION);
+ return ::GetSerializeSize(*this, PROTOCOL_VERSION);
}
std::string CTransaction::ToString() const
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 360615ec56..aad991e2f1 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -21,7 +21,9 @@ public:
uint256 hash;
uint32_t n;
- COutPoint(): n((uint32_t) -1) { }
+ static constexpr uint32_t NULL_INDEX = std::numeric_limits<uint32_t>::max();
+
+ COutPoint(): n(NULL_INDEX) { }
COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { }
ADD_SERIALIZE_METHODS;
@@ -32,8 +34,8 @@ public:
READWRITE(n);
}
- void SetNull() { hash.SetNull(); n = (uint32_t) -1; }
- bool IsNull() const { return (hash.IsNull() && n == (uint32_t) -1); }
+ void SetNull() { hash.SetNull(); n = NULL_INDEX; }
+ bool IsNull() const { return (hash.IsNull() && n == NULL_INDEX); }
friend bool operator<(const COutPoint& a, const COutPoint& b)
{
@@ -64,7 +66,7 @@ public:
COutPoint prevout;
CScript scriptSig;
uint32_t nSequence;
- CScriptWitness scriptWitness; //! Only serialized through CTransaction
+ CScriptWitness scriptWitness; //!< Only serialized through CTransaction
/* Setting nSequence to this value for every input in a transaction
* disables nLockTime. */
@@ -73,7 +75,7 @@ public:
/* Below flags apply in the context of BIP 68*/
/* If this flag set, CTxIn::nSequence is NOT interpreted as a
* relative lock-time. */
- static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);
+ static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1U << 31);
/* If CTxIn::nSequence encodes a relative lock-time and this flag
* is set, the relative lock-time has units of 512 seconds,
@@ -220,6 +222,10 @@ inline void UnserializeTransaction(TxType& tx, Stream& s) {
for (size_t i = 0; i < tx.vin.size(); i++) {
s >> tx.vin[i].scriptWitness.stack;
}
+ if (!tx.HasWitness()) {
+ /* It's illegal to encode witnesses when all witness stacks are empty. */
+ throw std::ios_base::failure("Superfluous witness record");
+ }
}
if (flags) {
/* Unknown flag in the serialization */
@@ -296,7 +302,7 @@ public:
CTransaction();
/** Convert a CMutableTransaction into a CTransaction. */
- CTransaction(const CMutableTransaction &tx);
+ explicit CTransaction(const CMutableTransaction &tx);
CTransaction(CMutableTransaction &&tx);
template <typename Stream>
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 2ec26fbd3e..bdf236c2c7 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -1,12 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <protocol.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#ifndef WIN32
# include <arpa/inet.h>
diff --git a/src/protocol.h b/src/protocol.h
index 3a9b2d2561..a790a06906 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -402,7 +402,6 @@ public:
std::string GetCommand() const;
std::string ToString() const;
- // TODO: make private (improves encapsulation)
public:
int type;
uint256 hash;
diff --git a/src/psbt.cpp b/src/psbt.cpp
new file mode 100644
index 0000000000..97bda51a63
--- /dev/null
+++ b/src/psbt.cpp
@@ -0,0 +1,370 @@
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <coins.h>
+#include <consensus/tx_verify.h>
+#include <policy/policy.h>
+#include <psbt.h>
+#include <util/strencodings.h>
+
+#include <numeric>
+
+PartiallySignedTransaction::PartiallySignedTransaction(const CMutableTransaction& tx) : tx(tx)
+{
+ inputs.resize(tx.vin.size());
+ outputs.resize(tx.vout.size());
+}
+
+bool PartiallySignedTransaction::IsNull() const
+{
+ return !tx && inputs.empty() && outputs.empty() && unknown.empty();
+}
+
+bool PartiallySignedTransaction::Merge(const PartiallySignedTransaction& psbt)
+{
+ // Prohibited to merge two PSBTs over different transactions
+ if (tx->GetHash() != psbt.tx->GetHash()) {
+ return false;
+ }
+
+ for (unsigned int i = 0; i < inputs.size(); ++i) {
+ inputs[i].Merge(psbt.inputs[i]);
+ }
+ for (unsigned int i = 0; i < outputs.size(); ++i) {
+ outputs[i].Merge(psbt.outputs[i]);
+ }
+ unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
+
+ return true;
+}
+
+bool PartiallySignedTransaction::IsSane() const
+{
+ for (PSBTInput input : inputs) {
+ if (!input.IsSane()) return false;
+ }
+ return true;
+}
+
+bool PartiallySignedTransaction::AddInput(const CTxIn& txin, PSBTInput& psbtin)
+{
+ if (std::find(tx->vin.begin(), tx->vin.end(), txin) != tx->vin.end()) {
+ return false;
+ }
+ tx->vin.push_back(txin);
+ psbtin.partial_sigs.clear();
+ psbtin.final_script_sig.clear();
+ psbtin.final_script_witness.SetNull();
+ inputs.push_back(psbtin);
+ return true;
+}
+
+bool PartiallySignedTransaction::AddOutput(const CTxOut& txout, const PSBTOutput& psbtout)
+{
+ tx->vout.push_back(txout);
+ outputs.push_back(psbtout);
+ return true;
+}
+
+bool PartiallySignedTransaction::GetInputUTXO(CTxOut& utxo, int input_index) const
+{
+ PSBTInput input = inputs[input_index];
+ int prevout_index = tx->vin[input_index].prevout.n;
+ if (input.non_witness_utxo) {
+ utxo = input.non_witness_utxo->vout[prevout_index];
+ } else if (!input.witness_utxo.IsNull()) {
+ utxo = input.witness_utxo;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool PSBTInput::IsNull() const
+{
+ return !non_witness_utxo && witness_utxo.IsNull() && partial_sigs.empty() && unknown.empty() && hd_keypaths.empty() && redeem_script.empty() && witness_script.empty();
+}
+
+void PSBTInput::FillSignatureData(SignatureData& sigdata) const
+{
+ if (!final_script_sig.empty()) {
+ sigdata.scriptSig = final_script_sig;
+ sigdata.complete = true;
+ }
+ if (!final_script_witness.IsNull()) {
+ sigdata.scriptWitness = final_script_witness;
+ sigdata.complete = true;
+ }
+ if (sigdata.complete) {
+ return;
+ }
+
+ sigdata.signatures.insert(partial_sigs.begin(), partial_sigs.end());
+ if (!redeem_script.empty()) {
+ sigdata.redeem_script = redeem_script;
+ }
+ if (!witness_script.empty()) {
+ sigdata.witness_script = witness_script;
+ }
+ for (const auto& key_pair : hd_keypaths) {
+ sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
+ }
+}
+
+void PSBTInput::FromSignatureData(const SignatureData& sigdata)
+{
+ if (sigdata.complete) {
+ partial_sigs.clear();
+ hd_keypaths.clear();
+ redeem_script.clear();
+ witness_script.clear();
+
+ if (!sigdata.scriptSig.empty()) {
+ final_script_sig = sigdata.scriptSig;
+ }
+ if (!sigdata.scriptWitness.IsNull()) {
+ final_script_witness = sigdata.scriptWitness;
+ }
+ return;
+ }
+
+ partial_sigs.insert(sigdata.signatures.begin(), sigdata.signatures.end());
+ if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
+ redeem_script = sigdata.redeem_script;
+ }
+ if (witness_script.empty() && !sigdata.witness_script.empty()) {
+ witness_script = sigdata.witness_script;
+ }
+ for (const auto& entry : sigdata.misc_pubkeys) {
+ hd_keypaths.emplace(entry.second);
+ }
+}
+
+void PSBTInput::Merge(const PSBTInput& input)
+{
+ if (!non_witness_utxo && input.non_witness_utxo) non_witness_utxo = input.non_witness_utxo;
+ if (witness_utxo.IsNull() && !input.witness_utxo.IsNull()) {
+ witness_utxo = input.witness_utxo;
+ non_witness_utxo = nullptr; // Clear out any non-witness utxo when we set a witness one.
+ }
+
+ partial_sigs.insert(input.partial_sigs.begin(), input.partial_sigs.end());
+ hd_keypaths.insert(input.hd_keypaths.begin(), input.hd_keypaths.end());
+ unknown.insert(input.unknown.begin(), input.unknown.end());
+
+ if (redeem_script.empty() && !input.redeem_script.empty()) redeem_script = input.redeem_script;
+ if (witness_script.empty() && !input.witness_script.empty()) witness_script = input.witness_script;
+ if (final_script_sig.empty() && !input.final_script_sig.empty()) final_script_sig = input.final_script_sig;
+ if (final_script_witness.IsNull() && !input.final_script_witness.IsNull()) final_script_witness = input.final_script_witness;
+}
+
+bool PSBTInput::IsSane() const
+{
+ // Cannot have both witness and non-witness utxos
+ if (!witness_utxo.IsNull() && non_witness_utxo) return false;
+
+ // If we have a witness_script or a scriptWitness, we must also have a witness utxo
+ if (!witness_script.empty() && witness_utxo.IsNull()) return false;
+ if (!final_script_witness.IsNull() && witness_utxo.IsNull()) return false;
+
+ return true;
+}
+
+void PSBTOutput::FillSignatureData(SignatureData& sigdata) const
+{
+ if (!redeem_script.empty()) {
+ sigdata.redeem_script = redeem_script;
+ }
+ if (!witness_script.empty()) {
+ sigdata.witness_script = witness_script;
+ }
+ for (const auto& key_pair : hd_keypaths) {
+ sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
+ }
+}
+
+void PSBTOutput::FromSignatureData(const SignatureData& sigdata)
+{
+ if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
+ redeem_script = sigdata.redeem_script;
+ }
+ if (witness_script.empty() && !sigdata.witness_script.empty()) {
+ witness_script = sigdata.witness_script;
+ }
+ for (const auto& entry : sigdata.misc_pubkeys) {
+ hd_keypaths.emplace(entry.second);
+ }
+}
+
+bool PSBTOutput::IsNull() const
+{
+ return redeem_script.empty() && witness_script.empty() && hd_keypaths.empty() && unknown.empty();
+}
+
+void PSBTOutput::Merge(const PSBTOutput& output)
+{
+ hd_keypaths.insert(output.hd_keypaths.begin(), output.hd_keypaths.end());
+ unknown.insert(output.unknown.begin(), output.unknown.end());
+
+ if (redeem_script.empty() && !output.redeem_script.empty()) redeem_script = output.redeem_script;
+ if (witness_script.empty() && !output.witness_script.empty()) witness_script = output.witness_script;
+}
+bool PSBTInputSigned(const PSBTInput& input)
+{
+ return !input.final_script_sig.empty() || !input.final_script_witness.IsNull();
+}
+
+bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash, SignatureData* out_sigdata, bool use_dummy)
+{
+ PSBTInput& input = psbt.inputs.at(index);
+ const CMutableTransaction& tx = *psbt.tx;
+
+ if (PSBTInputSigned(input)) {
+ return true;
+ }
+
+ // Fill SignatureData with input info
+ SignatureData sigdata;
+ input.FillSignatureData(sigdata);
+
+ // Get UTXO
+ bool require_witness_sig = false;
+ CTxOut utxo;
+
+ // Verify input sanity, which checks that at most one of witness or non-witness utxos is provided.
+ if (!input.IsSane()) {
+ return false;
+ }
+
+ if (input.non_witness_utxo) {
+ // If we're taking our information from a non-witness UTXO, verify that it matches the prevout.
+ COutPoint prevout = tx.vin[index].prevout;
+ if (input.non_witness_utxo->GetHash() != prevout.hash) {
+ return false;
+ }
+ utxo = input.non_witness_utxo->vout[prevout.n];
+ } else if (!input.witness_utxo.IsNull()) {
+ utxo = input.witness_utxo;
+ // When we're taking our information from a witness UTXO, we can't verify it is actually data from
+ // the output being spent. This is safe in case a witness signature is produced (which includes this
+ // information directly in the hash), but not for non-witness signatures. Remember that we require
+ // a witness signature in this situation.
+ require_witness_sig = true;
+ } else {
+ return false;
+ }
+
+ sigdata.witness = false;
+ bool sig_complete;
+ if (use_dummy) {
+ sig_complete = ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, utxo.scriptPubKey, sigdata);
+ } else {
+ MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue, sighash);
+ sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
+ }
+ // Verify that a witness signature was produced in case one was required.
+ if (require_witness_sig && !sigdata.witness) return false;
+ input.FromSignatureData(sigdata);
+
+ // If we have a witness signature, use the smaller witness UTXO.
+ if (sigdata.witness) {
+ input.witness_utxo = utxo;
+ input.non_witness_utxo = nullptr;
+ }
+
+ // Fill in the missing info
+ if (out_sigdata) {
+ out_sigdata->missing_pubkeys = sigdata.missing_pubkeys;
+ out_sigdata->missing_sigs = sigdata.missing_sigs;
+ out_sigdata->missing_redeem_script = sigdata.missing_redeem_script;
+ out_sigdata->missing_witness_script = sigdata.missing_witness_script;
+ }
+
+ return sig_complete;
+}
+
+bool FinalizePSBT(PartiallySignedTransaction& psbtx)
+{
+ // Finalize input signatures -- in case we have partial signatures that add up to a complete
+ // signature, but have not combined them yet (e.g. because the combiner that created this
+ // PartiallySignedTransaction did not understand them), this will combine them into a final
+ // script.
+ bool complete = true;
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, SIGHASH_ALL);
+ }
+
+ return complete;
+}
+
+bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransaction& result)
+{
+ // It's not safe to extract a PSBT that isn't finalized, and there's no easy way to check
+ // whether a PSBT is finalized without finalizing it, so we just do this.
+ if (!FinalizePSBT(psbtx)) {
+ return false;
+ }
+
+ result = *psbtx.tx;
+ for (unsigned int i = 0; i < result.vin.size(); ++i) {
+ result.vin[i].scriptSig = psbtx.inputs[i].final_script_sig;
+ result.vin[i].scriptWitness = psbtx.inputs[i].final_script_witness;
+ }
+ return true;
+}
+
+TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs)
+{
+ out = psbtxs[0]; // Copy the first one
+
+ // Merge
+ for (auto it = std::next(psbtxs.begin()); it != psbtxs.end(); ++it) {
+ if (!out.Merge(*it)) {
+ return TransactionError::PSBT_MISMATCH;
+ }
+ }
+ if (!out.IsSane()) {
+ return TransactionError::INVALID_PSBT;
+ }
+
+ return TransactionError::OK;
+}
+
+std::string PSBTRoleName(PSBTRole role) {
+ switch (role) {
+ case PSBTRole::UPDATER: return "updater";
+ case PSBTRole::SIGNER: return "signer";
+ case PSBTRole::FINALIZER: return "finalizer";
+ case PSBTRole::EXTRACTOR: return "extractor";
+ // no default case, so the compiler can warn about missing cases
+ }
+ assert(false);
+}
+
+bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
+{
+ bool invalid;
+ std::string tx_data = DecodeBase64(base64_tx, &invalid);
+ if (invalid) {
+ error = "invalid base64";
+ return false;
+ }
+ return DecodeRawPSBT(psbt, tx_data, error);
+}
+
+bool DecodeRawPSBT(PartiallySignedTransaction& psbt, const std::string& tx_data, std::string& error)
+{
+ CDataStream ss_data(tx_data.data(), tx_data.data() + tx_data.size(), SER_NETWORK, PROTOCOL_VERSION);
+ try {
+ ss_data >> psbt;
+ if (!ss_data.empty()) {
+ error = "extra data after PSBT";
+ return false;
+ }
+ } catch (const std::exception& e) {
+ error = e.what();
+ return false;
+ }
+ return true;
+}
diff --git a/src/psbt.h b/src/psbt.h
new file mode 100644
index 0000000000..1bc1e91a84
--- /dev/null
+++ b/src/psbt.h
@@ -0,0 +1,599 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_PSBT_H
+#define BITCOIN_PSBT_H
+
+#include <attributes.h>
+#include <node/transaction.h>
+#include <optional.h>
+#include <policy/feerate.h>
+#include <primitives/transaction.h>
+#include <pubkey.h>
+#include <script/sign.h>
+
+// Magic bytes
+static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
+
+// Global types
+static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00;
+
+// Input types
+static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00;
+static constexpr uint8_t PSBT_IN_WITNESS_UTXO = 0x01;
+static constexpr uint8_t PSBT_IN_PARTIAL_SIG = 0x02;
+static constexpr uint8_t PSBT_IN_SIGHASH = 0x03;
+static constexpr uint8_t PSBT_IN_REDEEMSCRIPT = 0x04;
+static constexpr uint8_t PSBT_IN_WITNESSSCRIPT = 0x05;
+static constexpr uint8_t PSBT_IN_BIP32_DERIVATION = 0x06;
+static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07;
+static constexpr uint8_t PSBT_IN_SCRIPTWITNESS = 0x08;
+
+// Output types
+static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00;
+static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01;
+static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
+
+// The separator is 0x00. Reading this in means that the unserializer can interpret it
+// as a 0 length key which indicates that this is the separator. The separator has no value.
+static constexpr uint8_t PSBT_SEPARATOR = 0x00;
+
+/** A structure for PSBTs which contain per-input information */
+struct PSBTInput
+{
+ CTransactionRef non_witness_utxo;
+ CTxOut witness_utxo;
+ CScript redeem_script;
+ CScript witness_script;
+ CScript final_script_sig;
+ CScriptWitness final_script_witness;
+ std::map<CPubKey, KeyOriginInfo> hd_keypaths;
+ std::map<CKeyID, SigPair> partial_sigs;
+ std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
+ int sighash_type = 0;
+
+ bool IsNull() const;
+ void FillSignatureData(SignatureData& sigdata) const;
+ void FromSignatureData(const SignatureData& sigdata);
+ void Merge(const PSBTInput& input);
+ bool IsSane() const;
+ PSBTInput() {}
+
+ template <typename Stream>
+ inline void Serialize(Stream& s) const {
+ // Write the utxo
+ // If there is a non-witness utxo, then don't add the witness one.
+ if (non_witness_utxo) {
+ SerializeToVector(s, PSBT_IN_NON_WITNESS_UTXO);
+ OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() | SERIALIZE_TRANSACTION_NO_WITNESS);
+ SerializeToVector(os, non_witness_utxo);
+ } else if (!witness_utxo.IsNull()) {
+ SerializeToVector(s, PSBT_IN_WITNESS_UTXO);
+ SerializeToVector(s, witness_utxo);
+ }
+
+ if (final_script_sig.empty() && final_script_witness.IsNull()) {
+ // Write any partial signatures
+ for (auto sig_pair : partial_sigs) {
+ SerializeToVector(s, PSBT_IN_PARTIAL_SIG, MakeSpan(sig_pair.second.first));
+ s << sig_pair.second.second;
+ }
+
+ // Write the sighash type
+ if (sighash_type > 0) {
+ SerializeToVector(s, PSBT_IN_SIGHASH);
+ SerializeToVector(s, sighash_type);
+ }
+
+ // Write the redeem script
+ if (!redeem_script.empty()) {
+ SerializeToVector(s, PSBT_IN_REDEEMSCRIPT);
+ s << redeem_script;
+ }
+
+ // Write the witness script
+ if (!witness_script.empty()) {
+ SerializeToVector(s, PSBT_IN_WITNESSSCRIPT);
+ s << witness_script;
+ }
+
+ // Write any hd keypaths
+ SerializeHDKeypaths(s, hd_keypaths, PSBT_IN_BIP32_DERIVATION);
+ }
+
+ // Write script sig
+ if (!final_script_sig.empty()) {
+ SerializeToVector(s, PSBT_IN_SCRIPTSIG);
+ s << final_script_sig;
+ }
+ // write script witness
+ if (!final_script_witness.IsNull()) {
+ SerializeToVector(s, PSBT_IN_SCRIPTWITNESS);
+ SerializeToVector(s, final_script_witness.stack);
+ }
+
+ // Write unknown things
+ for (auto& entry : unknown) {
+ s << entry.first;
+ s << entry.second;
+ }
+
+ s << PSBT_SEPARATOR;
+ }
+
+
+ template <typename Stream>
+ inline void Unserialize(Stream& s) {
+ // Read loop
+ bool found_sep = false;
+ while(!s.empty()) {
+ // Read
+ std::vector<unsigned char> key;
+ s >> key;
+
+ // the key is empty if that was actually a separator byte
+ // This is a special case for key lengths 0 as those are not allowed (except for separator)
+ if (key.empty()) {
+ found_sep = true;
+ break;
+ }
+
+ // First byte of key is the type
+ unsigned char type = key[0];
+
+ // Do stuff based on type
+ switch(type) {
+ case PSBT_IN_NON_WITNESS_UTXO:
+ {
+ if (non_witness_utxo) {
+ throw std::ios_base::failure("Duplicate Key, input non-witness utxo already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Non-witness utxo key is more than one byte type");
+ }
+ // Set the stream to unserialize with witness since this is always a valid network transaction
+ OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() & ~SERIALIZE_TRANSACTION_NO_WITNESS);
+ UnserializeFromVector(os, non_witness_utxo);
+ break;
+ }
+ case PSBT_IN_WITNESS_UTXO:
+ if (!witness_utxo.IsNull()) {
+ throw std::ios_base::failure("Duplicate Key, input witness utxo already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Witness utxo key is more than one byte type");
+ }
+ UnserializeFromVector(s, witness_utxo);
+ break;
+ case PSBT_IN_PARTIAL_SIG:
+ {
+ // Make sure that the key is the size of pubkey + 1
+ if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) {
+ throw std::ios_base::failure("Size of key was not the expected size for the type partial signature pubkey");
+ }
+ // Read in the pubkey from key
+ CPubKey pubkey(key.begin() + 1, key.end());
+ if (!pubkey.IsFullyValid()) {
+ throw std::ios_base::failure("Invalid pubkey");
+ }
+ if (partial_sigs.count(pubkey.GetID()) > 0) {
+ throw std::ios_base::failure("Duplicate Key, input partial signature for pubkey already provided");
+ }
+
+ // Read in the signature from value
+ std::vector<unsigned char> sig;
+ s >> sig;
+
+ // Add to list
+ partial_sigs.emplace(pubkey.GetID(), SigPair(pubkey, std::move(sig)));
+ break;
+ }
+ case PSBT_IN_SIGHASH:
+ if (sighash_type > 0) {
+ throw std::ios_base::failure("Duplicate Key, input sighash type already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Sighash type key is more than one byte type");
+ }
+ UnserializeFromVector(s, sighash_type);
+ break;
+ case PSBT_IN_REDEEMSCRIPT:
+ {
+ if (!redeem_script.empty()) {
+ throw std::ios_base::failure("Duplicate Key, input redeemScript already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Input redeemScript key is more than one byte type");
+ }
+ s >> redeem_script;
+ break;
+ }
+ case PSBT_IN_WITNESSSCRIPT:
+ {
+ if (!witness_script.empty()) {
+ throw std::ios_base::failure("Duplicate Key, input witnessScript already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Input witnessScript key is more than one byte type");
+ }
+ s >> witness_script;
+ break;
+ }
+ case PSBT_IN_BIP32_DERIVATION:
+ {
+ DeserializeHDKeypaths(s, key, hd_keypaths);
+ break;
+ }
+ case PSBT_IN_SCRIPTSIG:
+ {
+ if (!final_script_sig.empty()) {
+ throw std::ios_base::failure("Duplicate Key, input final scriptSig already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Final scriptSig key is more than one byte type");
+ }
+ s >> final_script_sig;
+ break;
+ }
+ case PSBT_IN_SCRIPTWITNESS:
+ {
+ if (!final_script_witness.IsNull()) {
+ throw std::ios_base::failure("Duplicate Key, input final scriptWitness already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Final scriptWitness key is more than one byte type");
+ }
+ UnserializeFromVector(s, final_script_witness.stack);
+ break;
+ }
+ // Unknown stuff
+ default:
+ if (unknown.count(key) > 0) {
+ throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
+ }
+ // Read in the value
+ std::vector<unsigned char> val_bytes;
+ s >> val_bytes;
+ unknown.emplace(std::move(key), std::move(val_bytes));
+ break;
+ }
+ }
+
+ if (!found_sep) {
+ throw std::ios_base::failure("Separator is missing at the end of an input map");
+ }
+ }
+
+ template <typename Stream>
+ PSBTInput(deserialize_type, Stream& s) {
+ Unserialize(s);
+ }
+};
+
+/** A structure for PSBTs which contains per output information */
+struct PSBTOutput
+{
+ CScript redeem_script;
+ CScript witness_script;
+ std::map<CPubKey, KeyOriginInfo> hd_keypaths;
+ std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
+
+ bool IsNull() const;
+ void FillSignatureData(SignatureData& sigdata) const;
+ void FromSignatureData(const SignatureData& sigdata);
+ void Merge(const PSBTOutput& output);
+ bool IsSane() const;
+ PSBTOutput() {}
+
+ template <typename Stream>
+ inline void Serialize(Stream& s) const {
+ // Write the redeem script
+ if (!redeem_script.empty()) {
+ SerializeToVector(s, PSBT_OUT_REDEEMSCRIPT);
+ s << redeem_script;
+ }
+
+ // Write the witness script
+ if (!witness_script.empty()) {
+ SerializeToVector(s, PSBT_OUT_WITNESSSCRIPT);
+ s << witness_script;
+ }
+
+ // Write any hd keypaths
+ SerializeHDKeypaths(s, hd_keypaths, PSBT_OUT_BIP32_DERIVATION);
+
+ // Write unknown things
+ for (auto& entry : unknown) {
+ s << entry.first;
+ s << entry.second;
+ }
+
+ s << PSBT_SEPARATOR;
+ }
+
+
+ template <typename Stream>
+ inline void Unserialize(Stream& s) {
+ // Read loop
+ bool found_sep = false;
+ while(!s.empty()) {
+ // Read
+ std::vector<unsigned char> key;
+ s >> key;
+
+ // the key is empty if that was actually a separator byte
+ // This is a special case for key lengths 0 as those are not allowed (except for separator)
+ if (key.empty()) {
+ found_sep = true;
+ break;
+ }
+
+ // First byte of key is the type
+ unsigned char type = key[0];
+
+ // Do stuff based on type
+ switch(type) {
+ case PSBT_OUT_REDEEMSCRIPT:
+ {
+ if (!redeem_script.empty()) {
+ throw std::ios_base::failure("Duplicate Key, output redeemScript already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Output redeemScript key is more than one byte type");
+ }
+ s >> redeem_script;
+ break;
+ }
+ case PSBT_OUT_WITNESSSCRIPT:
+ {
+ if (!witness_script.empty()) {
+ throw std::ios_base::failure("Duplicate Key, output witnessScript already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Output witnessScript key is more than one byte type");
+ }
+ s >> witness_script;
+ break;
+ }
+ case PSBT_OUT_BIP32_DERIVATION:
+ {
+ DeserializeHDKeypaths(s, key, hd_keypaths);
+ break;
+ }
+ // Unknown stuff
+ default: {
+ if (unknown.count(key) > 0) {
+ throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
+ }
+ // Read in the value
+ std::vector<unsigned char> val_bytes;
+ s >> val_bytes;
+ unknown.emplace(std::move(key), std::move(val_bytes));
+ break;
+ }
+ }
+ }
+
+ if (!found_sep) {
+ throw std::ios_base::failure("Separator is missing at the end of an output map");
+ }
+ }
+
+ template <typename Stream>
+ PSBTOutput(deserialize_type, Stream& s) {
+ Unserialize(s);
+ }
+};
+
+/** A version of CTransaction with the PSBT format*/
+struct PartiallySignedTransaction
+{
+ boost::optional<CMutableTransaction> tx;
+ std::vector<PSBTInput> inputs;
+ std::vector<PSBTOutput> outputs;
+ std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
+
+ bool IsNull() const;
+
+ /** Merge psbt into this. The two psbts must have the same underlying CTransaction (i.e. the
+ * same actual Bitcoin transaction.) Returns true if the merge succeeded, false otherwise. */
+ NODISCARD bool Merge(const PartiallySignedTransaction& psbt);
+ bool IsSane() const;
+ bool AddInput(const CTxIn& txin, PSBTInput& psbtin);
+ bool AddOutput(const CTxOut& txout, const PSBTOutput& psbtout);
+ PartiallySignedTransaction() {}
+ PartiallySignedTransaction(const PartiallySignedTransaction& psbt_in) : tx(psbt_in.tx), inputs(psbt_in.inputs), outputs(psbt_in.outputs), unknown(psbt_in.unknown) {}
+ explicit PartiallySignedTransaction(const CMutableTransaction& tx);
+ /**
+ * Finds the UTXO for a given input index
+ *
+ * @param[out] utxo The UTXO of the input if found
+ * @param[in] input_index Index of the input to retrieve the UTXO of
+ * @return Whether the UTXO for the specified input was found
+ */
+ bool GetInputUTXO(CTxOut& utxo, int input_index) const;
+
+ template <typename Stream>
+ inline void Serialize(Stream& s) const {
+
+ // magic bytes
+ s << PSBT_MAGIC_BYTES;
+
+ // unsigned tx flag
+ SerializeToVector(s, PSBT_GLOBAL_UNSIGNED_TX);
+
+ // Write serialized tx to a stream
+ OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() | SERIALIZE_TRANSACTION_NO_WITNESS);
+ SerializeToVector(os, *tx);
+
+ // Write the unknown things
+ for (auto& entry : unknown) {
+ s << entry.first;
+ s << entry.second;
+ }
+
+ // Separator
+ s << PSBT_SEPARATOR;
+
+ // Write inputs
+ for (const PSBTInput& input : inputs) {
+ s << input;
+ }
+ // Write outputs
+ for (const PSBTOutput& output : outputs) {
+ s << output;
+ }
+ }
+
+
+ template <typename Stream>
+ inline void Unserialize(Stream& s) {
+ // Read the magic bytes
+ uint8_t magic[5];
+ s >> magic;
+ if (!std::equal(magic, magic + 5, PSBT_MAGIC_BYTES)) {
+ throw std::ios_base::failure("Invalid PSBT magic bytes");
+ }
+
+ // Read global data
+ bool found_sep = false;
+ while(!s.empty()) {
+ // Read
+ std::vector<unsigned char> key;
+ s >> key;
+
+ // the key is empty if that was actually a separator byte
+ // This is a special case for key lengths 0 as those are not allowed (except for separator)
+ if (key.empty()) {
+ found_sep = true;
+ break;
+ }
+
+ // First byte of key is the type
+ unsigned char type = key[0];
+
+ // Do stuff based on type
+ switch(type) {
+ case PSBT_GLOBAL_UNSIGNED_TX:
+ {
+ if (tx) {
+ throw std::ios_base::failure("Duplicate Key, unsigned tx already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Global unsigned tx key is more than one byte type");
+ }
+ CMutableTransaction mtx;
+ // Set the stream to serialize with non-witness since this should always be non-witness
+ OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() | SERIALIZE_TRANSACTION_NO_WITNESS);
+ UnserializeFromVector(os, mtx);
+ tx = std::move(mtx);
+ // Make sure that all scriptSigs and scriptWitnesses are empty
+ for (const CTxIn& txin : tx->vin) {
+ if (!txin.scriptSig.empty() || !txin.scriptWitness.IsNull()) {
+ throw std::ios_base::failure("Unsigned tx does not have empty scriptSigs and scriptWitnesses.");
+ }
+ }
+ break;
+ }
+ // Unknown stuff
+ default: {
+ if (unknown.count(key) > 0) {
+ throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
+ }
+ // Read in the value
+ std::vector<unsigned char> val_bytes;
+ s >> val_bytes;
+ unknown.emplace(std::move(key), std::move(val_bytes));
+ }
+ }
+ }
+
+ if (!found_sep) {
+ throw std::ios_base::failure("Separator is missing at the end of the global map");
+ }
+
+ // Make sure that we got an unsigned tx
+ if (!tx) {
+ throw std::ios_base::failure("No unsigned transcation was provided");
+ }
+
+ // Read input data
+ unsigned int i = 0;
+ while (!s.empty() && i < tx->vin.size()) {
+ PSBTInput input;
+ s >> input;
+ inputs.push_back(input);
+
+ // Make sure the non-witness utxo matches the outpoint
+ if (input.non_witness_utxo && input.non_witness_utxo->GetHash() != tx->vin[i].prevout.hash) {
+ throw std::ios_base::failure("Non-witness UTXO does not match outpoint hash");
+ }
+ ++i;
+ }
+ // Make sure that the number of inputs matches the number of inputs in the transaction
+ if (inputs.size() != tx->vin.size()) {
+ throw std::ios_base::failure("Inputs provided does not match the number of inputs in transaction.");
+ }
+
+ // Read output data
+ i = 0;
+ while (!s.empty() && i < tx->vout.size()) {
+ PSBTOutput output;
+ s >> output;
+ outputs.push_back(output);
+ ++i;
+ }
+ // Make sure that the number of outputs matches the number of outputs in the transaction
+ if (outputs.size() != tx->vout.size()) {
+ throw std::ios_base::failure("Outputs provided does not match the number of outputs in transaction.");
+ }
+ // Sanity check
+ if (!IsSane()) {
+ throw std::ios_base::failure("PSBT is not sane.");
+ }
+ }
+
+ template <typename Stream>
+ PartiallySignedTransaction(deserialize_type, Stream& s) {
+ Unserialize(s);
+ }
+};
+
+enum class PSBTRole {
+ UPDATER,
+ SIGNER,
+ FINALIZER,
+ EXTRACTOR
+};
+
+std::string PSBTRoleName(PSBTRole role);
+
+/** Checks whether a PSBTInput is already signed. */
+bool PSBTInputSigned(const PSBTInput& input);
+
+/** Signs a PSBTInput, verifying that all provided data matches what is being signed. */
+bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash = SIGHASH_ALL, SignatureData* out_sigdata = nullptr, bool use_dummy = false);
+
+/**
+ * Finalizes a PSBT if possible, combining partial signatures.
+ *
+ * @param[in,out] &psbtx reference to PartiallySignedTransaction to finalize
+ * return True if the PSBT is now complete, false otherwise
+ */
+bool FinalizePSBT(PartiallySignedTransaction& psbtx);
+
+/**
+ * Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized.
+ *
+ * @param[in] &psbtx reference to PartiallySignedTransaction
+ * @param[out] result CMutableTransaction representing the complete transaction, if successful
+ * @return True if we successfully extracted the transaction, false otherwise
+ */
+bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransaction& result);
+
+/**
+ * Combines PSBTs with the same underlying transaction, resulting in a single PSBT with all partial signatures from each input.
+ *
+ * @param[out] &out the combined PSBT, if successful
+ * @param[in] psbtxs the PSBTs to combine
+ * @return error (OK if we successfully combined the transactions, other error if they were not compatible)
+ */
+NODISCARD TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs);
+
+//! Decode a base64ed PSBT into a PartiallySignedTransaction
+NODISCARD bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error);
+//! Decode a raw (binary blob) PSBT into a PartiallySignedTransaction
+NODISCARD bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, const std::string& raw_psbt, std::string& error);
+
+#endif // BITCOIN_PSBT_H
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index 1eb126434b..d38df716bd 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Copyright (c) 2017 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/pubkey.h b/src/pubkey.h
index 0985273f34..089324ffda 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Copyright (c) 2017 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/README.md b/src/qt/README.md
index 3ec538b4f4..0eb18f7cd5 100644
--- a/src/qt/README.md
+++ b/src/qt/README.md
@@ -64,8 +64,8 @@ Represents the view to a single wallet.
* `callback.h`
* `guiconstants.h`: UI colors, app name, etc
* `guiutil.h`: several helper functions
-* `macdockiconhandler.(h/cpp)`
-* `macdockiconhandler.(h/cpp)`: display notifications in macOS
+* `macdockiconhandler.(h/mm)`: macOS dock icon handler
+* `macnotificationhandler.(h/mm)`: display notifications in macOS
## Contribute
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index d51069d922..50d6afabcd 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -59,7 +59,7 @@ protected:
AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) :
QDialog(parent),
ui(new Ui::AddressBookPage),
- model(0),
+ model(nullptr),
mode(_mode),
tab(_tab)
{
@@ -85,7 +85,7 @@ AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode,
case SendingTab: setWindowTitle(tr("Choose the address to send coins to")); break;
case ReceivingTab: setWindowTitle(tr("Choose the address to receive coins with")); break;
}
- connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
+ connect(ui->tableView, &QTableView::doubleClicked, this, &QDialog::accept);
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableView->setFocus();
ui->closeButton->setText(tr("C&hoose"));
@@ -107,7 +107,7 @@ AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode,
ui->newAddress->setVisible(true);
break;
case ReceivingTab:
- ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction."));
+ ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses."));
ui->deleteAddress->setVisible(false);
ui->newAddress->setVisible(false);
break;
@@ -129,14 +129,14 @@ AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode,
contextMenu->addSeparator();
// Connect signals for context menu actions
- connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyAddress_clicked()));
- connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
- connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
- connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteAddress_clicked()));
+ connect(copyAddressAction, &QAction::triggered, this, &AddressBookPage::on_copyAddress_clicked);
+ connect(copyLabelAction, &QAction::triggered, this, &AddressBookPage::onCopyLabelAction);
+ connect(editAction, &QAction::triggered, this, &AddressBookPage::onEditAction);
+ connect(deleteAction, &QAction::triggered, this, &AddressBookPage::on_deleteAddress_clicked);
- connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
+ connect(ui->tableView, &QWidget::customContextMenuRequested, this, &AddressBookPage::contextualMenu);
- connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(ui->closeButton, &QPushButton::clicked, this, &QDialog::accept);
}
AddressBookPage::~AddressBookPage()
@@ -154,7 +154,7 @@ void AddressBookPage::setModel(AddressTableModel *_model)
proxyModel = new AddressBookSortFilterProxyModel(type, this);
proxyModel->setSourceModel(_model);
- connect(ui->searchLineEdit, SIGNAL(textChanged(QString)), proxyModel, SLOT(setFilterWildcard(QString)));
+ connect(ui->searchLineEdit, &QLineEdit::textChanged, proxyModel, &QSortFilterProxyModel::setFilterWildcard);
ui->tableView->setModel(proxyModel);
ui->tableView->sortByColumn(0, Qt::AscendingOrder);
@@ -163,11 +163,11 @@ void AddressBookPage::setModel(AddressTableModel *_model)
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
- connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
- this, SLOT(selectionChanged()));
+ connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
+ this, &AddressBookPage::selectionChanged);
// Select row for newly created address
- connect(_model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int)));
+ connect(_model, &AddressTableModel::rowsInserted, this, &AddressBookPage::selectNewAddress);
selectionChanged();
}
diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h
index ba420c5e15..6394d26801 100644
--- a/src/qt/addressbookpage.h
+++ b/src/qt/addressbookpage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -38,7 +38,7 @@ public:
ForEditing /**< Open address book for editing */
};
- explicit AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent = 0);
+ explicit AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent = nullptr);
~AddressBookPage();
void setModel(AddressTableModel *model);
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 25b615e6f8..c3143e948a 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -71,7 +71,7 @@ public:
QList<AddressTableEntry> cachedAddressTable;
AddressTableModel *parent;
- AddressTablePriv(AddressTableModel *_parent):
+ explicit AddressTablePriv(AddressTableModel *_parent):
parent(_parent) {}
void refreshAddressTable(interfaces::Wallet& wallet)
@@ -153,7 +153,7 @@ public:
}
else
{
- return 0;
+ return nullptr;
}
}
};
@@ -300,8 +300,8 @@ QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation,
Qt::ItemFlags AddressTableModel::flags(const QModelIndex &index) const
{
- if(!index.isValid())
- return 0;
+ if (!index.isValid()) return Qt::NoItemFlags;
+
AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h
index 6e1b53b049..035f3e0571 100644
--- a/src/qt/addresstablemodel.h
+++ b/src/qt/addresstablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2015 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -25,7 +25,7 @@ class AddressTableModel : public QAbstractTableModel
Q_OBJECT
public:
- explicit AddressTableModel(WalletModel *parent = 0);
+ explicit AddressTableModel(WalletModel *parent = nullptr);
~AddressTableModel();
enum ColumnIndex {
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index 0270af98b7..a89a15bc9d 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -22,7 +22,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) :
QDialog(parent),
ui(new Ui::AskPassphraseDialog),
mode(_mode),
- model(0),
+ model(nullptr),
fCapsLock(false)
{
ui->setupUi(this);
@@ -70,10 +70,10 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) :
break;
}
textChanged();
- connect(ui->toggleShowPasswordButton, SIGNAL(toggled(bool)), this, SLOT(toggleShowPassword(bool)));
- connect(ui->passEdit1, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
- connect(ui->passEdit2, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
- connect(ui->passEdit3, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
+ connect(ui->toggleShowPasswordButton, &QPushButton::toggled, this, &AskPassphraseDialog::toggleShowPassword);
+ connect(ui->passEdit1, &QLineEdit::textChanged, this, &AskPassphraseDialog::textChanged);
+ connect(ui->passEdit2, &QLineEdit::textChanged, this, &AskPassphraseDialog::textChanged);
+ connect(ui->passEdit3, &QLineEdit::textChanged, this, &AskPassphraseDialog::textChanged);
}
AskPassphraseDialog::~AskPassphraseDialog()
@@ -123,16 +123,15 @@ void AskPassphraseDialog::accept()
{
QMessageBox::warning(this, tr("Wallet encrypted"),
"<qt>" +
- tr("%1 will close now to finish the encryption process. "
+ tr("Your wallet is now encrypted. "
"Remember that encrypting your wallet cannot fully protect "
- "your bitcoins from being stolen by malware infecting your computer.").arg(tr(PACKAGE_NAME)) +
+ "your bitcoins from being stolen by malware infecting your computer.") +
"<br><br><b>" +
tr("IMPORTANT: Any previous backups you have made of your wallet file "
"should be replaced with the newly generated, encrypted wallet file. "
"For security reasons, previous backups of the unencrypted wallet file "
"will become useless as soon as you start using the new, encrypted wallet.") +
"</b></qt>");
- QApplication::quit();
}
else
{
@@ -153,14 +152,15 @@ void AskPassphraseDialog::accept()
}
} break;
case Unlock:
- if(!model->setWalletLocked(false, oldpass))
- {
- QMessageBox::critical(this, tr("Wallet unlock failed"),
- tr("The passphrase entered for the wallet decryption was incorrect."));
- }
- else
- {
- QDialog::accept(); // Success
+ try {
+ if (!model->setWalletLocked(false, oldpass)) {
+ QMessageBox::critical(this, tr("Wallet unlock failed"),
+ tr("The passphrase entered for the wallet decryption was incorrect."));
+ } else {
+ QDialog::accept(); // Success
+ }
+ } catch (const std::runtime_error& e) {
+ QMessageBox::critical(this, tr("Wallet unlock failed"), e.what());
}
break;
case Decrypt:
diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h
index 7ec8bf0a15..ac31569f63 100644
--- a/src/qt/askpassphrasedialog.h
+++ b/src/qt/askpassphrasedialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index aa0d4a31d3..00c446cc63 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
#include <interfaces/node.h>
#include <sync.h>
-#include <utiltime.h>
+#include <util/time.h>
#include <QDebug>
#include <QList>
@@ -40,8 +40,8 @@ class BanTablePriv
public:
/** Local cache of peer information */
QList<CCombinedBan> cachedBanlist;
- /** Column to sort nodes by */
- int sortColumn;
+ /** Column to sort nodes by (default to unsorted) */
+ int sortColumn{-1};
/** Order (ascending or descending) to sort nodes by */
Qt::SortOrder sortOrder;
@@ -76,7 +76,7 @@ public:
if (idx >= 0 && idx < cachedBanlist.size())
return &cachedBanlist[idx];
- return 0;
+ return nullptr;
}
};
@@ -87,8 +87,6 @@ BanTableModel::BanTableModel(interfaces::Node& node, ClientModel *parent) :
{
columns << tr("IP/Netmask") << tr("Banned Until");
priv.reset(new BanTablePriv());
- // default to unsorted
- priv->sortColumn = -1;
// load initial data
refresh();
@@ -147,8 +145,7 @@ QVariant BanTableModel::headerData(int section, Qt::Orientation orientation, int
Qt::ItemFlags BanTableModel::flags(const QModelIndex &index) const
{
- if(!index.isValid())
- return 0;
+ if (!index.isValid()) return Qt::NoItemFlags;
Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return retval;
diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h
index d6c8dbf6dd..9dec5fa6a9 100644
--- a/src/qt/bantablemodel.h
+++ b/src/qt/bantablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -45,7 +45,7 @@ class BanTableModel : public QAbstractTableModel
Q_OBJECT
public:
- explicit BanTableModel(interfaces::Node& node, ClientModel *parent = 0);
+ explicit BanTableModel(interfaces::Node& node, ClientModel *parent = nullptr);
~BanTableModel();
void startAutoRefresh();
void stopAutoRefresh();
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 5d0e384cf8..81255aaae9 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,6 +6,7 @@
#include <config/bitcoin-config.h>
#endif
+#include <qt/bitcoin.h>
#include <qt/bitcoingui.h>
#include <chainparams.h>
@@ -23,15 +24,17 @@
#ifdef ENABLE_WALLET
#include <qt/paymentserver.h>
-#include <qt/walletmodel.h>
+#include <qt/walletcontroller.h>
#endif
#include <interfaces/handler.h>
#include <interfaces/node.h>
+#include <noui.h>
+#include <util/threadnames.h>
#include <rpc/server.h>
#include <ui_interface.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
#include <warnings.h>
#include <walletinitinterface.h>
@@ -50,13 +53,9 @@
#include <QThread>
#include <QTimer>
#include <QTranslator>
-#include <QSslConfiguration>
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
-#if QT_VERSION < 0x050400
-Q_IMPORT_PLUGIN(AccessibleFactory)
-#endif
#if defined(QT_QPA_PLATFORM_XCB)
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
#elif defined(QT_QPA_PLATFORM_WINDOWS)
@@ -71,19 +70,6 @@ Q_DECLARE_METATYPE(bool*)
Q_DECLARE_METATYPE(CAmount)
Q_DECLARE_METATYPE(uint256)
-static void InitMessage(const std::string &message)
-{
- LogPrintf("init message: %s\n", message);
-}
-
-/*
- Translate string to current locale using Qt.
- */
-static std::string Translate(const char* psz)
-{
- return QCoreApplication::translate("bitcoin-core", psz).toStdString();
-}
-
static QString GetLangTerritory()
{
QSettings settings;
@@ -148,101 +134,6 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
}
}
-/** Class encapsulating Bitcoin Core startup and shutdown.
- * Allows running startup and shutdown in a different thread from the UI thread.
- */
-class BitcoinCore: public QObject
-{
- Q_OBJECT
-public:
- explicit BitcoinCore(interfaces::Node& node);
-
-public Q_SLOTS:
- void initialize();
- void shutdown();
-
-Q_SIGNALS:
- void initializeResult(bool success);
- void shutdownResult();
- void runawayException(const QString &message);
-
-private:
- /// Pass fatal exception message to UI thread
- void handleRunawayException(const std::exception *e);
-
- interfaces::Node& m_node;
-};
-
-/** Main Bitcoin application object */
-class BitcoinApplication: public QApplication
-{
- Q_OBJECT
-public:
- explicit BitcoinApplication(interfaces::Node& node, int &argc, char **argv);
- ~BitcoinApplication();
-
-#ifdef ENABLE_WALLET
- /// Create payment server
- void createPaymentServer();
-#endif
- /// parameter interaction/setup based on rules
- void parameterSetup();
- /// Create options model
- void createOptionsModel(bool resetSettings);
- /// Create main window
- void createWindow(const NetworkStyle *networkStyle);
- /// Create splash screen
- void createSplashScreen(const NetworkStyle *networkStyle);
-
- /// Request core initialization
- void requestInitialize();
- /// Request core shutdown
- void requestShutdown();
-
- /// Get process return value
- int getReturnValue() const { return returnValue; }
-
- /// Get window identifier of QMainWindow (BitcoinGUI)
- WId getMainWinId() const;
-
- /// Setup platform style
- void setupPlatformStyle();
-
-public Q_SLOTS:
- void initializeResult(bool success);
- void shutdownResult();
- /// Handle runaway exceptions. Shows a message box with the problem and quits the program.
- void handleRunawayException(const QString &message);
- void addWallet(WalletModel* walletModel);
- void removeWallet();
-
-Q_SIGNALS:
- void requestedInitialize();
- void requestedShutdown();
- void stopThread();
- void splashFinished(QWidget *window);
-
-private:
- QThread *coreThread;
- interfaces::Node& m_node;
- OptionsModel *optionsModel;
- ClientModel *clientModel;
- BitcoinGUI *window;
- QTimer *pollShutdownTimer;
-#ifdef ENABLE_WALLET
- PaymentServer* paymentServer;
- std::vector<WalletModel*> m_wallet_models;
- std::unique_ptr<interfaces::Handler> m_handler_load_wallet;
-#endif
- int returnValue;
- const PlatformStyle *platformStyle;
- std::unique_ptr<QWidget> shutdownWindow;
-
- void startThread();
-};
-
-#include <qt/bitcoin.moc>
-
BitcoinCore::BitcoinCore(interfaces::Node& node) :
QObject(), m_node(node)
{
@@ -259,6 +150,7 @@ void BitcoinCore::initialize()
try
{
qDebug() << __func__ << ": Running initialization in thread";
+ util::ThreadRename("qt-init");
bool rv = m_node.appInitMain();
Q_EMIT initializeResult(rv);
} catch (const std::exception& e) {
@@ -285,18 +177,14 @@ void BitcoinCore::shutdown()
BitcoinApplication::BitcoinApplication(interfaces::Node& node, int &argc, char **argv):
QApplication(argc, argv),
- coreThread(0),
+ coreThread(nullptr),
m_node(node),
- optionsModel(0),
- clientModel(0),
- window(0),
- pollShutdownTimer(0),
-#ifdef ENABLE_WALLET
- paymentServer(0),
- m_wallet_models(),
-#endif
+ optionsModel(nullptr),
+ clientModel(nullptr),
+ window(nullptr),
+ pollShutdownTimer(nullptr),
returnValue(0),
- platformStyle(0)
+ platformStyle(nullptr)
{
setQuitOnLastWindowClosed(false);
}
@@ -319,21 +207,23 @@ BitcoinApplication::~BitcoinApplication()
if(coreThread)
{
qDebug() << __func__ << ": Stopping thread";
- Q_EMIT stopThread();
+ coreThread->quit();
coreThread->wait();
qDebug() << __func__ << ": Stopped thread";
}
delete window;
- window = 0;
+ window = nullptr;
#ifdef ENABLE_WALLET
delete paymentServer;
- paymentServer = 0;
+ paymentServer = nullptr;
+ delete m_wallet_controller;
+ m_wallet_controller = nullptr;
#endif
delete optionsModel;
- optionsModel = 0;
+ optionsModel = nullptr;
delete platformStyle;
- platformStyle = 0;
+ platformStyle = nullptr;
}
#ifdef ENABLE_WALLET
@@ -350,20 +240,25 @@ void BitcoinApplication::createOptionsModel(bool resetSettings)
void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
{
- window = new BitcoinGUI(m_node, platformStyle, networkStyle, 0);
+ window = new BitcoinGUI(m_node, platformStyle, networkStyle, nullptr);
pollShutdownTimer = new QTimer(window);
- connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown()));
+ connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown);
}
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
{
- SplashScreen *splash = new SplashScreen(m_node, 0, networkStyle);
+ SplashScreen *splash = new SplashScreen(m_node, nullptr, 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 slotFinish happens.
+ // screen will take care of deleting itself when finish() happens.
splash->show();
- connect(this, SIGNAL(splashFinished(QWidget*)), splash, SLOT(slotFinish(QWidget*)));
- connect(this, SIGNAL(requestedShutdown()), splash, SLOT(close()));
+ connect(this, &BitcoinApplication::splashFinished, splash, &SplashScreen::finish);
+ connect(this, &BitcoinApplication::requestedShutdown, splash, &QWidget::close);
+}
+
+bool BitcoinApplication::baseInitialize()
+{
+ return m_node.baseInitialize();
}
void BitcoinApplication::startThread()
@@ -375,14 +270,13 @@ void BitcoinApplication::startThread()
executor->moveToThread(coreThread);
/* communication to and from thread */
- connect(executor, SIGNAL(initializeResult(bool)), this, SLOT(initializeResult(bool)));
- connect(executor, SIGNAL(shutdownResult()), this, SLOT(shutdownResult()));
- connect(executor, SIGNAL(runawayException(QString)), this, SLOT(handleRunawayException(QString)));
- connect(this, SIGNAL(requestedInitialize()), executor, SLOT(initialize()));
- connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown()));
+ connect(executor, &BitcoinCore::initializeResult, this, &BitcoinApplication::initializeResult);
+ connect(executor, &BitcoinCore::shutdownResult, this, &BitcoinApplication::shutdownResult);
+ connect(executor, &BitcoinCore::runawayException, this, &BitcoinApplication::handleRunawayException);
+ connect(this, &BitcoinApplication::requestedInitialize, executor, &BitcoinCore::initialize);
+ connect(this, &BitcoinApplication::requestedShutdown, executor, &BitcoinCore::shutdown);
/* make sure executor object is deleted in its own thread */
- connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
- connect(this, SIGNAL(stopThread()), coreThread, SLOT(quit()));
+ connect(coreThread, &QThread::finished, executor, &QObject::deleteLater);
coreThread->start();
}
@@ -414,52 +308,24 @@ void BitcoinApplication::requestShutdown()
qDebug() << __func__ << ": Requesting shutdown";
startThread();
window->hide();
- window->setClientModel(0);
+ // Must disconnect node signals otherwise current thread can deadlock since
+ // no event loop is running.
+ window->unsubscribeFromCoreSignals();
+ // Request node shutdown, which can interrupt long operations, like
+ // rescanning a wallet.
+ m_node.startShutdown();
+ // Unsetting the client model can cause the current thread to wait for node
+ // to complete an operation, like wait for a RPC execution to complate.
+ window->setClientModel(nullptr);
pollShutdownTimer->stop();
-#ifdef ENABLE_WALLET
- window->removeAllWallets();
- for (WalletModel *walletModel : m_wallet_models) {
- delete walletModel;
- }
- m_wallet_models.clear();
-#endif
delete clientModel;
- clientModel = 0;
-
- m_node.startShutdown();
+ clientModel = nullptr;
// Request shutdown from core thread
Q_EMIT requestedShutdown();
}
-void BitcoinApplication::addWallet(WalletModel* walletModel)
-{
-#ifdef ENABLE_WALLET
- window->addWallet(walletModel);
-
- if (m_wallet_models.empty()) {
- window->setCurrentWallet(walletModel->getWalletName());
- }
-
- connect(walletModel, SIGNAL(coinsSent(WalletModel*, SendCoinsRecipient, QByteArray)),
- paymentServer, SLOT(fetchPaymentACK(WalletModel*, const SendCoinsRecipient&, QByteArray)));
- connect(walletModel, SIGNAL(unload()), this, SLOT(removeWallet()));
-
- m_wallet_models.push_back(walletModel);
-#endif
-}
-
-void BitcoinApplication::removeWallet()
-{
-#ifdef ENABLE_WALLET
- WalletModel* walletModel = static_cast<WalletModel*>(sender());
- m_wallet_models.erase(std::find(m_wallet_models.begin(), m_wallet_models.end(), walletModel));
- window->removeWallet(walletModel);
- walletModel->deleteLater();
-#endif
-}
-
void BitcoinApplication::initializeResult(bool success)
{
qDebug() << __func__ << ": Initialization result: " << success;
@@ -470,51 +336,50 @@ void BitcoinApplication::initializeResult(bool success)
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
qWarning() << "Platform customization:" << platformStyle->getName();
#ifdef ENABLE_WALLET
+ m_wallet_controller = new WalletController(m_node, platformStyle, optionsModel, this);
+#ifdef ENABLE_BIP70
PaymentServer::LoadRootCAs();
- paymentServer->setOptionsModel(optionsModel);
+#endif
+ if (paymentServer) {
+ paymentServer->setOptionsModel(optionsModel);
+#ifdef ENABLE_BIP70
+ connect(m_wallet_controller, &WalletController::coinsSent, paymentServer, &PaymentServer::fetchPaymentACK);
+#endif
+ }
#endif
clientModel = new ClientModel(m_node, optionsModel);
window->setClientModel(clientModel);
-
#ifdef ENABLE_WALLET
- m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
- WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel, nullptr);
- // Fix wallet model thread affinity.
- wallet_model->moveToThread(thread());
- QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model));
- });
-
- for (auto& wallet : m_node.getWallets()) {
- addWallet(new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel));
- }
+ window->setWalletController(m_wallet_controller);
#endif
- // If -min option passed, start window minimized.
- if(gArgs.GetBoolArg("-min", false))
- {
- window->showMinimized();
- }
- else
- {
+ // If -min option passed, start window minimized (iconified) or minimized to tray
+ if (!gArgs.GetBoolArg("-min", false)) {
window->show();
+ } else if (clientModel->getOptionsModel()->getMinimizeToTray() && window->hasTrayIcon()) {
+ // do nothing as the window is managed by the tray icon
+ } else {
+ window->showMinimized();
}
- Q_EMIT splashFinished(window);
+ Q_EMIT splashFinished();
+ Q_EMIT windowShown(window);
#ifdef ENABLE_WALLET
// Now that initialization/startup is done, process any command-line
// bitcoin: URIs or payment requests:
- connect(paymentServer, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
- window, SLOT(handlePaymentRequest(SendCoinsRecipient)));
- connect(window, SIGNAL(receivedURI(QString)),
- paymentServer, SLOT(handleURIOrFile(QString)));
- connect(paymentServer, SIGNAL(message(QString,QString,unsigned int)),
- window, SLOT(message(QString,QString,unsigned int)));
- QTimer::singleShot(100, paymentServer, SLOT(uiReady()));
+ if (paymentServer) {
+ connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest);
+ connect(window, &BitcoinGUI::receivedURI, paymentServer, &PaymentServer::handleURIOrFile);
+ connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) {
+ window->message(title, message, style);
+ });
+ QTimer::singleShot(100, paymentServer, &PaymentServer::uiReady);
+ }
#endif
pollShutdownTimer->start(200);
} else {
- Q_EMIT splashFinished(window); // Make sure splash screen doesn't stick around during shutdown
+ Q_EMIT splashFinished(); // Make sure splash screen doesn't stick around during shutdown
quit(); // Exit first main loop invocation
}
}
@@ -526,7 +391,7 @@ void BitcoinApplication::shutdownResult()
void BitcoinApplication::handleRunawayException(const QString &message)
{
- QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + message);
+ QMessageBox::critical(nullptr, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + message);
::exit(EXIT_FAILURE);
}
@@ -540,7 +405,7 @@ WId BitcoinApplication::getMainWinId() const
static void SetupUIArgs()
{
-#ifdef ENABLE_WALLET
+#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
gArgs.AddArg("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS), true, OptionsCategory::GUI);
#endif
gArgs.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), false, OptionsCategory::GUI);
@@ -553,12 +418,22 @@ static void SetupUIArgs()
}
#ifndef BITCOIN_QT_TEST
-int main(int argc, char *argv[])
+int GuiMain(int argc, char* argv[])
{
+#ifdef WIN32
+ util::WinCmdLineArgs winArgs;
+ std::tie(argc, argv) = winArgs.get();
+#endif
SetupEnvironment();
+ util::ThreadRename("main");
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode();
+ // Subscribe to global signals from core
+ std::unique_ptr<interfaces::Handler> handler_message_box = node->handleMessageBox(noui_ThreadSafeMessageBox);
+ std::unique_ptr<interfaces::Handler> handler_question = node->handleQuestion(noui_ThreadSafeQuestion);
+ std::unique_ptr<interfaces::Handler> handler_init_message = node->handleInitMessage(noui_InitMessage);
+
// Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
/// 1. Basic Qt initialization (not dependent on parameters or configuration)
@@ -566,41 +441,29 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(bitcoin_locale);
BitcoinApplication app(*node, argc, argv);
-#if QT_VERSION > 0x050100
// Generate high-dpi pixmaps
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
-#endif
#if QT_VERSION >= 0x050600
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
#ifdef Q_OS_MAC
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
#endif
-#if QT_VERSION >= 0x050500
- // Because of the POODLE attack it is recommended to disable SSLv3 (https://disablessl3.com/),
- // so set SSL protocols to TLS1.0+.
- QSslConfiguration sslconf = QSslConfiguration::defaultConfiguration();
- sslconf.setProtocol(QSsl::TlsV1_0OrLater);
- QSslConfiguration::setDefaultConfiguration(sslconf);
-#endif
// Register meta types used for QMetaObject::invokeMethod
qRegisterMetaType< bool* >();
// Need to pass name here as CAmount is a typedef (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType)
// IMPORTANT if it is no longer a typedef use the normal variant above
qRegisterMetaType< CAmount >("CAmount");
- qRegisterMetaType< std::function<void(void)> >("std::function<void(void)>");
-#ifdef ENABLE_WALLET
- qRegisterMetaType<WalletModel*>("WalletModel*");
-#endif
-
+ qRegisterMetaType< std::function<void()> >("std::function<void()>");
+ qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
// Command-line options take precedence:
node->setupServerArgs();
SetupUIArgs();
std::string error;
if (!node->parseParameters(argc, argv, error)) {
- QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
+ QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME),
QObject::tr("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
return EXIT_FAILURE;
}
@@ -619,7 +482,6 @@ int main(int argc, char *argv[])
// Now that QSettings are accessible, initialize translations
QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
- translationInterface.Translate.connect(Translate);
// Show help message immediately after parsing command-line options (for "-lang") and setting locale,
// but before showing splash screen.
@@ -638,12 +500,12 @@ int main(int argc, char *argv[])
/// - Do not call GetDataDir(true) before this step finishes
if (!fs::is_directory(GetDataDir(false)))
{
- QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
- QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", ""))));
+ QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME),
+ QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", ""))));
return EXIT_FAILURE;
}
if (!node->readConfigFiles(error)) {
- QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
+ QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME),
QObject::tr("Error: Cannot parse configuration file: %1.").arg(QString::fromStdString(error)));
return EXIT_FAILURE;
}
@@ -658,7 +520,7 @@ int main(int argc, char *argv[])
try {
node->selectParams(gArgs.GetChainName());
} catch(std::exception &e) {
- QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QObject::tr("Error: %1").arg(e.what()));
+ QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME), QObject::tr("Error: %1").arg(e.what()));
return EXIT_FAILURE;
}
#ifdef ENABLE_WALLET
@@ -702,9 +564,6 @@ int main(int argc, char *argv[])
// Load GUI settings from QSettings
app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
- // Subscribe to global signals from core
- std::unique_ptr<interfaces::Handler> handler = node->handleInitMessage(InitMessage);
-
if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false))
app.createSplashScreen(networkStyle.data());
@@ -715,7 +574,7 @@ int main(int argc, char *argv[])
// Perform base initialization before spinning up initialization/shutdown thread
// This is acceptable because this function only contains steps that are quick to execute,
// so the GUI thread won't be held up.
- if (node->baseInitialize()) {
+ if (app.baseInitialize()) {
app.requestInitialize();
#if defined(Q_OS_WIN)
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId());
diff --git a/src/qt/bitcoin.h b/src/qt/bitcoin.h
new file mode 100644
index 0000000000..370712d953
--- /dev/null
+++ b/src/qt/bitcoin.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2011-2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_QT_BITCOIN_H
+#define BITCOIN_QT_BITCOIN_H
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#include <QApplication>
+#include <memory>
+#include <vector>
+
+class BitcoinGUI;
+class ClientModel;
+class NetworkStyle;
+class OptionsModel;
+class PaymentServer;
+class PlatformStyle;
+class WalletController;
+class WalletModel;
+
+namespace interfaces {
+class Handler;
+class Node;
+} // namespace interfaces
+
+/** Class encapsulating Bitcoin Core startup and shutdown.
+ * Allows running startup and shutdown in a different thread from the UI thread.
+ */
+class BitcoinCore: public QObject
+{
+ Q_OBJECT
+public:
+ explicit BitcoinCore(interfaces::Node& node);
+
+public Q_SLOTS:
+ void initialize();
+ void shutdown();
+
+Q_SIGNALS:
+ void initializeResult(bool success);
+ void shutdownResult();
+ void runawayException(const QString &message);
+
+private:
+ /// Pass fatal exception message to UI thread
+ void handleRunawayException(const std::exception *e);
+
+ interfaces::Node& m_node;
+};
+
+/** Main Bitcoin application object */
+class BitcoinApplication: public QApplication
+{
+ Q_OBJECT
+public:
+ explicit BitcoinApplication(interfaces::Node& node, int &argc, char **argv);
+ ~BitcoinApplication();
+
+#ifdef ENABLE_WALLET
+ /// Create payment server
+ void createPaymentServer();
+#endif
+ /// parameter interaction/setup based on rules
+ void parameterSetup();
+ /// Create options model
+ void createOptionsModel(bool resetSettings);
+ /// Create main window
+ void createWindow(const NetworkStyle *networkStyle);
+ /// Create splash screen
+ void createSplashScreen(const NetworkStyle *networkStyle);
+ /// Basic initialization, before starting initialization/shutdown thread. Return true on success.
+ bool baseInitialize();
+
+ /// Request core initialization
+ void requestInitialize();
+ /// Request core shutdown
+ void requestShutdown();
+
+ /// Get process return value
+ int getReturnValue() const { return returnValue; }
+
+ /// Get window identifier of QMainWindow (BitcoinGUI)
+ WId getMainWinId() const;
+
+ /// Setup platform style
+ void setupPlatformStyle();
+
+public Q_SLOTS:
+ void initializeResult(bool success);
+ void shutdownResult();
+ /// Handle runaway exceptions. Shows a message box with the problem and quits the program.
+ void handleRunawayException(const QString &message);
+
+Q_SIGNALS:
+ void requestedInitialize();
+ void requestedShutdown();
+ void splashFinished();
+ void windowShown(BitcoinGUI* window);
+
+private:
+ QThread *coreThread;
+ interfaces::Node& m_node;
+ OptionsModel *optionsModel;
+ ClientModel *clientModel;
+ BitcoinGUI *window;
+ QTimer *pollShutdownTimer;
+#ifdef ENABLE_WALLET
+ PaymentServer* paymentServer{nullptr};
+ WalletController* m_wallet_controller{nullptr};
+#endif
+ int returnValue;
+ const PlatformStyle *platformStyle;
+ std::unique_ptr<QWidget> shutdownWindow;
+
+ void startThread();
+};
+
+int GuiMain(int argc, char* argv[]);
+
+#endif // BITCOIN_QT_BITCOIN_H
diff --git a/src/qt/bitcoinaddressvalidator.cpp b/src/qt/bitcoinaddressvalidator.cpp
index 6a76358a78..a2adca6eac 100644
--- a/src/qt/bitcoinaddressvalidator.cpp
+++ b/src/qt/bitcoinaddressvalidator.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index 68a9dc4c27..5854ade655 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -23,13 +23,11 @@ class AmountSpinBox: public QAbstractSpinBox
public:
explicit AmountSpinBox(QWidget *parent):
- QAbstractSpinBox(parent),
- currentUnit(BitcoinUnits::BTC),
- singleStep(100000) // satoshis
+ QAbstractSpinBox(parent)
{
setAlignment(Qt::AlignRight);
- connect(lineEdit(), SIGNAL(textEdited(QString)), this, SIGNAL(valueChanged()));
+ connect(lineEdit(), &QLineEdit::textEdited, this, &AmountSpinBox::valueChanged);
}
QValidator::State validate(QString &text, int &pos) const
@@ -44,16 +42,25 @@ public:
void fixup(QString &input) const
{
- bool valid = false;
- CAmount val = parse(input, &valid);
- if(valid)
- {
+ bool valid;
+ CAmount val;
+
+ if (input.isEmpty() && !m_allow_empty) {
+ valid = true;
+ val = m_min_amount;
+ } else {
+ valid = false;
+ val = parse(input, &valid);
+ }
+
+ if (valid) {
+ val = qBound(m_min_amount, val, m_max_amount);
input = BitcoinUnits::format(currentUnit, val, false, BitcoinUnits::separatorAlways);
lineEdit()->setText(input);
}
}
- CAmount value(bool *valid_out=0) const
+ CAmount value(bool *valid_out=nullptr) const
{
return parse(text(), valid_out);
}
@@ -64,12 +71,27 @@ public:
Q_EMIT valueChanged();
}
+ void SetAllowEmpty(bool allow)
+ {
+ m_allow_empty = allow;
+ }
+
+ void SetMinValue(const CAmount& value)
+ {
+ m_min_amount = value;
+ }
+
+ void SetMaxValue(const CAmount& value)
+ {
+ m_max_amount = value;
+ }
+
void stepBy(int steps)
{
bool valid = false;
CAmount val = value(&valid);
val = val + steps * singleStep;
- val = qMin(qMax(val, CAmount(0)), BitcoinUnits::maxMoney());
+ val = qBound(m_min_amount, val, m_max_amount);
setValue(val);
}
@@ -125,16 +147,19 @@ public:
}
private:
- int currentUnit;
- CAmount singleStep;
+ int currentUnit{BitcoinUnits::BTC};
+ CAmount singleStep{CAmount(100000)}; // satoshis
mutable QSize cachedMinimumSizeHint;
+ bool m_allow_empty{true};
+ CAmount m_min_amount{CAmount(0)};
+ CAmount m_max_amount{BitcoinUnits::maxMoney()};
/**
* Parse a string into a number of base monetary units and
* return validity.
* @note Must return 0 if !valid.
*/
- CAmount parse(const QString &text, bool *valid_out=0) const
+ CAmount parse(const QString &text, bool *valid_out=nullptr) const
{
CAmount val = 0;
bool valid = BitcoinUnits::parse(currentUnit, text, &val);
@@ -171,14 +196,13 @@ protected:
if (text().isEmpty()) // Allow step-up with empty field
return StepUpEnabled;
- StepEnabled rv = 0;
+ StepEnabled rv = StepNone;
bool valid = false;
CAmount val = value(&valid);
- if(valid)
- {
- if(val > 0)
+ if (valid) {
+ if (val > m_min_amount)
rv |= StepDownEnabled;
- if(val < BitcoinUnits::maxMoney())
+ if (val < m_max_amount)
rv |= StepUpEnabled;
}
return rv;
@@ -192,7 +216,7 @@ Q_SIGNALS:
BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
QWidget(parent),
- amount(0)
+ amount(nullptr)
{
amount = new AmountSpinBox(this);
amount->setLocale(QLocale::c());
@@ -213,8 +237,8 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
setFocusProxy(amount);
// If one if the widgets changes, the combined content changes as well
- connect(amount, SIGNAL(valueChanged()), this, SIGNAL(valueChanged()));
- connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));
+ connect(amount, &AmountSpinBox::valueChanged, this, &BitcoinAmountField::valueChanged);
+ connect(unit, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &BitcoinAmountField::unitChanged);
// Set default based on configuration
unitChanged(unit->currentIndex());
@@ -275,6 +299,21 @@ void BitcoinAmountField::setValue(const CAmount& value)
amount->setValue(value);
}
+void BitcoinAmountField::SetAllowEmpty(bool allow)
+{
+ amount->SetAllowEmpty(allow);
+}
+
+void BitcoinAmountField::SetMinValue(const CAmount& value)
+{
+ amount->SetMinValue(value);
+}
+
+void BitcoinAmountField::SetMaxValue(const CAmount& value)
+{
+ amount->SetMaxValue(value);
+}
+
void BitcoinAmountField::setReadOnly(bool fReadOnly)
{
amount->setReadOnly(fReadOnly);
diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h
index 8e2cceeb5e..2db6b65f2c 100644
--- a/src/qt/bitcoinamountfield.h
+++ b/src/qt/bitcoinamountfield.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -26,11 +26,20 @@ class BitcoinAmountField: public QWidget
Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY valueChanged USER true)
public:
- explicit BitcoinAmountField(QWidget *parent = 0);
+ explicit BitcoinAmountField(QWidget *parent = nullptr);
- CAmount value(bool *value=0) const;
+ CAmount value(bool *value=nullptr) const;
void setValue(const CAmount& value);
+ /** If allow empty is set to false the field will be set to the minimum allowed value if left empty. **/
+ void SetAllowEmpty(bool allow);
+
+ /** Set the minimum value in satoshis **/
+ void SetMinValue(const CAmount& value);
+
+ /** Set the maximum value in satoshis **/
+ void SetMaxValue(const CAmount& value);
+
/** Set single step in satoshis **/
void setSingleStep(const CAmount& step);
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index c8f8b9c7d3..ff66df376b 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,6 +19,7 @@
#include <qt/utilitydialog.h>
#ifdef ENABLE_WALLET
+#include <qt/walletcontroller.h>
#include <qt/walletframe.h>
#include <qt/walletmodel.h>
#include <qt/walletview.h>
@@ -28,13 +29,15 @@
#include <qt/macdockiconhandler.h>
#endif
+#include <chain.h>
#include <chainparams.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <iostream>
+#include <memory>
#include <QAction>
#include <QApplication>
@@ -43,6 +46,7 @@
#include <QDesktopWidget>
#include <QDragEnterEvent>
#include <QListWidget>
+#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QMimeData>
@@ -52,10 +56,13 @@
#include <QStackedWidget>
#include <QStatusBar>
#include <QStyle>
+#include <QSystemTrayIcon>
#include <QTimer>
#include <QToolBar>
#include <QUrlQuery>
#include <QVBoxLayout>
+#include <QWindow>
+
const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
#if defined(Q_OS_MAC)
@@ -70,7 +77,9 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
m_node(node),
- platformStyle(_platformStyle)
+ trayIconMenu{new QMenu()},
+ platformStyle(_platformStyle),
+ m_network_style(networkStyle)
{
QSettings settings;
if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
@@ -78,26 +87,14 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
}
- QString windowTitle = tr(PACKAGE_NAME) + " - ";
#ifdef ENABLE_WALLET
enableWallet = WalletModel::isWalletEnabled();
#endif // ENABLE_WALLET
- if(enableWallet)
- {
- windowTitle += tr("Wallet");
- } else {
- windowTitle += tr("Node");
- }
- windowTitle += " " + networkStyle->getTitleAddText();
-#ifndef Q_OS_MAC
- QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon());
- setWindowIcon(networkStyle->getTrayAndWindowIcon());
-#else
- MacDockIconHandler::instance()->setIcon(networkStyle->getAppIcon());
-#endif
- setWindowTitle(windowTitle);
+ QApplication::setWindowIcon(m_network_style->getTrayAndWindowIcon());
+ setWindowIcon(m_network_style->getTrayAndWindowIcon());
+ updateWindowTitle();
- rpcConsole = new RPCConsole(node, _platformStyle, 0);
+ rpcConsole = new RPCConsole(node, _platformStyle, nullptr);
helpMessageDialog = new HelpMessageDialog(node, this, false);
#ifdef ENABLE_WALLET
if(enableWallet)
@@ -112,6 +109,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
* the central widget is the rpc console.
*/
setCentralWidget(rpcConsole);
+ Q_EMIT consoleShown(rpcConsole);
}
// Accept D&D of URIs
@@ -128,7 +126,10 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
createToolBars();
// Create system tray icon and notification
- createTrayIcon(networkStyle);
+ if (QSystemTrayIcon::isSystemTrayAvailable()) {
+ createTrayIcon();
+ }
+ notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
// Create status bar
statusBar();
@@ -146,7 +147,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle);
labelWalletEncryptionIcon = new QLabel();
labelWalletHDStatusIcon = new QLabel();
- labelProxyIcon = new QLabel();
+ labelProxyIcon = new GUIUtil::ClickableLabel();
connectionsControl = new GUIUtil::ClickableLabel();
labelBlocksIcon = new GUIUtil::ClickableLabel();
if(enableWallet)
@@ -193,16 +194,25 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
// Subscribe to notifications from core
subscribeToCoreSignals();
- connect(connectionsControl, SIGNAL(clicked(QPoint)), this, SLOT(toggleNetworkActive()));
+ connect(connectionsControl, &GUIUtil::ClickableLabel::clicked, [this] {
+ m_node.setNetworkActive(!m_node.getNetworkActive());
+ });
+ connect(labelProxyIcon, &GUIUtil::ClickableLabel::clicked, [this] {
+ openOptionsDialogWithTab(OptionsDialog::TAB_NETWORK);
+ });
modalOverlay = new ModalOverlay(this->centralWidget());
#ifdef ENABLE_WALLET
if(enableWallet) {
- connect(walletFrame, SIGNAL(requestedSyncWarningInfo()), this, SLOT(showModalOverlay()));
- connect(labelBlocksIcon, SIGNAL(clicked(QPoint)), this, SLOT(showModalOverlay()));
- connect(progressBar, SIGNAL(clicked(QPoint)), this, SLOT(showModalOverlay()));
+ connect(walletFrame, &WalletFrame::requestedSyncWarningInfo, this, &BitcoinGUI::showModalOverlay);
+ connect(labelBlocksIcon, &GUIUtil::ClickableLabel::clicked, this, &BitcoinGUI::showModalOverlay);
+ connect(progressBar, &GUIUtil::ClickableProgressBar::clicked, this, &BitcoinGUI::showModalOverlay);
}
#endif
+
+#ifdef Q_OS_MAC
+ m_app_nap_inhibitor = new CAppNapInhibitor;
+#endif
}
BitcoinGUI::~BitcoinGUI()
@@ -215,6 +225,7 @@ BitcoinGUI::~BitcoinGUI()
if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
trayIcon->hide();
#ifdef Q_OS_MAC
+ delete m_app_nap_inhibitor;
delete appMenuBar;
MacDockIconHandler::cleanup();
#endif
@@ -265,18 +276,18 @@ void BitcoinGUI::createActions()
#ifdef ENABLE_WALLET
// These showNormalIfMinimized are needed because Send Coins and Receive Coins
// can be triggered from the tray menu, and need to show the GUI to be useful.
- connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
- connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
- connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
- connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
- connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
- connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
+ connect(overviewAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(overviewAction, &QAction::triggered, this, &BitcoinGUI::gotoOverviewPage);
+ connect(sendCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(sendCoinsAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
+ connect(sendCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(sendCoinsMenuAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
+ connect(receiveCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
+ connect(receiveCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(receiveCoinsMenuAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
+ connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage);
#endif // ENABLE_WALLET
quitAction = new QAction(platformStyle->TextColorIcon(":/icons/quit"), tr("E&xit"), this);
@@ -313,45 +324,104 @@ void BitcoinGUI::createActions()
openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console"));
// initially disable the debug window menu item
openRPCConsoleAction->setEnabled(false);
+ openRPCConsoleAction->setObjectName("openRPCConsoleAction");
- usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
+ usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses"), this);
usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
- usedReceivingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Receiving addresses..."), this);
+ usedReceivingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Receiving addresses"), this);
usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("Open &URI..."), this);
openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
+ m_open_wallet_action = new QAction(tr("Open Wallet"), this);
+ m_open_wallet_action->setMenu(new QMenu(this));
+ m_open_wallet_action->setStatusTip(tr("Open a wallet"));
+
+ m_close_wallet_action = new QAction(tr("Close Wallet..."), this);
+ m_close_wallet_action->setStatusTip(tr("Close wallet"));
+
showHelpMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/info"), tr("&Command-line options"), this);
showHelpMessageAction->setMenuRole(QAction::NoRole);
showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Bitcoin command-line options").arg(tr(PACKAGE_NAME)));
- connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
- connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
- connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
- connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
- connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
- connect(showHelpMessageAction, SIGNAL(triggered()), this, SLOT(showHelpMessageClicked()));
- connect(openRPCConsoleAction, SIGNAL(triggered()), this, SLOT(showDebugWindow()));
+ connect(quitAction, &QAction::triggered, qApp, QApplication::quit);
+ connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
+ connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
+ connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
+ connect(toggleHideAction, &QAction::triggered, this, &BitcoinGUI::toggleHidden);
+ connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked);
+ connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow);
// prevents an open debug window from becoming stuck/unusable on client shutdown
- connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
+ connect(quitAction, &QAction::triggered, rpcConsole, &QWidget::hide);
#ifdef ENABLE_WALLET
if(walletFrame)
{
- connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool)));
- connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet()));
- connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase()));
- connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
- connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
- connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses()));
- connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
- connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
+ connect(encryptWalletAction, &QAction::triggered, walletFrame, &WalletFrame::encryptWallet);
+ connect(backupWalletAction, &QAction::triggered, walletFrame, &WalletFrame::backupWallet);
+ connect(changePassphraseAction, &QAction::triggered, walletFrame, &WalletFrame::changePassphrase);
+ connect(signMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(signMessageAction, &QAction::triggered, [this]{ gotoSignMessageTab(); });
+ connect(verifyMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(verifyMessageAction, &QAction::triggered, [this]{ gotoVerifyMessageTab(); });
+ connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses);
+ connect(usedReceivingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedReceivingAddresses);
+ connect(openAction, &QAction::triggered, this, &BitcoinGUI::openClicked);
+ connect(m_open_wallet_action->menu(), &QMenu::aboutToShow, [this] {
+ m_open_wallet_action->menu()->clear();
+ std::vector<std::string> available_wallets = m_wallet_controller->getWalletsAvailableToOpen();
+ std::vector<std::string> wallets = m_node.listWalletDir();
+ for (const auto& path : wallets) {
+ QString name = path.empty() ? QString("["+tr("default wallet")+"]") : QString::fromStdString(path);
+ QAction* action = m_open_wallet_action->menu()->addAction(name);
+
+ if (std::find(available_wallets.begin(), available_wallets.end(), path) == available_wallets.end()) {
+ // This wallet is already loaded
+ action->setEnabled(false);
+ continue;
+ }
+
+ connect(action, &QAction::triggered, [this, name, path] {
+ OpenWalletActivity* activity = m_wallet_controller->openWallet(path);
+
+ QProgressDialog* dialog = new QProgressDialog(this);
+ dialog->setLabelText(tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));
+ dialog->setRange(0, 0);
+ dialog->setCancelButton(nullptr);
+ dialog->setWindowModality(Qt::ApplicationModal);
+ dialog->show();
+
+ connect(activity, &OpenWalletActivity::message, this, [this] (QMessageBox::Icon icon, QString text) {
+ QMessageBox box;
+ box.setIcon(icon);
+ box.setText(tr("Open Wallet Failed"));
+ box.setInformativeText(text);
+ box.setStandardButtons(QMessageBox::Ok);
+ box.setDefaultButton(QMessageBox::Ok);
+ connect(this, &QObject::destroyed, &box, &QDialog::accept);
+ box.exec();
+ });
+ connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet);
+ connect(activity, &OpenWalletActivity::finished, activity, &QObject::deleteLater);
+ connect(activity, &OpenWalletActivity::finished, dialog, &QObject::deleteLater);
+ bool invoked = QMetaObject::invokeMethod(activity, "open");
+ assert(invoked);
+ });
+ }
+ if (wallets.empty()) {
+ QAction* action = m_open_wallet_action->menu()->addAction(tr("No wallets available"));
+ action->setEnabled(false);
+ }
+ });
+ connect(m_close_wallet_action, &QAction::triggered, [this] {
+ m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
+ });
}
#endif // ENABLE_WALLET
- new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), this, SLOT(showDebugWindowActivateConsole()));
- new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_D), this, SLOT(showDebugWindow()));
+ connect(new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindowActivateConsole);
+ connect(new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_D), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindow);
}
void BitcoinGUI::createMenuBar()
@@ -368,14 +438,14 @@ void BitcoinGUI::createMenuBar()
QMenu *file = appMenuBar->addMenu(tr("&File"));
if(walletFrame)
{
+ file->addAction(m_open_wallet_action);
+ file->addAction(m_close_wallet_action);
+ file->addSeparator();
file->addAction(openAction);
file->addAction(backupWalletAction);
file->addAction(signMessageAction);
file->addAction(verifyMessageAction);
file->addSeparator();
- file->addAction(usedSendingAddressesAction);
- file->addAction(usedReceivingAddressesAction);
- file->addSeparator();
}
file->addAction(quitAction);
@@ -388,11 +458,64 @@ void BitcoinGUI::createMenuBar()
}
settings->addAction(optionsAction);
- QMenu *help = appMenuBar->addMenu(tr("&Help"));
- if(walletFrame)
- {
- help->addAction(openRPCConsoleAction);
+ QMenu* window_menu = appMenuBar->addMenu(tr("&Window"));
+
+ QAction* minimize_action = window_menu->addAction(tr("Minimize"));
+ minimize_action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
+ connect(minimize_action, &QAction::triggered, [] {
+ qApp->focusWindow()->showMinimized();
+ });
+ connect(qApp, &QApplication::focusWindowChanged, [minimize_action] (QWindow* window) {
+ minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
+ });
+
+#ifdef Q_OS_MAC
+ QAction* zoom_action = window_menu->addAction(tr("Zoom"));
+ connect(zoom_action, &QAction::triggered, [] {
+ QWindow* window = qApp->focusWindow();
+ if (window->windowState() != Qt::WindowMaximized) {
+ window->showMaximized();
+ } else {
+ window->showNormal();
+ }
+ });
+
+ connect(qApp, &QApplication::focusWindowChanged, [zoom_action] (QWindow* window) {
+ zoom_action->setEnabled(window != nullptr);
+ });
+#else
+ QAction* restore_action = window_menu->addAction(tr("Restore"));
+ connect(restore_action, &QAction::triggered, [] {
+ qApp->focusWindow()->showNormal();
+ });
+
+ connect(qApp, &QApplication::focusWindowChanged, [restore_action] (QWindow* window) {
+ restore_action->setEnabled(window != nullptr);
+ });
+#endif
+
+ if (walletFrame) {
+ window_menu->addSeparator();
+ QAction* main_window_action = window_menu->addAction(tr("Main Window"));
+ connect(main_window_action, &QAction::triggered, [this] {
+ GUIUtil::bringToFront(this);
+ });
+
+ window_menu->addSeparator();
+ window_menu->addAction(usedSendingAddressesAction);
+ window_menu->addAction(usedReceivingAddressesAction);
+ }
+
+ window_menu->addSeparator();
+ for (RPCConsole::TabTypes tab_type : rpcConsole->tabs()) {
+ QAction* tab_action = window_menu->addAction(rpcConsole->tabTitle(tab_type));
+ connect(tab_action, &QAction::triggered, [this, tab_type] {
+ rpcConsole->setTabFocus(tab_type);
+ showDebugWindow();
+ });
}
+
+ QMenu *help = appMenuBar->addMenu(tr("&Help"));
help->addAction(showHelpMessageAction);
help->addSeparator();
help->addAction(aboutAction);
@@ -420,7 +543,8 @@ void BitcoinGUI::createToolBars()
toolbar->addWidget(spacer);
m_wallet_selector = new QComboBox();
- connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
+ m_wallet_selector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ connect(m_wallet_selector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &BitcoinGUI::setCurrentWalletBySelectorIndex);
m_wallet_selector_label = new QLabel();
m_wallet_selector_label->setText(tr("Wallet:") + " ");
@@ -446,18 +570,20 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
// Keep up to date with client
updateNetworkState();
- connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
- connect(_clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
+ connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections);
+ connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
setNumBlocks(m_node.getNumBlocks(), QDateTime::fromTime_t(m_node.getLastBlockTime()), m_node.getVerificationProgress(), false);
- connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
+ connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
// Receive and report messages from client model
- connect(_clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
+ connect(_clientModel, &ClientModel::message, [this](const QString &title, const QString &message, unsigned int style){
+ this->message(title, message, style);
+ });
// Show progress dialog
- connect(_clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
+ connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
rpcConsole->setClientModel(_clientModel);
@@ -472,10 +598,9 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel());
OptionsModel* optionsModel = _clientModel->getOptionsModel();
- if(optionsModel)
- {
+ if (optionsModel && trayIcon) {
// be aware of the tray icon disable state change reported by the OptionsModel object.
- connect(optionsModel,SIGNAL(hideTrayIconChanged(bool)),this,SLOT(setTrayIconVisible(bool)));
+ connect(optionsModel, &OptionsModel::hideTrayIconChanged, this, &BitcoinGUI::setTrayIconVisible);
// initialize the disable state of the tray icon with the current value in the model.
setTrayIconVisible(optionsModel->getHideTrayIcon());
@@ -501,27 +626,39 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
}
#ifdef ENABLE_WALLET
-bool BitcoinGUI::addWallet(WalletModel *walletModel)
+void BitcoinGUI::setWalletController(WalletController* wallet_controller)
{
- if(!walletFrame)
- return false;
- const QString name = walletModel->getWalletName();
- QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name;
+ assert(!m_wallet_controller);
+ assert(wallet_controller);
+
+ m_wallet_controller = wallet_controller;
+
+ connect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
+ connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
+
+ for (WalletModel* wallet_model : m_wallet_controller->getWallets()) {
+ addWallet(wallet_model);
+ }
+}
+
+void BitcoinGUI::addWallet(WalletModel* walletModel)
+{
+ if (!walletFrame) return;
+ const QString display_name = walletModel->getDisplayName();
setWalletActionsEnabled(true);
- m_wallet_selector->addItem(display_name, name);
+ rpcConsole->addWallet(walletModel);
+ walletFrame->addWallet(walletModel);
+ m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
if (m_wallet_selector->count() == 2) {
m_wallet_selector_label_action->setVisible(true);
m_wallet_selector_action->setVisible(true);
}
- rpcConsole->addWallet(walletModel);
- return walletFrame->addWallet(walletModel);
}
-bool BitcoinGUI::removeWallet(WalletModel* walletModel)
+void BitcoinGUI::removeWallet(WalletModel* walletModel)
{
- if (!walletFrame) return false;
- QString name = walletModel->getWalletName();
- int index = m_wallet_selector->findData(name);
+ if (!walletFrame) return;
+ int index = m_wallet_selector->findData(QVariant::fromValue(walletModel));
m_wallet_selector->removeItem(index);
if (m_wallet_selector->count() == 0) {
setWalletActionsEnabled(false);
@@ -530,20 +667,27 @@ bool BitcoinGUI::removeWallet(WalletModel* walletModel)
m_wallet_selector_action->setVisible(false);
}
rpcConsole->removeWallet(walletModel);
- return walletFrame->removeWallet(name);
+ walletFrame->removeWallet(walletModel);
+ updateWindowTitle();
}
-bool BitcoinGUI::setCurrentWallet(const QString& name)
+void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
{
- if(!walletFrame)
- return false;
- return walletFrame->setCurrentWallet(name);
+ if (!walletFrame) return;
+ walletFrame->setCurrentWallet(wallet_model);
+ for (int index = 0; index < m_wallet_selector->count(); ++index) {
+ if (m_wallet_selector->itemData(index).value<WalletModel*>() == wallet_model) {
+ m_wallet_selector->setCurrentIndex(index);
+ break;
+ }
+ }
+ updateWindowTitle();
}
-bool BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
+void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
{
- QString internal_name = m_wallet_selector->itemData(index).toString();
- return setCurrentWallet(internal_name);
+ WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>();
+ if (wallet_model) setCurrentWallet(wallet_model);
}
void BitcoinGUI::removeAllWallets()
@@ -571,52 +715,55 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
usedSendingAddressesAction->setEnabled(enabled);
usedReceivingAddressesAction->setEnabled(enabled);
openAction->setEnabled(enabled);
+ m_close_wallet_action->setEnabled(enabled);
}
-void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle)
+void BitcoinGUI::createTrayIcon()
{
+ assert(QSystemTrayIcon::isSystemTrayAvailable());
+
#ifndef Q_OS_MAC
- trayIcon = new QSystemTrayIcon(this);
- QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText();
- trayIcon->setToolTip(toolTip);
- trayIcon->setIcon(networkStyle->getTrayAndWindowIcon());
- trayIcon->hide();
+ if (QSystemTrayIcon::isSystemTrayAvailable()) {
+ trayIcon = new QSystemTrayIcon(m_network_style->getTrayAndWindowIcon(), this);
+ QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + m_network_style->getTitleAddText();
+ trayIcon->setToolTip(toolTip);
+ }
#endif
-
- notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
}
void BitcoinGUI::createTrayIconMenu()
{
#ifndef Q_OS_MAC
- // return if trayIcon is unset (only on non-Mac OSes)
+ // return if trayIcon is unset (only on non-macOSes)
if (!trayIcon)
return;
- trayIconMenu = new QMenu(this);
- trayIcon->setContextMenu(trayIconMenu);
-
- connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
- this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
+ trayIcon->setContextMenu(trayIconMenu.get());
+ connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated);
#else
- // Note: On Mac, the dock icon is used to provide the tray's functionality.
+ // Note: On macOS, the Dock icon is used to provide the tray's functionality.
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
- dockIconHandler->setMainWindow(static_cast<QMainWindow*>(this));
- trayIconMenu = dockIconHandler->dockMenu();
+ connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated);
+ trayIconMenu->setAsDockMenu();
#endif
- // Configuration of the tray icon (or dock icon) icon menu
+ // Configuration of the tray icon (or Dock icon) menu
+#ifndef Q_OS_MAC
+ // Note: On macOS, the Dock icon's menu already has Show / Hide action.
trayIconMenu->addAction(toggleHideAction);
trayIconMenu->addSeparator();
- trayIconMenu->addAction(sendCoinsMenuAction);
- trayIconMenu->addAction(receiveCoinsMenuAction);
- trayIconMenu->addSeparator();
- trayIconMenu->addAction(signMessageAction);
- trayIconMenu->addAction(verifyMessageAction);
- trayIconMenu->addSeparator();
+#endif
+ if (enableWallet) {
+ trayIconMenu->addAction(sendCoinsMenuAction);
+ trayIconMenu->addAction(receiveCoinsMenuAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addAction(signMessageAction);
+ trayIconMenu->addAction(verifyMessageAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addAction(openRPCConsoleAction);
+ }
trayIconMenu->addAction(optionsAction);
- trayIconMenu->addAction(openRPCConsoleAction);
-#ifndef Q_OS_MAC // This is built-in on Mac
+#ifndef Q_OS_MAC // This is built-in on macOS
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
#endif
@@ -631,16 +778,17 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
toggleHidden();
}
}
+#else
+void BitcoinGUI::macosDockIconActivated()
+{
+ show();
+ activateWindow();
+}
#endif
void BitcoinGUI::optionsClicked()
{
- if(!clientModel || !clientModel->getOptionsModel())
- return;
-
- OptionsDialog dlg(this, enableWallet);
- dlg.setModel(clientModel->getOptionsModel());
- dlg.exec();
+ openOptionsDialogWithTab(OptionsDialog::TAB_MAIN);
}
void BitcoinGUI::aboutClicked()
@@ -654,10 +802,8 @@ void BitcoinGUI::aboutClicked()
void BitcoinGUI::showDebugWindow()
{
- rpcConsole->showNormal();
- rpcConsole->show();
- rpcConsole->raise();
- rpcConsole->activateWindow();
+ GUIUtil::bringToFront(rpcConsole);
+ Q_EMIT consoleShown(rpcConsole);
}
void BitcoinGUI::showDebugWindowActivateConsole()
@@ -764,8 +910,24 @@ void BitcoinGUI::updateHeadersSyncProgressLabel()
progressBarLabel->setText(tr("Syncing Headers (%1%)...").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
}
+void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab)
+{
+ if (!clientModel || !clientModel->getOptionsModel())
+ return;
+
+ OptionsDialog dlg(this, enableWallet);
+ dlg.setCurrentTab(tab);
+ dlg.setModel(clientModel->getOptionsModel());
+ dlg.exec();
+}
+
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header)
{
+// Disabling macOS App Nap on initial sync, disk and reindex operations.
+#ifdef Q_OS_MAC
+ (m_node.isInitialBlockDownload() || m_node.getReindex() || m_node.getImporting()) ? m_app_nap_inhibitor->disableAppNap() : m_app_nap_inhibitor->enableAppNap();
+#endif
+
if (modalOverlay)
{
if (header)
@@ -816,8 +978,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
tooltip = tr("Processed %n block(s) of transaction history.", "", count);
// Set icon state: spinning if catching up, tick otherwise
- if(secs < 90*60)
- {
+ if (secs < MAX_BLOCK_TIME_GAP) {
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
labelBlocksIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
@@ -945,12 +1106,12 @@ void BitcoinGUI::changeEvent(QEvent *e)
QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
{
- QTimer::singleShot(0, this, SLOT(hide()));
+ QTimer::singleShot(0, this, &BitcoinGUI::hide);
e->ignore();
}
else if((wsevt->oldState() & Qt::WindowMinimized) && !isMinimized())
{
- QTimer::singleShot(0, this, SLOT(show()));
+ QTimer::singleShot(0, this, &BitcoinGUI::show);
e->ignore();
}
}
@@ -1052,10 +1213,10 @@ bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
return false;
}
-void BitcoinGUI::setHDStatus(int hdEnabled)
+void BitcoinGUI::setHDStatus(bool privkeyDisabled, int hdEnabled)
{
- labelWalletHDStatusIcon->setPixmap(platformStyle->SingleColorIcon(hdEnabled ? ":/icons/hd_enabled" : ":/icons/hd_disabled").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
- labelWalletHDStatusIcon->setToolTip(hdEnabled ? tr("HD key generation is <b>enabled</b>") : tr("HD key generation is <b>disabled</b>"));
+ labelWalletHDStatusIcon->setPixmap(platformStyle->SingleColorIcon(privkeyDisabled ? ":/icons/eye" : hdEnabled ? ":/icons/hd_enabled" : ":/icons/hd_disabled").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
+ labelWalletHDStatusIcon->setToolTip(privkeyDisabled ? tr("Private key <b>disabled</b>") : hdEnabled ? tr("HD key generation is <b>enabled</b>") : tr("HD key generation is <b>disabled</b>"));
// eventually disable the QLabel to set its opacity to 50%
labelWalletHDStatusIcon->setEnabled(hdEnabled);
@@ -1101,7 +1262,7 @@ void BitcoinGUI::updateWalletStatus()
}
WalletModel * const walletModel = walletView->getWalletModel();
setEncryptionStatus(walletModel->getEncryptionStatus());
- setHDStatus(walletModel->wallet().hdEnabled());
+ setHDStatus(walletModel->privateKeysDisabled(), walletModel->wallet().hdEnabled());
}
#endif // ENABLE_WALLET
@@ -1111,7 +1272,7 @@ void BitcoinGUI::updateProxyIcon()
bool proxy_enabled = clientModel->getProxyInfo(ip_port);
if (proxy_enabled) {
- if (labelProxyIcon->pixmap() == 0) {
+ if (labelProxyIcon->pixmap() == nullptr) {
QString ip_port_q = QString::fromStdString(ip_port);
labelProxyIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/proxy").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q));
@@ -1123,29 +1284,33 @@ void BitcoinGUI::updateProxyIcon()
}
}
+void BitcoinGUI::updateWindowTitle()
+{
+ QString window_title = tr(PACKAGE_NAME);
+#ifdef ENABLE_WALLET
+ if (walletFrame) {
+ WalletModel* const wallet_model = walletFrame->currentWalletModel();
+ if (wallet_model && !wallet_model->getWalletName().isEmpty()) {
+ window_title += " - " + wallet_model->getDisplayName();
+ }
+ }
+#endif
+ if (!m_network_style->getTitleAddText().isEmpty()) {
+ window_title += " - " + m_network_style->getTitleAddText();
+ }
+ setWindowTitle(window_title);
+}
+
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
{
if(!clientModel)
return;
- // activateWindow() (sometimes) helps with keyboard focus on Windows
- if (isHidden())
- {
- show();
- activateWindow();
- }
- else if (isMinimized())
- {
- showNormal();
- activateWindow();
- }
- else if (GUIUtil::isObscured(this))
- {
- raise();
- activateWindow();
- }
- else if(fToggleHidden)
+ if (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this) && fToggleHidden) {
hide();
+ } else {
+ GUIUtil::bringToFront(this);
+ }
}
void BitcoinGUI::toggleHidden()
@@ -1165,25 +1330,21 @@ void BitcoinGUI::detectShutdown()
void BitcoinGUI::showProgress(const QString &title, int nProgress)
{
- if (nProgress == 0)
- {
- progressDialog = new QProgressDialog(title, "", 0, 100);
+ if (nProgress == 0) {
+ progressDialog = new QProgressDialog(title, QString(), 0, 100);
+ GUIUtil::PolishProgressDialog(progressDialog);
progressDialog->setWindowModality(Qt::ApplicationModal);
progressDialog->setMinimumDuration(0);
- progressDialog->setCancelButton(0);
progressDialog->setAutoClose(false);
progressDialog->setValue(0);
- }
- else if (nProgress == 100)
- {
- if (progressDialog)
- {
+ } else if (nProgress == 100) {
+ if (progressDialog) {
progressDialog->close();
progressDialog->deleteLater();
}
- }
- else if (progressDialog)
+ } else if (progressDialog) {
progressDialog->setValue(nProgress);
+ }
}
void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon)
@@ -1200,7 +1361,7 @@ void BitcoinGUI::showModalOverlay()
modalOverlay->toggleVisibility();
}
-static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style)
+static bool ThreadSafeMessageBox(BitcoinGUI* gui, const std::string& message, const std::string& caption, unsigned int style)
{
bool modal = (style & CClientUIInterface::MODAL);
// The SECURE flag has no effect in the Qt GUI.
@@ -1220,8 +1381,8 @@ static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, co
void BitcoinGUI::subscribeToCoreSignals()
{
// Connect signals to client
- m_handler_message_box = m_node.handleMessageBox(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
- m_handler_question = m_node.handleQuestion(boost::bind(ThreadSafeMessageBox, this, _1, _3, _4));
+ m_handler_message_box = m_node.handleMessageBox(std::bind(ThreadSafeMessageBox, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ m_handler_question = m_node.handleQuestion(std::bind(ThreadSafeMessageBox, this, std::placeholders::_1, std::placeholders::_3, std::placeholders::_4));
}
void BitcoinGUI::unsubscribeFromCoreSignals()
@@ -1231,14 +1392,9 @@ void BitcoinGUI::unsubscribeFromCoreSignals()
m_handler_question->disconnect();
}
-void BitcoinGUI::toggleNetworkActive()
-{
- m_node.setNetworkActive(!m_node.getNetworkActive());
-}
-
UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle) :
- optionsModel(0),
- menu(0)
+ optionsModel(nullptr),
+ menu(nullptr)
{
createContextMenu();
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
@@ -1264,13 +1420,13 @@ void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
void UnitDisplayStatusBarControl::createContextMenu()
{
menu = new QMenu(this);
- for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
+ for (const BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
{
QAction *menuAction = new QAction(QString(BitcoinUnits::longName(u)), this);
menuAction->setData(QVariant(u));
menu->addAction(menuAction);
}
- connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*)));
+ connect(menu, &QMenu::triggered, this, &UnitDisplayStatusBarControl::onMenuSelection);
}
/** Lets the control know about the Options Model (and its signals) */
@@ -1281,7 +1437,7 @@ void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel)
this->optionsModel = _optionsModel;
// be aware of a display unit change reported by the OptionsModel object.
- connect(_optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int)));
+ connect(_optionsModel, &OptionsModel::displayUnitChanged, this, &UnitDisplayStatusBarControl::updateDisplayUnit);
// initialize the display units label with the current value in the model.
updateDisplayUnit(_optionsModel->getDisplayUnit());
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index d7ca8081d1..b58ccbb455 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,15 +9,20 @@
#include <config/bitcoin-config.h>
#endif
+#include <qt/optionsdialog.h>
+
#include <amount.h>
#include <QLabel>
#include <QMainWindow>
#include <QMap>
-#include <QMenu>
#include <QPoint>
#include <QSystemTrayIcon>
+#ifdef Q_OS_MAC
+#include <qt/macos_appnap.h>
+#endif
+
#include <memory>
class ClientModel;
@@ -28,6 +33,7 @@ class PlatformStyle;
class RPCConsole;
class SendCoinsRecipient;
class UnitDisplayStatusBarControl;
+class WalletController;
class WalletFrame;
class WalletModel;
class HelpMessageDialog;
@@ -41,10 +47,16 @@ class Node;
QT_BEGIN_NAMESPACE
class QAction;
class QComboBox;
+class QMenu;
class QProgressBar;
class QProgressDialog;
QT_END_NAMESPACE
+namespace GUIUtil {
+class ClickableLabel;
+class ClickableProgressBar;
+}
+
/**
Bitcoin GUI main class. This class represents the main window of the Bitcoin UI. It communicates with both the client and
wallet models to give the user an up-to-date view of the current core state.
@@ -56,25 +68,36 @@ class BitcoinGUI : public QMainWindow
public:
static const std::string DEFAULT_UIPLATFORM;
- explicit BitcoinGUI(interfaces::Node& node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = 0);
+ explicit BitcoinGUI(interfaces::Node& node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = nullptr);
~BitcoinGUI();
/** Set the client model.
The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
*/
void setClientModel(ClientModel *clientModel);
+#ifdef ENABLE_WALLET
+ void setWalletController(WalletController* wallet_controller);
+#endif
#ifdef ENABLE_WALLET
/** Set the wallet model.
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
functionality.
*/
- bool addWallet(WalletModel *walletModel);
- bool removeWallet(WalletModel* walletModel);
+ void addWallet(WalletModel* walletModel);
+ void removeWallet(WalletModel* walletModel);
void removeAllWallets();
#endif // ENABLE_WALLET
bool enableWallet = false;
+ /** Get the tray icon status.
+ Some systems have not "system tray" or "notification area" available.
+ */
+ bool hasTrayIcon() const { return trayIcon; }
+
+ /** Disconnect core signals from GUI client */
+ void unsubscribeFromCoreSignals();
+
protected:
void changeEvent(QEvent *e);
void closeEvent(QCloseEvent *event);
@@ -85,6 +108,7 @@ protected:
private:
interfaces::Node& m_node;
+ WalletController* m_wallet_controller{nullptr};
std::unique_ptr<interfaces::Handler> m_handler_message_box;
std::unique_ptr<interfaces::Handler> m_handler_question;
ClientModel* clientModel = nullptr;
@@ -93,11 +117,11 @@ private:
UnitDisplayStatusBarControl* unitDisplayControl = nullptr;
QLabel* labelWalletEncryptionIcon = nullptr;
QLabel* labelWalletHDStatusIcon = nullptr;
- QLabel* labelProxyIcon = nullptr;
- QLabel* connectionsControl = nullptr;
- QLabel* labelBlocksIcon = nullptr;
+ GUIUtil::ClickableLabel* labelProxyIcon = nullptr;
+ GUIUtil::ClickableLabel* connectionsControl = nullptr;
+ GUIUtil::ClickableLabel* labelBlocksIcon = nullptr;
QLabel* progressBarLabel = nullptr;
- QProgressBar* progressBar = nullptr;
+ GUIUtil::ClickableProgressBar* progressBar = nullptr;
QProgressDialog* progressDialog = nullptr;
QMenuBar* appMenuBar = nullptr;
@@ -123,6 +147,8 @@ private:
QAction* openRPCConsoleAction = nullptr;
QAction* openAction = nullptr;
QAction* showHelpMessageAction = nullptr;
+ QAction* m_open_wallet_action{nullptr};
+ QAction* m_close_wallet_action{nullptr};
QAction* m_wallet_selector_label_action = nullptr;
QAction* m_wallet_selector_action = nullptr;
@@ -130,17 +156,22 @@ private:
QComboBox* m_wallet_selector = nullptr;
QSystemTrayIcon* trayIcon = nullptr;
- QMenu* trayIconMenu = nullptr;
+ const std::unique_ptr<QMenu> trayIconMenu;
Notificator* notificator = nullptr;
RPCConsole* rpcConsole = nullptr;
HelpMessageDialog* helpMessageDialog = nullptr;
ModalOverlay* modalOverlay = nullptr;
+#ifdef Q_OS_MAC
+ CAppNapInhibitor* m_app_nap_inhibitor = nullptr;
+#endif
+
/** Keep track of previous number of blocks, to detect progress */
int prevBlocks = 0;
int spinnerFrame = 0;
const PlatformStyle *platformStyle;
+ const NetworkStyle* const m_network_style;
/** Create the main UI actions. */
void createActions();
@@ -149,7 +180,7 @@ private:
/** Create the toolbars */
void createToolBars();
/** Create system tray icon and notification */
- void createTrayIcon(const NetworkStyle *networkStyle);
+ void createTrayIcon();
/** Create system tray menu (or setup the dock menu) */
void createTrayIconMenu();
@@ -158,17 +189,20 @@ private:
/** Connect core signals to GUI client */
void subscribeToCoreSignals();
- /** Disconnect core signals from GUI client */
- void unsubscribeFromCoreSignals();
/** Update UI with latest network info from model. */
void updateNetworkState();
void updateHeadersSyncProgressLabel();
+ /** Open the OptionsDialog on the specified tab index */
+ void openOptionsDialogWithTab(OptionsDialog::Tab tab);
+
Q_SIGNALS:
/** Signal raised when a URI was entered or dragged to the GUI */
void receivedURI(const QString &uri);
+ /** Signal raised when RPC console shown */
+ void consoleShown(RPCConsole* console);
public Q_SLOTS:
/** Set number of connections shown in the UI */
@@ -188,8 +222,8 @@ public Q_SLOTS:
void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr);
#ifdef ENABLE_WALLET
- bool setCurrentWallet(const QString& name);
- bool setCurrentWalletBySelectorIndex(int index);
+ void setCurrentWallet(WalletModel* wallet_model);
+ void setCurrentWalletBySelectorIndex(int index);
/** Set the UI status indicators based on the currently selected wallet.
*/
void updateWalletStatus();
@@ -202,10 +236,10 @@ private:
void setEncryptionStatus(int status);
/** Set the hd-enabled status as shown in the UI.
- @param[in] status current hd enabled status
+ @param[in] hdEnabled current hd enabled status
@see WalletModel::EncryptionStatus
*/
- void setHDStatus(int hdEnabled);
+ void setHDStatus(bool privkeyDisabled, int hdEnabled);
public Q_SLOTS:
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
@@ -217,8 +251,9 @@ public Q_SLOTS:
private:
/** Set the proxy-enabled icon as shown in the UI. */
void updateProxyIcon();
+ void updateWindowTitle();
-private Q_SLOTS:
+public Q_SLOTS:
#ifdef ENABLE_WALLET
/** Switch to overview (home) page */
void gotoOverviewPage();
@@ -250,10 +285,14 @@ private Q_SLOTS:
#ifndef Q_OS_MAC
/** Handle tray icon clicked */
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
+#else
+ /** Handle macOS Dock icon clicked */
+ void macosDockIconActivated();
#endif
/** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */
- void showNormalIfMinimized(bool fToggleHidden = false);
+ void showNormalIfMinimized() { showNormalIfMinimized(false); }
+ void showNormalIfMinimized(bool fToggleHidden);
/** Simply calls showNormalIfMinimized(true) for use in SLOT() macro */
void toggleHidden();
@@ -266,9 +305,6 @@ private Q_SLOTS:
/** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */
void setTrayIconVisible(bool);
- /** Toggle networking */
- void toggleNetworkActive();
-
void showModalOverlay();
};
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index ab7e56a9da..dc997e96cc 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -30,8 +30,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Distributed under the MIT software license, see the accompanying file %s or "
"%s"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Error loading %s: You can't enable HD on an already existing non-HD wallet"),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error reading %s! All keys read correctly, but transaction data or address "
"book entries might be missing or incorrect."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -85,12 +83,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Unable to rewind the database to a pre-fork state. You will need to "
"redownload the blockchain"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Unsupported argument -socks found. Setting SOCKS version isn't possible "
-"anymore, only SOCKS5 proxies are supported."),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/"
-"or -whitelistforcerelay."),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: Private keys detected in wallet {%s} with disabled private keys"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: The network does not appear to fully agree! Some miners appear to "
@@ -116,18 +108,17 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -%s address: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write to data directory '%s'; check permissions."),
QT_TRANSLATE_NOOP("bitcoin-core", "Change index out of range"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Config setting for %s only applied on %s network when in [%s] section."),
QT_TRANSLATE_NOOP("bitcoin-core", "Copyright (C) %i-%i"),
QT_TRANSLATE_NOOP("bitcoin-core", "Corrupted block database detected"),
QT_TRANSLATE_NOOP("bitcoin-core", "Do you want to rebuild the block database now?"),
QT_TRANSLATE_NOOP("bitcoin-core", "Done loading"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Error creating %s: You can't create non-HD wallets with this version."),
QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing block database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing wallet database environment %s!"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Private keys can only be disabled during creation"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Wallet corrupted"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Wallet requires newer version of %s"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: You can't disable HD on an already existing HD wallet"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading block database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet %s. Duplicate -wallet filename specified."),
QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"),
@@ -135,6 +126,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error reading from database, shutting down.")
QT_TRANSLATE_NOOP("bitcoin-core", "Error upgrading chainstate database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: A fatal internal error occurred, see debug.log for details"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low for %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low!"),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to rescan the wallet during initialization"),
@@ -164,13 +156,15 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Reducing -maxconnections from %d to %d, becau
QT_TRANSLATE_NOOP("bitcoin-core", "Replaying blocks..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Rewinding blocks..."),
+QT_TRANSLATE_NOOP("bitcoin-core", "Section [%s] is not recognized."),
QT_TRANSLATE_NOOP("bitcoin-core", "Signing transaction failed"),
QT_TRANSLATE_NOOP("bitcoin-core", "Specified -walletdir \"%s\" does not exist"),
QT_TRANSLATE_NOOP("bitcoin-core", "Specified -walletdir \"%s\" is a relative path"),
QT_TRANSLATE_NOOP("bitcoin-core", "Specified -walletdir \"%s\" is not a directory"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Specified blocks directory \"%s\" does not exist.\n"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Specified blocks directory \"%s\" does not exist."),
QT_TRANSLATE_NOOP("bitcoin-core", "Starting network threads..."),
QT_TRANSLATE_NOOP("bitcoin-core", "The source code is available from %s."),
+QT_TRANSLATE_NOOP("bitcoin-core", "The specified config file %s does not exist\n"),
QT_TRANSLATE_NOOP("bitcoin-core", "The transaction amount is too small to pay the fee"),
QT_TRANSLATE_NOOP("bitcoin-core", "The wallet will avoid paying less than the minimum relay fee."),
QT_TRANSLATE_NOOP("bitcoin-core", "This is experimental software."),
@@ -189,9 +183,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Unable to generate initial keys"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to generate keys"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to start HTTP server. See debug log for details."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -benchmark ignored, use -debug=bench."),
-QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -debugnet ignored, use -debug=net."),
-QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -tor found, use -onion."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported logging category %s=%s."),
QT_TRANSLATE_NOOP("bitcoin-core", "Upgrading UTXO database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Upgrading txindex database"),
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index 30625f419a..8aa1fdba4d 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h
index 9b01b4678a..06a1544fa2 100644
--- a/src/qt/bitcoinunits.h
+++ b/src/qt/bitcoinunits.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/callback.h b/src/qt/callback.h
deleted file mode 100644
index da6b0c4c2e..0000000000
--- a/src/qt/callback.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef BITCOIN_QT_CALLBACK_H
-#define BITCOIN_QT_CALLBACK_H
-
-#include <QObject>
-
-class Callback : public QObject
-{
- Q_OBJECT
-public Q_SLOTS:
- virtual void call() = 0;
-};
-
-template <typename F>
-class FunctionCallback : public Callback
-{
- F f;
-
-public:
- explicit FunctionCallback(F f_) : f(std::move(f_)) {}
- ~FunctionCallback() override {}
- void call() override { f(this); }
-};
-
-template <typename F>
-FunctionCallback<F>* makeCallback(F f)
-{
- return new FunctionCallback<F>(std::move(f));
-}
-
-#endif // BITCOIN_QT_CALLBACK_H
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 8a4a2955f6..88a35534c2 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,6 @@
#include <chain.h>
#include <chainparams.h>
-#include <checkpoints.h>
#include <clientversion.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
@@ -20,7 +19,7 @@
#include <netbase.h>
#include <txmempool.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <warnings.h>
#include <stdint.h>
@@ -35,16 +34,16 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO
QObject(parent),
m_node(node),
optionsModel(_optionsModel),
- peerTableModel(0),
- banTableModel(0),
- pollTimer(0)
+ peerTableModel(nullptr),
+ banTableModel(nullptr),
+ pollTimer(nullptr)
{
cachedBestHeaderHeight = -1;
cachedBestHeaderTime = -1;
peerTableModel = new PeerTableModel(m_node, this);
banTableModel = new BanTableModel(m_node, this);
pollTimer = new QTimer(this);
- connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
+ connect(pollTimer, &QTimer::timeout, this, &ClientModel::updateTimer);
pollTimer->start(MODEL_UPDATE_DELAY);
subscribeToCoreSignals();
@@ -177,6 +176,11 @@ QString ClientModel::dataDir() const
return GUIUtil::boostPathToQString(GetDataDir());
}
+QString ClientModel::blocksDir() const
+{
+ return GUIUtil::boostPathToQString(GetBlocksDir());
+}
+
void ClientModel::updateBanlist()
{
banTableModel->refresh();
@@ -232,8 +236,8 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, int heig
clientmodel->cachedBestHeaderHeight = height;
clientmodel->cachedBestHeaderTime = blockTime;
}
- // if we are in-sync, update the UI regardless of last update time
- if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
+ // if we are in-sync or if we notify a header update, update the UI regardless of last update time
+ if (fHeader || !initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
//pass an async signal to the UI thread
QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
Q_ARG(int, height),
@@ -247,13 +251,13 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, int heig
void ClientModel::subscribeToCoreSignals()
{
// Connect signals to client
- m_handler_show_progress = m_node.handleShowProgress(boost::bind(ShowProgress, this, _1, _2));
- m_handler_notify_num_connections_changed = m_node.handleNotifyNumConnectionsChanged(boost::bind(NotifyNumConnectionsChanged, this, _1));
- m_handler_notify_network_active_changed = m_node.handleNotifyNetworkActiveChanged(boost::bind(NotifyNetworkActiveChanged, this, _1));
- m_handler_notify_alert_changed = m_node.handleNotifyAlertChanged(boost::bind(NotifyAlertChanged, this));
- m_handler_banned_list_changed = m_node.handleBannedListChanged(boost::bind(BannedListChanged, this));
- m_handler_notify_block_tip = m_node.handleNotifyBlockTip(boost::bind(BlockTipChanged, this, _1, _2, _3, _4, false));
- m_handler_notify_header_tip = m_node.handleNotifyHeaderTip(boost::bind(BlockTipChanged, this, _1, _2, _3, _4, true));
+ m_handler_show_progress = m_node.handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2));
+ m_handler_notify_num_connections_changed = m_node.handleNotifyNumConnectionsChanged(std::bind(NotifyNumConnectionsChanged, this, std::placeholders::_1));
+ m_handler_notify_network_active_changed = m_node.handleNotifyNetworkActiveChanged(std::bind(NotifyNetworkActiveChanged, this, std::placeholders::_1));
+ m_handler_notify_alert_changed = m_node.handleNotifyAlertChanged(std::bind(NotifyAlertChanged, this));
+ m_handler_banned_list_changed = m_node.handleBannedListChanged(std::bind(BannedListChanged, this));
+ m_handler_notify_block_tip = m_node.handleNotifyBlockTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, false));
+ m_handler_notify_header_tip = m_node.handleNotifyHeaderTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, true));
}
void ClientModel::unsubscribeFromCoreSignals()
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 9d4fa74b7a..95f4521f06 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -46,7 +46,7 @@ class ClientModel : public QObject
Q_OBJECT
public:
- explicit ClientModel(interfaces::Node& node, OptionsModel *optionsModel, QObject *parent = 0);
+ explicit ClientModel(interfaces::Node& node, OptionsModel *optionsModel, QObject *parent = nullptr);
~ClientModel();
interfaces::Node& node() const { return m_node; }
@@ -69,6 +69,7 @@ public:
bool isReleaseVersion() const;
QString formatClientStartupTime() const;
QString dataDir() const;
+ QString blocksDir() const;
bool getProxyInfo(std::string& ip_port) const;
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 9b6480a915..6c9bae7673 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -1,11 +1,16 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/coincontroldialog.h>
#include <qt/forms/ui_coincontroldialog.h>
#include <qt/addresstablemodel.h>
+#include <base58.h>
#include <qt/bitcoinunits.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
@@ -44,7 +49,7 @@ bool CCoinControlWidgetItem::operator<(const QTreeWidgetItem &other) const {
CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::CoinControlDialog),
- model(0),
+ model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
@@ -68,13 +73,13 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
contextMenu->addAction(unlockAction);
// context menu signals
- connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint)));
- connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
- connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
- connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
- connect(copyTransactionHashAction, SIGNAL(triggered()), this, SLOT(copyTransactionHash()));
- connect(lockAction, SIGNAL(triggered()), this, SLOT(lockCoin()));
- connect(unlockAction, SIGNAL(triggered()), this, SLOT(unlockCoin()));
+ connect(ui->treeWidget, &QWidget::customContextMenuRequested, this, &CoinControlDialog::showMenu);
+ connect(copyAddressAction, &QAction::triggered, this, &CoinControlDialog::copyAddress);
+ connect(copyLabelAction, &QAction::triggered, this, &CoinControlDialog::copyLabel);
+ connect(copyAmountAction, &QAction::triggered, this, &CoinControlDialog::copyAmount);
+ connect(copyTransactionHashAction, &QAction::triggered, this, &CoinControlDialog::copyTransactionHash);
+ connect(lockAction, &QAction::triggered, this, &CoinControlDialog::lockCoin);
+ connect(unlockAction, &QAction::triggered, this, &CoinControlDialog::unlockCoin);
// clipboard actions
QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this);
@@ -85,13 +90,13 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this);
QAction *clipboardChangeAction = new QAction(tr("Copy change"), this);
- connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(clipboardQuantity()));
- connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(clipboardAmount()));
- connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(clipboardFee()));
- connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(clipboardAfterFee()));
- connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(clipboardBytes()));
- connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(clipboardLowOutput()));
- connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(clipboardChange()));
+ connect(clipboardQuantityAction, &QAction::triggered, this, &CoinControlDialog::clipboardQuantity);
+ connect(clipboardAmountAction, &QAction::triggered, this, &CoinControlDialog::clipboardAmount);
+ connect(clipboardFeeAction, &QAction::triggered, this, &CoinControlDialog::clipboardFee);
+ connect(clipboardAfterFeeAction, &QAction::triggered, this, &CoinControlDialog::clipboardAfterFee);
+ connect(clipboardBytesAction, &QAction::triggered, this, &CoinControlDialog::clipboardBytes);
+ connect(clipboardLowOutputAction, &QAction::triggered, this, &CoinControlDialog::clipboardLowOutput);
+ connect(clipboardChangeAction, &QAction::triggered, this, &CoinControlDialog::clipboardChange);
ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
ui->labelCoinControlAmount->addAction(clipboardAmountAction);
@@ -102,21 +107,21 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
ui->labelCoinControlChange->addAction(clipboardChangeAction);
// toggle tree/list mode
- connect(ui->radioTreeMode, SIGNAL(toggled(bool)), this, SLOT(radioTreeMode(bool)));
- connect(ui->radioListMode, SIGNAL(toggled(bool)), this, SLOT(radioListMode(bool)));
+ connect(ui->radioTreeMode, &QRadioButton::toggled, this, &CoinControlDialog::radioTreeMode);
+ connect(ui->radioListMode, &QRadioButton::toggled, this, &CoinControlDialog::radioListMode);
// click on checkbox
- connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(viewItemChanged(QTreeWidgetItem*, int)));
+ connect(ui->treeWidget, &QTreeWidget::itemChanged, this, &CoinControlDialog::viewItemChanged);
// click on header
ui->treeWidget->header()->setSectionsClickable(true);
- connect(ui->treeWidget->header(), SIGNAL(sectionClicked(int)), this, SLOT(headerSectionClicked(int)));
+ connect(ui->treeWidget->header(), &QHeaderView::sectionClicked, this, &CoinControlDialog::headerSectionClicked);
// ok button
- connect(ui->buttonBox, SIGNAL(clicked( QAbstractButton*)), this, SLOT(buttonBoxClicked(QAbstractButton*)));
+ connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &CoinControlDialog::buttonBoxClicked);
// (un)select all
- connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this, SLOT(buttonSelectAllClicked()));
+ connect(ui->pushButtonSelectAll, &QPushButton::clicked, this, &CoinControlDialog::buttonSelectAllClicked);
ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84);
ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 110);
@@ -124,8 +129,6 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 320);
ui->treeWidget->setColumnWidth(COLUMN_DATE, 130);
ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 110);
- ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transaction hash in this column, but don't show it
- ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true); // store vout index in this column, but don't show it
// default view is sorted by amount desc
sortView(COLUMN_AMOUNT, Qt::DescendingOrder);
@@ -198,10 +201,10 @@ void CoinControlDialog::showMenu(const QPoint &point)
contextMenuItem = item;
// disable some items (like Copy Transaction ID, lock, unlock) for tree roots in context menu
- if (item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means it is a child node, so it is not a parent node in tree mode)
+ if (item->data(COLUMN_ADDRESS, TxHashRole).toString().length() == 64) // transaction hash is 64 characters (this means it is a child node, so it is not a parent node in tree mode)
{
copyTransactionHashAction->setEnabled(true);
- if (model->wallet().isLockedCoin(COutPoint(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())))
+ if (model->wallet().isLockedCoin(COutPoint(uint256S(item->data(COLUMN_ADDRESS, TxHashRole).toString().toStdString()), item->data(COLUMN_ADDRESS, VOutRole).toUInt())))
{
lockAction->setEnabled(false);
unlockAction->setEnabled(true);
@@ -251,7 +254,7 @@ void CoinControlDialog::copyAddress()
// context menu action: copy transaction id
void CoinControlDialog::copyTransactionHash()
{
- GUIUtil::setClipboard(contextMenuItem->text(COLUMN_TXHASH));
+ GUIUtil::setClipboard(contextMenuItem->data(COLUMN_ADDRESS, TxHashRole).toString());
}
// context menu action: lock coin
@@ -260,7 +263,7 @@ void CoinControlDialog::lockCoin()
if (contextMenuItem->checkState(COLUMN_CHECKBOX) == Qt::Checked)
contextMenuItem->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
- COutPoint outpt(uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt());
+ COutPoint outpt(uint256S(contextMenuItem->data(COLUMN_ADDRESS, TxHashRole).toString().toStdString()), contextMenuItem->data(COLUMN_ADDRESS, VOutRole).toUInt());
model->wallet().lockCoin(outpt);
contextMenuItem->setDisabled(true);
contextMenuItem->setIcon(COLUMN_CHECKBOX, platformStyle->SingleColorIcon(":/icons/lock_closed"));
@@ -270,7 +273,7 @@ void CoinControlDialog::lockCoin()
// context menu action: unlock coin
void CoinControlDialog::unlockCoin()
{
- COutPoint outpt(uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt());
+ COutPoint outpt(uint256S(contextMenuItem->data(COLUMN_ADDRESS, TxHashRole).toString().toStdString()), contextMenuItem->data(COLUMN_ADDRESS, VOutRole).toUInt());
model->wallet().unlockCoin(outpt);
contextMenuItem->setDisabled(false);
contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon());
@@ -366,9 +369,9 @@ void CoinControlDialog::radioListMode(bool checked)
// checkbox clicked by user
void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
{
- if (column == COLUMN_CHECKBOX && item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means it is a child node, so it is not a parent node in tree mode)
+ if (column == COLUMN_CHECKBOX && item->data(COLUMN_ADDRESS, TxHashRole).toString().length() == 64) // transaction hash is 64 characters (this means it is a child node, so it is not a parent node in tree mode)
{
- COutPoint outpt(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt());
+ COutPoint outpt(uint256S(item->data(COLUMN_ADDRESS, TxHashRole).toString().toStdString()), item->data(COLUMN_ADDRESS, VOutRole).toUInt());
if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked)
coinControl()->UnSelect(outpt);
@@ -468,8 +471,8 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
else if(ExtractDestination(out.txout.scriptPubKey, address))
{
CPubKey pubkey;
- CKeyID *keyid = boost::get<CKeyID>(&address);
- if (keyid && model->wallet().getPubKey(*keyid, pubkey))
+ PKHash *pkhash = boost::get<PKHash>(&address);
+ if (pkhash && model->wallet().getPubKey(CKeyID(*pkhash), pubkey))
{
nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
}
@@ -688,10 +691,10 @@ void CoinControlDialog::updateView()
itemOutput->setData(COLUMN_CONFIRMATIONS, Qt::UserRole, QVariant((qlonglong)out.depth_in_main_chain));
// transaction hash
- itemOutput->setText(COLUMN_TXHASH, QString::fromStdString(output.hash.GetHex()));
+ itemOutput->setData(COLUMN_ADDRESS, TxHashRole, QString::fromStdString(output.hash.GetHex()));
// vout index
- itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(output.n));
+ itemOutput->setData(COLUMN_ADDRESS, VOutRole, output.n);
// disable locked coins
if (model->wallet().isLockedCoin(output))
diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h
index a254c55556..efc06a7656 100644
--- a/src/qt/coincontroldialog.h
+++ b/src/qt/coincontroldialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -43,7 +43,7 @@ class CoinControlDialog : public QDialog
Q_OBJECT
public:
- explicit CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~CoinControlDialog();
void setModel(WalletModel *model);
@@ -80,9 +80,14 @@ private:
COLUMN_ADDRESS,
COLUMN_DATE,
COLUMN_CONFIRMATIONS,
- COLUMN_TXHASH,
- COLUMN_VOUT_INDEX,
};
+
+ enum
+ {
+ TxHashRole = Qt::UserRole,
+ VOutRole
+ };
+
friend class CCoinControlWidgetItem;
private Q_SLOTS:
diff --git a/src/qt/coincontroltreewidget.cpp b/src/qt/coincontroltreewidget.cpp
index e7326d3f7a..4ffbd832e9 100644
--- a/src/qt/coincontroltreewidget.cpp
+++ b/src/qt/coincontroltreewidget.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/coincontroltreewidget.h b/src/qt/coincontroltreewidget.h
index 62645fcdb0..88fc8b704f 100644
--- a/src/qt/coincontroltreewidget.h
+++ b/src/qt/coincontroltreewidget.h
@@ -13,7 +13,7 @@ class CoinControlTreeWidget : public QTreeWidget
Q_OBJECT
public:
- explicit CoinControlTreeWidget(QWidget *parent = 0);
+ explicit CoinControlTreeWidget(QWidget *parent = nullptr);
protected:
virtual void keyPressEvent(QKeyEvent *event);
diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp
index 672226ca11..656afb6e87 100644
--- a/src/qt/csvmodelwriter.cpp
+++ b/src/qt/csvmodelwriter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
CSVModelWriter::CSVModelWriter(const QString &_filename, QObject *parent) :
QObject(parent),
- filename(_filename), model(0)
+ filename(_filename), model(nullptr)
{
}
diff --git a/src/qt/csvmodelwriter.h b/src/qt/csvmodelwriter.h
index edea369ad1..e8611bea35 100644
--- a/src/qt/csvmodelwriter.h
+++ b/src/qt/csvmodelwriter.h
@@ -20,7 +20,7 @@ class CSVModelWriter : public QObject
Q_OBJECT
public:
- explicit CSVModelWriter(const QString &filename, QObject *parent = 0);
+ explicit CSVModelWriter(const QString &filename, QObject *parent = nullptr);
void setModel(const QAbstractItemModel *model);
void addColumn(const QString &title, int column, int role=Qt::EditRole);
diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp
index f26a31158e..4711412ac4 100644
--- a/src/qt/editaddressdialog.cpp
+++ b/src/qt/editaddressdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,9 +15,9 @@
EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) :
QDialog(parent),
ui(new Ui::EditAddressDialog),
- mapper(0),
+ mapper(nullptr),
mode(_mode),
- model(0)
+ model(nullptr)
{
ui->setupUi(this);
@@ -39,6 +39,10 @@ EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) :
mapper = new QDataWidgetMapper(this);
mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
+
+ GUIUtil::ItemDelegate* delegate = new GUIUtil::ItemDelegate(mapper);
+ connect(delegate, &GUIUtil::ItemDelegate::keyEscapePressed, this, &EditAddressDialog::reject);
+ mapper->setItemDelegate(delegate);
}
EditAddressDialog::~EditAddressDialog()
diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h
index 3aba74bf08..4d0e0709be 100644
--- a/src/qt/editaddressdialog.h
+++ b/src/qt/editaddressdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2015 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -30,7 +30,7 @@ public:
EditSendingAddress
};
- explicit EditAddressDialog(Mode mode, QWidget *parent = 0);
+ explicit EditAddressDialog(Mode mode, QWidget *parent = nullptr);
~EditAddressDialog();
void setModel(AddressTableModel *model);
diff --git a/src/qt/forms/coincontroldialog.ui b/src/qt/forms/coincontroldialog.ui
index d1237ad283..bd7f3c5f56 100644
--- a/src/qt/forms/coincontroldialog.ui
+++ b/src/qt/forms/coincontroldialog.ui
@@ -402,7 +402,7 @@
<bool>false</bool>
</property>
<property name="columnCount">
- <number>10</number>
+ <number>6</number>
</property>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>true</bool>
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index 695ed61228..f0b976001e 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -127,6 +127,9 @@
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
+ <property name="toolTip">
+ <string>To specify a non-default location of the data directory use the '%1' option.</string>
+ </property>
<property name="text">
<string>N/A</string>
</property>
@@ -142,13 +145,42 @@
</widget>
</item>
<item row="5" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>Blocksdir</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2">
+ <widget class="QLabel" name="blocksDir">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>To specify a non-default location of the blocks directory use the '%1' option.</string>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Startup time</string>
</property>
</widget>
</item>
- <item row="5" column="1" colspan="2">
+ <item row="6" column="1" colspan="2">
<widget class="QLabel" name="startupTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -164,7 +196,7 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="labelNetwork">
<property name="font">
<font>
@@ -177,14 +209,14 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
- <item row="7" column="1" colspan="2">
+ <item row="8" column="1" colspan="2">
<widget class="QLabel" name="networkName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -200,14 +232,14 @@
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Number of connections</string>
</property>
</widget>
</item>
- <item row="8" column="1" colspan="2">
+ <item row="9" column="1" colspan="2">
<widget class="QLabel" name="numberOfConnections">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -223,7 +255,7 @@
</property>
</widget>
</item>
- <item row="9" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
@@ -236,14 +268,14 @@
</property>
</widget>
</item>
- <item row="10" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Current number of blocks</string>
</property>
</widget>
</item>
- <item row="10" column="1" colspan="2">
+ <item row="11" column="1" colspan="2">
<widget class="QLabel" name="numberOfBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -259,14 +291,14 @@
</property>
</widget>
</item>
- <item row="11" column="0">
+ <item row="12" column="0">
<widget class="QLabel" name="labelLastBlockTime">
<property name="text">
<string>Last block time</string>
</property>
</widget>
</item>
- <item row="11" column="1" colspan="2">
+ <item row="12" column="1" colspan="2">
<widget class="QLabel" name="lastBlockTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -282,7 +314,7 @@
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="13" column="0">
<widget class="QLabel" name="labelMempoolTitle">
<property name="font">
<font>
@@ -295,14 +327,14 @@
</property>
</widget>
</item>
- <item row="13" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="labelNumberOfTransactions">
<property name="text">
<string>Current number of transactions</string>
</property>
</widget>
</item>
- <item row="13" column="1">
+ <item row="14" column="1">
<widget class="QLabel" name="mempoolNumberTxs">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -318,14 +350,14 @@
</property>
</widget>
</item>
- <item row="14" column="0">
+ <item row="15" column="0">
<widget class="QLabel" name="labelMemoryUsage">
<property name="text">
<string>Memory usage</string>
</property>
</widget>
</item>
- <item row="14" column="1">
+ <item row="15" column="1">
<widget class="QLabel" name="mempoolSize">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -341,7 +373,7 @@
</property>
</widget>
</item>
- <item row="12" column="2" rowspan="3">
+ <item row="13" column="2" rowspan="3">
<layout class="QVBoxLayout" name="verticalLayoutDebugButton">
<property name="spacing">
<number>3</number>
@@ -381,7 +413,7 @@
</item>
</layout>
</item>
- <item row="15" column="0">
+ <item row="16" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -421,6 +453,9 @@
</item>
<item>
<widget class="QComboBox" name="WalletSelector">
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToContents</enum>
+ </property>
<item>
<property name="text">
<string>(none)</string>
@@ -864,570 +899,593 @@
<attribute name="title">
<string>&amp;Peers</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0" rowspan="2">
- <layout class="QVBoxLayout" name="verticalLayout_101">
- <property name="spacing">
- <number>0</number>
- </property>
- <item>
- <widget class="QTableView" name="peerWidget">
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAsNeeded</enum>
- </property>
- <property name="tabKeyNavigation">
- <bool>false</bool>
- </property>
- <property name="sortingEnabled">
- <bool>true</bool>
- </property>
- <attribute name="horizontalHeaderHighlightSections">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="banHeading">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>300</width>
- <height>32</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>32</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>Banned peers</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::NoTextInteraction</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTableView" name="banlistWidget">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAsNeeded</enum>
- </property>
- <property name="tabKeyNavigation">
- <bool>false</bool>
- </property>
- <property name="sortingEnabled">
- <bool>true</bool>
- </property>
- <attribute name="horizontalHeaderHighlightSections">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- </layout>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="peerHeading">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>300</width>
- <height>32</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>10</pointsize>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>Select a peer to view detailed information.</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignHCenter|Qt::AlignTop</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QWidget" name="detailWidget" native="true">
- <property name="minimumSize">
- <size>
- <width>300</width>
- <height>0</height>
- </size>
+ <property name="childrenCollapsible">
+ <bool>false</bool>
</property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QLabel" name="label_30">
- <property name="text">
- <string>Whitelisted</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QLabel" name="peerWhitelisted">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_23">
- <property name="text">
- <string>Direction</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="peerDirection">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_21">
- <property name="text">
- <string>Version</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QLabel" name="peerVersion">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_28">
- <property name="text">
- <string>User Agent</string>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QLabel" name="peerSubversion">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Services</string>
- </property>
- </widget>
- </item>
- <item row="4" column="2">
- <widget class="QLabel" name="peerServices">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_29">
- <property name="text">
- <string>Starting Block</string>
- </property>
- </widget>
- </item>
- <item row="5" column="2">
- <widget class="QLabel" name="peerHeight">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="label_27">
- <property name="text">
- <string>Synced Headers</string>
- </property>
- </widget>
- </item>
- <item row="6" column="2">
- <widget class="QLabel" name="peerSyncHeight">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="7" column="0">
- <widget class="QLabel" name="label_25">
- <property name="text">
- <string>Synced Blocks</string>
- </property>
- </widget>
- </item>
- <item row="7" column="2">
- <widget class="QLabel" name="peerCommonHeight">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="8" column="0">
- <widget class="QLabel" name="label_24">
- <property name="text">
- <string>Ban Score</string>
- </property>
- </widget>
- </item>
- <item row="8" column="2">
- <widget class="QLabel" name="peerBanScore">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="9" column="0">
- <widget class="QLabel" name="label_22">
- <property name="text">
- <string>Connection Time</string>
- </property>
- </widget>
- </item>
- <item row="9" column="2">
- <widget class="QLabel" name="peerConnTime">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="10" column="0">
- <widget class="QLabel" name="label_15">
- <property name="text">
- <string>Last Send</string>
- </property>
- </widget>
- </item>
- <item row="10" column="2">
- <widget class="QLabel" name="peerLastSend">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="11" column="0">
- <widget class="QLabel" name="label_19">
- <property name="text">
- <string>Last Receive</string>
- </property>
- </widget>
- </item>
- <item row="11" column="2">
- <widget class="QLabel" name="peerLastRecv">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="12" column="0">
- <widget class="QLabel" name="label_18">
- <property name="text">
- <string>Sent</string>
- </property>
- </widget>
- </item>
- <item row="12" column="2">
- <widget class="QLabel" name="peerBytesSent">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="13" column="0">
- <widget class="QLabel" name="label_20">
- <property name="text">
- <string>Received</string>
- </property>
- </widget>
- </item>
- <item row="13" column="2">
- <widget class="QLabel" name="peerBytesRecv">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="14" column="0">
- <widget class="QLabel" name="label_26">
- <property name="text">
- <string>Ping Time</string>
- </property>
- </widget>
- </item>
- <item row="14" column="2">
- <widget class="QLabel" name="peerPingTime">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="15" column="0">
- <widget class="QLabel" name="peerPingWaitLabel">
- <property name="toolTip">
- <string>The duration of a currently outstanding ping.</string>
- </property>
- <property name="text">
- <string>Ping Wait</string>
- </property>
- </widget>
- </item>
- <item row="15" column="2">
- <widget class="QLabel" name="peerPingWait">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="16" column="0">
- <widget class="QLabel" name="peerMinPingLabel">
- <property name="text">
- <string>Min Ping</string>
- </property>
- </widget>
- </item>
- <item row="16" column="2">
- <widget class="QLabel" name="peerMinPing">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="17" column="0">
- <widget class="QLabel" name="label_timeoffset">
- <property name="text">
- <string>Time Offset</string>
- </property>
- </widget>
- </item>
- <item row="17" column="2">
- <widget class="QLabel" name="timeoffset">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="18" column="1">
- <spacer name="verticalSpacer_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <widget class="QWidget" name="widget_1" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>400</width>
+ <height>0</height>
+ </size>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <widget class="QTableView" name="peerWidget">
+ <property name="tabKeyNavigation">
+ <bool>false</bool>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="banHeading">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>Banned peers</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::NoTextInteraction</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableView" name="banlistWidget">
+ <property name="tabKeyNavigation">
+ <bool>false</bool>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="widget_2" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_8">
+ <item>
+ <widget class="QLabel" name="peerHeading">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>Select a peer to view detailed information.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="detailWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>426</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_30">
+ <property name="text">
+ <string>Whitelisted</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="peerWhitelisted">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_23">
+ <property name="text">
+ <string>Direction</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="peerDirection">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_21">
+ <property name="text">
+ <string>Version</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="peerVersion">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_28">
+ <property name="text">
+ <string>User Agent</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="peerSubversion">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Services</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="peerServices">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_29">
+ <property name="text">
+ <string>Starting Block</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLabel" name="peerHeight">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_27">
+ <property name="text">
+ <string>Synced Headers</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QLabel" name="peerSyncHeight">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_25">
+ <property name="text">
+ <string>Synced Blocks</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QLabel" name="peerCommonHeight">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_24">
+ <property name="text">
+ <string>Ban Score</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QLabel" name="peerBanScore">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0">
+ <widget class="QLabel" name="label_22">
+ <property name="text">
+ <string>Connection Time</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="QLabel" name="peerConnTime">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="0">
+ <widget class="QLabel" name="label_15">
+ <property name="text">
+ <string>Last Send</string>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="1">
+ <widget class="QLabel" name="peerLastSend">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="0">
+ <widget class="QLabel" name="label_19">
+ <property name="text">
+ <string>Last Receive</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="1">
+ <widget class="QLabel" name="peerLastRecv">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="0">
+ <widget class="QLabel" name="label_18">
+ <property name="text">
+ <string>Sent</string>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="1">
+ <widget class="QLabel" name="peerBytesSent">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="0">
+ <widget class="QLabel" name="label_20">
+ <property name="text">
+ <string>Received</string>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="1">
+ <widget class="QLabel" name="peerBytesRecv">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="14" column="0">
+ <widget class="QLabel" name="label_26">
+ <property name="text">
+ <string>Ping Time</string>
+ </property>
+ </widget>
+ </item>
+ <item row="14" column="1">
+ <widget class="QLabel" name="peerPingTime">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="0">
+ <widget class="QLabel" name="peerPingWaitLabel">
+ <property name="toolTip">
+ <string>The duration of a currently outstanding ping.</string>
+ </property>
+ <property name="text">
+ <string>Ping Wait</string>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="1">
+ <widget class="QLabel" name="peerPingWait">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="0">
+ <widget class="QLabel" name="peerMinPingLabel">
+ <property name="text">
+ <string>Min Ping</string>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="1">
+ <widget class="QLabel" name="peerMinPing">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="0">
+ <widget class="QLabel" name="label_timeoffset">
+ <property name="text">
+ <string>Time Offset</string>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="1">
+ <widget class="QLabel" name="timeoffset">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
</layout>
diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index 8f34e6bc82..240a7a7e92 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -121,7 +121,7 @@
<item>
<widget class="QLabel" name="databaseCacheUnitLabel">
<property name="text">
- <string>MB</string>
+ <string>MiB</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
@@ -714,7 +714,7 @@
<item>
<widget class="QLabel" name="overriddenByCommandLineInfoLabel">
<property name="text">
- <string>Active command-line options that override above options:</string>
+ <string>Options set in this dialog are overridden by the command line or in the configuration file:</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui
index 2f916d0b44..0d280f2993 100644
--- a/src/qt/forms/receivecoinsdialog.ui
+++ b/src/qt/forms/receivecoinsdialog.ui
@@ -108,7 +108,7 @@
</size>
</property>
<property name="text">
- <string>&amp;Request payment</string>
+ <string>&amp;Create new receiving address</string>
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
@@ -189,7 +189,7 @@
</widget>
</item>
<item>
- <widget class="QCheckBox" name="useBech32">
+ <widget class="QCheckBox" name="useLegacyAddress">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -206,10 +206,10 @@
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
- <string>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</string>
+ <string>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When checked, an address compatible with older wallets will be created instead.</string>
</property>
<property name="text">
- <string>Generate native segwit (Bech32) address</string>
+ <string>Generate legacy address</string>
</property>
</widget>
</item>
@@ -360,7 +360,7 @@
<tabstops>
<tabstop>reqLabel</tabstop>
<tabstop>reqAmount</tabstop>
- <tabstop>useBech32</tabstop>
+ <tabstop>useLegacyAddress</tabstop>
<tabstop>reqMessage</tabstop>
<tabstop>receiveButton</tabstop>
<tabstop>clearButton</tabstop>
diff --git a/src/qt/forms/receiverequestdialog.ui b/src/qt/forms/receiverequestdialog.ui
index dbe966b241..9f896ee3b1 100644
--- a/src/qt/forms/receiverequestdialog.ui
+++ b/src/qt/forms/receiverequestdialog.ui
@@ -127,7 +127,7 @@
<customwidget>
<class>QRImageWidget</class>
<extends>QLabel</extends>
- <header>qt/receiverequestdialog.h</header>
+ <header>qt/qrimagewidget.h</header>
</customwidget>
</customwidgets>
<resources/>
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index 6b31ddea90..386d559281 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -878,28 +878,15 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<item>
<layout class="QHBoxLayout" name="horizontalLayoutFee8">
<item>
- <widget class="QCheckBox" name="checkBoxMinimumFee">
- <property name="toolTip">
- <string>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="labelMinFeeWarning">
+ <widget class="QLabel" name="labelCustomFeeWarning">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
- <string>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</string>
+ <string>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</string>
</property>
<property name="text">
- <string>(read the tooltip)</string>
- </property>
- <property name="margin">
- <number>5</number>
+ <string>A too low fee might result in a never confirming transaction (read the tooltip)</string>
</property>
</widget>
</item>
@@ -992,9 +979,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<property name="text">
<string/>
</property>
- <property name="margin">
- <number>2</number>
- </property>
</widget>
</item>
<item>
@@ -1009,9 +993,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<property name="text">
<string>(Smart fee not initialized yet. This usually takes a few blocks...)</string>
</property>
- <property name="margin">
- <number>2</number>
- </property>
</widget>
</item>
<item>
@@ -1038,24 +1019,8 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<property name="text">
<string>Confirmation time target:</string>
</property>
- <property name="margin">
- <number>2</number>
- </property>
</widget>
</item>
- <item>
- <spacer name="verticalSpacer_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>1</width>
- <height>1</height>
- </size>
- </property>
- </spacer>
- </item>
</layout>
</item>
<item>
diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h
index ff47653fb7..d8f5594983 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2016 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -37,12 +37,6 @@ static const bool DEFAULT_SPLASHSCREEN = true;
*/
static const int TOOLTIP_WRAP_THRESHOLD = 80;
-/* Maximum allowed URI length */
-static const int MAX_URI_LENGTH = 255;
-
-/* QRCodeDialog -- size of exported QR Code image */
-#define QR_IMAGE_SIZE 300
-
/* Number of frames in spinner animation */
#define SPINNER_FRAMES 36
@@ -50,5 +44,9 @@ static const int MAX_URI_LENGTH = 255;
#define QAPP_ORG_DOMAIN "bitcoin.org"
#define QAPP_APP_NAME_DEFAULT "Bitcoin-Qt"
#define QAPP_APP_NAME_TESTNET "Bitcoin-Qt-testnet"
+#define QAPP_APP_NAME_REGTEST "Bitcoin-Qt-regtest"
+
+/* One gigabyte (GB) in bytes */
+static constexpr uint64_t GB_BYTES{1000000000};
#endif // BITCOIN_QT_GUICONSTANTS_H
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 9dde2c392c..45f21d50fc 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -18,13 +18,9 @@
#include <protocol.h>
#include <script/script.h>
#include <script/standard.h>
-#include <util.h>
+#include <util/system.h>
#ifdef WIN32
-#ifdef _WIN32_WINNT
-#undef _WIN32_WINNT
-#endif
-#define _WIN32_WINNT 0x0501
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif
@@ -38,8 +34,6 @@
#include <shlwapi.h>
#endif
-#include <boost/scoped_array.hpp>
-
#include <QAbstractItemView>
#include <QApplication>
#include <QClipboard>
@@ -49,20 +43,25 @@
#include <QDoubleValidator>
#include <QFileDialog>
#include <QFont>
+#include <QFontDatabase>
+#include <QFontMetrics>
+#include <QKeyEvent>
#include <QLineEdit>
+#include <QMouseEvent>
+#include <QProgressDialog>
#include <QSettings>
#include <QTextDocument> // for Qt::mightBeRichText
#include <QThread>
#include <QUrlQuery>
-#include <QMouseEvent>
+#if defined(Q_OS_MAC)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#if QT_VERSION >= 0x50200
-#include <QFontDatabase>
+#include <objc/objc-runtime.h>
+#include <CoreServices/CoreServices.h>
#endif
-static fs::detail::utf8_codecvt_facet utf8;
-
namespace GUIUtil {
QString dateTimeStr(const QDateTime &date)
@@ -77,13 +76,7 @@ QString dateTimeStr(qint64 nTime)
QFont fixedPitchFont()
{
-#if QT_VERSION >= 0x50200
return QFontDatabase::systemFont(QFontDatabase::FixedFont);
-#else
- QFont font("Monospace");
- font.setStyleHint(QFont::Monospace);
- return font;
-#endif
}
// Just some dummy data to generate a convincing random-looking (but consistent) address
@@ -182,7 +175,9 @@ bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
QString formatBitcoinURI(const SendCoinsRecipient &info)
{
- QString ret = QString("bitcoin:%1").arg(info.address);
+ bool bech_32 = info.address.startsWith(QString::fromStdString(Params().Bech32HRP() + "1"));
+
+ QString ret = QString("bitcoin:%1").arg(bech_32 ? info.address.toUpper() : info.address);
int paramCount = 0;
if (info.amount)
@@ -251,6 +246,11 @@ QList<QModelIndex> getEntryData(QAbstractItemView *view, int column)
return view->selectionModel()->selectedRows(column);
}
+QString getDefaultDataDirectory()
+{
+ return boostPathToQString(GetDefaultDataDir());
+}
+
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter,
QString *selectedSuffixOut)
@@ -344,7 +344,7 @@ bool checkPoint(const QPoint &p, const QWidget *w)
{
QWidget *atW = QApplication::widgetAt(w->mapToGlobal(p));
if (!atW) return false;
- return atW->topLevelWidget() == w;
+ return atW->window() == w;
}
bool isObscured(QWidget *w)
@@ -356,6 +356,27 @@ bool isObscured(QWidget *w)
&& checkPoint(QPoint(w->width() / 2, w->height() / 2), w));
}
+void bringToFront(QWidget* w)
+{
+#ifdef Q_OS_MAC
+ // Force application activation on macOS. With Qt 5.4 this is required when
+ // an action in the dock menu is triggered.
+ id app = objc_msgSend((id) objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
+ objc_msgSend(app, sel_registerName("activateIgnoringOtherApps:"), YES);
+#endif
+
+ if (w) {
+ // activateWindow() (sometimes) helps with keyboard focus on Windows
+ if (w->isMinimized()) {
+ w->showNormal();
+ } else {
+ w->show();
+ }
+ w->activateWindow();
+ w->raise();
+ }
+}
+
void openDebugLogfile()
{
fs::path pathDebug = GetDataDir() / "debug.log";
@@ -367,10 +388,10 @@ void openDebugLogfile()
bool openBitcoinConf()
{
- boost::filesystem::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
+ fs::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
/* Create the file */
- boost::filesystem::ofstream configFile(pathConfig, std::ios_base::app);
+ fsbridge::ofstream configFile(pathConfig, std::ios_base::app);
if (!configFile.good())
return false;
@@ -408,15 +429,15 @@ bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt)
void TableViewLastColumnResizingFixer::connectViewHeadersSignals()
{
- connect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int)));
- connect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged()));
+ connect(tableView->horizontalHeader(), &QHeaderView::sectionResized, this, &TableViewLastColumnResizingFixer::on_sectionResized);
+ connect(tableView->horizontalHeader(), &QHeaderView::geometriesChanged, this, &TableViewLastColumnResizingFixer::on_geometriesChanged);
}
// We need to disconnect these while handling the resize events, otherwise we can enter infinite loops.
void TableViewLastColumnResizingFixer::disconnectViewHeadersSignals()
{
- disconnect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int)));
- disconnect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged()));
+ disconnect(tableView->horizontalHeader(), &QHeaderView::sectionResized, this, &TableViewLastColumnResizingFixer::on_sectionResized);
+ disconnect(tableView->horizontalHeader(), &QHeaderView::geometriesChanged, this, &TableViewLastColumnResizingFixer::on_geometriesChanged);
}
// Setup the resize mode, handles compatibility for Qt5 and below as the method signatures changed.
@@ -547,40 +568,28 @@ bool SetStartOnSystemStartup(bool fAutoStart)
CoInitialize(nullptr);
// Get a pointer to the IShellLink interface.
- IShellLink* psl = nullptr;
+ IShellLinkW* psl = nullptr;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr,
- CLSCTX_INPROC_SERVER, IID_IShellLink,
+ CLSCTX_INPROC_SERVER, IID_IShellLinkW,
reinterpret_cast<void**>(&psl));
if (SUCCEEDED(hres))
{
// Get the current executable path
- TCHAR pszExePath[MAX_PATH];
- GetModuleFileName(nullptr, pszExePath, sizeof(pszExePath));
+ WCHAR pszExePath[MAX_PATH];
+ GetModuleFileNameW(nullptr, pszExePath, ARRAYSIZE(pszExePath));
// Start client minimized
QString strArgs = "-min";
// Set -testnet /-regtest options
strArgs += QString::fromStdString(strprintf(" -testnet=%d -regtest=%d", gArgs.GetBoolArg("-testnet", false), gArgs.GetBoolArg("-regtest", false)));
-#ifdef UNICODE
- boost::scoped_array<TCHAR> args(new TCHAR[strArgs.length() + 1]);
- // Convert the QString to TCHAR*
- strArgs.toWCharArray(args.get());
- // Add missing '\0'-termination to string
- args[strArgs.length()] = '\0';
-#endif
-
// Set the path to the shortcut target
psl->SetPath(pszExePath);
- PathRemoveFileSpec(pszExePath);
+ PathRemoveFileSpecW(pszExePath);
psl->SetWorkingDirectory(pszExePath);
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
-#ifndef UNICODE
- psl->SetArguments(strArgs.toStdString().c_str());
-#else
- psl->SetArguments(args.get());
-#endif
+ psl->SetArguments(strArgs.toStdWString().c_str());
// Query IShellLink for the IPersistFile interface for
// saving the shortcut in persistent storage.
@@ -588,11 +597,8 @@ bool SetStartOnSystemStartup(bool fAutoStart)
hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf));
if (SUCCEEDED(hres))
{
- WCHAR pwsz[MAX_PATH];
- // Ensure that the string is ANSI.
- MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH);
// Save the link by calling IPersistFile::Save.
- hres = ppf->Save(pwsz, TRUE);
+ hres = ppf->Save(StartupShortcutPath().wstring().c_str(), TRUE);
ppf->Release();
psl->Release();
CoUninitialize();
@@ -629,7 +635,7 @@ fs::path static GetAutostartFilePath()
bool GetStartOnSystemStartup()
{
- fs::ifstream optionFile(GetAutostartFilePath());
+ fsbridge::ifstream optionFile(GetAutostartFilePath());
if (!optionFile.good())
return false;
// Scan through file for "Hidden=true":
@@ -660,7 +666,7 @@ bool SetStartOnSystemStartup(bool fAutoStart)
fs::create_directories(GetAutostartDir());
- fs::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
+ fsbridge::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc);
if (!optionFile.good())
return false;
std::string chain = gArgs.GetChainName();
@@ -680,18 +686,11 @@ bool SetStartOnSystemStartup(bool fAutoStart)
}
-#elif defined(Q_OS_MAC)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(Q_OS_MAC) && defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED <= 101100
// based on: https://github.com/Mozketo/LaunchAtLoginController/blob/master/LaunchAtLoginController.m
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreServices/CoreServices.h>
-
-LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
-LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
+LSSharedFileListItemRef findStartupItemInList(CFArrayRef listSnapshot, LSSharedFileListRef list, CFURLRef findUrl)
{
- CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(list, nullptr);
if (listSnapshot == nullptr) {
return nullptr;
}
@@ -716,15 +715,12 @@ LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef
if(currentItemURL) {
if (CFEqual(currentItemURL, findUrl)) {
// found
- CFRelease(listSnapshot);
CFRelease(currentItemURL);
return item;
}
CFRelease(currentItemURL);
}
}
-
- CFRelease(listSnapshot);
return nullptr;
}
@@ -736,10 +732,12 @@ bool GetStartOnSystemStartup()
}
LSSharedFileListRef loginItems = LSSharedFileListCreate(nullptr, kLSSharedFileListSessionLoginItems, nullptr);
- LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
-
+ CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(loginItems, nullptr);
+ bool res = (findStartupItemInList(listSnapshot, loginItems, bitcoinAppUrl) != nullptr);
CFRelease(bitcoinAppUrl);
- return !!foundItem; // return boolified object
+ CFRelease(loginItems);
+ CFRelease(listSnapshot);
+ return res;
}
bool SetStartOnSystemStartup(bool fAutoStart)
@@ -750,7 +748,8 @@ bool SetStartOnSystemStartup(bool fAutoStart)
}
LSSharedFileListRef loginItems = LSSharedFileListCreate(nullptr, kLSSharedFileListSessionLoginItems, nullptr);
- LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
+ CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(loginItems, nullptr);
+ LSSharedFileListItemRef foundItem = findStartupItemInList(listSnapshot, loginItems, bitcoinAppUrl);
if(fAutoStart && !foundItem) {
// add bitcoin app to startup item list
@@ -762,6 +761,8 @@ bool SetStartOnSystemStartup(bool fAutoStart)
}
CFRelease(bitcoinAppUrl);
+ CFRelease(loginItems);
+ CFRelease(listSnapshot);
return true;
}
#pragma GCC diagnostic pop
@@ -780,12 +781,12 @@ void setClipboard(const QString& str)
fs::path qstringToBoostPath(const QString &path)
{
- return fs::path(path.toStdString(), utf8);
+ return fs::path(path.toStdString());
}
QString boostPathToQString(const fs::path &path)
{
- return QString::fromStdString(path.string(utf8));
+ return QString::fromStdString(path.string());
}
QString formatDurationStr(int secs)
@@ -927,4 +928,26 @@ void ClickableProgressBar::mouseReleaseEvent(QMouseEvent *event)
Q_EMIT clicked(event->pos());
}
+bool ItemDelegate::eventFilter(QObject *object, QEvent *event)
+{
+ if (event->type() == QEvent::KeyPress) {
+ if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
+ Q_EMIT keyEscapePressed();
+ }
+ }
+ return QItemDelegate::eventFilter(object, event);
+}
+
+void PolishProgressDialog(QProgressDialog* dialog)
+{
+#ifdef Q_OS_MAC
+ // Workaround for macOS-only Qt bug; see: QTBUG-65750, QTBUG-70357.
+ const int margin = dialog->fontMetrics().width("X");
+ dialog->resize(dialog->width() + 2 * margin, dialog->height());
+ dialog->show();
+#else
+ Q_UNUSED(dialog);
+#endif
+}
+
} // namespace GUIUtil
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 6aa65369fa..bea4a83494 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,6 +10,7 @@
#include <QEvent>
#include <QHeaderView>
+#include <QItemDelegate>
#include <QMessageBox>
#include <QObject>
#include <QProgressBar>
@@ -30,6 +31,7 @@ class QAbstractItemView;
class QDateTime;
class QFont;
class QLineEdit;
+class QProgressDialog;
class QUrl;
class QWidget;
QT_END_NAMESPACE
@@ -77,6 +79,11 @@ namespace GUIUtil
void setClipboard(const QString& str);
+ /**
+ * Determine default data directory for operating system.
+ */
+ QString getDefaultDataDirectory();
+
/** Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix
when no suffix is provided by the user.
@@ -114,6 +121,9 @@ namespace GUIUtil
// Determine whether a widget is hidden behind other windows
bool isObscured(QWidget *w);
+ // Activate, show and raise the widget
+ void bringToFront(QWidget* w);
+
// Open debug.log
void openDebugLogfile();
@@ -129,7 +139,7 @@ namespace GUIUtil
Q_OBJECT
public:
- explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = 0);
+ explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = nullptr);
protected:
bool eventFilter(QObject *obj, QEvent *evt);
@@ -232,6 +242,21 @@ namespace GUIUtil
typedef ClickableProgressBar ProgressBar;
+ class ItemDelegate : public QItemDelegate
+ {
+ Q_OBJECT
+ public:
+ ItemDelegate(QObject* parent) : QItemDelegate(parent) {}
+
+ Q_SIGNALS:
+ void keyEscapePressed();
+
+ private:
+ bool eventFilter(QObject *object, QEvent *event);
+ };
+
+ // Fix known bugs in QProgressDialog class.
+ void PolishProgressDialog(QProgressDialog* dialog);
} // namespace GUIUtil
#endif // BITCOIN_QT_GUIUTIL_H
diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp
index 8c00ca0363..c595361934 100644
--- a/src/qt/intro.cpp
+++ b/src/qt/intro.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,10 +10,11 @@
#include <qt/intro.h>
#include <qt/forms/ui_intro.h>
+#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <interfaces/node.h>
-#include <util.h>
+#include <util/system.h>
#include <QFileDialog>
#include <QSettings>
@@ -21,11 +22,6 @@
#include <cmath>
-static const uint64_t GB_BYTES = 1000000000LL;
-/* Minimum free space (in GB) needed for data directory */
-static const uint64_t BLOCK_CHAIN_SIZE = 200;
-/* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */
-static const uint64_t CHAIN_STATE_SIZE = 3;
/* Total required space (in GB) depending on user choice (prune, not prune) */
static uint64_t requiredSpace;
@@ -114,11 +110,13 @@ void FreespaceChecker::check()
}
-Intro::Intro(QWidget *parent) :
+Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_size) :
QDialog(parent),
ui(new Ui::Intro),
- thread(0),
- signalled(false)
+ thread(nullptr),
+ signalled(false),
+ m_blockchain_size(blockchain_size),
+ m_chain_state_size(chain_state_size)
{
ui->setupUi(this);
ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME)));
@@ -126,14 +124,14 @@ Intro::Intro(QWidget *parent) :
ui->lblExplanation1->setText(ui->lblExplanation1->text()
.arg(tr(PACKAGE_NAME))
- .arg(BLOCK_CHAIN_SIZE)
+ .arg(m_blockchain_size)
.arg(2009)
.arg(tr("Bitcoin"))
);
ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(tr(PACKAGE_NAME)));
uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0));
- requiredSpace = BLOCK_CHAIN_SIZE;
+ requiredSpace = m_blockchain_size;
QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time.");
if (pruneTarget) {
uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES);
@@ -145,7 +143,7 @@ Intro::Intro(QWidget *parent) :
} else {
ui->lblExplanation3->setVisible(false);
}
- requiredSpace += CHAIN_STATE_SIZE;
+ requiredSpace += m_chain_state_size;
ui->sizeWarningLabel->setText(
tr("%1 will download and store a copy of the Bitcoin block chain.").arg(tr(PACKAGE_NAME)) + " " +
storageRequiresMsg.arg(requiredSpace) + " " +
@@ -158,7 +156,7 @@ Intro::~Intro()
{
delete ui;
/* Ensure thread is finished before it is deleted */
- Q_EMIT stopThread();
+ thread->quit();
thread->wait();
}
@@ -170,7 +168,7 @@ QString Intro::getDataDirectory()
void Intro::setDataDirectory(const QString &dataDir)
{
ui->dataDirectory->setText(dataDir);
- if(dataDir == getDefaultDataDirectory())
+ if(dataDir == GUIUtil::getDefaultDataDirectory())
{
ui->dataDirDefault->setChecked(true);
ui->dataDirectory->setEnabled(false);
@@ -182,11 +180,6 @@ void Intro::setDataDirectory(const QString &dataDir)
}
}
-QString Intro::getDefaultDataDirectory()
-{
- return GUIUtil::boostPathToQString(GetDefaultDataDir());
-}
-
bool Intro::pickDataDirectory(interfaces::Node& node)
{
QSettings settings;
@@ -195,14 +188,21 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
if(!gArgs.GetArg("-datadir", "").empty())
return true;
/* 1) Default data directory for operating system */
- QString dataDir = getDefaultDataDirectory();
+ QString dataDir = GUIUtil::getDefaultDataDirectory();
/* 2) Allow QSettings to override default dir */
dataDir = settings.value("strDataDir", dataDir).toString();
if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || settings.value("fReset", false).toBool() || gArgs.GetBoolArg("-resetguisettings", false))
{
+ /* Use selectParams here to guarantee Params() can be used by node interface */
+ try {
+ node.selectParams(gArgs.GetChainName());
+ } catch (const std::exception&) {
+ return false;
+ }
+
/* If current default data directory does not exist, let the user choose one */
- Intro intro;
+ Intro intro(0, node.getAssumedBlockchainSize(), node.getAssumedChainStateSize());
intro.setDataDirectory(dataDir);
intro.setWindowIcon(QIcon(":icons/bitcoin"));
@@ -221,7 +221,7 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
}
break;
} catch (const fs::filesystem_error&) {
- QMessageBox::critical(0, tr(PACKAGE_NAME),
+ QMessageBox::critical(nullptr, tr(PACKAGE_NAME),
tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir));
/* fall through, back to choosing screen */
}
@@ -234,7 +234,7 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
* override -datadir in the bitcoin.conf file in the default data directory
* (to be consistent with bitcoind behavior)
*/
- if(dataDir != getDefaultDataDirectory()) {
+ if(dataDir != GUIUtil::getDefaultDataDirectory()) {
node.softSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting
}
return true;
@@ -281,14 +281,14 @@ void Intro::on_dataDirectory_textChanged(const QString &dataDirStr)
void Intro::on_ellipsisButton_clicked()
{
- QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(0, "Choose data directory", ui->dataDirectory->text()));
+ QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(nullptr, "Choose data directory", ui->dataDirectory->text()));
if(!dir.isEmpty())
ui->dataDirectory->setText(dir);
}
void Intro::on_dataDirDefault_clicked()
{
- setDataDirectory(getDefaultDataDirectory());
+ setDataDirectory(GUIUtil::getDefaultDataDirectory());
}
void Intro::on_dataDirCustom_clicked()
@@ -303,11 +303,10 @@ void Intro::startThread()
FreespaceChecker *executor = new FreespaceChecker(this);
executor->moveToThread(thread);
- connect(executor, SIGNAL(reply(int,QString,quint64)), this, SLOT(setStatus(int,QString,quint64)));
- connect(this, SIGNAL(requestCheck()), executor, SLOT(check()));
+ connect(executor, &FreespaceChecker::reply, this, &Intro::setStatus);
+ connect(this, &Intro::requestCheck, executor, &FreespaceChecker::check);
/* make sure executor object is deleted in its own thread */
- connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
- connect(this, SIGNAL(stopThread()), thread, SLOT(quit()));
+ connect(thread, &QThread::finished, executor, &QObject::deleteLater);
thread->start();
}
diff --git a/src/qt/intro.h b/src/qt/intro.h
index b0937aedcb..c3b26808d4 100644
--- a/src/qt/intro.h
+++ b/src/qt/intro.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2016 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -30,7 +30,8 @@ class Intro : public QDialog
Q_OBJECT
public:
- explicit Intro(QWidget *parent = 0);
+ explicit Intro(QWidget *parent = nullptr,
+ uint64_t blockchain_size = 0, uint64_t chain_state_size = 0);
~Intro();
QString getDataDirectory();
@@ -47,14 +48,8 @@ public:
*/
static bool pickDataDirectory(interfaces::Node& node);
- /**
- * Determine default data directory for operating system.
- */
- static QString getDefaultDataDirectory();
-
Q_SIGNALS:
void requestCheck();
- void stopThread();
public Q_SLOTS:
void setStatus(int status, const QString &message, quint64 bytesAvailable);
@@ -71,6 +66,8 @@ private:
QMutex mutex;
bool signalled;
QString pathToCheck;
+ uint64_t m_blockchain_size;
+ uint64_t m_chain_state_size;
void startThread();
void checkPath(const QString &dataDir);
diff --git a/src/qt/locale/bitcoin_af.ts b/src/qt/locale/bitcoin_af.ts
index 444952eea2..c7e7fdd56a 100644
--- a/src/qt/locale/bitcoin_af.ts
+++ b/src/qt/locale/bitcoin_af.ts
@@ -3,11 +3,11 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Regs-kliek om die adres of etiket te verander</translation>
+ <translation>Regsklik om adres of etiket te verander</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>Skep 'n nuwe adres</translation>
+ <translation>Skep ’n nuwe adres</translation>
</message>
<message>
<source>&amp;New</source>
@@ -132,6 +132,10 @@
<translation>Herhaal nuwe wagwoord</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Wys wagwoord</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Tik die nuwe wagwoord vir u beursie.&lt;br/&gt;Gerbuik asseblief 'n wagwoord met &lt;b&gt;tien of meer lukrake karakters&lt;/b&gt;, of &lt;b&gt;agt of meer woorde&lt;/b&gt;.</translation>
</message>
@@ -690,10 +694,6 @@
<translation>&amp;Adres</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nuwe ontvang adres</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nuwe stuur adres</translation>
</message>
@@ -710,10 +710,6 @@
<translation>Die ingevoerde adres "%1" is nie 'n geldige Bitcoin adres nie.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Die ingevoerde adres "%1" is reeds in die adres boek.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Kon beursie nie oopsluit nie.</translation>
</message>
@@ -763,42 +759,6 @@
<source>Command-line options</source>
<translation>Opdrag lyn opsies</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Gebruik:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opdrag lyn opsies</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Gebruikerkoppelvlakopsies:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Kies data gids by aanvang (standaard: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Stel taal, byvoorbeeld "de_DE" (standaard: stelsel lokaal)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Begin geminimeer</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Stel SSL-wortelsertifikate vir betaling versoek (standaard: -stelsel-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Wys spatskerm tydens opstart (standaard: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Alle instellings wat in die grafiese gebruikerkoppelvlak gewysig is, terugstel</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1245,6 +1205,10 @@
</context>
<context>
<name>QRImageWidget</name>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Stoor beeld</translation>
+ </message>
</context>
<context>
<name>RPCConsole</name>
@@ -1404,6 +1368,10 @@
<translation>&amp;Boodslap:</translation>
</message>
<message>
+ <source>Clear all fields of the form.</source>
+ <translation>Vee alle velde op die vorm skoon</translation>
+ </message>
+ <message>
<source>Clear</source>
<translation>Skoonmaak</translation>
</message>
@@ -1439,10 +1407,18 @@
<translation>QR Kode</translation>
</message>
<message>
+ <source>Copy &amp;URI</source>
+ <translation>Kopieer &amp;URI</translation>
+ </message>
+ <message>
<source>Copy &amp;Address</source>
<translation>Kopieer &amp;Address</translation>
</message>
<message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Stoor beeld</translation>
+ </message>
+ <message>
<source>Request payment to %1</source>
<translation>Versoek betaling van %1</translation>
</message>
@@ -1470,7 +1446,19 @@
<source>Message</source>
<translation>Boodskap</translation>
</message>
- </context>
+ <message>
+ <source>Wallet</source>
+ <translation>Beursie</translation>
+ </message>
+ <message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>Gevolglike URI te lank, probeer teks verkort vir etiket/boodskap</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Fout met enkodering van URI na QR kode</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1557,6 +1545,20 @@
<translation>Kies...</translation>
</message>
<message>
+ <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
+ <translation>Die verstekfooi kan veroorsaak dat 'n transaksie gestuur word wat
+etlike ure of dae (of nooit) sal neem om te bevestig. Oorweeg om
+'n fooi met die hand te kies, of wag tot jy die hele ketting bevestig het.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Waarskuwing: fooiskatting is tans onbeskikbaar</translation>
+ </message>
+ <message>
+ <source>collapse fee-settings</source>
+ <translation>Vou fooi-nistellings in</translation>
+ </message>
+ <message>
<source>per kilobyte</source>
<translation>per kilogreep</translation>
</message>
@@ -1565,6 +1567,13 @@
<translation>Versteek</translation>
</message>
<message>
+ <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
+ <translation>Om die minimumfooi te betaal is in die haak, mits daar minder transaksievolume
+as ruimte in die blok is. Wees bewus dat de gevolg kan wees dat 'n transaksie nooit
+bevestig nie indien daar meer aanvraag vir bitcoin transaksies is as wat die netwerk kan
+verwerk.</translation>
+ </message>
+ <message>
<source>Recommended:</source>
<translation>Aanbeveel:</translation>
</message>
@@ -1573,14 +1582,40 @@
<translation>Aangepaste:</translation>
</message>
<message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Slimfooi nog nie opgestel nie. Dit neem gewoonlik 'n paar blokke...)</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>Stuur aan veelvuldige ontvangers tegelyk</translation>
+ </message>
+ <message>
<source>Add &amp;Recipient</source>
<translation>Voeg by &amp;Ontvanger</translation>
</message>
<message>
+ <source>Clear all fields of the form.</source>
+ <translation>Vee alle velde op die vorm skoon</translation>
+ </message>
+ <message>
<source>Dust:</source>
<translation>Stof:</translation>
</message>
<message>
+ <source>Confirmation time target:</source>
+ <translation>Bevestigingstyd teiken:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Bemontlik vervang-deur-fooi</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Met Vervang-Met-Fooi (BIP-125) kan jy 'n transaskiefooi verhoog nadat dit gestuur is.
+Daarsonder mag 'n hoër fooi dalk aanbeveel word om te kompenseer vir 'n verhoogde
+transaksievertragingsrisiko.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Maak skoon &amp;Alles</translation>
</message>
@@ -1589,6 +1624,10 @@
<translation>Balans:</translation>
</message>
<message>
+ <source>Confirm the send action</source>
+ <translation>Bevestig stuuraksie</translation>
+ </message>
+ <message>
<source>S&amp;end</source>
<translation>S&amp;tuur</translation>
</message>
@@ -1629,10 +1668,80 @@
<translation>%1 tot %2</translation>
</message>
<message>
+ <source>Are you sure you want to send?</source>
+ <translation>Is u seker u wil verstuur?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>of</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>U kan die fooi later verhoog (sein Vervang-met-Fooi, BIP-125)</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaksie fooi</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Sein nie Vervang-Met-Fooi nie, BIP-25</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Bevestig versending van munte</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>Die ontvangeradres is ongeldig. Kyk asseblief weer mooi.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Bedrag moet groter as nul wees</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Die bedrag oorskry jou saldo</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>Die somtotaal oorskry jou saldo as die %1 transaksiefooi ingereken word</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>Duplikaatadres: adresse behoort slegs eenkeer gebruik te word</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Transaksieopstelling het gefaal</translation>
+ </message>
+ <message>
+ <source>The transaction was rejected with the following reason: %1</source>
+ <translation>Die transaksie is afgekeur met die volgende rede: %1</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>'n Fooi hoër as %1 word as buitensporig beskou</translation>
+ </message>
+ <message>
<source>Payment request expired.</source>
<translation>Betalings versoek verstryk.</translation>
</message>
<message>
+ <source>Pay only the required fee of %1</source>
+ <translation>Betaal slegs die verlangde fooi van %1</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Waarskuwing: Ongeldige Bitcoinadres</translation>
+ </message>
+ <message>
+ <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
+ <translation>Die adres wat u gekies het vir verandering is nie deel van hierdie
+beursie nie. Enige of alle fondse mag dalk daarheen gestuur word.
+Is u seker?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(geen etiket)</translation>
</message>
@@ -1648,14 +1757,57 @@
<translation>&amp;Etiket:</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation>Kies voorhen gebruikte adres</translation>
+ </message>
+ <message>
+ <source>This is a normal payment.</source>
+ <translation>Hierdie is 'n gewone betaling</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>Die Bitcoinadres waarheen die betaling gestuur word</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
<message>
+ <source>Paste address from clipboard</source>
+ <translation>Plak adres van aanknipbord af</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation>Verwyder hierdie inskrywing</translation>
+ </message>
+ <message>
+ <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
+ <translation>De fooi word afgetrek van die gestuurde bedrag.
+Die ontvanger sal minder ontvang as wat u in die
+bedrag opgee. As daar meer as een ontvanger is,
+word die fooi eweredig verdeel.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>Bedrag &amp;Sonder fooi </translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Gebruik beskikbare saldo</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Boodskap:</translation>
</message>
<message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>Hierdie is 'n ongemagtigde uitbetalingsversoek</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>Hierdie is 'n gemagtigde uitbetalingsversoek</translation>
+ </message>
+ <message>
<source>Pay To:</source>
<translation>Betaal Vir:</translation>
</message>
@@ -1677,10 +1829,18 @@
<translation>&amp;Teken Boodskap</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation>Kies voorhen gebruikte adres</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
<message>
+ <source>Paste address from clipboard</source>
+ <translation>Plak adres van aanknipbord af</translation>
+ </message>
+ <message>
<source>Signature</source>
<translation>Handtekening</translation>
</message>
@@ -1910,18 +2070,10 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opsies:</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Kern</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Konneksie opsies:</translation>
- </message>
- <message>
<source>Error loading %s</source>
<translation>Fout met laai %s</translation>
</message>
@@ -1930,26 +2082,10 @@
<translation>Besig met invoer...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Beursie opsies:</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(standaard: %u)</translation>
- </message>
- <message>
<source>Information</source>
<translation>Inligting</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Node aflos opsies:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC bediener opsies:</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Teken van transaksie het misluk</translation>
</message>
@@ -1974,58 +2110,10 @@
<translation>Waarskuwing</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Moenie transaksies vir langer as &lt;n&gt; ure in die geheuepoel hou nie (verstek: %u)</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is baie hoog gestel!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(standaard: %s)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Luister vir JSON-RPC konneksies op &lt;port&gt; (verstek: %u of testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Luister vir konneksies op &lt;port&gt; (verstek: %u of testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Handhaaf hoogstens &lt;n&gt; verbindings na portuurs (verstek: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Maak dat die beursie transaksies uitsaai</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maksimum per-konneksie ontvang buffer, &lt;n&gt;*1000 grepe (verstek: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maksimum per-konneksie stuur buffer, &lt;n&gt;*1000 grepe (verstek: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Voeg ontfout-uitset met tydstempel by (verstek: %u)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Spesifiseer konfigurasie lêer (verstek: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Spesifiseer konneksie timeout in millisekondes (minimum: 1, verstek: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Spesifiseer pid lêer (verstek: %s)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Begin tans netwerkdrade...</translation>
</message>
@@ -2038,10 +2126,6 @@
<translation>Dit is die transaksie fooi wat u sal betaal as u 'n transaksie stuur.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Drumpel vir die ontkoppel van misdadige portuurs (verstek: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Transaksies bedrae moet nie negatief wees nie</translation>
</message>
@@ -2055,7 +2139,7 @@
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Onbekend netwerk gespesifiseer in -onlynet: '%s'</translation>
+ <translation>Onbekende netwerk gespesifiseer in -onlynet: '%s'</translation>
</message>
<message>
<source>Insufficient funds</source>
@@ -2079,11 +2163,11 @@
</message>
<message>
<source>Done loading</source>
- <translation>Klaar met laai</translation>
+ <translation>Klaar gelaai</translation>
</message>
<message>
<source>Error</source>
<translation>Fout</translation>
</message>
</context>
-</TS> \ No newline at end of file
+</TS>
diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts
index 8c05010fb9..4f31d4cd62 100644
--- a/src/qt/locale/bitcoin_af_ZA.ts
+++ b/src/qt/locale/bitcoin_af_ZA.ts
@@ -136,6 +136,10 @@
<translation>Wys wagwoord</translation>
</message>
<message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Tik die nuwe wagwoord vir die beursie in.&lt;br/&gt;Gebruik asseblief 'n wagwoord van &lt;b&gt;ten minste 10 ewekansige karakters&lt;/b&gt;, of &lt;b&gt;agt (8) of meer woorde.&lt;/b&gt;</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Enkripteer beursie</translation>
</message>
@@ -168,12 +172,28 @@
<translation>Bevestig beursie enkripsie.</translation>
</message>
<message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Waarskuwing: As jy jou beursie enkripteer en jou wagwoord verloor, sal jy &lt;b&gt;AL JOU BITCOINS VERLOOR&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Is jy seker jy wil jou beursie enkripteer?</translation>
+ </message>
+ <message>
<source>Wallet encrypted</source>
- <translation>Beursie Enkripteer</translation>
+ <translation>Beursie enkriptasie voltooi</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 gaan nou toe maak om die enkripsie proses klaar te maak. Onthou dat jou bitcoins nie ten volle beskerm kan word deur die beursie te enkrip teen "malware" wat jou rekenaar besmet.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>BELANGRIK: Enige vorige rugsteune wat u gemaak het van u beursie-lêer moet vervang word met die nuut-gegenereerde, versleutelde beursie-lêer. Vir sekuriteitsredes sal vorige rugsteune van die onversleutelde beursie-lêer onbruikbaar word sodra u die nuwe, versleutelde beursie begin gebruik.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
- <translation>Die beursie kon nie bewaak word nie</translation>
+ <translation>Beursie enkriptasie het misluk</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
@@ -199,13 +219,29 @@
<source>Wallet passphrase was successfully changed.</source>
<translation>Die beursie se wagfrase verandering was suksesvol.</translation>
</message>
- </context>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Waarskuwing: Die Caps Lock is aan!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
- </context>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Netmasker</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Verban Tot</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
+ <source>Sign &amp;message...</source>
+ <translation>Teken &amp;Boodskap</translation>
+ </message>
+ <message>
<source>Synchronizing with network...</source>
<translation>Sinchroniseer met die netwerk ...</translation>
</message>
@@ -238,6 +274,18 @@
<translation>Sluit af</translation>
</message>
<message>
+ <source>&amp;About %1</source>
+ <translation>&amp;Oor %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Wys inligting oor %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>Oor &amp;Qt</translation>
+ </message>
+ <message>
<source>Show information about Qt</source>
<translation>Wys inligting oor Qt</translation>
</message>
@@ -246,6 +294,78 @@
<translation>&amp;Opsies</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Verander konfigurasie opsies vir %1</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;Enkripteer Beursie...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>&amp;Rugsteun Beursie...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>Verander wagwoord frase...</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses...</source>
+ <translation>Uitstuur adresse...</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses...</source>
+ <translation>&amp;Ontvang adresse...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Maak &amp;URI oop...</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Klik om netwerk aktiwiteit af te skakel.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Netwerk aktiwiteid afgeskakel.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Klik om netwerk aktiwiteit weer aan te skakel.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Sinkroniseer tans Hoofde (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Herindekseer blokke op skyf...</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>Stuur muntstukke na 'n Bitcoin adres</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>Rugsteun beursie na 'n ander plek</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Verander die wagwoordfrase wat vir beursie-versleuteling gebruik word</translation>
+ </message>
+ <message>
+ <source>&amp;Debug window</source>
+ <translation>&amp;Ontfoutvenster</translation>
+ </message>
+ <message>
+ <source>Open debugging and diagnostic console</source>
+ <translation>Open ontfouting en diagnostiese konsole</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Verifieer boodskap...</translation>
+ </message>
+ <message>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
@@ -262,6 +382,26 @@
<translation>&amp;Ontvang</translation>
</message>
<message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Wys / Versteek</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Wys of versteek die hoof Venster</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Versleutel die private sleutels wat aan u beursie behoort</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Teken boodskappe met u Bitcoin adresse om te bewys dat u hul besit</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Bevestig boodskappe om te verseker dat hulle geteken was met gespesifiseerde Bitcoin adresse</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Lêer</translation>
</message>
@@ -278,10 +418,34 @@
<translation>Blad nutsbalk</translation>
</message>
<message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Versoek betalings (genereer QR kodes en bitcoin: URIs)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Wys die lys van gebruikte stuur adresse en etikette</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Wys die lys van gebruikte ontvangsadresse en etikette</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI or payment request</source>
+ <translation>Open 'n bitcoin: URI of betalingsversoek</translation>
+ </message>
+ <message>
<source>&amp;Command-line options</source>
<translation>&amp;Opdrag lys opsies</translation>
</message>
<message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Indekseer tans blokke op skyf...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Prosesseer tans blokke op skyf...</translation>
+ </message>
+ <message>
<source>%1 behind</source>
<translation>%1 agter</translation>
</message>
@@ -290,6 +454,10 @@
<translation>Ontvangs van laaste blok is %1 terug.</translation>
</message>
<message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Opvolgende transaksies sal nog nie sigbaar wees nie.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Fout</translation>
</message>
@@ -306,23 +474,87 @@
<translation>Op datum</translation>
</message>
<message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Wys die %1 hulpboodskap om 'n lys met moontlike Bitcoin bevel-lyn opsies te verkry</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 klient</translation>
+ </message>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Verbind tans aan eweknieë...</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Besig om op te vang...</translation>
</message>
<message>
+ <source>Date: %1
+</source>
+ <translation>Datum: %1
+</translation>
+ </message>
+ <message>
<source>Amount: %1
</source>
<translation>Bedrag: %1
</translation>
</message>
<message>
+ <source>Type: %1
+</source>
+ <translation>Tipe: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Etiket: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Adres: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Gestuurde transaksie</translation>
+ </message>
+ <message>
<source>Incoming transaction</source>
<translation>Inkomende transaksie</translation>
</message>
- </context>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>HD sleutel generasie is &lt;b&gt;aangesit&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>HD sleutel generasie is &lt;b&gt;afgesit&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation>Beursie is &lt;b&gt;versleutel&lt;/b&gt; en is tans &lt;b&gt;oopgesluit&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation>Beursie is &lt;b&gt;versleutel&lt;/b&gt; en is tans &lt;b&gt;gesluit&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>'n Noodlottige fout het voorgekom. Bitcoin kan nie langer voortgaan nie en sal afsluit.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation>Munt Keuse</translation>
+ </message>
+ <message>
<source>Quantity:</source>
<translation>Hoeveelheid:</translation>
</message>
@@ -335,10 +567,26 @@
<translation>Bedrag:</translation>
</message>
<message>
+ <source>Fee:</source>
+ <translation>Fooi:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Stof:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Na Fooi:</translation>
+ </message>
+ <message>
<source>Change:</source>
<translation>Verander:</translation>
</message>
<message>
+ <source>(un)select all</source>
+ <translation>(on)selekteer alles</translation>
+ </message>
+ <message>
<source>Tree mode</source>
<translation>Boom wyse</translation>
</message>
@@ -431,6 +679,14 @@
<translation>nee</translation>
</message>
<message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Hierdie etiket verander na rooi as enige ontvanger 'n bedrag kleiner as die huidige stof drempelwaarde ontvang.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Kan wissel met +/- %1 satoshi(s) per inset.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(geen etiket)</translation>
</message>
@@ -454,12 +710,16 @@
<translation>&amp;Etiket</translation>
</message>
<message>
- <source>&amp;Address</source>
- <translation>&amp;Adres</translation>
+ <source>The label associated with this address list entry</source>
+ <translation>Die etiket geassosieer met hierdie adreslys inskrywing</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nuwe ontvangende adres</translation>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>Die adres geassosieer met hierdie adreslys inskrywing. Dié kan slegs gewysig word vir stuur-adresse.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;Adres</translation>
</message>
<message>
<source>New sending address</source>
@@ -474,17 +734,37 @@
<translation>Wysig stuurende adres</translation>
</message>
<message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Die ingeskrewe adres "%1" is nie 'n geldige Bitcoin adres nie.</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation>Kon nie die beursie oopsluit nie.</translation>
</message>
- </context>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Nuwe sleutel genereering het misluk.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
+ <source>A new data directory will be created.</source>
+ <translation>n Nuwe data lêer sal geskep word.</translation>
+ </message>
+ <message>
<source>name</source>
<translation>naam</translation>
</message>
<message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Lêer bestaan reeds. Voeg %1 indien u van plan is om n nuwe lêer hier te skep.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>Pad bestaan reeds en is nie 'n lêergids nie.</translation>
+ </message>
+ <message>
<source>Cannot create data directory here.</source>
<translation>Kan nie data gids hier skep nie.</translation>
</message>
@@ -507,27 +787,7 @@
<source>Command-line options</source>
<translation>Opdrag lys opsies</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Gebruik:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opdrag lys opsies</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Gebruikerskoppelvlak Opsies:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Kies data gids op aanvang (standaard: %u)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Begin verminderd</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -543,6 +803,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Die beursie sal ook gestoor word in hierdie lêer.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Fout</translation>
</message>
@@ -554,6 +818,10 @@
<translation>Vorm</translation>
</message>
<message>
+ <source>Progress</source>
+ <translation>Vorderering</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation>Steek weg</translation>
</message>
@@ -642,6 +910,10 @@
<source>Balances</source>
<translation>Balans</translation>
</message>
+ <message>
+ <source>Total:</source>
+ <translation>Totaal:</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -656,6 +928,30 @@
<translation>Bedrag</translation>
</message>
<message>
+ <source>%1 d</source>
+ <translation>%1 d</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 h</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 m</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 s</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>Geen</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation>%1 ms</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>onbekend</translation>
</message>
@@ -710,6 +1006,10 @@
<source>Message</source>
<translation>Boodskap</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Beursie</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -753,6 +1053,14 @@
<translation>Bedrag:</translation>
</message>
<message>
+ <source>Fee:</source>
+ <translation>Fooi:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Na Fooi:</translation>
+ </message>
+ <message>
<source>Change:</source>
<translation>Verander:</translation>
</message>
@@ -769,6 +1077,10 @@
<translation>Stuur aan vele ontvangers op eens</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>Stof:</translation>
+ </message>
+ <message>
<source>Balance:</source>
<translation>Balans:</translation>
</message>
@@ -813,6 +1125,10 @@
<translation>of</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Transaksie fooi</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(geen etiket)</translation>
</message>
@@ -1118,14 +1434,14 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opsies:</translation>
- </message>
- <message>
<source>Error: Disk space is low!</source>
<translation>Fout: Hardeskyf spasie is baie laag!</translation>
</message>
<message>
+ <source>Importing...</source>
+ <translation>Invoer proses tans besig..</translation>
+ </message>
+ <message>
<source>Information</source>
<translation>Informasie</translation>
</message>
diff --git a/src/qt/locale/bitcoin_am.ts b/src/qt/locale/bitcoin_am.ts
new file mode 100644
index 0000000000..46942066e2
--- /dev/null
+++ b/src/qt/locale/bitcoin_am.ts
@@ -0,0 +1,451 @@
+<TS language="am" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>አድራሻ ወይም መለያ ስም ለመቀየር ቀኙን ጠቅ ያድርጉ</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>አዲስ አድራሻ ፍጠር</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;አዲስ</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>አሁን የተመረጠውን አድራሻ ወደ ሲስተሙ ቅንጥብ ሰሌዳ ቅዳ</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;ቅዳ</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>ዝጋ</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>አሁን የተመረጠውን አድራሻ ከዝርዝሩ ውስጥ ሰርዝ</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>በአሁኑ ማውጫ ውስጥ ያለውን መረጃ ወደ አንድ ፋይል ላክ</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;ላክ</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;ሰርዝ</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>ገንዘብ/ኮይኖች የሚልኩለትን አድራሻ ይምረጡ</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>ገንዘብ/ኮይኖች የሚቀበሉበትን አድራሻ ይምረጡ</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>ምረጥ</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>የመላኪያ አድራሻዎች</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>የመቀበያ አድራሻዎች</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>እነኚ የቢትኮይን ክፍያ የመላኪያ አድራሻዎችዎ ናቸው:: ገንዘብ/ኮይኖች ከመላክዎ በፊት መጠኑን እና የመቀበያ አድራሻውን ሁልጊዜ ያረጋግጡ::</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>እነኚ የቢትኮይን ክፍያ የመቀበያ አድራሻዎችዎ ናቸው:: ለእያንዳንዱ ግብይት አዲስ የመቀበያ አድራሻ እንዲጠቀሙ ይመከራል:: </translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;አድራሻ ቅዳ</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>ቅዳ &amp;መለያ ስም</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation> &amp;ቀይር</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>የአድራሻ ዝርዝር ላክ</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>ኮማ ሴፓሬትድ ፋይል (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>ወደ ውጪ መላክ አልተሳካም</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>የአድራሻ ዝርዝሩን ወደ %1 ለማስቀመጥ ሲሞከር ስህተት አጋጥሟል:: እባክዎ መልሰው ይሞክሩ::</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>አድራሻ</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation>የይለፍ-ሐረግ ንግግር</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>የይለፍ-ሐረግዎን ያስገቡ</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>አዲስ የይለፍ-ሐረግ</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>አዲስ የይለፍ-ሐረጉን ይድገሙት</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>አዲስ የይለፍ ሐረግዎን ወደ ቢትኮይን ቦርሳዎ ያስገቡ:: &lt;br/&gt;እባክዎ ለየይለፍ ሐረግዎ&lt;b&gt;አስር ወይም ከዚያ በላይ የዘፈቀደ ዓይነተ-ፊደላት&lt;/b&gt;, ወይም&lt;b&gt;ስምንት ወይም ከዚያ በላይ ቃላት&lt;/b&gt; ይጠቀሙ ::</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>የቢትኮይን ቦርሳውን አመስጥር</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>ይህ ክንዋኔ የቢትኮይን ቦርሳዎን ለመክፈት የቦርሳዎ ይለፍ-ሐረግ ያስፈልገዋል::</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>የቢትኮይን ቦርሳውን ክፈት</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>ይህ ክንዋኔ የቢትኮይን ቦርሳዎን ለመፍታት የቦርሳዎ ይለፍ-ሐረግ ያስፈልገዋል::</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>የቢትኮይን ቦርሳውን ፍታ</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>ይለፍ-ሐረግ ለውጥ</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>የድሮውን የይለፍ-ሐረግ እና አዲሱን የይለፍ-ሐረግ ወደ ቢትኮይን ቦርሳዎ ያስገቡ::</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>የቢትኮይን ቦርሳዎን ማመስጠር ያረጋግጡ</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>ማስጠንቀቂያ: የቢትኮይን ቦርሳዎን አመስጥረው የይለፍ-ሐረግዎን ካጡት&lt;b&gt;ቢትኮይኖቾን በሙሉ ያጣሉ&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>እርግጠኛ ነዎት ቦርሳዎን ማመስጠር ይፈልጋሉ?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>ቦርሳዎ ምስጢር ተደርጓል</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 የማመስጠር ሂደቱን ለመጨረስ አሁን ይዘጋል:: ያስታውሱ፣ ኮምፒተርዎ በተንኮል አዘል ሶፍትዌር ከተበከለ ቦርሳዎን ማመስጠር ቢትኮይኖቾን ሙሉበሙሉ እንዳይሰረቁ ሊከላከል አይችልም::</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>አስፈላጊ: ከ ቦርሳ ፋይልዎ ያከናወኗቸው ቀደም ያሉ ምትኬዎች በአዲስ በተፈጠረ የማመስጠሪያ ፋይል ውስጥ መተካት አለባቸው. ለደህንነት ሲባል, አዲሱን የተመሰጠ የቦርሳ ፋይል መጠቀም ሲጀመሩ ወዲያውኑ ቀደም ሲል ያልተመሰጠሩ የቦርሳ ፋይል ቅጂዎች ዋጋ ቢስ ይሆናሉ::</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>የቦርሳ ማመስጠር አልተሳካም</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>የቦርሳ ማመስጠር በውስጣዊ ስህተት ምክንያት አልተሳካም:: ቦርሳዎ አልተመሰጠረም::</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>የተሰጡት የይለፍ-ሐረግዎች አይዛመዱም::</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>ቦርሳ መክፈት አልተሳካም</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>ቦርሳ ለመፍታት ያስገቡት የይለፍ-ሐረግ ትክክል አልነበረም::</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>ቦርሳ መፍታት አልተሳካም </translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>የቦርሳ የይለፍ-ሐረግ በተሳካ ሁኔታ ተቀይሯል.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>ማስጠንቀቂያ: የ "Caps Lock" ቁልፍ በርቷል!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>አይፒ/ኔትማስክ IP/Netmask</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>ታግደዋል እስከ</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>ምልክትና መልእክት...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>ከኔትወርክ ጋራ በማመሳሰል ላይ ነው...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;አጠቃላይ እይታ</translation>
+ </message>
+ <message>
+ <source>Node</source>
+ <translation>እትር</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>የቦርሳ አጠቃላይ እይታ ኣሳይ</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;ግብይቶች</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>የግብይት ታሪክ ያስሱ</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>ውጣ</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>አፕሊኬሽኑን አቁም</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;ስለ %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>ስለ %1 መረጃ አሳይ</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>ስለ &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>ስለ Qt መረጃ አሳይ</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;አማራጮች...</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</translation>
+ </message>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ </context>
+<context>
+ <name>QObject::QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Address</source>
+ <translation>አድራሻ</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ </context>
+<context>
+ <name>SendConfirmationDialog</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ </context>
+<context>
+ <name>SplashScreen</name>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(መለያ ስም የለም)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>ኮማ ሴፓሬትድ ፋይል (*.csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>መለያ ስም</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>አድራሻ</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>ወደ ውጪ መላክ አልተሳካም</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;ላክ</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>በአሁኑ ማውጫ ውስጥ ያለውን መረጃ ወደ አንድ ፋይል ላክ</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts
index 3937367446..d176505ac3 100644
--- a/src/qt/locale/bitcoin_ar.ts
+++ b/src/qt/locale/bitcoin_ar.ts
@@ -7,7 +7,7 @@
</message>
<message>
<source>Create a new address</source>
- <translation>انشأ عنوان جديد</translation>
+ <translation>انشاء عنوان جديد</translation>
</message>
<message>
<source>&amp;New</source>
@@ -30,6 +30,10 @@
<translation>حذف العنوان المحدد من القائمة</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>ادخل عنوان أووصف للبحث</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>تحميل البيانات في علامة التبويب الحالية إلى ملف.</translation>
</message>
@@ -63,11 +67,11 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>هذه هي عناوين Bitcion التابعة لك من أجل إرسال الدفعات. تحقق دائما من المبلغ و عنوان المرسل المستقبل قبل إرسال العملات</translation>
+ <translation>هذه هي عناوين Bitcoin التابعة لك من أجل إرسال الدفعات. تحقق دائما من المبلغ و عنوان المرسل المستقبل قبل إرسال العملات</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>هذه هي عناوين Bitcion التابعة لك من أجل إستقبال الدفعات. ينصح استخدام عنوان جديد من أجل كل صفقة</translation>
+ <translation>هذه هي عناوين Bitcoin التابعة لك من أجل إستقبال الدفعات. ينصح استخدام عنوان جديد من أجل كل صفقة</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -184,6 +188,10 @@
<translation>محفظة مشفرة</translation>
</message>
<message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>سيتم إغلاق %1 الآن لإنهاء عملية التشفير. تذكر أن تشفير محفظتك لا يمكن أن يحمي البتكوين الخاص بك بالكامل من السرقة عبر البرامج الضارة التي بامكانها أن تصيب جهاز الكمبيوتر الخاص بك.</translation>
+ </message>
+ <message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
<translation>هام: أي نسخة إحتياطية سابقة قمت بها لمحفظتك يجب استبدالها بأخرى حديثة، مشفرة. لأسباب أمنية، النسخ الاحتياطية السابقة لملفات المحفظة الغير مشفرة تصبح عديمة الفائدة مع بداية استخدام المحفظة المشفرة الجديدة.</translation>
</message>
@@ -330,8 +338,12 @@
<translation>اضغط لتفعيل الشبكه مره أخرى</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>مزامنة الرؤوس (%1%)...</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
- <translation>إعادة الفهرسة الكتل على القرص ...</translation>
+ <translation>إعادة فهرسة الكتل على القرص ...</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
@@ -431,7 +443,7 @@
</message>
<message>
<source>Indexing blocks on disk...</source>
- <translation>ترتيب الفهرسة الكتل على القرص...</translation>
+ <translation>ترتيب فهرسة الكتل على القرص...</translation>
</message>
<message>
<source>Processing blocks on disk...</source>
@@ -522,6 +534,14 @@
<translation>المعاملات الواردة</translation>
</message>
<message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>توليد المفاتيح الهرمية الحتمية HD &lt;b&gt;مفعل&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>توليد المفاتيح الهرمية الحتمية HD &lt;b&gt;معطل&lt;/b&gt;</translation>
+ </message>
+ <message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>المحفظة &lt;b&gt;مشفرة&lt;/b&gt; و &lt;b&gt;مفتوحة&lt;/b&gt; حاليا</translation>
</message>
@@ -621,6 +641,14 @@
<translation>نسخ رقم العملية</translation>
</message>
<message>
+ <source>Lock unspent</source>
+ <translation>قفل غير المنفق</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>فتح غير المنفق</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation>نسخ الكمية </translation>
</message>
@@ -637,6 +665,10 @@
<translation>نسخ البايتات </translation>
</message>
<message>
+ <source>Copy dust</source>
+ <translation>نسخ الغبار</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation>نسخ التعديل</translation>
</message>
@@ -649,6 +681,14 @@
<translation>لا</translation>
</message>
<message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>يتحول هذا الملصق إلى اللون الأحمر إذا تلقى أي مستلم كمية أصغر من عتبة الغبار الحالية.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>يمكن أن يختلف +/- %1 من ساتوشي(s) لكل إدخال.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(لا وصف)</translation>
</message>
@@ -680,10 +720,6 @@
<translation>&amp;العنوان</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>عنوان أستلام جديد</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>عنوان إرسال جديد</translation>
</message>
@@ -700,10 +736,6 @@
<translation>العنوان المدخل "%1" ليس عنوان بيت كوين صحيح.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>هدا العنوان "%1" موجود مسبقا في دفتر العناوين</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation> يمكن فتح المحفظة.</translation>
</message>
@@ -716,7 +748,7 @@
<name>FreespaceChecker</name>
<message>
<source>A new data directory will be created.</source>
- <translation>سيتم انشاء دليل بيانات جديد</translation>
+ <translation>سيتم انشاء دليل بيانات جديد.</translation>
</message>
<message>
<source>name</source>
@@ -724,7 +756,7 @@
</message>
<message>
<source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>الدليل موجوج بالفعل. أضف %1 لو نويت إنشاء دليل جديد هنا.</translation>
+ <translation>الدليل موجوج بالفعل. أضف %1 اذا نويت إنشاء دليل جديد هنا.</translation>
</message>
<message>
<source>Path already exists, and is not a directory.</source>
@@ -742,6 +774,10 @@
<translation>النسخة</translation>
</message>
<message>
+ <source>(%1-bit)</source>
+ <translation>(%1-بت)</translation>
+ </message>
+ <message>
<source>About %1</source>
<translation>حوالي %1</translation>
</message>
@@ -749,42 +785,6 @@
<source>Command-line options</source>
<translation>خيارات سطر الأوامر</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>المستخدم</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>خيارات سطر الأوامر</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>خيارات واجهة المستخدم</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>اختر دليل البيانات عند بدء التشغير (افتراضي: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>أضع لغة, على سبيل المثال " de_DE " (افتراضي:- مكان النظام)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>الدخول مصغر</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>أضع شهادة بروتوكول الشبقة الأمنية لطلب المدفوع (افتراضي: -نظام-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>أظهر شاشة البداية عند بدء التشغيل (افتراضي: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>اعد تعديل جميع النظم المتغيرة في GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -801,6 +801,18 @@
<translation>بما انه هذه اول مرة لانطلاق هذا البرنامج, فيمكنك ان تختار اين سيخزن %1 بياناته</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>عند النقر على "موافق" ، سيبدأ %1 في تنزيل ومعالجة سلسلة الكتل %4 الكاملة (%2 جيجابايت) بدءًا من المعاملات الأقدم في %3 عند تشغيل %4 في البداية.</translation>
+ </message>
+ <message>
+ <source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
+ <translation>تُعد هذه المزامنة الأولية أمرًا شاقًا للغاية، وقد تعرض جهاز الكمبيوتر الخاص بك للمشاكل الذي لم يلاحظها أحد سابقًا. في كل مرة تقوم فيها بتشغيل %1، سيتابع التحميل من حيث تم التوقف.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>إذا كنت قد اخترت تقييد تخزين سلسلة الكتل (التجريد)، فيجب تحميل البيانات القديمة ومعالجتها، ولكن سيتم حذفها بعد ذلك للحفاظ على انخفاض استخدام القرص.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>استخدام دليل البانات الافتراضي</translation>
</message>
@@ -813,6 +825,22 @@
<translation>بتكوين</translation>
</message>
<message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>سيتم تخزين %1 جيجابايت على الأقل من البيانات في هذا الدليل، وستنمو مع الوقت.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>سيتم تخزين %1 جيجابايت تقريباً من البيانات في هذا الدليل.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>سيقوم %1 بتنزيل نسخة من سلسلة كتل بتكوين وتخزينها.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>سوف يتم تخزين المحفظة في هذا الدليل.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" cannot be created.</source>
<translation>خطأ: لا يمكن تكوين دليل بيانات مخصص ل %1</translation>
</message>
@@ -828,6 +856,14 @@
<translation>نمودج</translation>
</message>
<message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation>قد لا تكون المعاملات الأخيرة مرئية بعد، وبالتالي قد يكون رصيد محفظتك غير صحيح. ستكون هذه المعلومات صحيحة بمجرد الانتهاء من محفظتك مع شبكة البيتكوين، كما هو مفصل أدناه.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation>لن تقبل الشبكة محاولة إنفاق البتكوين المتأثرة بالمعاملات التي لم يتم عرضها بعد.</translation>
+ </message>
+ <message>
<source>Number of blocks left</source>
<translation>عدد الكتل الفاضلة</translation>
</message>
@@ -859,7 +895,11 @@
<source>Hide</source>
<translation>إخفاء</translation>
</message>
- </context>
+ <message>
+ <source>Unknown. Syncing Headers (%1)...</source>
+ <translation>غير معروف. مزامنة الرؤوس (%1) ...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -871,6 +911,10 @@
<translation>حدد طلب الدفع من ملف او URI</translation>
</message>
<message>
+ <source>URI:</source>
+ <translation>العنوان:</translation>
+ </message>
+ <message>
<source>Select payment request file</source>
<translation>حدد ملف طلب الدفع</translation>
</message>
@@ -890,14 +934,62 @@
<translation>&amp;الرئيسي</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>ابدأ تلقائيًا %1 بعد تسجيل الدخول إلى النظام.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>تشغيل %1 عند الدخول إلى النظام</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>حجم ذاكرة التخزين المؤقت لقاعدة البيانات</translation>
+ </message>
+ <message>
<source>MB</source>
<translation>م ب</translation>
</message>
<message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>عدد مؤشرات التحقق من البرنامج النصي</translation>
+ </message>
+ <message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation>إظهار ما إذا كان وكيل SOCKS5 الافتراضي الموفر تم استخدامه للوصول إلى النظراء عبر نوع الشبكة هذا.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>استخدام وكيل SOCKS5 منفصل للوصول إلى الأقران عبر خدمات Tor المخفية:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>إخفاء الآيقونة من صينية النظام.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>اخفاء آيقونة الصينية</translation>
+ </message>
+ <message>
+ <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
+ <translation>التصغير بدلاً من الخروج من التطبيق عند إغلاق النافذة. عند تفعيل هذا الخيار، سيتم إغلاق التطبيق فقط بعد اختيار الخروج من القائمة.</translation>
+ </message>
+ <message>
+ <source>Active command-line options that override above options:</source>
+ <translation>خيارات سطر الأوامر النشطة التي تتجاوز الخيارات أعلاه:</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>فتح ملف الإعدادات %1 من الدليل العامل.</translation>
+ </message>
+ <message>
<source>Open Configuration File</source>
<translation>فتح ملف الإعدادات</translation>
</message>
<message>
+ <source>Reset all client options to default.</source>
+ <translation>إعادة تعيين كل إعدادات العميل للحالة الإفتراضية.</translation>
+ </message>
+ <message>
<source>&amp;Reset Options</source>
<translation>&amp;استعادة الخيارات</translation>
</message>
@@ -914,6 +1006,34 @@
<translation>تصدير</translation>
</message>
<message>
+ <source>Enable coin &amp;control features</source>
+ <translation>تفعيل ميزات التحكم في العملة</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation>دفع الفكة غير المؤكدة</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation>ربط المنفذ باستخدام UPnP</translation>
+ </message>
+ <message>
+ <source>Accept connections from outside.</source>
+ <translation>قبول الاتصالات من الخارج.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>السماح بالاتصالات الواردة.</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>الاتصال بشبكة البتكوين عبر وكيل SOCKS5.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>الاتصال من خلال وكيل SOCKS5 (الوكيل الافتراضي):</translation>
+ </message>
+ <message>
<source>Proxy &amp;IP:</source>
<translation>بروكسي &amp;اي بي:</translation>
</message>
@@ -942,10 +1062,26 @@
<translation>تور</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>قم بالاتصال بشبكة بتكوين عبر وكيل SOCKS5 منفصل لخدمات تور المخفية.</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>نافذه</translation>
</message>
<message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation>إظهار آيقونة الصينية فقط بعد تصغير النافذة.</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation>التصغير إلى صينية النظام بدلاً من شريط المهام</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation>تصغير عند الإغلاق</translation>
+ </message>
+ <message>
<source>&amp;Display</source>
<translation>&amp;عرض</translation>
</message>
@@ -954,6 +1090,22 @@
<translation>واجهة المستخدم &amp;اللغة:</translation>
</message>
<message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>الوحدة لإظهار المبالغ فيها:</translation>
+ </message>
+ <message>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation>اختر وحدة التقسيم الفرعية الافتراضية للعرض في الواجهة وعند إرسال العملات.</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>ما اذا أردت إظهار ميزات التحكم في العملة أم لا.</translation>
+ </message>
+ <message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>العناوين (URL) لجهات خارجية</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>تم</translation>
</message>
@@ -974,6 +1126,14 @@
<translation>تأكيد استعادة الخيارات</translation>
</message>
<message>
+ <source>Client restart required to activate changes.</source>
+ <translation>يتطلب إعادة تشغيل العميل لتفعيل التغييرات.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>سوف يتم إيقاف العميل تماماً. هل تريد الإستمرار؟</translation>
+ </message>
+ <message>
<source>Configuration options</source>
<translation>إعداد الخيارات</translation>
</message>
@@ -982,6 +1142,14 @@
<translation>خطأ</translation>
</message>
<message>
+ <source>The configuration file could not be opened.</source>
+ <translation>لم تتمكن من فتح ملف الإعدادات.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>هذا التغيير يتطلب إعادة تشغيل العميل بشكل كامل.</translation>
+ </message>
+ <message>
<source>The supplied proxy address is invalid.</source>
<translation>عنوان الوكيل توفيره غير صالح.</translation>
</message>
@@ -993,18 +1161,42 @@
<translation>نمودج</translation>
</message>
<message>
+ <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
+ <translation>قد تكون المعلومات المعروضة قديمة. تتزامن محفظتك تلقائيًا مع شبكة البتكوين بعد إنشاء الاتصال، ولكن هذه العملية لم تكتمل بعد.</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>مشاهدة فقط:</translation>
+ </message>
+ <message>
<source>Available:</source>
<translation>متوفر</translation>
</message>
<message>
+ <source>Your current spendable balance</source>
+ <translation>رصيدك القابل للصرف</translation>
+ </message>
+ <message>
<source>Pending:</source>
<translation>معلق:</translation>
</message>
<message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation>إجمالي المعاملات التي لم يتم تأكيدها بعد ولا تحتسب ضمن الرصيد القابل للانفاق</translation>
+ </message>
+ <message>
<source>Immature:</source>
<translation>غير ناضجة</translation>
</message>
<message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>الرصيد المعدّن الذي لم ينضج بعد</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>الأرصدة</translation>
+ </message>
+ <message>
<source>Total:</source>
<translation>المجموع:</translation>
</message>
@@ -1012,17 +1204,137 @@
<source>Your current total balance</source>
<translation>رصيدك الكلي الحالي</translation>
</message>
- </context>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>رصيدك الحالي في العناوين المشاهدة فقط</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>قابل للصرف:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>أحدث المعاملات</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>معاملات غير مؤكدة للعناوين المشاهدة فقط</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>الرصيد المعدّن في العناوين المشاهدة فقط التي لم تنضج بعد</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>الرصيد الإجمالي الحالي في العناوين المشاهدة فقط</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
<message>
+ <source>Payment request error</source>
+ <translation>خطأ في طلب الدفع</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>لا يمكن تشغيل بتكوين: معالج النقر للدفع</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>التعامل مع العنوان</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>عنوان الدفع غير صالح %1</translation>
+ </message>
+ <message>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation>لا يمكن تحليل العنوان (URI)! يمكن أن يحدث هذا بسبب عنوان بتكوين غير صالح أو معلمات عنوان (URI) غير صحيحة.</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>التعامل مع ملف طلب الدفع</translation>
+ </message>
+ <message>
+ <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
+ <translation>لا يمكن قراءة ملف طلب الدفع! يمكن أن يحدث هذا بسبب ملف لطلب الدفع غير صالح.</translation>
+ </message>
+ <message>
+ <source>Payment request rejected</source>
+ <translation>تم رفض طلب الدفع</translation>
+ </message>
+ <message>
+ <source>Payment request network doesn't match client network.</source>
+ <translation>لا تتطابق شبكة طلب الدفع مع شبكة العميل.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>انتهاء صلاحية طلب الدفع.</translation>
+ </message>
+ <message>
+ <source>Payment request is not initialized.</source>
+ <translation>لم يتم تهيئة طلب الدفع.</translation>
+ </message>
+ <message>
+ <source>Unverified payment requests to custom payment scripts are unsupported.</source>
+ <translation>طلبات الدفع غير المؤكدة إلى نصوص الدفع المخصصة غير مدعومة.</translation>
+ </message>
+ <message>
+ <source>Invalid payment request.</source>
+ <translation>طلب دفع غير صالح.</translation>
+ </message>
+ <message>
+ <source>Requested payment amount of %1 is too small (considered dust).</source>
+ <translation>المبلغ المطلوب للدفع %1 صغير جداً (يعتبر غبار).</translation>
+ </message>
+ <message>
+ <source>Refund from %1</source>
+ <translation>إعادة مال من %1</translation>
+ </message>
+ <message>
+ <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
+ <translation>طلب الدفع %1 كبير جداً (%2 بايت، المسموح به %3 بايت).</translation>
+ </message>
+ <message>
+ <source>Error communicating with %1: %2</source>
+ <translation>حدث خطأ في الاتصال بـ %1: %2</translation>
+ </message>
+ <message>
+ <source>Payment request cannot be parsed!</source>
+ <translation>لا يمكن تحليل طلب الدفع!</translation>
+ </message>
+ <message>
<source>Bad response from server %1</source>
<translation>استجابة سيئة من الملقم %1</translation>
</message>
- </context>
+ <message>
+ <source>Network request error</source>
+ <translation>خطأ في طلب الشبكة</translation>
+ </message>
+ <message>
+ <source>Payment acknowledged</source>
+ <translation>اعتراف بالدفع</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>User Agent</source>
+ <translation>وكيل المستخدم</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>عقدة/خدمة</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>رقم العقدة</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>رنين</translation>
+ </message>
+ <message>
<source>Sent</source>
<translation>تم الإرسال</translation>
</message>
@@ -1038,6 +1350,14 @@
<translation>مبلغ</translation>
</message>
<message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>ادخل عنوان محفطة البتكوين (مثال %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 يوم</translation>
+ </message>
+ <message>
<source>%1 h</source>
<translation>%1 ساعة</translation>
</message>
@@ -1046,10 +1366,22 @@
<translation>%1 دقيقة</translation>
</message>
<message>
+ <source>%1 s</source>
+ <translation>%1 ثانية</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>لا شيء</translation>
+ </message>
+ <message>
<source>N/A</source>
<translation>غير معروف</translation>
</message>
<message>
+ <source>%1 ms</source>
+ <translation>%1 جزء من الثانية</translation>
+ </message>
+ <message>
<source>%1 and %2</source>
<translation>%1 و %2</translation>
</message>
@@ -1070,13 +1402,25 @@
<translation>%1 قيقا بايت</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation>%1 لم يخرج بعد بأمان...</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>غير معروف</translation>
</message>
</context>
<context>
<name>QObject::QObject</name>
- </context>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>خطأ: دليل البيانات المحدد "%1" غير موجود.</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>خطأ: %1</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
<message>
@@ -1119,6 +1463,14 @@
<translation>عام</translation>
</message>
<message>
+ <source>Using BerkeleyDB version</source>
+ <translation>باستخدام BerkeleyDB إصدار</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>دليل البيانات</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>وقت البدء</translation>
</message>
@@ -1139,6 +1491,26 @@
<translation>سلسلة الكتل</translation>
</message>
<message>
+ <source>Current number of blocks</source>
+ <translation>عدد الكتل الحالي</translation>
+ </message>
+ <message>
+ <source>Memory Pool</source>
+ <translation>تجمع الذاكرة</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>عدد المعاملات الحالي</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>استخدام الذاكرة</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>إعادة تعيين</translation>
+ </message>
+ <message>
<source>Received</source>
<translation>إستقبل</translation>
</message>
@@ -1151,6 +1523,18 @@
<translation>&amp;اصدقاء</translation>
</message>
<message>
+ <source>Banned peers</source>
+ <translation>الأقران الممنوعين</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>حدد نظير لعرض معلومات مفصلة.</translation>
+ </message>
+ <message>
+ <source>Whitelisted</source>
+ <translation>اللائحة البيضاء</translation>
+ </message>
+ <message>
<source>Direction</source>
<translation>جهة</translation>
</message>
@@ -1163,10 +1547,38 @@
<translation>كتلة البداية</translation>
</message>
<message>
+ <source>Synced Headers</source>
+ <translation>رؤوس متزامنة</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>كتل متزامنة</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>وكيل المستخدم</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>تصغير حجم الخط</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>تكبير حجم الخط</translation>
+ </message>
+ <message>
<source>Services</source>
<translation>خدمات</translation>
</message>
<message>
+ <source>Ban Score</source>
+ <translation>نقاط الحظر</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>مدة الاتصال</translation>
+ </message>
+ <message>
<source>Last Send</source>
<translation>آخر استقبال</translation>
</message>
@@ -1175,6 +1587,26 @@
<translation>آخر إرسال</translation>
</message>
<message>
+ <source>Ping Time</source>
+ <translation>وقت الرنين</translation>
+ </message>
+ <message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation>مدة الرنين المعلقة حالياً.</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>انتظار الرنين</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>أقل رنين</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation>إزاحة الوقت</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation>اخر وقت الكتلة</translation>
</message>
@@ -1183,6 +1615,10 @@
<translation>الفتح</translation>
</message>
<message>
+ <source>&amp;Console</source>
+ <translation>وحدة التحكم</translation>
+ </message>
+ <message>
<source>&amp;Network Traffic</source>
<translation>&amp;حركة مرور الشبكة</translation>
</message>
@@ -1199,6 +1635,14 @@
<translation>خارج:</translation>
</message>
<message>
+ <source>Debug log file</source>
+ <translation>تصحيح ملف السجل</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation>مسح وحدة التحكم</translation>
+ </message>
+ <message>
<source>1 &amp;hour</source>
<translation>1 &amp;ساعة</translation>
</message>
@@ -1215,6 +1659,50 @@
<translation>1 &amp; سنة</translation>
</message>
<message>
+ <source>&amp;Disconnect</source>
+ <translation>قطع الاتصال</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>حظر ل</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>رفع الحظر</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>مرحبًا بك في وحدة التحكم %1 RPC.</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>استخدم السهمين لأعلى ولأسفل لتصفح السجل، و%1 لمسح الشاشة.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>اكتب %1 للحصول على نظرة عامة على الأوامر المتوفرة.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>لمزيد من المعلومات حول استخدام نوع وحدة التحكم هذه اكتب %1.</translation>
+ </message>
+ <message>
+ <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
+ <translation>تحذير: المخادعون نشطون، ويطلبون من المستخدمين كتابة الأوامر هنا، من أجل سرقة محتويات محفظتهم. لا تستخدم وحدة التحكم هذه بدون فهم تبعات الأمر بشكل كامل.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>تم تعطيل نشاط الشبكة</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(معرف العقدة: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>خلال %1</translation>
+ </message>
+ <message>
<source>never</source>
<translation>ابدا</translation>
</message>
@@ -1254,6 +1742,22 @@
<translation>&amp;رسالة:</translation>
</message>
<message>
+ <source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
+ <translation>رسالة اختيارية لإرفاقها بطلب الدفع، والتي سيتم عرضها عند فتح الطلب. ملاحظة: لن يتم إرسال الرسالة مع الدفعة عبر شبكة البتكوين.</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation>تسمية اختيارية لربطها بعنوان المستلم الجديد.</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>استخدم هذا النموذج لطلب الدفعات. جميع الحقول &lt;b&gt;اختيارية&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation>مبلغ اختياري للطلب. اترك هذا فارغًا أو صفراً لعدم طلب مبلغ محدد.</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>مسح كل حقول النموذج المطلوبة</translation>
</message>
@@ -1266,14 +1770,30 @@
<translation>سجل طلبات الدفع</translation>
</message>
<message>
+ <source>&amp;Request payment</source>
+ <translation>&amp;طلب دفعة</translation>
+ </message>
+ <message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation>إظهار الطلب المحدد (يقوم بنفس نتيجة النقر المزدوج على أي إدخال)</translation>
+ </message>
+ <message>
<source>Show</source>
<translation>عرض</translation>
</message>
<message>
+ <source>Remove the selected entries from the list</source>
+ <translation>قم بإزالة الإدخالات المحددة من القائمة</translation>
+ </message>
+ <message>
<source>Remove</source>
<translation>ازل</translation>
</message>
<message>
+ <source>Copy URI</source>
+ <translation>نسخ العنوان</translation>
+ </message>
+ <message>
<source>Copy label</source>
<translation> انسخ التسمية</translation>
</message>
@@ -1305,6 +1825,10 @@
<translation>&amp;حفظ الصورة</translation>
</message>
<message>
+ <source>Request payment to %1</source>
+ <translation>طلب الدفعة إلى %1</translation>
+ </message>
+ <message>
<source>Payment information</source>
<translation>معلومات الدفع</translation>
</message>
@@ -1328,7 +1852,19 @@
<source>Message</source>
<translation>رسالة </translation>
</message>
- </context>
+ <message>
+ <source>Wallet</source>
+ <translation>محفظة</translation>
+ </message>
+ <message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>العنوان المستخدم طويل جدًا، حاول أن تقوم بتقليل نص التسمية / الرسالة.</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>خطأ في ترميز العنوان إلى الرمز المربع.</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1351,7 +1887,15 @@
<source>(no message)</source>
<translation>( لا رسائل )</translation>
</message>
- </context>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(لا يوجد مبلغ مطلوب)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>تم الطلب</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -1359,6 +1903,14 @@
<translation>إرسال Coins</translation>
</message>
<message>
+ <source>Coin Control Features</source>
+ <translation>ميزات التحكم بالعملة</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>المدخلات...</translation>
+ </message>
+ <message>
<source>automatically selected</source>
<translation>اختيار تلقائيا</translation>
</message>
@@ -1391,6 +1943,14 @@
<translation>تعديل :</translation>
</message>
<message>
+ <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
+ <translation>إذا تم تنشيط هذا، ولكن عنوان الفكة فارغ أو غير صالح، فسيتم إرسال الفكة إلى عنوان تم إنشاؤه حديثًا.</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation>تغيير عنوان الفكة</translation>
+ </message>
+ <message>
<source>Transaction Fee:</source>
<translation>رسوم المعاملة:</translation>
</message>
@@ -1399,10 +1959,42 @@
<translation>إختر …</translation>
</message>
<message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>تحذير: تقدير الرسوم غير ممكن في الوقت الحالي.</translation>
+ </message>
+ <message>
+ <source>collapse fee-settings</source>
+ <translation>خفض اعدادات الرسوم</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>لكل كيلوبايت</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation>إخفاء</translation>
</message>
<message>
+ <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
+ <translation>إن دفع الحد الأدنى فقط من الرسوم يجوز طالما أن حجم المعاملات أقل من المساحة الموجودة في الكتل. ولكن كن على علم بأن هذا يمكن أن ينتهي في معاملة غير مؤكدة أبداً عندما يكون هناك طلب أكبر على معاملات البتكوين مما تستطيع الشبكة معالجته.</translation>
+ </message>
+ <message>
+ <source>(read the tooltip)</source>
+ <translation>(اقرأ تلميح الأدوات)</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>موصى به:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>تخصيص:</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(الرسوم الذكية لم يتم تهيئتها بعد. عادة ما يستغرق ذلك بضع كتل ...)</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>إرسال إلى عدة مستلمين في وقت واحد</translation>
</message>
@@ -1419,6 +2011,18 @@
<translation>غبار:</translation>
</message>
<message>
+ <source>Confirmation time target:</source>
+ <translation>هدف وقت التأكيد:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>تفعيل الإستبدال بواسطة الرسوم</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>مع الإستبدال بواسطة الرسوم (BIP-125) يمكنك زيادة رسوم المعاملة بعد إرسالها. وبدون ذلك، قد نوصي برسوم أعلى للتعويض عن مخاطر تأخير المعاملة المتزايدة.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>مسح الكل</translation>
</message>
@@ -1455,22 +2059,50 @@
<translation>نسخ البايتات </translation>
</message>
<message>
+ <source>Copy dust</source>
+ <translation>نسخ الغبار</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation>نسخ التعديل</translation>
</message>
<message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 كثلة)</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 الى %2</translation>
</message>
<message>
+ <source>Are you sure you want to send?</source>
+ <translation>هل أنت متأكد من أنك تريد أن ترسل؟</translation>
+ </message>
+ <message>
<source>or</source>
<translation>أو</translation>
</message>
<message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>يمكنك زيادة الرسوم لاحقًا (بإشارة الإستبدال بواسطة الرسوم، BIP-125).</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>رسوم المعاملة</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>لا يشير إلى الإستبدال بواسطة الرسوم، BIP-125.</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>تأكيد الإرسال Coins</translation>
</message>
<message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>عنوان المستلم غير صالح. يرجى إعادة الفحص.</translation>
+ </message>
+ <message>
<source>The amount to pay must be larger than 0.</source>
<translation>المبلغ المدفوع يجب ان يكون اكبر من 0</translation>
</message>
@@ -1483,6 +2115,42 @@
<translation>المجموع يتجاوز رصيدك عندما يتم اضافة %1 رسوم العملية</translation>
</message>
<message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>تم العثور على عنوان مكرر: يجب استخدام العناوين مرة واحدة فقط.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>فشل في إنشاء المعاملة!</translation>
+ </message>
+ <message>
+ <source>The transaction was rejected with the following reason: %1</source>
+ <translation>تم رفض المعاملة للسبب التالي: %1</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>تعتبر الرسوم الأعلى من %1 رسوماً باهظة.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>انتهاء صلاحية طلب الدفع.</translation>
+ </message>
+ <message>
+ <source>Pay only the required fee of %1</source>
+ <translation>دفع فقط الرسوم المطلوبة ل %1</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>تحذير: عنوان بتكوين غير صالح</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>تحذير: عنوان الفكة غير معروف</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>تأكيد تغيير العنوان الفكة</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(لا وصف)</translation>
</message>
@@ -1530,14 +2198,46 @@
<translation>ازل هذه المداخله</translation>
</message>
<message>
+ <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
+ <translation>سيتم خصم الرسوم من المبلغ الذي يتم إرساله. لذا سوف يتلقى المستلم مبلغ أقل من البتكوين المدخل في حقل المبلغ. في حالة تحديد عدة مستلمين، يتم تقسيم الرسوم بالتساوي.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>طرح الرسوم من المبلغ</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>استخدام الرصيد المتاح</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>الرسائل</translation>
</message>
<message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>هذا طلب دفع لم يتم مصادقته.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>هذا طلب دفع تمت مصادقته.</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <translation>أدخل تسمية لهذا العنوان لإضافته إلى قائمة العناوين المستخدمة</translation>
+ </message>
+ <message>
+ <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
+ <translation>الرسالة التي تم إرفاقها مع البتكوين: العنوان الذي سيتم تخزينه مع المعاملة للرجوع إليه. ملاحظة: لن يتم إرسال هذه الرسالة عبر شبكة البتكوين.</translation>
+ </message>
+ <message>
<source>Pay To:</source>
<translation>ادفع &amp;الى :</translation>
</message>
<message>
+ <source>Memo:</source>
+ <translation>مذكرة:</translation>
+ </message>
+ <message>
<source>Enter a label for this address to add it to your address book</source>
<translation>إدخال تسمية لهذا العنوان لإضافته إلى دفتر العناوين الخاص بك</translation>
</message>
@@ -1552,6 +2252,10 @@
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down...</source>
+ <translation>اتمام إيقاف %1...</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation>لا توقف عمل الكمبيوتر حتى تختفي هذه النافذة</translation>
</message>
@@ -1559,10 +2263,18 @@
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>التواقيع - التوقيع / التحقق من الرسالة</translation>
+ </message>
+ <message>
<source>&amp;Sign Message</source>
<translation>&amp;توقيع الرسالة</translation>
</message>
<message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>عنوان البتكوين لتوقيع الرسالة به</translation>
+ </message>
+ <message>
<source>Choose previously used address</source>
<translation>اختر عنوانا مستخدم سابقا</translation>
</message>
@@ -1587,6 +2299,10 @@
<translation>التوقيع</translation>
</message>
<message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>نسخ التوقيع الحالي إلى حافظة النظام</translation>
+ </message>
+ <message>
<source>Sign the message to prove you own this Bitcoin address</source>
<translation>وقع الرسالة لتثبت انك تمتلك عنوان البت كوين هذا</translation>
</message>
@@ -1595,6 +2311,10 @@
<translation>توقيع $الرسالة</translation>
</message>
<message>
+ <source>Reset all sign message fields</source>
+ <translation>إعادة تعيين كافة حقول رسالة التوقيع</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>مسح الكل</translation>
</message>
@@ -1603,10 +2323,22 @@
<translation>&amp;تحقق رسالة</translation>
</message>
<message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>عنوان البتكوين الذي تم توقيع الرسالة به</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>تحقق من الرسالة للتأكد من توقيعها مع عنوان البتكوين المحدد</translation>
+ </message>
+ <message>
<source>Verify &amp;Message</source>
<translation>تحقق &amp;الرسالة</translation>
</message>
<message>
+ <source>Reset all verify message fields</source>
+ <translation>إعادة تعيين جميع حقول التحقق من الرسالة</translation>
+ </message>
+ <message>
<source>Click "Sign Message" to generate signature</source>
<translation>اضغط "توقيع الرسالة" لتوليد التوقيع</translation>
</message>
@@ -1639,10 +2371,18 @@
<translation>الرسالة موقعة.</translation>
</message>
<message>
+ <source>The signature could not be decoded.</source>
+ <translation>لا يمكن فك تشفير التوقيع.</translation>
+ </message>
+ <message>
<source>Please check the signature and try again.</source>
<translation>فضلا تاكد من التوقيع وحاول مرة اخرى</translation>
</message>
<message>
+ <source>The signature did not match the message digest.</source>
+ <translation>لم يتطابق التوقيع مع ملخص الرسالة.</translation>
+ </message>
+ <message>
<source>Message verification failed.</source>
<translation>فشلت عملية التأكد من الرسالة.</translation>
</message>
@@ -1660,7 +2400,11 @@
</context>
<context>
<name>TrafficGraphWidget</name>
- </context>
+ <message>
+ <source>KB/s</source>
+ <translation>كيلوبايت/ث</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
@@ -1668,8 +2412,20 @@
<translation>مفتوح حتى %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1 غير متواجد</translation>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>تعارضت مع معاملة لديها %1 تأكيدات</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>في تجمع الذاكرة</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>ليس في تجمع الذاكرة</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>مهجور</translation>
</message>
<message>
<source>%1/unconfirmed</source>
@@ -1684,10 +2440,6 @@
<translation>الحالة.</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, لم يتم حتى الآن البث بنجاح</translation>
- </message>
- <message>
<source>Date</source>
<translation>تاريخ</translation>
</message>
@@ -1724,6 +2476,10 @@
<translation>علامة</translation>
</message>
<message>
+ <source>Credit</source>
+ <translation>رصيد</translation>
+ </message>
+ <message>
<source>not accepted</source>
<translation>غير مقبولة</translation>
</message>
@@ -1732,10 +2488,22 @@
<translation>دين</translation>
</message>
<message>
+ <source>Total debit</source>
+ <translation>إجمالي الخصم</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>إجمالي الرصيد</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>رسوم المعاملة</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>صافي المبلغ</translation>
+ </message>
+ <message>
<source>Message</source>
<translation>رسالة </translation>
</message>
@@ -1748,14 +2516,30 @@
<translation>رقم المعاملة</translation>
</message>
<message>
+ <source>Transaction total size</source>
+ <translation>الحجم الكلي للمعاملات</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>مؤشر المخرجات</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>تاجر</translation>
</message>
<message>
+ <source>Debug information</source>
+ <translation>معلومات التصحيح</translation>
+ </message>
+ <message>
<source>Transaction</source>
<translation>معاملة</translation>
</message>
<message>
+ <source>Inputs</source>
+ <translation>المدخلات</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>مبلغ</translation>
</message>
@@ -1774,7 +2558,11 @@
<source>This pane shows a detailed description of the transaction</source>
<translation>يبين هذا الجزء وصفا مفصلا لهده المعاملة</translation>
</message>
- </context>
+ <message>
+ <source>Details for %1</source>
+ <translation>تفاصيل عن %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
@@ -1794,16 +2582,24 @@
<translation>مفتوح حتى %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>غير متصل</translation>
+ <source>Unconfirmed</source>
+ <translation>غير مؤكد</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>مهجور</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>قيد التأكيد (%1 من %2 تأكيد موصى به)</translation>
</message>
<message>
<source>Conflicted</source>
<translation>يتعارض</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>لم يتم تلقى هذه الكتلة (Block) من قبل أي العقد الأخرى وربما لن تكون مقبولة!</translation>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>غير ناضجة (تأكيدات %1 ، ستكون متوفرة بعد %2)</translation>
</message>
<message>
<source>Generated but not accepted</source>
@@ -1854,6 +2650,10 @@
<translation>نوع المعاملات</translation>
</message>
<message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>ما إذا كان العنوان المشاهدة فقط متضمنًا في هذه المعاملة أم لا.</translation>
+ </message>
+ <message>
<source>Amount removed from or added to balance.</source>
<translation>المبلغ الذي أزيل أو أضيف الى الرصيد</translation>
</message>
@@ -1909,10 +2709,22 @@
<translation>اخرى</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>أدخل العنوان أو معرف المعاملة أو التصنيف للبحث</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>الحد الأدنى</translation>
</message>
<message>
+ <source>Abandon transaction</source>
+ <translation>التخلي عن المعاملة</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>زيادة رسوم المعاملة</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation> انسخ عنوان</translation>
</message>
@@ -1929,6 +2741,14 @@
<translation>نسخ رقم العملية</translation>
</message>
<message>
+ <source>Copy raw transaction</source>
+ <translation>نسخ المعاملة الخام</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>نسخ كامل تفاصيل المعاملة</translation>
+ </message>
+ <message>
<source>Edit label</source>
<translation>عدل الوصف</translation>
</message>
@@ -1937,6 +2757,10 @@
<translation>عرض تفاصيل المعاملة</translation>
</message>
<message>
+ <source>Export Transaction History</source>
+ <translation>تصدير تفاصيل المعاملات</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>ملف مفصول بفواصل (*.csv)</translation>
</message>
@@ -1945,6 +2769,10 @@
<translation>تأكيد</translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation>مشاهدة فقط</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>تاريخ</translation>
</message>
@@ -1969,10 +2797,18 @@
<translation>فشل التصدير</translation>
</message>
<message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>حدث خطأ أثناء محاولة حفظ محفوظات المعاملة إلى %1.</translation>
+ </message>
+ <message>
<source>Exporting Successful</source>
<translation>نجح التصدير</translation>
</message>
<message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>تم حفظ محفوظات المعاملة بنجاح إلى %1.</translation>
+ </message>
+ <message>
<source>Range:</source>
<translation>المدى:</translation>
</message>
@@ -1983,7 +2819,11 @@
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>الوحدة لإظهار المبالغ فيها. انقر لتحديد وحدة أخرى.</translation>
+ </message>
+</context>
<context>
<name>WalletFrame</name>
<message>
@@ -1998,14 +2838,42 @@
<translation>إرسال Coins</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>خطأ في زيادة الرسوم</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>فشل في زيادة رسوم المعاملة</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>هل تريد زيادة الرسوم؟</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>الأجر الحالي:</translation>
</message>
<message>
+ <source>Increase:</source>
+ <translation>زيادة:</translation>
+ </message>
+ <message>
<source>New fee:</source>
<translation>أجر جديد:</translation>
</message>
- </context>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>تأكيد زيادة الرسوم</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>لا يمكن توقيع المعاملة.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>لا يمكن تنفيذ المعاملة</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -2021,6 +2889,10 @@
<translation>نسخ احتياط للمحفظة</translation>
</message>
<message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>بيانات المحفظة (*.dat)</translation>
+ </message>
+ <message>
<source>Backup Failed</source>
<translation>فشل النسخ الاحتياطي</translation>
</message>
@@ -2028,28 +2900,89 @@
<source>Backup Successful</source>
<translation>نجاح النسخ الاحتياطي</translation>
</message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>تم حفظ بيانات المحفظة بنجاح إلى %1.</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>خيارات: </translation>
+ <source>Error: A fatal internal error occurred, see debug.log for details</source>
+ <translation>خطأ: حدث خطأ داخلي فادح، راجع debug.log للحصول على التفاصيل</translation>
+ </message>
+ <message>
+ <source>Pruning blockstore...</source>
+ <translation>تجريد مخزن الكتل...</translation>
</message>
<message>
- <source>Specify data directory</source>
- <translation>حدد مجلد المعلومات</translation>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>غير قادر على بدء خادم ال HTTP. راجع سجل تصحيح الأخطاء للحصول على التفاصيل.</translation>
</message>
<message>
<source>Bitcoin Core</source>
<translation>جوهر بيتكوين</translation>
</message>
<message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>قبول الاتصالات من خارج</translation>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>لا يمكن الحصول على قفل على دليل البيانات %s. من المحتمل أن %s يعمل بالفعل.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>لا يمكن توفير اتصالات محددة ولابد أن يكون لدى addrman اتصالات صادرة في نفس الوقت.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>يرجى المساهمة إذا وجدت %s مفيداً. تفضل بزيارة %s لمزيد من المعلومات حول البرنامج.</translation>
+ </message>
+ <message>
+ <source>%s corrupt, salvage failed</source>
+ <translation>
+%s تالف, فشل الانقاذ.</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>خيارات الاتصال:</translation>
+ <source>Change index out of range</source>
+ <translation>فهرس الفكة خارج النطاق</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>حقوق الطبع والنشر (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation>تم الكشف عن قاعدة بيانات كتل تالفة</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>هل تريد إعادة بناء قاعدة بيانات الكتل الآن؟</translation>
+ </message>
+ <message>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>خطأ في إنشاء %s: لا يمكنك إنشاء محافظ بلا خاصية الهرمية الحتمية non-HD باستخدام هذا الإصدار.</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>خطأ في تحميل %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>خطأ في تحميل %s: لا يمكن تعطيل المفاتيح الخاصة إلا أثناء الإنشاء.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>خطأ في التحميل %s: المحفظة تالفة.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>خطا تحميل %s: المحفظة تتطلب النسخة الجديدة من %s.</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>خطأ في تحميل قاعدة بيانات الكتل</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation>خطأ في فتح قاعدة بيانات الكتل</translation>
</message>
<message>
<source>Error: Disk space is low!</source>
@@ -2060,24 +2993,92 @@
<translation>فشل في الاستماع على أي منفذ. استخدام الاستماع = 0 إذا كنت تريد هذا.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>فشل في اعادة مسح المحفظة خلال عملية التهيئة.</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>استيراد...</translation>
</message>
<message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>لم يتم العثور على كتلة تكوين أو لم تكون صحيحة. datadir خاطئة للشبكة؟</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>فشل بالتحقق في اختبار التعقل. تم إيقاف %s.</translation>
+ </message>
+ <message>
<source>Loading P2P addresses...</source>
<translation>تحميل عناوين P2P...</translation>
</message>
<message>
- <source>Use the test chain</source>
- <translation>إستخدم السلسلة التجريبية</translation>
+ <source>Loading banlist...</source>
+ <translation>جاري تحميل قائمة الحظر...</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation>لا تتوفر واصفات ملفات كافية.</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>لا يمكن تهيئة التجريد بقيمة سالبة.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>وضع التجريد غير متوافق مع -txindex.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>إعادة لعب الكتل...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>العودة بالكتل...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>شفرة المصدر متاحة من %s.</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation> غير قادر على توليد مفاتيح.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -tor found, use -onion.</source>
+ <translation>تم العثور على وسيطة غير مدعومة -tor ، استخدم -onion.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>ترقية قاعدة بيانات UTXO</translation>
</message>
<message>
<source>Verifying blocks...</source>
<translation>التحقق من الكتل...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>خيارات المحفظة :</translation>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>يلزم إعادة كتابة المحفظة: إعادة تشغيل %s لإكمال العملية</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation>قيمة المعاملة صغيرة جدًا ولا يمكن إرسالها بعد خصم الرسوم</translation>
+ </message>
+ <message>
+ <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
+ <translation>تحتاج إلى إعادة إنشاء قاعدة البيانات باستخدام -reindex للعودة إلى الوضعية الغير مجردة. هذا سوف يعيد تحميل سلسلة الكتل بأكملها</translation>
+ </message>
+ <message>
+ <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
+ <translation>خطأ أثناء تحميل %s: لا يمكنك تعطيل خاصية الهرمية الحتمية HD في محفظة مفعلة بخاصية الهرمية الحتمية HD مسبقاً</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation>خطأ في القراءة من قاعدة البيانات ، والتوقف.</translation>
+ </message>
+ <message>
+ <source>Error upgrading chainstate database</source>
+ <translation>خطأ في ترقية قاعدة بيانات chainstate</translation>
</message>
<message>
<source>Information</source>
@@ -2108,6 +3109,14 @@
<translation>المعاملة كبيرة جدا</translation>
</message>
<message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation>يتعذر الربط مع %s على هذا الكمبيوتر (الربط انتج خطأ %s)</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>غير قادر على توليد مفاتيح أولية</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>التحقق من المحفظة (المحافظ)...</translation>
</message>
@@ -2116,18 +3125,50 @@
<translation>تحذير</translation>
</message>
<message>
+ <source>Zapping all transactions from wallet...</source>
+ <translation>إزالة جميع المعاملات من المحفظة...</translation>
+ </message>
+ <message>
+ <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
+ <translation>خطأ أثناء تحميل %s: لا يمكنك تفعيل خاصية الهرمية الحتمية HD في محفظة لا تملك خاصية الهرمية الحتمية non-HD مسبقاً</translation>
+ </message>
+ <message>
+ <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
+ <translation>تحذير: ملف المحفظة فاسد ، تم انقاذ البيانات! تم حفظ %s الأصلي ك %s في %s؛ إذا كان رصيدك أو كانت معاملاتك غير صحيحة، فيجب عليك الإستعادة من نسخة احتياطية.</translation>
+ </message>
+ <message>
<source>%s is set very high!</source>
<translation>%s عالٍ جداً</translation>
</message>
<message>
- <source>Make the wallet broadcast transactions</source>
- <translation>إنتاج معاملات بث المحفظة</translation>
+ <source>Starting network threads...</source>
+ <translation>بدء مؤشرات شبكة الاتصال...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>سوف تتجنب المحفظة دفع أقل من الحد الأدنى لرسوم التتابع.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>يجب ألا تكون قيمة المعاملة سلبية</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>المعاملات طويلة جداً على حجم سلسلة الذاكرة </translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>يجب أن تحتوي المعاملة على مستلم واحد على الأقل</translation>
</message>
<message>
<source>Insufficient funds</source>
<translation>اموال غير كافية</translation>
</message>
<message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>لايمكن الكتابة على دليل البيانات '%s'؛ تحقق من السماحيات.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>تحميل مؤشر الكتلة</translation>
</message>
diff --git a/src/qt/locale/bitcoin_be_BY.ts b/src/qt/locale/bitcoin_be_BY.ts
index 762f375a53..ab80936a59 100644
--- a/src/qt/locale/bitcoin_be_BY.ts
+++ b/src/qt/locale/bitcoin_be_BY.ts
@@ -30,6 +30,10 @@
<translation>Выдаліць абраны адрас са спісу</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Увядзіце адрас ці пазнаку для пошуку</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Экспартаваць гэтыя звесткі у файл</translation>
</message>
@@ -602,10 +606,6 @@
<translation>Адрас</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Новы адрас для атрымання</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Новы адрас для дасылання</translation>
</message>
@@ -618,10 +618,6 @@
<translation>Рэдагаваць адрас дасылання</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Уведзены адрас "%1" ужо ў кніге адрасоў</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Немагчыма разблакаваць гаманец</translation>
</message>
@@ -655,19 +651,7 @@
<source>Command-line options</source>
<translation>Опцыі каманднага радка</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Ужыванне:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>опцыі каманднага радка</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Стартаваць ммінімізаванай</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -802,6 +786,10 @@
<source>Message</source>
<translation>Паведамленне</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Гаманец</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -986,10 +974,6 @@
<context>
<name>TransactionDesc</name>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>%1/unconfirmed</source>
<translation>%1/непацверджана</translation>
</message>
@@ -1002,10 +986,6 @@
<translation>Статус</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, пакуль не было паспяхова транслявана</translation>
- </message>
- <message>
<source>Date</source>
<translation>Дата</translation>
</message>
@@ -1056,10 +1036,6 @@
<translation>Пацверджана (%1 пацверджанняў)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Гэты блок не быў прыняты іншымі вузламі і магчыма не будзе ўхвалены!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Згенеравана, але не прынята</translation>
</message>
@@ -1250,22 +1226,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Опцыі:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Вызначыць каталог даных</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Прымаць камандны радок і JSON-RPC каманды</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Запусціць у фоне як дэман і прымаць каманды</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
@@ -1302,30 +1262,14 @@
<translation>Не хапае файлавых дэскрыптараў.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Use UPnP to map the listening port (default: %u)</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>Праверка блокаў...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Опцыі гаманца:</translation>
- </message>
- <message>
<source>Information</source>
<translation>Інфармацыя</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>Опцыі RPC сервера:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Слаць trace/debug звесткі ў кансоль замест файла debug.log</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Памылка подпісу транзакцыі</translation>
</message>
@@ -1342,22 +1286,10 @@
<translation>Транзакцыя занадта вялікая</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Імя карыстальника для JSON-RPC злучэнняў</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Увага</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Пароль для JSON-RPC злучэнняў</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Выканаць каманду калі лепшы блок зменіцца (%s замяняецца на хэш блока)</translation>
- </message>
- <message>
<source>Insufficient funds</source>
<translation>Недастаткова сродкаў</translation>
</message>
diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts
index e893390f58..c9d33ed6bb 100644
--- a/src/qt/locale/bitcoin_bg.ts
+++ b/src/qt/locale/bitcoin_bg.ts
@@ -30,6 +30,10 @@
<translation>Изтрий избрания адрес от списъка</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Търсене по адрес или име</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Запишете данните от текущия раздел във файл</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Въведете новата парола повторно</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Покажи парола</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Въведете новата парола към портфейла.&lt;br/&gt;Моля ползвайте парола съставена от &lt;b&gt;десет или повече произволни символа&lt;/b&gt;, или &lt;b&gt;осем или повече думи&lt;/b&gt;.</translation>
</message>
@@ -314,6 +322,14 @@
<translation>Отвори &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Портфейл</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Портфейл по подразбиране</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Натиснете за деактивиране на мрежата</translation>
</message>
@@ -326,6 +342,10 @@
<translation>Натиснете за повторно активиране на мрежата.</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Синхронизиране на хедъри (%1%)</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>Повторно индексиране на блоковете на диска...</translation>
</message>
@@ -694,10 +714,6 @@
<translation>&amp;Адрес</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Нов адрес за получаване</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Нов адрес за изпращане</translation>
</message>
@@ -714,10 +730,6 @@
<translation>"%1" не е валиден Биткоин адрес.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Вече има адрес "%1" в списъка с адреси.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Отключването на портфейла беше неуспешно.</translation>
</message>
@@ -767,42 +779,6 @@
<source>Command-line options</source>
<translation>Списък с команди</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Използване:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Списък с налични команди</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Опции на интерфейс:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Избери директория за данни при стартирване (по подразбиране: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Избери език, примерно "de_DE" (по подразбиране: system locale)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Стартирай минимизиран</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Задай SSL root сертификат за молба за изплащане (по подразбиране: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Покажи splash екран при стартирване (по подразбиране %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Нулиране на всички настройки променени в GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -916,6 +892,10 @@
<translation>&amp;Мрежа</translation>
</message>
<message>
+ <source>GB</source>
+ <translation>ГБ</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation>По&amp;ртфейл</translation>
</message>
@@ -940,6 +920,14 @@
<translation>Отваряне на входящия порт чрез &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Позволи външни връзки</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Позволи входящи връзки</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Свързване с Биткойн мрежата чрез SOCKS5 прокси.</translation>
</message>
@@ -960,6 +948,10 @@
<translation>Порт на прокси сървъра (пр. 9050)</translation>
</message>
<message>
+ <source>Tor</source>
+ <translation>Тор</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;Прозорец</translation>
</message>
@@ -1020,6 +1012,10 @@
<translation>Изисква се рестартиране на клиента за активиране на извършените промени.</translation>
</message>
<message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>Клиентът ще бъде изключен. Искате ли да продължите?</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Грешка</translation>
</message>
@@ -1389,6 +1385,10 @@
<translation>Изчисти конзолата</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>Портфейл по подразбиране</translation>
+ </message>
+ <message>
<source>via %1</source>
<translation>посредством %1</translation>
</message>
@@ -1519,6 +1519,10 @@
<translation>Съобщение</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Портфейл</translation>
+ </message>
+ <message>
<source>Error encoding URI into QR Code.</source>
<translation>Грешка при създаването на QR Code от URI.</translation>
</message>
@@ -1681,14 +1685,14 @@
<translation>Наистина ли искате да изпратите?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>добавено като такса за транзакция</translation>
- </message>
- <message>
<source>or</source>
<translation>или</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Такса</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Потвърждаване</translation>
</message>
@@ -1930,10 +1934,6 @@
<translation>Подлежи на промяна до %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/офлайн</translation>
- </message>
- <message>
<source>%1/unconfirmed</source>
<translation>%1/непотвърдени</translation>
</message>
@@ -1946,10 +1946,6 @@
<translation>Статус</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, все още не е изпратено</translation>
- </message>
- <message>
<source>Date</source>
<translation>Дата</translation>
</message>
@@ -2080,10 +2076,6 @@
<translation>Подлежи на промяна до %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Извън линия</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Непотвърдено</translation>
</message>
@@ -2104,10 +2096,6 @@
<translation>Неплатим (%1 потвърждения, ще бъде платим след %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Блокът не е получен от останалите участници и най-вероятно няма да бъде одобрен.</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Генерирана, но отхвърлена от мрежата</translation>
</message>
@@ -2346,42 +2334,14 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Информацията за портфейла беше успешно запазена в %1.</translation>
</message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Опции:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Определете директория за данните</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Свържете се към сървър за да можете да извлечете адресите на пиърите след което се разкачете.</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Въведете Ваш публичен адрес</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Биткойн ядро</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; може да бъде:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Приемайте връзки отвън.(по подразбиране:1 в противен случай -proxy или -connect)</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Настройки на връзката:</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Желаете ли да пресъздадете базата данни с блокове сега?</translation>
</message>
@@ -2406,22 +2366,10 @@
<translation>Проверка на блоковете...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Настройки на портфейла:</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Свързване чрез SOCKS5 прокси</translation>
- </message>
- <message>
<source>Information</source>
<translation>Информация</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Изпрати локализиращата или дебъг информацията към конзолата, вместо файлът debug.log</translation>
- </message>
- <message>
<source>This is experimental software.</source>
<translation>Това е експериментален софтуер.</translation>
</message>
@@ -2434,30 +2382,10 @@
<translation>Транзакцията е твърде голяма</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Потребителско име за JSON-RPC връзките</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Предупреждение</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Парола за JSON-RPC връзките</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Назовете конфигурационен файл(по подразбиране %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Задайте време на изключване при проблеми със свързването в милисекунди(минимум:1, по подразбиране %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Задайте pid файл(по подразбиране: %s)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Стартиране на мрежовите нишки...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_bg_BG.ts b/src/qt/locale/bitcoin_bg_BG.ts
index e08ca935fa..2bf9d4ff7f 100644
--- a/src/qt/locale/bitcoin_bg_BG.ts
+++ b/src/qt/locale/bitcoin_bg_BG.ts
@@ -442,10 +442,6 @@
<translation>Редактирайте адреса</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Нов адрес за получаване</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Нов адрес за изпращане</translation>
</message>
@@ -678,6 +674,10 @@
<source>Label</source>
<translation>Етикет</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>портфейл</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts
index 22dcd36f94..2926736498 100644
--- a/src/qt/locale/bitcoin_ca.ts
+++ b/src/qt/locale/bitcoin_ca.ts
@@ -30,6 +30,10 @@
<translation>Elimina l'adreça sel·leccionada actualment de la llista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduïu una adreça o una etiqueta per cercar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exporta les dades de la pestanya actual a un fitxer</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Repetiu la nova contrasenya</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Ensenya la contrasenya</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Introduïu la contrasenya nova al moneder.&lt;br/&gt;Utilitzeu una contrasenya de &lt;b&gt;deu o més caràcters aleatoris&lt;/b&gt;, o &lt;b&gt;vuit o més paraules&lt;/b&gt;.</translation>
</message>
@@ -318,6 +326,14 @@
<translation>Obre un &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Moneder:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>moneder per defecte</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Feu clic per inhabilitar l'activitat de la xarxa.</translation>
</message>
@@ -338,6 +354,10 @@
<translation>S'estan reindexant els blocs al disc...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>El servidor proxy està &lt;b&gt;activat&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Envia monedes a una adreça Bitcoin</translation>
</message>
@@ -433,6 +453,10 @@
<source>&amp;Command-line options</source>
<translation>Opcions de la &amp;línia d'ordres</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n connexió activa a la xarxa Bitcoin</numerusform><numerusform>%n connexions actives a la xarxa Bitcoin</numerusform></translation>
+ </message>
<message>
<source>Indexing blocks on disk...</source>
<translation>S'estan indexant els blocs al disc...</translation>
@@ -441,6 +465,10 @@
<source>Processing blocks on disk...</source>
<translation>S'estan processant els blocs al disc...</translation>
</message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Processat %n bloc de l'històric de transaccions.</numerusform><numerusform>Processats %n blocs de l'històric de transaccions.</numerusform></translation>
+ </message>
<message>
<source>%1 behind</source>
<translation>%1 darrere</translation>
@@ -498,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Mondeder: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Tipus: %1
@@ -718,10 +752,6 @@
<translation>&amp;Adreça</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nova adreça de recepció</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nova adreça d'enviament</translation>
</message>
@@ -738,8 +768,12 @@
<translation>L'adreça introduïda «%1» no és una adreça de Bitcoin vàlida.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>L'adreça introduïda «%1» ja és present a la llibreta d'adreces.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>L'adreça "%1" ja existeix com una adreça per rebre amb l'etiqueta "%2" i per tant no pot ésser afegida com adreça per enviar.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>L'adreça introduïda "%1" ja existeix al directori d'adreces amb l'etiqueta "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -791,42 +825,6 @@
<source>Command-line options</source>
<translation>Opcions de línia d'ordres</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Ús:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Opcions de la línia d'ordres</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opcions d'interfície d'usuari:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Trieu el directori de dades a l'inici (per defecte: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Defineix la llengua, per exemple «de_DE» (per defecte: la definida pel sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Inicia minimitzat</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Defineix els certificats arrel SSL per a la sol·licitud de pagament (per defecte: els del sistema)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Mostra la pantalla de benvinguda a l'inici (per defecte: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Reinicialitza tots els canvis de configuració fets des de la interfície gràfica</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -890,7 +888,15 @@
<source>Error</source>
<translation>Error</translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>%n GB d'espai lliure disponible</numerusform><numerusform>%n GB d'espai lliure disponibles</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(de %n GB necessari)</numerusform><numerusform>(de %n GB necessaris)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -1004,6 +1010,18 @@
<translation>Mostra si el proxy SOCKS5 predeterminat subministrat s'utilitza per arribar a altres nodes a través d'aquest tipus de xarxa.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Usi un proxy SOCKS&amp;5 separat per connectar amb nodes a través dels serveis ocults de Tor:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Amaga la icona de la safata del sistema</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>Amaga la icona de la safata</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Minimitza en comptes de sortir de l'aplicació quan la finestra es tanca. Quan s'habilita aquesta opció l'aplicació es tancara només quan se selecciona Surt del menú. </translation>
</message>
@@ -1036,6 +1054,22 @@
<translation>&amp;Xarxa</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Deshabilita unes característiques avançades però tots els blocs encara seran validats completament. Revertir aquesta configuració requereix tornar a descarregar la cadena de blocs sencera un altre cop. L'espai en ús del disc és possible que augmenti.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Prunar emmagatzemament de &amp;block a</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Revertir aquesta configuració requereix tornar a descarregar la cadena de blocs sencera un altre cop.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt;0 = deixa tants nuclis lliures)</translation>
</message>
@@ -1068,6 +1102,14 @@
<translation>Port obert amb &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Accepta connexions de fora</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Permet connexions entrants</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Connecta a la xarxa Bitcoin a través d'un proxy SOCKS5.</translation>
</message>
@@ -1148,6 +1190,10 @@
<translation>Si voleu mostrar les funcions de control de monedes o no.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>URL de transaccions de tercers</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;D'acord</translation>
</message>
@@ -1290,6 +1336,10 @@
<translation>Gestió d'URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' no és una URI vàlida. Usi 'bitcoin:' en lloc seu.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>L'URL de recuperació de la sol·licitud de pagament no és vàlida: %1</translation>
</message>
@@ -1431,10 +1481,34 @@
<source>%1 ms</source>
<translation>%1 ms</translation>
</message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation><numerusform>%n segon</numerusform><numerusform>%n segons</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation><numerusform>%n minut</numerusform><numerusform>%n minuts</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation><numerusform>%n hora</numerusform><numerusform>%n hores</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation><numerusform>%n dia</numerusform><numerusform>%n dies</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation><numerusform>%n setmana</numerusform><numerusform>%n setmanes</numerusform></translation>
+ </message>
<message>
<source>%1 and %2</source>
<translation>%1 i %2</translation>
</message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation><numerusform>%n any</numerusform><numerusform>%n anys</numerusform></translation>
+ </message>
<message>
<source>%1 B</source>
<translation>%1 B</translation>
@@ -1463,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Error interpretant els arguments de la línia de comandes: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Error: El directori de dades especificat «%1» no existeix.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Error: no es pot analitzar el fitxer de configuració: %1. Feu servir només la sintaxi clau=valor.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Error: No es pot interpretar el fitxer de configuració: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1561,6 +1639,14 @@
<translation>Us de memoria</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Moneder:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(cap)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Reset</translation>
</message>
@@ -1729,6 +1815,10 @@
<translation>Desbandeja per</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>moneder per defecte</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Benvingut a la consola RPC de %1.</translation>
</message>
@@ -1737,6 +1827,14 @@
<translation>Utilitzeu les fletxes amunt i avall per navegar per l'historial i %1 per netejar la pantalla.</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Escriu %1 per veure un sumari de les comandes disponibles.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Per més informació per usar aquesta consola de comandes, escriu %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>ADVERTIMENT: Els estafadors han estat actius, dient als usuaris que escriguin comandaments aquí, robant els contingut dels seus moneders. No utilitzeu aquesta consola sense comprendre completament les ramificacions d'un comandament.</translation>
</message>
@@ -1745,6 +1843,14 @@
<translation>Activitat de xarxa inhabilitada</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Executant comanda sense cap moneder</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Executant comanda usant el moneder "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(id del node: %1)</translation>
</message>
@@ -1816,6 +1922,14 @@
<translation>Neteja</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Les adreces segwit natives (més conegudes com Bech32 o BIP-173) redueixen les vostres comisions de les transaccions i ofereixen millor protecció contra errades tipogràfiques, però els moneders antics no les suporten. Quan desmarqui la casella, es generarà una adreça compatible amb moneders antics.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generar una adreça segwit nativa (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Historial de pagaments sol·licitats</translation>
</message>
@@ -1903,6 +2017,10 @@
<translation>Missatge</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Moneder</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultant massa llarga, intenta reduir el text per a la etiqueta / missatge</translation>
</message>
@@ -2017,12 +2135,16 @@
<translation>redueix els paràmetres de comissió</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>per kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Especifiqui una comissió personalitzada per kB (1.000 bytes) de la mida virtual de la transacció.
+
+Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "100 satoshis per cada kB" per una transacció de mida 500 bytes (la meitat de 1 kB) comportaria finalment una comissió de la transacció de només 50 satoshis.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Si la comissió personalitzada es defineix a 1000 satoshis i la transacció és de només 250 bytes, llavors «per kilobyte» només es paguen 250 satoshis en una comissió, mentre que amb la de «total com a mínim» es pagarien 1000 satoshis. Per a transaccions superiors al kilobyte, en tots dos casos es paga per kilobyte.</translation>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2069,6 +2191,14 @@
<translation>Temps de confirmació objectiu:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Habilita Replace-By-Fee: substitució per comissió</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Amb la substitució per comissió o Replace-By-Fee (BIP-125) pot incrementar la comissió de la transacció després d'enviar-la. Sense això, seria recomenable una comissió més alta per compensar el risc d'increment del retard de la transacció.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Neteja-ho &amp;tot</translation>
</message>
@@ -2125,16 +2255,16 @@
<translation>Esteu segur que ho voleu enviar?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>S'ha afegit una taxa de transacció</translation>
+ <source>or</source>
+ <translation>o</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Import total %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Pot incrementar la comissió més tard (senyala Replace-By-Fee o substitució per comissió, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>o</translation>
+ <source>Transaction fee</source>
+ <translation>Comissió de transacció</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2466,10 +2596,6 @@
<translation>produït un conflicte amb una transacció amb %1 confirmacions</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/fora de línia</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/no confirmades, %1</translation>
</message>
@@ -2498,10 +2624,6 @@
<translation>Estat</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, encara no ha estat emès correctement</translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2648,10 +2770,6 @@
<translation>Obert fins %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Fora de línia</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Sense confirmar</translation>
</message>
@@ -2676,10 +2794,6 @@
<translation>Immadur (%1 confirmacions, serà disponible després de %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Aquest bloc no ha estat rebut per cap altre node i probablement no serà acceptat!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generat però no acceptat</translation>
</message>
@@ -2986,38 +3100,14 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>S'han desat les dades del moneder correctament a %1.</translation>
</message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opcions:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Especifica el directori de dades</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Connecta al node per obtenir les adreces de les connexions, i desconnecta</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especifiqueu la vostra adreça pública</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accepta la línia d'ordres i ordres JSON-RPC </translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distribuït sota la llicència del programari MIT, consulteu el fitxer d'acompanyament %s o %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Si no es proporciona &lt;category&gt; o si &lt;category&gt; = 1, treu a la sortida tota la informació de depuració.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior.</translation>
</message>
@@ -3034,18 +3124,10 @@
<translation>Error: s'ha produït un error intern fatal. Vegeu debug.log per a més detalls</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Comissió (en %s/kB) per afegir a les transaccions que envieu (per defecte: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>S'està podant la cadena de blocs...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Executa en segon pla com a programa dimoni i accepta ordres</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>No s'ha pogut iniciar el servidor HTTP. Vegeu debug.log per a més detalls.</translation>
</message>
@@ -3058,54 +3140,14 @@
<translation>Els desenvolupadors %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Una taxa de tarifes (en %s / kB) que s'utilitzarà quan l'estimació de tarifes no tingui prou dades (per defecte: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Acceptar les transaccions retransmeses rebudes de nodes de llista blanca, fins i tot quan no es retransmetin transaccions (per defecte: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Vincula a una adreça específica i sempre escolta-hi. Utilitza la notació [host]:port per IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>No es pot obtenir un bloqueig al directori de dades %s. %s probablement ja s'estigui executant.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Elimina totes les transaccions del moneder i només recupera aquelles de la cadena de blocs a través de -rescan a l'inici</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>S'ha produït un error en llegir %s. Totes les claus es llegeixen correctament, però les dades de la transacció o les entrades de la llibreta d'adreces podrien faltar o ser incorrectes.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Excloeu la informació de depuració d'una categoria. Pot ser usat juntament amb -debug = 1 per generar registres de depuració per a totes les categories, excepte una o més categories especificades.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Executa una ordre quan una transacció del moneder canviï (%s en cmd es canvia per TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Transaccions addicionals a conservar en memòria per a les reconstruccions de blocs compactes (per defecte: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Si aquest bloc es troba a la cadena, suposa que ell i els seus avantpassats són vàlids i que es pot saltar la seva verificació d'script (0 per verificar-ho tot, per defecte: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Màxim ajust mitjà permès per desplaçament del temps d'iguals. La perspectiva local del temps pot estar influenciada per iguals avançats o endarrerits per aquesta quantitat. (per defecte: %u segons)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Tarifes totals màximes (en %s) per utilitzar-les en una sola transacció de monedes o transaccions en brut; establir-lo massa baix pot cancel·lar grans transaccions (per defecte: %s)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>Comproveu que la data i hora de l'ordinador són correctes. Si el rellotge és incorrecte, %s no funcionarà correctament.</translation>
</message>
@@ -3114,18 +3156,6 @@
<translation>Contribueix si trobes %s útil. Visita %s per obtenir més informació sobre el programari.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Consulta adreces d'iguals a través de la cerca del DNS, si tens poques adreces (per defecte: 1, tret que s'utilitzi la connexió)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Redueix els requisits d'emmagatzematge permetent la poda (supressió) dels blocs antics. Això permet executar la crida RPC prunblockclass per eliminar blocs específics i permet la poda automàtica de blocs antics si es proporciona una mida de destinació en MiB. Aquest mode és incompatible amb -txindex i -rescan. Advertència: si torna a iniciar aquesta configuració, cal que torneu a baixar la cadena de blocs completa. (per defecte: 0 = desactivar poda de blocs, 1 = permetre la poda manual a través de RPC,&gt;%u = poda automàticament els fitxers de bloc per quedar sota la mida de destinació especificada en MiB)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Defineix el nombre de fils de verificació d'scripts (%u a %d, 0 = auto, &lt;0 = deixa tants nuclis lliures, per defecte: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>La base de dades de blocs conté un bloc que sembla ser del futur. Això pot ser degut a que la data i l'hora del vostre ordinador s'estableix incorrectament. Només reconstruïu la base de dades de blocs si esteu segur que la data i l'hora del vostre ordinador són correctes</translation>
</message>
@@ -3146,18 +3176,6 @@
<translation>No es pot rebobinar la base de dades a un estat de pre-bifurcament. Haureu de tornar a descarregar la cadena de blocks</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Utilitzeu UPnP per mapejar el port d'escolta (per defecte: 1 quan s'escolta i no -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Nom d'usuari i contrasenya resumida per a les connexions JSON-RPC. El camp &lt;userpw&gt; ve en el format: &lt;USERNAME&gt; : &lt;SALT&gt; $ &lt;HASH&gt; . Un script canònic python està inclòs a share / rpcuser. El client es connecta normalment utilitzant rpcuser =&lt;USERNAME&gt;/ rpcpassword =&lt;PASSWORD&gt; com a parell d'arguments. Aquesta opció es pot especificar diverses vegades</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>El moneder no crearà transaccions que infringeixin els límits de la cadena mempool (per defecte: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Avís: la xarxa no sembla que hi estigui plenament d'acord. Alguns miners sembla que estan experimentant problemes.</translation>
</message>
@@ -3166,10 +3184,6 @@
<translation>Avís: sembla que no estem plenament d'acord amb els nostres iguals! Podria caler que actualitzar l'aplicació, o potser que ho facin altres nodes.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Si es guarda el mempool quan s'apaga i es carrega quan es reinicia (per defecte: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d dels últims 100 blocs tenen una versió inesperada</translation>
</message>
@@ -3182,42 +3196,14 @@
<translation>-maxmempool ha de tenir almenys %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; pot ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accepta connexions de fora (per defecte: 1 si no -proxy o -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Afegiu un comentari a la cadena de l'agent d'usuari</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Intent de recuperació de claus privades d'una cartera malmesa a l'inici</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opcions de la creació de blocs:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>No es pot resoldre -%s adreça: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Opcions de selecció de cadenes:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Canvieu l'índex fora de l'abast</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Opcions de connexió:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3226,38 +3212,10 @@
<translation>S'ha detectat una base de dades de blocs corrupta</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opcions de depuració/proves:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>No carreguis el moneder i inhabilita les crides RPC del moneder</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Voleu reconstruir la base de dades de blocs ara?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Habiliteu publicar el bloc de hash a &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Habilita la publicació de la transacció hash a &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Habiliteu publicar el bloc cru a &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Habiliteu publicar transaccions en cru a &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Activa el reemplaçament de transaccions al grup de memòria (per defecte: %u)</translation>
- </message>
- <message>
<source>Error initializing block database</source>
<translation>Error carregant la base de dades de blocs</translation>
</message>
@@ -3318,10 +3276,6 @@
<translation>Import invàlid per -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Manteniu el grup de memòria de la transacció per sota de &lt;n&gt; megabytes (per defecte: %u)</translation>
- </message>
- <message>
<source>Loading P2P addresses...</source>
<translation>S'estan carregant les adreces P2P ...</translation>
</message>
@@ -3330,26 +3284,10 @@
<translation>Carregant banlist ...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Ubicació de la cookie auth (per defecte: directori de dades)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>No hi ha suficient descriptors de fitxers disponibles.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Només connecta als nodes de la xarxa &lt;net&gt; (ipv4, ipv6 o onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Imprimiu aquest missatge d'ajuda i sortiu</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Imprimir versió i sortir</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>La poda no es pot configurar amb un valor negatiu.</translation>
</message>
@@ -3358,14 +3296,6 @@
<translation>El mode de poda és incompatible amb -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Reconstrueix l'estat de la cadena i l'índex de blocs des dels fitxers blk*.dat del disc</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Reconstrueix l'estat de cadena dels blocs actualment indexats</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Reproduïnt blocs ...</translation>
</message>
@@ -3374,14 +3304,6 @@
<translation>Rebobinant blocs...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Defineix la mida de la memòria cau de la base de dades en megabytes (%d a %d, per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especifica un fitxer de moneder (dins del directori de dades)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>El codi font està disponible a %s.</translation>
</message>
@@ -3414,14 +3336,6 @@
<translation>Actualització de la base de dades UTXO</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Utilitza UPnP per a mapejar el port d'escolta (per defecte: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Utilitza la cadena de proves</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>El comentari de l'agent d'usuari (%s) conté caràcters insegurs.</translation>
</message>
@@ -3430,90 +3344,26 @@
<translation>S'estan verificant els blocs...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opcions de depuració/proves del moneder:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Cal reescriure el moneder: reinicieu %s per a completar-ho</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opcions de moneder:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permet les connexions JSON-RPC d'una font específica. Vàlid per a &lt;ip&gt; són una IP individual (p. ex., 1.2.3.4), una xarxa / màscara de xarxa (p. ex., 1.2.3.4/255.255.255.0) o una xarxa/CIDR (p. ex., 1.2.3.4/24). Es pot especificar aquesta opció moltes vegades</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Vincula l'adreça donada i posa a la llista blanca els iguals que s'hi connectin. Feu servir la notació [host]:port per a IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Descobreix l'adreça IP pròpia (per defecte: 1 quan s'escolta i no -externalip o -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Executa l'ordre quan es rebi un avís rellevant o veiem una forquilla molt llarga (%s en cmd és reemplaçat per un missatge)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Les comissions (en %s/kB) més petites que això es consideren tarifes zero per a la retransmissió, la mineria i la creació de transaccions (per defecte: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Si no s'especifica una paytxfee (comissió de transacció de pagament), inclogueu suficient comissió per tal que les transaccions comencin a confirmar-se en una mitja de n blocs (per defecte: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Import no vàlid per a -maxtxfee=&lt;amount&gt;: '%s' (cal que sigui com a mínim la comissió de minrelay de %s per evitar que les comissions s'encallin)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Mida màxima de les dades en les transaccions de l'operador en què confiem i en les meves (per defecte: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Genera a l'atzar credencials per a cada connexió proxy. Això habilita l'aïllament del flux de Tor (per defecte: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>L'import de la transacció és massa petit per enviar-la després que se'n dedueixi la comissió</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Els iguals en la llista blanca no poden ser bandejats per DoS i es transmetran sempre llurs transaccions, fins i tot si ja són a la mempool. Això és útil, p. ex., per a una passarel·la</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Cal que torneu a construir la base de dades fent servir -reindex per tornar al mode no podat. Això tornarà a baixar la cadena de blocs sencera</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(per defecte: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Accepta sol·licituds REST públiques (per defecte: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Crea automàticament el servei ocult de Tor (per defecte: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Connecta a través del proxy SOCKS5</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>S'ha produït un error en carregar %s: no es pot desactivar HD en un moneder HD ja existent</translation>
</message>
@@ -3526,10 +3376,6 @@
<translation>S'ha produït un error en actualitzar la base de dades de chainstate</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importa blocs de fitxers externs blk000?.dat a l'inici de l'apliació</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informació</translation>
</message>
@@ -3550,42 +3396,14 @@
<translation>S'ha especificat una màscara de xarxa no vàlida a -whitelist: «%s»</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Manté com a màxim &lt;n&gt; transaccions no connectables en memòria (per defecte: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Cal especificar un port amb -whitebind: «%s»</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opcions de transmissió del node:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opcions del servidor RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reducció de -maxconnections de %d a %d, a causa de les limitacions del sistema.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Reescaneja la cadena de blocs per a les operacions del moneder que falten a l'inici</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Envia informació de traça/depuració a la consola en comptes del fitxer debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Mostra totes les opcions de depuració (ús: --help --help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Redueix el fitxer debug.log durant l'inici del client (per defecte: 1 quan no -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Ha fallat la signatura de la transacció</translation>
</message>
@@ -3598,14 +3416,6 @@
<translation>Això és programari experimental.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Contrasenya del port de control Tor (per defecte: buida)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Port de control de tor si l'escolta onion està habilitada (per defecte: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Import de la transacció massa petit</translation>
</message>
@@ -3622,14 +3432,6 @@
<translation>No s'ha pogut vincular a %s en aquest ordinador (la vinculació ha retornat l'error %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Actualitza el moneder al format més recent a l'inici de l'aplicació</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nom d'usuari per a connexions JSON-RPC</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>S'està verificant el moneder(s) ...</translation>
</message>
@@ -3642,98 +3444,18 @@
<translation>Advertència: regles noves desconegudes activades (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Si s'ha d'operar en un mode de blocs només (per defecte: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Heu de reconstruir la base de dades mitjançant -reindex per canviar -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Se suprimeixen totes les transaccions del moneder...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Opcions de notificació ZeroMQ:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Contrasenya per a connexions JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Executa l'ordre quan el millor bloc canviï (%s en cmd es reemplaça per un resum de bloc)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permet consultes DNS per a -addnode, -seednode i -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = manté les metadades de les tx, p. ex., propietari del compte i informació de sol·licitud del pagament, 2 = prescindeix de les metadades de les tx)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee especificat molt alt! Comissions tan grans podrien pagar-se en una única transacció.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Enllaçar a una adreça determinada per escoltar les connexions JSON-RPC. Aquesta opció s'ignora a menys que -rpcallowip també s'especifiqui. El port és opcional i sobreescriu -rpcport. Utilitzeu la notació [host]:port per a IPv6. Aquesta opció es pot especificar diverses vegades (per defecte: 127.0.0.1 i :: 1, és a dir, localhost, o si s'ha especificat -rpcallowip, 0.0.0.0 i :: és a dir, totes les adreces)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>No mantingueu les transaccions en el mempool més de &lt;n&gt; hora (per defecte: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Bytes equivalents per sigop en transaccions de relé i mineria (per defecte: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>S'ha produït un error en carregar %s: no es pot activar HD en un moneder existent que no sigui HD</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>S'ha produït un error en carregar el moneder %s. El paràmetre -wallet només ha d'especificar un nom de fitxer (no una ruta d'accés).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Les comissions (en %s/kB) més petites que això es consideren comissions zero per a la creació de transaccions (per defecte: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Forçar la retranmissió de les transaccions de nodes de llista blanca encara que infringeixin la política de retransmissió local (per defecte: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Com d'exhaustiva és la verificació de blocs del -checkblocks (0-4, per defecte: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Manté un índex complet de transaccions, utilitzat per la crida rpc getrawtransaction (per defecte: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Nombre de segons necessaris perquè els iguals de comportament qüestionable puguin tornar a connectar-se (per defecte: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Informació de sortida de la depuració (per defecte: %u, proporcionar &lt;category&gt; és opcional)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Estableix la serialització de transaccions crues o bloc hexadecimal retornat en mode no verbose, no-segwit (0) o segwit(1) (per defecte: %d)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Suport de filtrat de blocs i transaccions amb filtres bloom (per defecte: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>El tipus de tarifa (en %s/kB) que indica la vostra tolerància per descartar el canvi afegint-lo a la tarifa (per defecte: %s). Nota: Es descarta una sortida si és polsim a aquesta tarifa, però sempre anem a descartar la quota de relleu de polsim i una tarifa de descartat per sobre d'això està limitada per l'estimació de tarifes per al destí més llarg</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Aquesta és la tarifa de transacció que podeu pagar quan les estimacions de tarifes no estan disponibles.</translation>
</message>
@@ -3746,10 +3468,6 @@
<translation>La longitud total de la cadena de la versió de xarxa (%i) supera la longitud màxima (%i). Redueix el nombre o la mida de uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Intenta mantenir el trànsit sortint sota l'objectiu indicat (a MiB per 24 hores), 0 = sense límit (per defecte: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>S'ha trobat l'argument -socks no compatible. L'establiment de la versió SOCKS ja no és possible, només es permeten els servidors proxy SOCKS5.</translation>
</message>
@@ -3758,10 +3476,6 @@
<translation>S'ha ignorat l'argument no acceptat -whitelistalways, utilitza -whitelistrelay i/o -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Utilitza un proxy SOCKS4 apart per a arribar als iguals a través de serveis ocults de Tor (per defecte: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Advertència: s'està minant versions de blocs desconegudes. És possible que s'estiguin aplicant regles desconegudes</translation>
</message>
@@ -3770,110 +3484,18 @@
<translation>Advertència: el moender està malmès, les dades es recuperen! Original %s guardat com a %s en %s; si el vostre saldo o transaccions són incorrectes, haureu de restaurar des d'una còpia de seguretat.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Nodes de llista blanca s'estan connectant des de l'adreça IP indicada (p. Ex. 1.2.3.4) o la xarxa notificada per CIDR (p. Ex. 1.2.3.0/24). Es pot especificar diverses vegades.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s està especificat molt alt!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(per defecte: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Demana sempre les adreces dels iguals a través de consultes DNS (per defecte: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>S'ha produït un error en carregar el moneder %s. El nom del fitxer -wallet ha de ser un fitxer normal.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>S'ha produït un error en carregar el moneder %s. S'ha especificat un nom de fitxer duplicat -wallet.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>S'ha produït un error en carregar el moneder %s. Caràcters no vàlids al nom del fitxer -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Quants blocs per comprovar a l'inici (per defecte: %u, 0 = tots)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Inclou l'adreça IP a la sortida de depuració (per defecte: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>S'ha acabat el Keypool, si us plau, crideu a keypoolrefill primer</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escolta les connexions JSON-RPC en &lt;port&gt; (per defecte: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escolta les connexions en &lt;port&gt; (per defecte: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Manté com a màxim &lt;n&gt; connexions a iguals (per defecte: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Fes que el moneder faci difusió de les transaccions</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Memòria intermèdia màxima de recepció per connexió, &lt;n&gt;*1000 bytes (per defecte: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Memòria intermèdia màxima d'enviament per connexió, &lt;n&gt;*1000 bytes (per defecte: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Posa davant de la sortida de depuració una marca horària (per defecte: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Retransmet i mina les transaccions de l'operador (per defecte: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Retransmet multisig no P2SH (per defecte: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Defineix la mida clau disponible a &lt;n&gt; (per defecte: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Estableix el pes màxim del bloc BIP141 (per defecte: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Defineix el nombre de fils a crides de servei RPC (per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Especifica el fitxer de configuració (per defecte: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Especifica el temps d'espera de la connexió en milisegons (mínim: 1, per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Especifica el fitxer pid (per defecte: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Gasta el canvi no confirmat en enviar les transaccions (per defecte: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>S'estan iniciant els fils de la xarxa...</translation>
</message>
@@ -3890,10 +3512,6 @@
<translation>Aquesta és la comissió de transacció que pagareu si envieu una transacció.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Llindar per a desconnectar els iguals de comportament qüestionable (per defecte: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Els imports de la transacció no han de ser negatius</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ca@valencia.ts b/src/qt/locale/bitcoin_ca@valencia.ts
index 107642f18b..b5e65bc4bf 100644
--- a/src/qt/locale/bitcoin_ca@valencia.ts
+++ b/src/qt/locale/bitcoin_ca@valencia.ts
@@ -30,6 +30,10 @@
<translation>Elimina l'adreça sel·leccionada actualment de la llista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduïu una adreça o una etiqueta per cercar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exporta les dades de la pestanya actual a un fitxer</translation>
</message>
@@ -646,10 +650,6 @@
<translation>&amp;Adreça</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nova adreça de recepció.</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nova adreça d'enviament</translation>
</message>
@@ -666,10 +666,6 @@
<translation>L'adreça introduïda «%1» no és una adreça de Bitcoin vàlida.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>L'adreça introduïda «%1» ja és present a la llibreta d'adreces.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>No s'ha pogut desbloquejar el moneder.</translation>
</message>
@@ -715,31 +711,7 @@
<source>Command-line options</source>
<translation>Opcions de línia d'ordes</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Ús:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Opcions de la línia d'ordes</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opcions d'interfície:</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Defineix un idioma, per exemple «de_DE» (per defecte: preferències locals de sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Inicia minimitzat</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Defineix certificats arrel SSL per a la sol·licitud de pagament (per defecte: -sistema-)</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -1238,10 +1210,6 @@
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Error: El directori de dades especificat «%1» no existeix.</translation>
</message>
- <message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Error: no es pot analitzar el fitxer de configuració: %1. Feu servir només la sintaxi clau=valor.</translation>
- </message>
</context>
<context>
<name>QRImageWidget</name>
@@ -1555,6 +1523,10 @@
<translation>Missatge</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Moneder</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultant massa llarga, intenta reduir el text per a la etiqueta / missatge</translation>
</message>
@@ -1657,10 +1629,6 @@
<translation>per kilobyte</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Si la comissió personalitzada es defineix a 1000 satoshis i la transacció és de només 250 bytes, llavors «per kilobyte» només es paguen 250 satoshis en una comissió, mentre que amb la de «total com a mínim» es pagarien 1000 satoshis. Per a transaccions superiors al kilobyte, en tots dos casos es paga per kilobyte.</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Amaga</translation>
</message>
@@ -1753,14 +1721,14 @@
<translation>Esteu segur que ho voleu enviar?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>S'ha afegit una taxa de transacció</translation>
- </message>
- <message>
<source>or</source>
<translation>o</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Comissió de transacció</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirma l'enviament de monedes</translation>
</message>
@@ -2066,10 +2034,6 @@
<translation>Obert fins %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/fora de línia</translation>
- </message>
- <message>
<source>%1/unconfirmed</source>
<translation>%1/sense confirmar</translation>
</message>
@@ -2082,10 +2046,6 @@
<translation>Estat</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, encara no ha estat emés correctement</translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2220,10 +2180,6 @@
<translation>Obert fins %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Fora de línia</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Sense confirmar</translation>
</message>
@@ -2244,10 +2200,6 @@
<translation>Immadur (%1 confirmacions, serà disponible després de %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Este bloc no ha estat rebut per cap altre node i probablement no serà acceptat!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generat però no acceptat</translation>
</message>
@@ -2502,30 +2454,10 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>S'han guardat les dades del moneder correctament a %1.</translation>
</message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opcions:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Especifica el directori de dades</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Connecta al node per obtindre les adreces de les connexions, i desconnecta</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especifiqueu la vostra adreça pública</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accepta la línia d'ordes i ordes JSON-RPC </translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>Error: s'ha produït un error intern fatal. Vegeu debug.log per a més detalls</translation>
</message>
@@ -2534,30 +2466,10 @@
<translation>S'està podant l'emmagatzemament de blocs...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Executa en segon pla com a programa dimoni i accepta ordes</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Vincula a una adreça específica i sempre escolta-hi. Utilitza la notació [host]:port per IPv6</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Elimina totes les transaccions del moneder i només recupera aquelles de la cadena de blocs a través de -rescan a l'inici</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Executa una orde quan una transacció del moneder canvie (%s en cmd es canvia per TxID)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Defineix el nombre de fils de verificació d'scripts (%u a %d, 0 = auto, &lt;0 = deixa tants nuclis lliures, per defecte: %d)</translation>
- </message>
- <message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
<translation>Esta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda</translation>
</message>
@@ -2570,34 +2482,10 @@
<translation>Avís: pareix que no estem plenament d'acord amb els nostres iguals! Podria caldre que actualitzar l'aplicació, o potser que ho facen altres nodes.</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; pot ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accepta connexions de fora (per defecte: 1 si no -proxy o -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opcions de la creació de blocs:</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Opcions de connexió:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>S'ha detectat una base de dades de blocs corrupta</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opcions de depuració/proves:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>No carreguis el moneder i inhabilita les crides RPC del moneder</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Voleu reconstruir la base de dades de blocs ara?</translation>
</message>
@@ -2638,10 +2526,6 @@
<translation>No hi ha suficient descriptors de fitxers disponibles.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Només connecta als nodes de la xarxa &lt;net&gt; (ipv4, ipv6 o onion)</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>La poda no es pot configurar amb un valor negatiu.</translation>
</message>
@@ -2650,90 +2534,26 @@
<translation>El mode de poda és incompatible amb -txindex.</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Defineix la mida de la memòria cau de la base de dades en megabytes (%d a %d, per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especifica un fitxer de moneder (dins del directori de dades)</translation>
- </message>
- <message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Utilitza UPnP per a mapejar el port d'escolta (per defecte: %u)</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>S'estan verificant els blocs...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opcions de moneder:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permet les connexions JSON-RPC d'una font específica. Vàlid per a &lt;ip&gt; són una IP individual (p. ex., 1.2.3.4), una xarxa / màscara de xarxa (p. ex., 1.2.3.4/255.255.255.0) o una xarxa/CIDR (p. ex., 1.2.3.4/24). Es pot especificar esta opció moltes vegades</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Vincula l'adreça donada i posa a la llista blanca els iguals que s'hi connecten. Feu servir la notació [host]:port per a IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Descobreix l'adreça IP pròpia (per defecte: 1 quan s'escolta i no -externalip o -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Executa l'orde quan es reba un avís rellevant o veiem una forquilla molt llarga (%s en cmd és reemplaçat per un missatge)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Si no s'especifica una paytxfee (comissió de transacció de pagament), inclogueu suficient comissió per tal que les transaccions comencen a confirmar-se en una mitja de n blocs (per defecte: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Import no vàlid per a -maxtxfee=&lt;amount&gt;: '%s' (cal que siga com a mínim la comissió de minrelay de %s per evitar que les comissions s'encallin)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Mida màxima de les dades en les transaccions de l'operador en què confiem i en les meues (per defecte: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Genera a l'atzar credencials per a cada connexió proxy. Això habilita l'aïllament del flux de Tor (per defecte: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>L'import de la transacció és massa petit per enviar-la després que se'n deduïsca la comissió</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Els iguals en la llista blanca no poden ser bandejats per DoS i es transmetran sempre llurs transaccions, fins i tot si ja són a la mempool. Això és útil, p. ex., per a una passarel·la</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Cal que torneu a construir la base de dades fent servir -reindex per tornar al mode no podat. Això tornarà a baixar la cadena de blocs sencera</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(per defecte: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Accepta sol·licituds REST públiques (per defecte: %u)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Connecta a través del proxy SOCKS5</translation>
- </message>
- <message>
<source>Error reading from database, shutting down.</source>
<translation>Error en llegir la base de dades, tancant.</translation>
</message>
@@ -2750,34 +2570,10 @@
<translation>S'ha especificat una màscara de xarxa no vàlida a -whitelist: «%s»</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Manté com a màxim &lt;n&gt; transaccions no connectables en memòria (per defecte: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Cal especificar un port amb -whitebind: «%s»</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opcions de transmissió del node:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opcions del servidor RPC:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Envia informació de traça/depuració a la consola en comptes del fitxer debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Mostra totes les opcions de depuració (ús: --help --help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Redueix el fitxer debug.log durant l'inici del client (per defecte: 1 quan no -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Ha fallat la signatura de la transacció</translation>
</message>
@@ -2806,138 +2602,14 @@
<translation>No s'ha pogut vincular a %s en este ordinador (la vinculació ha retornat l'error %s)</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nom d'usuari per a connexions JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Avís</translation>
</message>
<message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Cal que reconstruïu la base de dades fent servir -reindex per canviar -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Se suprimeixen totes les transaccions del moneder...</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Contrasenya per a connexions JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Executa l'orde quan el millor bloc canvie (%s en cmd es reemplaça per un resum de bloc)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permet consultes DNS per a -addnode, -seednode i -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = manté les metadades de les tx, p. ex., propietari del compte i informació de sol·licitud del pagament, 2 = prescindeix de les metadades de les tx)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Com d'exhaustiva és la verificació de blocs del -checkblocks (0-4, per defecte: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Manté un índex complet de transaccions, utilitzat per la crida rpc getrawtransaction (per defecte: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Nombre de segons necessaris perquè els iguals de comportament qüestionable puguen tornar a connectar-se (per defecte: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Informació d'eixida de la depuració (per defecte: %u, proporcionar &lt;category&gt; és opcional)</translation>
- </message>
- <message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Utilitza un proxy SOCKS4 apart per a arribar als iguals a través de serveis ocults de Tor (per defecte: %s)</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(per defecte: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Demana sempre les adreces dels iguals a través de consultes DNS (per defecte: %u)</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Quants blocs per comprovar a l'inici (per defecte: %u, 0 = tots)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Inclou l'adreça IP a l'eixida de depuració (per defecte: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escolta les connexions JSON-RPC en &lt;port&gt; (per defecte: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escolta les connexions en &lt;port&gt; (per defecte: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Manté com a màxim &lt;n&gt; connexions a iguals (per defecte: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Fes que el moneder faça difusió de les transaccions</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Memòria intermèdia màxima de recepció per connexió, &lt;n&gt;*1000 bytes (per defecte: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Memòria intermèdia màxima d'enviament per connexió, &lt;n&gt;*1000 bytes (per defecte: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Posa davant de l'eixida de depuració una marca horària (per defecte: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Retransmet i mina les transaccions de l'operador (per defecte: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Retransmet multisig no P2SH (per defecte: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Defineix la mida clau disponible a &lt;n&gt; (per defecte: %u)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Defineix el nombre de fils a crides de servei RPC (per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Especifica el fitxer de configuració (per defecte: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Especifica el temps d'espera de la connexió en milisegons (mínim: 1, per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Especifica el fitxer pid (per defecte: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Gasta el canvi no confirmat en enviar les transaccions (per defecte: %u)</translation>
- </message>
- <message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Llindar per a desconnectar els iguals de comportament qüestionable (per defecte: %u)</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>Xarxa desconeguda especificada a -onlynet: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts
index c45c5e07ec..03c5dd853e 100644
--- a/src/qt/locale/bitcoin_ca_ES.ts
+++ b/src/qt/locale/bitcoin_ca_ES.ts
@@ -30,6 +30,10 @@
<translation>Elimina l'adreça sel·leccionada actualment de la llista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduïu una adreça o una etiqueta per cercar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exporta les dades de la pestanya actual a un fitxer</translation>
</message>
@@ -718,10 +722,6 @@
<translation>&amp;Adreça</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nova adreça de recepció</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nova adreça d'enviament</translation>
</message>
@@ -738,10 +738,6 @@
<translation>L'adreça introduïda «%1» no és una adreça de Bitcoin vàlida.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>L'adreça introduïda «%1» ja és present a la llibreta d'adreces.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>No s'ha pogut desbloquejar el moneder.</translation>
</message>
@@ -791,42 +787,6 @@
<source>Command-line options</source>
<translation>Opcions de línia d'ordres</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Ús:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Opcions de la línia d'ordres</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opcions d'interfície d'usuari:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Trieu el directori de dades a l'inici (per defecte: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Defineix la llengua, per exemple «de_DE» (per defecte: la definida pel sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Inicia minimitzat</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Defineix els certificats arrel SSL per a la sol·licitud de pagament (per defecte: els del sistema)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Mostra la pantalla de benvinguda a l'inici (per defecte: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Reinicialitza tots els canvis de configuració fets des de la interfície gràfica</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1407,10 +1367,6 @@
<translation>Error: El directori de dades especificat «%1» no existeix.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Error: no es pot analitzar el fitxer de configuració: %1. Feu servir només la sintaxi clau=valor.</translation>
- </message>
- <message>
<source>Error: %1</source>
<translation>Avís: %1</translation>
</message>
@@ -1791,6 +1747,10 @@
<translation>Missatge</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Moneder</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultant massa llarga, intenta reduir el text per a la etiqueta / missatge</translation>
</message>
@@ -1901,10 +1861,6 @@
<translation>per kilobyte</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Si la comissió personalitzada es defineix a 1000 satoshis i la transacció és de només 250 bytes, llavors «per kilobyte» només es paguen 250 satoshis en una comissió, mentre que amb la de «total com a mínim» es pagarien 1000 satoshis. Per a transaccions superiors al kilobyte, en tots dos casos es paga per kilobyte.</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Amaga</translation>
</message>
@@ -2001,18 +1957,14 @@
<translation>Esteu segur que ho voleu enviar?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>S'ha afegit una taxa de transacció</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Import total %1</translation>
- </message>
- <message>
<source>or</source>
<translation>o</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Comissió de transacció</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirma l'enviament de monedes</translation>
</message>
@@ -2322,10 +2274,6 @@
<translation>Obert fins %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/fora de línia</translation>
- </message>
- <message>
<source>abandoned</source>
<translation>abandonada</translation>
</message>
@@ -2342,10 +2290,6 @@
<translation>Estat</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, encara no ha estat emès correctement</translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2484,10 +2428,6 @@
<translation>Obert fins %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Fora de línia</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Sense confirmar</translation>
</message>
@@ -2512,10 +2452,6 @@
<translation>Immadur (%1 confirmacions, serà disponible després de %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Aquest bloc no ha estat rebut per cap altre node i probablement no serà acceptat!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generat però no acceptat</translation>
</message>
@@ -2778,34 +2714,10 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>S'han desat les dades del moneder correctament a %1.</translation>
</message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opcions:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Especifica el directori de dades</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Connecta al node per obtenir les adreces de les connexions, i desconnecta</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especifiqueu la vostra adreça pública</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accepta la línia d'ordres i ordres JSON-RPC </translation>
- </message>
- <message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Si no es proporciona &lt;category&gt; o si &lt;category&gt; = 1, treu a la sortida tota la informació de depuració.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Poda configurada per sota el mínim de %d MiB. Utilitzeu un nombre superior.</translation>
</message>
@@ -2822,18 +2734,10 @@
<translation>Error: s'ha produït un error intern fatal. Vegeu debug.log per a més detalls</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Comissió (en %s/kB) per afegir a les transaccions que envieu (per defecte: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>S'està podant la cadena de blocs...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Executa en segon pla com a programa dimoni i accepta ordres</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>No s'ha pogut iniciar el servidor HTTP. Vegeu debug.log per a més detalls.</translation>
</message>
@@ -2842,22 +2746,6 @@
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Vincula a una adreça específica i sempre escolta-hi. Utilitza la notació [host]:port per IPv6</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Elimina totes les transaccions del moneder i només recupera aquelles de la cadena de blocs a través de -rescan a l'inici</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Executa una ordre quan una transacció del moneder canviï (%s en cmd es canvia per TxID)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Defineix el nombre de fils de verificació d'scripts (%u a %d, 0 = auto, &lt;0 = deixa tants nuclis lliures, per defecte: %d)</translation>
- </message>
- <message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
<translation>Aquesta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda</translation>
</message>
@@ -2870,34 +2758,10 @@
<translation>Avís: sembla que no estem plenament d'acord amb els nostres iguals! Podria caler que actualitzar l'aplicació, o potser que ho facin altres nodes.</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; pot ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accepta connexions de fora (per defecte: 1 si no -proxy o -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opcions de la creació de blocs:</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Opcions de connexió:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>S'ha detectat una base de dades de blocs corrupta</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opcions de depuració/proves:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>No carreguis el moneder i inhabilita les crides RPC del moneder</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Voleu reconstruir la base de dades de blocs ara?</translation>
</message>
@@ -2938,10 +2802,6 @@
<translation>No hi ha suficient descriptors de fitxers disponibles.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Només connecta als nodes de la xarxa &lt;net&gt; (ipv4, ipv6 o onion)</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>La poda no es pot configurar amb un valor negatiu.</translation>
</message>
@@ -2950,102 +2810,30 @@
<translation>El mode de poda és incompatible amb -txindex.</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Defineix la mida de la memòria cau de la base de dades en megabytes (%d a %d, per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especifica un fitxer de moneder (dins del directori de dades)</translation>
- </message>
- <message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Utilitza UPnP per a mapejar el port d'escolta (per defecte: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Utilitza la cadena de proves</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>S'estan verificant els blocs...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opcions de depuració/proves del moneder:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Cal reescriure el moneder: reinicieu %s per a completar-ho</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opcions de moneder:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permet les connexions JSON-RPC d'una font específica. Vàlid per a &lt;ip&gt; són una IP individual (p. ex., 1.2.3.4), una xarxa / màscara de xarxa (p. ex., 1.2.3.4/255.255.255.0) o una xarxa/CIDR (p. ex., 1.2.3.4/24). Es pot especificar aquesta opció moltes vegades</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Vincula l'adreça donada i posa a la llista blanca els iguals que s'hi connectin. Feu servir la notació [host]:port per a IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Descobreix l'adreça IP pròpia (per defecte: 1 quan s'escolta i no -externalip o -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Executa l'ordre quan es rebi un avís rellevant o veiem una forquilla molt llarga (%s en cmd és reemplaçat per un missatge)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Si no s'especifica una paytxfee (comissió de transacció de pagament), inclogueu suficient comissió per tal que les transaccions comencin a confirmar-se en una mitja de n blocs (per defecte: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Import no vàlid per a -maxtxfee=&lt;amount&gt;: '%s' (cal que sigui com a mínim la comissió de minrelay de %s per evitar que les comissions s'encallin)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Mida màxima de les dades en les transaccions de l'operador en què confiem i en les meves (per defecte: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Genera a l'atzar credencials per a cada connexió proxy. Això habilita l'aïllament del flux de Tor (per defecte: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>L'import de la transacció és massa petit per enviar-la després que se'n dedueixi la comissió</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Els iguals en la llista blanca no poden ser bandejats per DoS i es transmetran sempre llurs transaccions, fins i tot si ja són a la mempool. Això és útil, p. ex., per a una passarel·la</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Cal que torneu a construir la base de dades fent servir -reindex per tornar al mode no podat. Això tornarà a baixar la cadena de blocs sencera</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(per defecte: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Accepta sol·licituds REST públiques (per defecte: %u)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Connecta a través del proxy SOCKS5</translation>
- </message>
- <message>
<source>Error reading from database, shutting down.</source>
<translation>Error en llegir la base de dades, tancant.</translation>
</message>
@@ -3062,34 +2850,10 @@
<translation>S'ha especificat una màscara de xarxa no vàlida a -whitelist: «%s»</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Manté com a màxim &lt;n&gt; transaccions no connectables en memòria (per defecte: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Cal especificar un port amb -whitebind: «%s»</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opcions de transmissió del node:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opcions del servidor RPC:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Envia informació de traça/depuració a la consola en comptes del fitxer debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Mostra totes les opcions de depuració (ús: --help --help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Redueix el fitxer debug.log durant l'inici del client (per defecte: 1 quan no -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Ha fallat la signatura de la transacció</translation>
</message>
@@ -3118,10 +2882,6 @@
<translation>No s'ha pogut vincular a %s en aquest ordinador (la vinculació ha retornat l'error %s)</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nom d'usuari per a connexions JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Avís</translation>
</message>
@@ -3130,134 +2890,14 @@
<translation>Avís: regles noves desconegudes activades (versionbit %i)</translation>
</message>
<message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Cal que reconstruïu la base de dades fent servir -reindex per canviar -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Se suprimeixen totes les transaccions del moneder...</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Contrasenya per a connexions JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Executa l'ordre quan el millor bloc canviï (%s en cmd es reemplaça per un resum de bloc)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permet consultes DNS per a -addnode, -seednode i -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = manté les metadades de les tx, p. ex., propietari del compte i informació de sol·licitud del pagament, 2 = prescindeix de les metadades de les tx)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Com d'exhaustiva és la verificació de blocs del -checkblocks (0-4, per defecte: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Manté un índex complet de transaccions, utilitzat per la crida rpc getrawtransaction (per defecte: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Nombre de segons necessaris perquè els iguals de comportament qüestionable puguin tornar a connectar-se (per defecte: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Informació de sortida de la depuració (per defecte: %u, proporcionar &lt;category&gt; és opcional)</translation>
- </message>
- <message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Utilitza un proxy SOCKS4 apart per a arribar als iguals a través de serveis ocults de Tor (per defecte: %s)</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(per defecte: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Demana sempre les adreces dels iguals a través de consultes DNS (per defecte: %u)</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Quants blocs per comprovar a l'inici (per defecte: %u, 0 = tots)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Inclou l'adreça IP a la sortida de depuració (per defecte: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escolta les connexions JSON-RPC en &lt;port&gt; (per defecte: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escolta les connexions en &lt;port&gt; (per defecte: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Manté com a màxim &lt;n&gt; connexions a iguals (per defecte: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Fes que el moneder faci difusió de les transaccions</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Memòria intermèdia màxima de recepció per connexió, &lt;n&gt;*1000 bytes (per defecte: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Memòria intermèdia màxima d'enviament per connexió, &lt;n&gt;*1000 bytes (per defecte: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Posa davant de la sortida de depuració una marca horària (per defecte: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Retransmet i mina les transaccions de l'operador (per defecte: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Retransmet multisig no P2SH (per defecte: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Defineix la mida clau disponible a &lt;n&gt; (per defecte: %u)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Defineix el nombre de fils a crides de servei RPC (per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Especifica el fitxer de configuració (per defecte: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Especifica el temps d'espera de la connexió en milisegons (mínim: 1, per defecte: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Especifica el fitxer pid (per defecte: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Gasta el canvi no confirmat en enviar les transaccions (per defecte: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>S'estan iniciant els fils de la xarxa...</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Llindar per a desconnectar els iguals de comportament qüestionable (per defecte: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Els imports de la transacció no han de ser negatius</translation>
</message>
diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts
index 4ea142937c..a08cc960da 100644
--- a/src/qt/locale/bitcoin_cs.ts
+++ b/src/qt/locale/bitcoin_cs.ts
@@ -7,19 +7,19 @@
</message>
<message>
<source>Create a new address</source>
- <translation>Vytvořit novou adresu</translation>
+ <translation>Vytvoř novou adresu</translation>
</message>
<message>
<source>&amp;New</source>
- <translation>&amp;Nová/&amp;Nový/&amp;Nové</translation>
+ <translation>&amp;Nová</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>Zkopíruj tuto adresu do schránky</translation>
+ <translation>Zkopíruj tuto adresu do systémové schránky</translation>
</message>
<message>
<source>&amp;Copy</source>
- <translation>&amp;Zkopírovat</translation>
+ <translation>&amp;Kopíruj</translation>
</message>
<message>
<source>C&amp;lose</source>
@@ -27,27 +27,31 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>Smazat tuto adresu ze seznamu</translation>
+ <translation>Smaž tuto adresu ze seznamu</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Zadej adresu nebo označení pro její vyhledání</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>Exportuj data z aktuálního panelu do souboru</translation>
+ <translation>Exportuj data z tohoto panelu do souboru</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation>&amp;Exportovat</translation>
+ <translation>&amp;Export</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation>&amp;Smaž</translation>
+ <translation>S&amp;maž</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Zvol adresu, na kterou pošleš coiny</translation>
+ <translation>Zvol adresu, na kterou pošleš mince</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>Zvol adresu na příjem mincí</translation>
+ <translation>Zvol adres na příjem mincí</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -55,7 +59,7 @@
</message>
<message>
<source>Sending addresses</source>
- <translation>Odesílající adresy</translation>
+ <translation>Odesílací adresy</translation>
</message>
<message>
<source>Receiving addresses</source>
@@ -67,27 +71,27 @@
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Tohle jsou tvé bitcoinové adresy pro příjem plateb. Je doporučeno pro každou transakci vždy vygenerovat novou adresu.</translation>
+ <translation>Tohle jsou tvé bitcoinové adresy pro příjem plateb. Nezapomeň si pro každou transakci vždy vygenerovat novou adresu.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>&amp;Zkopírovat adresu</translation>
+ <translation>&amp;Kopíruj adresu</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>Kopíruj &amp;Označ</translation>
+ <translation>Kopíruj &amp;označení</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation>&amp;Upravit</translation>
+ <translation>&amp;Uprav</translation>
</message>
<message>
<source>Export Address List</source>
- <translation>Exportuj seznam adres</translation>
+ <translation>Export seznamu adres</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>CSV formát (*.csv)</translation>
+ <translation>Formát CSV (*.csv)</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -133,7 +137,7 @@
</message>
<message>
<source>Show password</source>
- <translation>Zobrazit heslo</translation>
+ <translation>Ukaž heslo</translation>
</message>
<message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
@@ -322,6 +326,14 @@
<translation>Načíst &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Peněženka:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>výchozí peněženka</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Kliknutím zařízneš spojení se sítí.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Vytvářím nový index bloků na disku...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy je &lt;b&gt;zapnutá&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Pošli mince na bitcoinovou adresu</translation>
</message>
@@ -439,7 +455,7 @@
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n aktivní spojení do bitcoinové sítě</numerusform><numerusform>%n aktivní spojení do bitcoinové sítě</numerusform><numerusform>%n aktivních spojení do bitcoinové sítě</numerusform></translation>
+ <translation><numerusform>%n aktivní spojení do bitcoinové sítě</numerusform><numerusform>%n aktivní spojení do bitcoinové sítě</numerusform><numerusform>%n aktivních spojení do bitcoinové sítě</numerusform><numerusform>%n aktivních spojení do bitcoinové sítě</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
@@ -451,7 +467,7 @@
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>Zpracován %n blok transakční historie.</numerusform><numerusform>Zpracovány %n bloky transakční historie.</numerusform><numerusform>Zpracováno %n bloků transakční historie.</numerusform></translation>
+ <translation><numerusform>Zpracován %n blok transakční historie.</numerusform><numerusform>Zpracovány %n bloky transakční historie.</numerusform><numerusform>Zpracováno %n bloků transakční historie.</numerusform><numerusform>Zpracováno %n bloků transakční historie.</numerusform></translation>
</message>
<message>
<source>%1 behind</source>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Peněženka: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Typ: %1
@@ -730,10 +752,6 @@
<translation>&amp;Adresa</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nová přijímací adresa</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nová odesílací adresa</translation>
</message>
@@ -750,8 +768,12 @@
<translation>Zadaná adresa „%1“ není platná bitcoinová adresa.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Zadaná adresa „%1“ už v adresáři je.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adresa "%1" již existuje jako přijímací adresa s označením "%2" a proto nemůže být přidána jako odesílací adresa.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Zadaná adresa „%1“ už v adresáři je s označením "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>Argumenty příkazové řádky</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Užití:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>možnosti příkazové řádky</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Možnosti UI:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Zvolit při startu adresář pro data (výchozí: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Nastavit jazyk, například „de_DE“ (výchozí: systémové nastavení)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Nastartovat minimalizovaně</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Nastavit kořenové SSL certifikáty pro platební požadavky (výchozí: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Zobrazit startovací obrazovku (výchozí: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Vrátit všechny volby měněné v GUI na výchozí hodnoty</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -904,11 +890,11 @@
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>%n GB volného místa</numerusform><numerusform>%n GB volného místa</numerusform><numerusform>%n GB volného místa</numerusform></translation>
+ <translation><numerusform>%n GB volného místa</numerusform><numerusform>%n GB volného místa</numerusform><numerusform>%n GB volného místa</numerusform><numerusform>%n GB volného místa</numerusform></translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
- <translation><numerusform>(z potřebného %n GB)</numerusform><numerusform>(z potřebných %n GB)</numerusform><numerusform>(z potřebných %n GB)</numerusform></translation>
+ <translation><numerusform>(z potřebného %n GB)</numerusform><numerusform>(z potřebných %n GB)</numerusform><numerusform>(z potřebných %n GB)</numerusform><numerusform>(z potřebných %n GB)</numerusform></translation>
</message>
</context>
<context>
@@ -1025,11 +1011,15 @@
</message>
<message>
<source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Použít samostatnou SOCKS5 proxy ke spojení s protějšky přes skryté služby v Toru:</translation>
+ <translation>Použít samostatnou SOCKS&amp;5 proxy ke spojení s protějšky přes skryté služby v Toru:</translation>
</message>
<message>
<source>Hide the icon from the system tray.</source>
- <translation>Skrýt ikonu z panelu.</translation>
+ <translation>Skryje ikonu, která se zobrazuje v panelu.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>Skrýt &amp;ikonu z panelu</translation>
</message>
<message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
@@ -1064,6 +1054,22 @@
<translation>&amp;Síť</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Zakáže některé pokročilé funkce, ale všechny bloky budou stále plně otevřené. Obnovení tohoto nastavení vyžaduje opětovné převzetí celého blockchainu. Skutečné využít disku může být o něco vyšší.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Redukovat prostor pro &amp;bloky na</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Obnovení tohoto nastavení vyžaduje opětovné převzetí celého blockchainu.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = automaticky, &lt;0 = nechat daný počet jader volný, výchozí: 0)</translation>
</message>
@@ -1097,7 +1103,11 @@
</message>
<message>
<source>Accept connections from outside.</source>
- <translation>Přijímat spojení z venku.</translation>
+ <translation>Přijímat spojení zvenčí.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Přijí&amp;mat příchozí spojení</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
@@ -1180,6 +1190,10 @@
<translation>Zda ukazovat možnosti pro ruční správu mincí nebo ne.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;URL třetích stran pro transakce</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;Budiž</translation>
</message>
@@ -1322,6 +1336,10 @@
<translation>Zpracování URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' není platné URI. Místo toho použij 'bitcoin:'.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>Zdrojová URL platebního požadavku není platná: %1</translation>
</message>
@@ -1465,23 +1483,23 @@
</message>
<message numerus="yes">
<source>%n second(s)</source>
- <translation><numerusform>%n vteřinu</numerusform><numerusform>%n vteřiny</numerusform><numerusform>%n vteřin</numerusform></translation>
+ <translation><numerusform>%n vteřinu</numerusform><numerusform>%n vteřiny</numerusform><numerusform>%n vteřin</numerusform><numerusform>%n vteřin</numerusform></translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
- <translation><numerusform>%n minutu</numerusform><numerusform>%n minuty</numerusform><numerusform>%n minut</numerusform></translation>
+ <translation><numerusform>%n minutu</numerusform><numerusform>%n minuty</numerusform><numerusform>%n minut</numerusform><numerusform>%n minut</numerusform></translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
- <translation><numerusform>%n hodinu</numerusform><numerusform>%n hodiny</numerusform><numerusform>%n hodin</numerusform></translation>
+ <translation><numerusform>%n hodinu</numerusform><numerusform>%n hodiny</numerusform><numerusform>%n hodin</numerusform><numerusform>%n hodin</numerusform></translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
- <translation><numerusform>%n den</numerusform><numerusform>%n dny</numerusform><numerusform>%n dnů</numerusform></translation>
+ <translation><numerusform>%n den</numerusform><numerusform>%n dny</numerusform><numerusform>%n dnů</numerusform><numerusform>%n dnů</numerusform></translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
- <translation><numerusform>%n týden</numerusform><numerusform>%n týdny</numerusform><numerusform>%n týdnů</numerusform></translation>
+ <translation><numerusform>%n týden</numerusform><numerusform>%n týdny</numerusform><numerusform>%n týdnů</numerusform><numerusform>%n týdnů</numerusform></translation>
</message>
<message>
<source>%1 and %2</source>
@@ -1489,7 +1507,7 @@
</message>
<message numerus="yes">
<source>%n year(s)</source>
- <translation><numerusform>%n rok</numerusform><numerusform>%n roky</numerusform><numerusform>%n roků</numerusform></translation>
+ <translation><numerusform>%n rok</numerusform><numerusform>%n roky</numerusform><numerusform>%n roků</numerusform><numerusform>%n roků</numerusform></translation>
</message>
<message>
<source>%1 B</source>
@@ -1519,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Chyba při zpracování argumentů příkazového řádku: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Chyba: Zadaný adresář pro data „%1“ neexistuje.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Chyba: Nemohu zpracovat konfigurační soubor: %1. Používej pouze syntaxi klíč=hodnota.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Chyba: Konfigurační soubor se nedá zpracovat: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1617,6 +1639,14 @@
<translation>Obsazenost paměti</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Peněženka:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(žádné)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Vynulovat</translation>
</message>
@@ -1785,6 +1815,10 @@
<translation>&amp;Odblokuj</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>výchozí peněženka</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Vítej v RPC konzoli %1.</translation>
</message>
@@ -1793,6 +1827,14 @@
<translation>V historii se pohybuješ šipkami nahoru a dolů a pomocí %1 čistíš obrazovku.</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Napiš %1 pro přehled dostupných příkazů.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Pro více informací jak používat tuto konzoli napište %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>UPOZORNĚNÍ: Podvodníci jsou aktivní a říkají uživatelům, aby sem zadávali příkazy, kterými jim pak ale vykradou jejich peněženky. Nepoužívej tuhle konzoli, pokud úplně neznáš důsledky jednotlivých příkazů.</translation>
</message>
@@ -1801,6 +1843,14 @@
<translation>Síť je vypnutá</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Spouštění příkazu bez jakékoliv peněženky</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Příkaz se vykonává s použitím peněženky "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(id uzlu: %1)</translation>
</message>
@@ -1872,6 +1922,14 @@
<translation>Vyčistit</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Nativní segwit adresy (Bech32 nebo BIP-173) snižují Vaše budoucí transakční poplatky a nabízejí lepší ochranu před překlepy, avšak staré peněženky je nepodporují. Pokud je toto pole nezaškrtnuté, bude vytvořena adresa kompatibilní se staršími peněženkami.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generovat nativní segwit adresu (Bench32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Historie vyžádaných plateb</translation>
</message>
@@ -1959,6 +2017,10 @@
<translation>Zpráva</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Peněženka</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Výsledná URI je příliš dlouhá, zkus zkrátit text označení/zprávy.</translation>
</message>
@@ -2073,12 +2135,16 @@
<translation>sbal nastavení poplatků</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>za kilobajt</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Specifikujte vlastní poplatek za kB (1000 bajtů) virtuální velikosti transakce.
+
+Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 satoshi za kB" a velikost transakce 500 bajtů (polovina z 1 kB) by stál jen 50 satoshi.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Pokud je vlastní poplatek nastavený na 1000 satoshi a transakce má pouze 250 bajtů, tak „za kilobajt“ zaplatí poplatek jen 250 satoshi, zatímco „přinejmenším“ zaplatí 1000 satoshi. Pro transakce větší než kilobajt obě možnosti platí za kilobajt.</translation>
+ <source>per kilobyte</source>
+ <translation>za kilobajt</translation>
</message>
<message>
<source>Hide</source>
@@ -2125,6 +2191,14 @@
<translation>Časové cílování potvrzení:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Povolit možnost dodatečně transakci navýšit poplatek (tzv. „replace-by-fee“)</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>S dodatečným navýšením poplatku (BIP-125, tzv. „Replace-By-Fee“) můžete zvýšit poplatek i po odeslání. Bez dodatečného navýšení bude navrhnut vyšší transakční poplatek, tak aby kompenzoval zvýšené riziko prodlení transakce.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Všechno s&amp;maž</translation>
</message>
@@ -2181,16 +2255,32 @@
<translation>Jsi si jistý, že tuhle transakci chceš poslat?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>přidáno jakožto transakční poplatek</translation>
+ <source>or</source>
+ <translation>nebo</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Celková částka %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Poplatek můžete navýšit později (vysílá se "Replace-By-Fee" - nahrazení poplatkem, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>nebo</translation>
+ <source>from wallet %1</source>
+ <translation>z peněženky %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Prosím, zkontrolujte vaši transakci.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transakční poplatek</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Nevysílá se "Replace-By-Fee" - nahrazení poplatkem, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Celková částka</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2238,7 +2328,7 @@
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
- <translation><numerusform>Potvrzování by podle odhadu mělo začít během %n bloku.</numerusform><numerusform>Potvrzování by podle odhadu mělo začít během %n bloků.</numerusform><numerusform>Potvrzování by podle odhadu mělo začít během %n bloků.</numerusform></translation>
+ <translation><numerusform>Potvrzování by podle odhadu mělo začít během %n bloku.</numerusform><numerusform>Potvrzování by podle odhadu mělo začít během %n bloků.</numerusform><numerusform>Potvrzování by podle odhadu mělo začít během %n bloků.</numerusform><numerusform>Potvrzování by podle odhadu mělo začít během %n bloků.</numerusform></translation>
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
@@ -2312,6 +2402,10 @@
<translation>Od&amp;ečíst poplatek od částky</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>Použít dostupný zůstatek</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Zpráva:</translation>
</message>
@@ -2519,7 +2613,7 @@
<name>TransactionDesc</name>
<message numerus="yes">
<source>Open for %n more block(s)</source>
- <translation><numerusform>Otevřeno pro %n další blok</numerusform><numerusform>Otevřeno pro %n další bloky</numerusform><numerusform>Otevřeno pro %n dalších bloků</numerusform></translation>
+ <translation><numerusform>Otevřeno pro %n další blok</numerusform><numerusform>Otevřeno pro %n další bloky</numerusform><numerusform>Otevřeno pro %n dalších bloků</numerusform><numerusform>Otevřeno pro %n dalších bloků</numerusform></translation>
</message>
<message>
<source>Open until %1</source>
@@ -2530,10 +2624,6 @@
<translation>koliduje s transakcí o %1 konfirmacích</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/nepotvrzeno, %1</translation>
</message>
@@ -2562,14 +2652,6 @@
<translation>Stav</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, ještě nebylo rozesláno</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, rozesláno přes %n uzel</numerusform><numerusform>, rozesláno přes %n uzly</numerusform><numerusform>, rozesláno přes %n uzlů</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Datum</translation>
</message>
@@ -2611,7 +2693,7 @@
</message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
- <translation><numerusform>dozraje po %n bloku</numerusform><numerusform>dozraje po %n blocích</numerusform><numerusform>dozraje po %n blocích</numerusform></translation>
+ <translation><numerusform>dozraje po %n bloku</numerusform><numerusform>dozraje po %n blocích</numerusform><numerusform>dozraje po %n blocích</numerusform><numerusform>dozraje po %n blocích</numerusform></translation>
</message>
<message>
<source>not accepted</source>
@@ -2654,6 +2736,10 @@
<translation>Celková velikost transakce</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Virtuální velikost transakce</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Pořadí výstupu</translation>
</message>
@@ -2717,17 +2803,13 @@
</message>
<message numerus="yes">
<source>Open for %n more block(s)</source>
- <translation><numerusform>Otevřeno pro %n další blok</numerusform><numerusform>Otevřeno pro %n další bloky</numerusform><numerusform>Otevřeno pro %n dalších bloků</numerusform></translation>
+ <translation><numerusform>Otevřeno pro %n další blok</numerusform><numerusform>Otevřeno pro %n další bloky</numerusform><numerusform>Otevřeno pro %n dalších bloků</numerusform><numerusform>Otevřeno pro %n dalších bloků</numerusform></translation>
</message>
<message>
<source>Open until %1</source>
<translation>Otřevřeno dokud %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Nepotvrzeno</translation>
</message>
@@ -2752,10 +2834,6 @@
<translation>Nedozráno (%1 potvrzení, dozraje při %2 potvrzeních)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Tento blok nedostal žádný jiný uzel a pravděpodobně nebude akceptován!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Vygenerováno, ale neakceptováno</translation>
</message>
@@ -2867,6 +2945,10 @@
<translation>Ostatní</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Zadej adresu, její označení nebo ID transakce pro vyhledání</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Minimální částka</translation>
</message>
@@ -3062,38 +3144,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Data z peněženky byla v pořádku uložena do %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Zrušit</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Možnosti:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Adresář pro data</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Připojit se k uzlu, získat adresy jeho protějšků a odpojit se</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Udej svou veřejnou adresu</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Akceptovat příkazy z příkazové řádky a přes JSON-RPC</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Šířen pod softwarovou licencí MIT, viz přiložený soubor %s nebo %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Pokud není &lt;category&gt; zadána nebo je &lt;category&gt; = 1, bude tisknout veškeré ladicí informace.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Prořezávání je nastaveno pod minimum %d MiB. Použij, prosím, nějaké vyšší číslo.</translation>
</message>
@@ -3110,18 +3172,10 @@
<translation>Chyba: Přihodila se závažná vnitřní chyba, podrobnosti viz v debug.log</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Poplatek (v %s/kB), který se přidá ke každé odeslané transakci (výchozí: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Prořezávám úložiště bloků...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Běžet na pozadí jako démon a přijímat příkazy</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Nemohu spustit HTTP server. Detaily viz v debug.log.</translation>
</message>
@@ -3134,52 +3188,20 @@
<translation>Vývojáři %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Sazba poplatku (v %s/kB), která se použije, pokud nebude k dispozici dostatek dat pro automatický odhad poplatku (výchozí: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Přijímat přeposílané transakce obdržené od vždy vítaných protějšků, i když transakce nepřeposíláme (výchozí: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Poslouchat na zadané adrese. Pro zápis IPv6 adresy použij notaci [adresa]:port</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Nedaří se mi získat zámek na datový adresář %s. %s pravděpodobně už jednou běží.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Smazat všechny transakce peněženky a při startu obnovit pouze relevantní části bločenky pomocí -rescan</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Nemohu poskytovat konkrétní spojení a současně chtít, aby addrman vyhledával odchozí spojení.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Nastala chyba při čtení souboru %s! Všechny klíče se přečetly správně, ale data o transakcích nebo záznamy v adresáři mohou chybět či být nesprávné.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Vyloučit ladicí informace dané kategorie. Dá se zkombinovat s -debug=1, aby se zaznamenávaly ladicí informace všech kategorií kromě jedné nebo několika zvolených.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Spustit příkaz, když se objeví transakce týkající se peněženky (%s se v příkazu nahradí za TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Počet extra transakcí, které se mají držet v paměti pro účely rekonstrukce kompaktních bloků (výchozí: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Pokud je tenhle blok v bločence, tak předpokládat, že on i jeho následníci jsou platní, a potenciálně přeskočit ověřování jejich skriptů (0 = ověřovat vše, výchozí: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Maximální povolené seřizování času mediánem časů protějšků. Místní vnímání času může být ovlivněno protějšky, a to dopředu nebo dozadu až o toto množství. (výchozí: %u vteřin)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Horní hranice pro celkový poplatek (v %s) za jednu transakci z peněženky nebo jednu surovou transakci; příliš nízká hodnota může zmařit velké transakce (výchozí: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Seskupení výstupů podle adresy, při výběru všech nebo žádných, namísto výběru báze za výstup. Zvýšena ochrana soukromí, protože je adresa použita pouze jednou (pokud nikdo na tuto adresu již nic po minutě nepošle). Může být spojeno s vyššími poplatky, jelikož neoptimalizovaný výběr mincí může vyústit v přidané omezení (předvolené: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3190,22 +3212,6 @@
<translation>Prosíme, zapoj se nebo přispěj, pokud ti %s přijde užitečný. Více informací o programu je na %s.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Při nedostatku adres získat další protějšky z DNS (výchozí: 1, pokud není použito -connect)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Omezit nároky na úložný prostor prořezáváním (mazáním) starých bloků. Tato volba také umožní použít RPC volání pruneblockchain ke smazání konkrétních bloků a dále automatické prořezávání starých bloků, pokud je zadána cílová velikost souborů s bloky v MiB. Tento režim není slučitelný s -txindex ani -rescan. Upozornění: opětovná změna tohoto nastavení bude vyžadovat nové stažení celé bločenky. (výchozí: 0 = bloky neprořezávat, 1 = povolit ruční prořezávání skrze RPC, &gt;%u = automatické prořezávání bloků tak, aby byla udržena cílová velikost souborů s bloky, v MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Nastavit nejnižší akceptovatelný poplatek (v %s/kB) pro transakce, které mají být zahrnuty do nových bloků. (výchozí: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Nastavení počtu vláken pro verifikaci skriptů (%u až %d, 0 = automaticky, &lt;0 = nechat daný počet jader volný, výchozí: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Databáze bloků obsahuje blok, který vypadá jako z budoucnosti, což může být kvůli špatně nastavenému datu a času na tvém počítači. Nech databázi bloků přestavět pouze v případě, že si jsi jistý, že máš na počítači správný datum a čas</translation>
</message>
@@ -3226,18 +3232,6 @@
<translation>Nedaří se mi vrátit databázi do stavu před štěpem. Budeš muset znovu stáhnout celou bločenku</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Použít UPnP k namapování naslouchacího portu (výchozí: 1, pokud naslouchá a nepoužívá -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Uživatelské jméno a zahašované heslo pro JSON-RPC spojení. Pole &lt;userpw&gt; má formát: &lt;UŽIVATELSKÉ_JMÉNO&gt;:&lt;SŮL&gt;$&lt;HAŠ&gt;. Pomocný pythonní skript je přiložen v share/rpcuser. Klient se pak už připojuje normálně pomocí páru argumentů rpcuser=&lt;UŽIVATELSKÉ_JMÉNO&gt;/rpcpassword=&lt;HESLO&gt;. Tuto volbu lze použít i vícekrát</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Peněženka nebude vytvářet transakce, které by porušovaly limity transakčního zásobníku na řetězce (výchozí: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Upozornění: Síť podle všeho není v konzistentním stavu. Někteří těžaři jsou zřejmě v potížích.</translation>
</message>
@@ -3246,10 +3240,6 @@
<translation>Upozornění: Nesouhlasím zcela se svými protějšky! Možná potřebuji aktualizovat nebo ostatní uzly potřebují aktualizovat.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Zda uchovat transakční zásobník mezi vypnutím a zapnutím (výchozí: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d z posledních 100 bloků má neočekávanou verzi</translation>
</message>
@@ -3262,42 +3252,14 @@
<translation>-maxmempool musí být alespoň %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; může být:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Přijímat spojení zvenčí (výchozí: 1, pokud není zadáno -proxy nebo -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Připojit komentář k typu klienta</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Pokusit se při startu zachránit soukromé klíče z poškozeného souboru s klíči</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Možnosti vytváření bloku:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Nemohu přeložit -%s adresu: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Možnosti výběru bločenky:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Index drobných je mimo platný rozsah</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Možnosti připojení:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i–%i</translation>
</message>
@@ -3306,36 +3268,12 @@
<translation>Bylo zjištěno poškození databáze bloků</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Možnosti ladění/testování:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Nenačítat peněženku a vypnout její RPC volání</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Chceš přestavět databázi bloků hned teď?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Zapnout oznamování hashů bloků na adrese &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Zapnout oznamování hashů transakcí na adrese &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Zapnout oznamování surových bloků na adrese &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Zapnout oznamování surových transakcí na adrese &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Povolit výměnu transakcí v transakčním zásobníku (výchozí: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Chyba při vytváření %s: v této verzi nemůžeš vytvářeš ne-HD peněženky.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3350,6 +3288,10 @@
<translation>Chyba při načítání %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Chyba při načítání %s: Soukromé klíče můžou být zakázané jen v průběhu vytváření.</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Chyba při načítání %s: peněženka je poškozená</translation>
</message>
@@ -3374,6 +3316,10 @@
<translation>Nepodařilo se naslouchat na žádném portu. Použij -listen=0, pokud to byl tvůj záměr.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Během inicializace se nepodařilo proskenovat peněženku</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importuji...</translation>
</message>
@@ -3398,8 +3344,12 @@
<translation>Neplatná částka pro -fallbackfee=&lt;částka&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Udržovat zasobník transakcí menší než &lt;n&gt; megabajtů (výchozí: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Zadaný adresář bloků "%s" neexistuje.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Aktualizuje se txindex databáze</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3410,26 +3360,10 @@
<translation>Načítám seznam klateb...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Místo pro autentizační cookie (výchozí: adresář pro data)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Je nedostatek deskriptorů souborů.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Připojovat se pouze k uzlům v &lt;net&gt; síti (ipv4, ipv6 nebo onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Vypsat tuto nápovědu a skončit</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Vypsat verzi a skončit</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Prořezávání nemůže být zkonfigurováno s negativní hodnotou.</translation>
</message>
@@ -3438,14 +3372,6 @@
<translation>Prořezávací režim není kompatibilní s -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Znovu vytvořit stav a index bločenky z blk*.dat souborů na disku</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Znovu vytvořit stav bločenky z aktuálně indexovaných bloků</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Znovu aplikuji bloky…</translation>
</message>
@@ -3454,14 +3380,6 @@
<translation>Vracím bloky…</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Nastavit velikost databázové vyrovnávací paměti v megabajtech (%d až %d, výchozí: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Udej název souboru s peněženkou (v rámci datového adresáře)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Zdrojový kód je dostupný na %s.</translation>
</message>
@@ -3474,6 +3392,10 @@
<translation>Nedaří se mi připojit na %s na tomhle počítači. %s už pravděpodobně jednou běží.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Nepodařilo se vygenerovat klíče</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Nepodporovaný argument -benchmark se ignoruje, použij -debug=bench.</translation>
</message>
@@ -3494,14 +3416,6 @@
<translation>Aktualizuji databázi neutracených výstupů (UTXO)</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Použít UPnP k namapování naslouchacího portu (výchozí: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Použít testovací bločenku</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Komentář u typu klienta (%s) obsahuje riskantní znaky.</translation>
</message>
@@ -3510,90 +3424,26 @@
<translation>Ověřuji bloky…</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Možnosti ladění/testování peněženky:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Soubor s peněženkou potřeboval přepsat: restartuj %s, aby se operace dokončila</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Možnosti peněženky:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Povolit JSON-RPC spojení ze specifikovaného zdroje. Platnou hodnotou &lt;ip&gt; je jednotlivá IP adresa (např. 1.2.3.4), síť/maska (např. 1.2.3.4/255.255.255.0) nebo síť/CIDR (např. 1.2.3.4/24). Tuto volbu lze použít i vícekrát</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Obsadit zadanou adresu a vždy vítat protějšky, které se na ni připojí. Pro zápis IPv6 adresy použij notaci [adresa]:port</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Vytvářet nové soubory s výchozími systémovými právy namísto umask 077 (uplatní se, pouze pokud je vypnutá funkce peněženky)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Zjistit vlastní IP adresu (výchozí: 1, pokud naslouchá a není zadáno -externalip nebo -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Chyba: Nelze naslouchat příchozí spojení (listen vrátil chybu %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Spustit příkaz, když přijde relevantní upozornění nebo když dojde k opravdu dlouhému rozštěpení řetezce bloků (%s se v příkazu nahradí zprávou)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Poplatky (v %s/kB) menší než tato hodnota jsou považovány za nulové pro účely přeposílání, těžení a vytváření transakcí (výchozí: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Pokud paytxfee není nastaveno, platit dostatečný poplatek na to, aby začaly být transakce potvrzovány v průměru během n bloků (výchozí: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Neplatná částka pro -maxtxfee=&lt;amount&gt;: '%s' (musí být alespoň jako poplatek minrelay %s, aby transakce nezůstávaly trčet)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maximální velikost dat v transakcích nesoucích data, se kterou jsme ochotni je ještě přeposílat a těžit (výchozí: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Použít náhodné údaje pro každé proxy spojení. To umožní izolovat nesouvisející datové toky v Toru (výchozí: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Částka v transakci po odečtení poplatku je příliš malá na odeslání</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Na vždy vítané protějšky se nevztahuje DoS klatba a jejich transakce jsou vždy přeposílány, i když už třeba jsou v transakčním zásobníku, což je užitečné např. pro bránu</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>K návratu k neprořezávacímu režimu je potřeba přestavět databázi použitím -reindex. Také se znovu stáhne celá bločenka</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(výchozí: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Přijímat veřejné REST požadavky (výchozí: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Automaticky v Toru vytvářet skryté služby (výchozí: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Připojit se přes SOCKS5 proxy</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Chyba při načítání %s: nemůžeš vypnout HD u existující HD peněženky</translation>
</message>
@@ -3606,10 +3456,6 @@
<translation>Chyba při aktualizaci stavové databáze bločenky</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importovat při startu bloky z externího souboru blk000??.dat</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informace</translation>
</message>
@@ -3630,44 +3476,28 @@
<translation>Ve -whitelist byla zadána neplatná podsíť: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Držet v paměti nejvýše &lt;n&gt; nespojitelných transakcí (výchozí: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>V rámci -whitebind je třeba specifikovat i port: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Možnosti přeposílání:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Možnosti RPC serveru:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Omezuji -maxconnections z %d na %d kvůli systémovým omezením.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Přeskenovat při startu bločenku na chybějící transakce tvé pěněženky</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Posílat stopovací/ladicí informace do konzole místo do souboru debug.log</translation>
+ <source>Signing transaction failed</source>
+ <translation>Nepodařilo se podepsat transakci</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Zobrazit všechny možnosti ladění (užití: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Uvedená -walletdir "%s" neexistuje</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Při spuštění klienta zmenšit soubor debug.log (výchozí: 1, pokud není zadáno -debug)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Uvedená -walletdir "%s" je relatívna cesta</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>Nepodařilo se podepsat transakci</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Uvedená -walletdir "%s" není složkou</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3678,14 +3508,6 @@
<translation>Tohle je experimentální program.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Heslo ovládacího portu Toru (výchozí: prázdné)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Ovládací port Toru, je-li zapnuté onion naslouchání (výchozí: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Částka v transakci je příliš malá</translation>
</message>
@@ -3702,18 +3524,18 @@
<translation>Nedaří se mi připojit na %s na tomhle počítači (operace bind vrátila chybu %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Převést při startu peněženku na nejnovější formát</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Uživatelské jméno pro JSON-RPC spojení</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Nepodařilo se mi vygenerovat počáteční klíče</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Kontroluji peněženku/y…</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Peněženka %s se nachází mimo adresář pro peněženky %s</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Upozornění</translation>
</message>
@@ -3722,98 +3544,18 @@
<translation>Upozornění: aktivována neznámá nová pravidla (verzový bit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Zda fungovat v čistě blokovém režimu (výchozí: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Je třeba přestavět databázi použitím -reindex, aby bylo možné změnit -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Vymazat všechny transakce z peněženky...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Možnosti ZeroMQ oznamování:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Heslo pro JSON-RPC spojení</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Spustit příkaz, když se změní nejlepší blok (%s se v příkazu nahradí hashem bloku)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Povolit DNS dotazy pro -addnode (přidání uzlu), -seednode a -connect (připojení)</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = ukládat transakční metadata, např. majitele účtu a informace o platebním požadavku, 2 = mazat transakční metadata)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee je nastaveno velmi vysoko! Takto vysoký poplatek může být zaplacen v jednotlivé transakci.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Čekat na zadané adrese na JSON-RPC spojení. Tato volba se ignoruje, pokud současně nezadáš i volbu -rpcallowip. Port je volitelný a má přednost před -rpcport. Pro zápis IPv6 adresy použij notaci [adresa]:port. Tuto volbu lze použít i vícekrát (výchozí: 127.0.0.1 a ::1, tzn. localhost, nebo pokud je zadáno -rpcallowip, tak 0.0.0.0 a ::, tzn. všechny adresy)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Nedržet transakce v zásobníku déle než &lt;n&gt; hodin (výchozí: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Ekvivalent bajtů za každý sigop v transakcích – pro účely přeposílání a těžení (výchozí: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Chyba při načítání %s: nemůžeš zapnout HD u existující ne-HD peněženky</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Chyba při načítání peněženky %s. Parametr -wallet smí uvádět pouze název souboru (nikoli cestu k němu).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Poplatky (v %s/kB) menší než tato hodnota jsou považovány za nulové pro účely vytváření transakcí (výchozí: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Vynutit přeposílání transakcí od vždy vítaných protějšků (tj. těch na bílé listině), i když porušují místní zásady pro přeposílání (výchozí: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Jak moc důkladná má být verifikace bloků -checkblocks (0-4, výchozí: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Spravovat úplný index transakcí, který je využíván rpc voláním getrawtransaction (výchozí: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Doba ve vteřinách, po kterou se nebudou moci zlobivé protějšky znovu připojit (výchozí: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Tisknout ladicí informace (výchozí: %u, zadání &lt;category&gt; je volitelné)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Nastaví serializaci surových transakcí nebo bloků, jak jsou vraceny v méně povídavém módu: ne-segwit (0) nebo segwit (1) (výchozí: %d)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Umožnit filtrování bloků a transakcí pomocí Bloomova filtru (výchozí: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Sazba poplatku (v %s/kB), která určuje tvou ochotu v případě potřeby proměnit drobné v poplatek (výchozí: %s). Poznámka: výstup se promění, pokud se při téhle sazbě změní v prach. Nicméně proměňovat budeme do výše poplatku pro přenos prachu a proměněný poplatek nad tuto výši bude omezený odhadem poplatku na nejdelší čas</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Toto je transakční poplatek, který se platí, pokud náhodou není k dispozici odhad poplatků.</translation>
</message>
@@ -3826,10 +3568,6 @@
<translation>Celková délka síťového identifikačního řetězce (%i) překročila svůj horní limit (%i). Omez počet nebo velikost voleb uacomment.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Pokusit se udržet odchozí provoz pod stanovenou hodnotou (v MiB za 24 hodin), 0 = bez omezení (výchozí: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Byl použit nepodporovaný argument -socks. Nastavení verze SOCKS už není možné, podporovány jsou pouze SOCKS5 proxy.</translation>
</message>
@@ -3838,10 +3576,6 @@
<translation>Nepodporovaný argument -whitelistalwaysrelay se ignoruje, použij -whitelistrelay a/nebo -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Použít samostatnou SOCKS5 proxy ke spojení s protějšky přes skryté služby v Toru (výchozí: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Upozornění: Síť těží neznámé verze bloků! Je možné, že jsou v platnosti neznámá pravidla</translation>
</message>
@@ -3850,106 +3584,18 @@
<translation>Upozornění: soubor s peněženkou je poškozený, data jsou však zachráněna! Původní soubor %s je uložený jako %s v %s. Pokud nejsou stav tvého účtu nebo transakce v pořádku, zřejmě bys měl obnovit zálohu.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Vždy vítat protějšky připojující se z dané IP adresy (např. 1.2.3.4) či podsítě (CIDR zápis, např. 1.2.3.0/24). Lze zadat i vícekrát.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s je nastaveno velmi vysoko!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(výchozí: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Vždy získávat adresy dalších protějšků přes DNS (výchozí: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Chyba při načítání peněženky %s. -wallet musí být obyčejný soubor.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Chyba při načítání peněženky %s. Udán duplicitní název souboru -wallet.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Chyba při načítání peněženky %s. Neplatné znaky v názvu souboru -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Kolik bloků při startu zkontrolovat (výchozí: %u, 0 = všechny)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Zaznamenávat do ladicích výstupů i IP adresy (výchozí: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Vyčerpal se zásobník klíčů, zavolej prvně, prosím, keypoolrefill</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Čekat na JSON-RPC spojení na &lt;portu&gt; (výchozí: %u nebo testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Čekat na spojení na &lt;portu&gt; (výchozí: %u nebo testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Povolit nejvýše &lt;n&gt; protějšků (výchozí: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Transakce z peněženky rozesílat</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximální velikost přijímacího bufferu pro každé spojení, &lt;n&gt;*1000 bajtů (výchozí: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximální velikost odesílacího bufferu pro každé spojení, &lt;n&gt;*1000 bajtů (výchozí: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Připojit před ladicí výstup časové razítko (výchozí: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Přeposílat a těžit transakce nesoucí data (výchozí: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Přeposílat ne-P2SH multisig (výchozí: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Nastavit zásobník klíčů na velikost &lt;n&gt; (výchozí: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Nastavit maximální váhu bloku pro BIP141 (výchozí: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Nastavení počtu vláken pro servisní RPC volání (výchozí: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Konfigurační soubor (výchozí: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Zadej časový limit spojení v milivteřinách (minimum: 1, výchozí: %d)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Utrácet i ještě nepotvrzené drobné při posílání transakcí (výchozí: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Spouštím síťová vlákna…</translation>
</message>
@@ -3966,10 +3612,6 @@
<translation>Toto je poplatek, který zaplatíš za každou poslanou transakci.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Práh pro odpojování zlobivých protějšků (výchozí: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Částky v transakci nemohou být záporné</translation>
</message>
@@ -3990,6 +3632,22 @@
<translation>Nedostatek prostředků</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Není možné vygenerovat klíč na změnu adresy. Soukromé klíče jsou pro tuto peněženku zakázané.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Není možné vylepšit peněženku bez HD bez aktualizace, která podporuje dělení keypoolu. Použijte prosím -upgradewallet=169900 nebo -upgradewallet bez specifikované verze.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Odhad poplatku se nepodařil. Fallbackfee je zakázaný. Počkejte několik bloků nebo povolte -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Upozornění: Byly zjištěné soukromé klíče v peněžence {%s} se zakázanými soukromými klíči.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Načítám index bloků...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_cy.ts b/src/qt/locale/bitcoin_cy.ts
index 68adce3e61..ecc21332e3 100644
--- a/src/qt/locale/bitcoin_cy.ts
+++ b/src/qt/locale/bitcoin_cy.ts
@@ -623,10 +623,6 @@
</context>
<context>
<name>HelpMessageDialog</name>
- <message>
- <source>Usage:</source>
- <translation>Cynefod:</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -778,6 +774,10 @@
<source>Label</source>
<translation>Label</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Waled</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1038,10 +1038,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opsiynau:</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Craidd Bitcoin</translation>
</message>
diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts
index 6143c412e4..c7a2422c8a 100644
--- a/src/qt/locale/bitcoin_da.ts
+++ b/src/qt/locale/bitcoin_da.ts
@@ -30,8 +30,12 @@
<translation>Slet den markerede adresse fra listen</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Indtast adresse eller mærkat for at søge</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
- <translation>Eksportér den aktuelle visning til en fil</translation>
+ <translation>Eksportér dataen i den aktuelle visning til en fil</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -322,6 +326,14 @@
<translation>&amp;Åbn URI…</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Tegnebog:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Standard tegnebog</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Klik for at deaktivere netværksaktivitet.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Genindekserer blokke på disken…</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy er &lt;b&gt;aktiveret&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Send bitcoins til en Bitcoin-adresse</translation>
</message>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Tegnebog: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Type: %1
@@ -730,10 +752,6 @@
<translation>&amp;Adresse</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Ny modtagelsesadresse</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Ny afsendelsesadresse</translation>
</message>
@@ -750,8 +768,12 @@
<translation>Den indtastede adresse “%1” er ikke en gyldig Bitcoin-adresse.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Den indtastede adresse “%1” er allerede i adressebogen.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adressen "%1" eksisterer allerede som modtagende adresse med mærkat "%2" og kan derfor ikke tilføjes som sende adresse.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Den indtastede adresse "%1" er allerede i adresse bogen med mærkat "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>Kommandolinjetilvalg</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Anvendelse:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>kommandolinjetilvalg</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Indstillinger for brugergrænseflade:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Vælg datamappe under opstart (standard: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Vælg sprog; fx “da_DK” (standard: systemsprog)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Start minimeret</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Opsæt SSL-rodcertifikater til betalingsadmodninger (standard: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Vis startskærm under opstart (standard: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Nulstil alle indstillinger, der er foretaget i den grafiske brugerflade</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1068,6 +1054,22 @@
<translation>&amp;Netværk</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Deaktiverer nogle avancerede funktioner men alle blokke vil stadig blive fuldt validerede. Tilbagevending af denne indstilling kræver afhentning af hele blokkæden igen. Det aktuelle disk forbrug kan være noget højere.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Beskære &amp;blok opbevaring til</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Tilbagevending af denne indstilling kræver afhentning af hele blokkæden igen.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt;0 = efterlad så mange kerner fri)</translation>
</message>
@@ -1334,6 +1336,10 @@
<translation>URI-håndtering</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' er ikke et gyldigt URI. Brug 'bitcoin:' istedet. </translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>Hentnings-URL for betalingsanmodning er ugyldig: %1</translation>
</message>
@@ -1531,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Fejl ved fortolkning af kommandolinje argumenter: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Fejl: Angivet datamappe “%1” eksisterer ikke.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Fejl: Kan ikke fortolke konfigurationsfil: %1. Brug kun syntaksen nøgle=værdi.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Fejl: Kan ikke fortolke konfigurations filen: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1629,6 +1639,14 @@
<translation>Hukommelsesforbrug</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Tegnebog:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(ingen)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Nulstil</translation>
</message>
@@ -1797,6 +1815,10 @@
<translation>&amp;Fjern bandlysning</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>Standard tegnebog</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Velkommen til %1s RPC-konsol.</translation>
</message>
@@ -1809,6 +1831,10 @@
<translation>Tast %1 for en oversigt over de tilgængelige kommandoer.</translation>
</message>
<message>
+ <source>For more information on using this console type %1.</source>
+ <translation>For mere information om at bruge denne konsol, tast %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>ADVARSEL: Svindlere har tidligere aktivt bedt brugere om at indtaste kommandoer her for at stjæle indholdet af deres tegnebøger. Brug ikke denne konsol uden fuldt ud at forstå følgerne af en kommando.</translation>
</message>
@@ -1817,6 +1843,14 @@
<translation>Netværksaktivitet deaktiveret</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Udfører kommando uden en tegnebog</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Eksekverer kommando ved brug af "%1" tegnebog</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(knude-id: %1)</translation>
</message>
@@ -1888,6 +1922,14 @@
<translation>Ryd</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Rene segwit-adresser (kendt som Bech32 eller BIP-173) reducerer dine transaktionsgebyrer i det lange løb og giver bedre beskyttelse imod tastefejl, men gamle tegnebøger understøtter dem ikke. Hvis dette ikke vælges, vil i stedet en adresse, der fungerer med ældre tegnebøger, oprettes.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generér rene segwit-adresser (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Historik over betalingsanmodninger</translation>
</message>
@@ -1896,10 +1938,6 @@
<translation>&amp;Anmod om betaling</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Generér Bech32-adresse</translation>
- </message>
- <message>
<source>Show the selected request (does the same as double clicking an entry)</source>
<translation>Vis den valgte anmodning (gør det samme som dobbeltklik på en indgang)</translation>
</message>
@@ -1979,6 +2017,10 @@
<translation>Besked</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Tegnebog</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Resulterende URI var for lang; prøv at forkorte teksten til mærkaten/beskeden.</translation>
</message>
@@ -2093,12 +2135,16 @@
<translation>sammenfold gebyropsætning</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>pr. kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Specificer et brugerdefineret gebyr per kB (1.000 bytes) af transaktionens virtuelle størrelse.
+
+Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satoshis per kB" for en transkationsstørrelse på 500 bytes (halvdelen af 1kB) ville ultimativt udbytte et gebyr på kun 50 satoshis.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Hvis det brugertilpassede gebyr er sat til 1000 satoshis, og transaktionen kun fylder 250 byte, betaler “pr. kilobyte” kun 250 satoshis i gebyr, mens “total mindst” betaler 1000 satoshis. For transaktioner større end en kilobyte betaler begge pr. kilobyte.</translation>
+ <source>per kilobyte</source>
+ <translation>pr. kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2209,14 +2255,6 @@
<translation>Er du sikker på, at du vil sende?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>tilføjet som transaktionsgebyr</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Beløb i alt %1</translation>
- </message>
- <message>
<source>or</source>
<translation>eller</translation>
</message>
@@ -2225,10 +2263,26 @@
<translation>Du kan øge gebyret senere (signalerer erstat-med-gebyr, BIP-125).</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>fra tegnebog %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Venligst, vurder din transaktion.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaktionsgebyr</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>Signalerer ikke erstat-med-gebyr, BIP-125.</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>Total Mængde</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Bekræft afsendelse af bitcoins</translation>
</message>
@@ -2570,10 +2624,6 @@
<translation>i konflikt med en transaktion, der har %1 bekræftelser</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/ubekræftet, %1</translation>
</message>
@@ -2602,14 +2652,6 @@
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, er ikke blevet transmitteret endnu</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, transmitteret igennem %n knude</numerusform><numerusform>, transmitteret igennem %n knuder</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Dato</translation>
</message>
@@ -2694,6 +2736,10 @@
<translation>Totalstørrelse af transaktion</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Transaktion virtuel størrelse</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Outputindeks</translation>
</message>
@@ -2764,10 +2810,6 @@
<translation>Åben indtil %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Ubekræftet</translation>
</message>
@@ -2792,10 +2834,6 @@
<translation>Umoden (%1 bekræftelser; vil være tilgængelig efter %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Denne blok blev ikke modtaget af nogen andre knuder og vil formentlig ikke blive accepteret!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Genereret, men ikke accepteret</translation>
</message>
@@ -3106,38 +3144,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Tegnebogsdata blev gemt til %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Fortryd</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Indstillinger:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Angiv datamappe</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Forbind til en knude for at modtage adresser på andre knuder, og afbryd derefter</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Angiv din egen offentlige adresse</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Acceptér kommandolinje- og JSON-RPC-kommandoer</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distribueret under MIT-softwarelicensen; se den vedlagte fil %s eller %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Hvis &lt;category&gt; ikke angives eller hvis &lt;category&gt; = 1, udskriv al fejlretningsinformation.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Beskæring er sat under minimumsgrænsen på %d MiB. Brug venligst et større tal.</translation>
</message>
@@ -3154,18 +3172,10 @@
<translation>Fejl: En alvorlig intern fejl er opstået. Se debug.log for detaljer</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Gebyr (i %s/kB) der skal lægges til de transaktioner du sender (standard: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Beskærer bloklager…</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Kør i baggrunden som en service, og acceptér kommandoer</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Kunne ikke starte HTTP-server. Se fejlretningslog for detaljer.</translation>
</message>
@@ -3178,52 +3188,20 @@
<translation>Udviklerne af %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>En gebyrsats (i %s/kB), som vil blive brugt, hvis gebyrestimering har utilstrækkelig data (standard: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Acceptér videresendte transaktioner, der modtages fra hvidlistede knuder, selv når transaktioner ikke videresendes (standard: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Tildel til den givne adresse og lyt altid på den. Brug [vært]:port-notation for IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Kan ikke opnå en lås på datamappe %s. %s kører sansynligvis allerede.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Slet alle transaktioner i tegnebogen og genskab kun disse dele af blokkæden gennem -rescan under opstart</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Kan ikke give specifikke forbindelser og få addrman til at finde udgående forbindelser på samme tid.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Fejl under læsning af %s! Alle nøgler blev læst korrekt, men transaktionsdata eller indgange i adressebogen kan mangle eller være ukorrekte.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Ekskludér fejlsøgningsinformation for en kategori. Kan bruges sammen med -debug=1 for at udskrive fejlsøgningslogs for alle kategorier undtaget én eller flere specificerede kategorier.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Udfør kommando, når en transaktion i tegnebogen ændres (%s i kommandoen erstattes med TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Ekstra transaktioner, der skal beholdes i hukommelsen til kompakte blokgenopbygninger (standard: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Hvis denne blok er i kæden, så antag at den og dens forgængere er gyldige, og spring potentielt deres scriptverificering over (0 for at verificere alle, standard: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Justering af maksimalt tilladt gennemsnitlig afvigelse fra peer-tid. Den lokale opfattelse af tid kan blive påvirket frem eller tilbage af peers med denne mængde tid. (standard: %u sekunder)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Maksimalt totalgebyr (i %s) der må bruges i en enkelt tegnebogstransaktion eller rå transaktion; en for lav en værdi kan afbryde store transaktioner (standard: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Gruppér output efter adresse og vælg alle eller ingen, i stedet for at vælge på per-output-basis. Højere sikring af privatliv, da en adresse kun bruges én gang (med mindre nogen sender til en adresse efter den er brugt), men kan resultere i en anelse højere gebyrer, da ikke-optimal valg af output-adresser kan forekomme på grund af den tilføjede begrænsning (standard: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3234,22 +3212,6 @@
<translation>Overvej venligst at bidrage til udviklingen, hvis du finder %s brugbar. Besøg %s for yderligere information om softwaren.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Hvis beholdning af adresser er lav, forespørg da adresser på andre knuder via DNS-opslag (standard: 1 med mindre -connect bruges)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Reducér pladskravene ved at beskære (slette, “prune”) gamle blokke. Dette tillader pruneblockchain-RPC'en at blive kaldt for at slette specifikke blokke, og det aktiverer automatisk beskæring af gamle blokke, hvis en målstørrelse i MiB er angivet. Denne tilstand er ikke kompatibel med -txindex og -rescan. Advarsel: Fortrydelse af denne indstilling kræver download af hele blokkæden igen. (standard: 0 = slå beskæring af blokke fra, 1 = tillad manuel beskæring via RPC, &gt;%u = beskær automatisk blokfiler for at bliver under den angivne målstørrelse i MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Sæt den laveste gebyrsats (i %s/kB) for transaktioner, der skal inkluderes i blokoprettelse. (standard: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Sæt antallet af scriptverificeringstråde (%u til %d, 0 = auto, &lt;0 = efterlad det antal kernet fri, standard: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Blokdatabasen indeholder en blok, som ser ud til at være fra fremtiden. Dette kan skyldes, at din computers dato og tid ikke er sat korrekt. Genopbyg kun blokdatabasen, hvis du er sikker på, at din computers dato og tid er korrekt</translation>
</message>
@@ -3270,18 +3232,6 @@
<translation>Kan ikke spole databasen tilbage til en tilstand inden en splitning. Du er nødt til at downloade blokkæden igen</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Brug UPnP for at konfigurere den lyttende port (standard: 1 under lytning og ingen -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Brugernavn og hashet adgangskode for JSON-RPC-forbindelser. Feltet &lt;userpw&gt; er i formatet: &lt;BRUGERNAVN&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Et kanonisk Python-skript er inkluderet i share/rpcuser. Klienten forbinder så normalt ved hjælp af argumentparret rpcuser=&lt;BRUGERNAVN&gt;/rpcpassword=&lt;ADGANGSKODE&gt;. Dette tilvalg kan angives flere gange</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Tegnebogen vil ikke oprette transaktioner, som overtræder begrænsningen for hukommelsespuljekæden (standard: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Advarsel: Netværket ser ikke ud til at være fuldt ud enige! Enkelte minere ser ud til at opleve problemer.</translation>
</message>
@@ -3290,10 +3240,6 @@
<translation>Advarsel: Vi ser ikke ud til at være fuldt ud enige med andre knuder! Du kan være nødt til at opgradere, eller andre knuder kan være nødt til at opgradere.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Hvorvidt hukommelsespuljen skal gemmes under nedlukning og indlæses under genstart (standard: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d af de seneste 100 blokke har en uventet version</translation>
</message>
@@ -3306,42 +3252,14 @@
<translation>-maxmempool skal være mindst %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;kategori&gt; kan være:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Acceptér forbindelser udefra (standard: 1 hvis hverken -proxy eller -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Føj kommentar til brugeragentstrengen</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Forsøg at genskabe private nøgler fra en ødelagt tegnebog under opstart</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Blokoprettelsestilvalg:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Kan ikke finde -%s-adressen: “%s”</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Indstillinger for kædevalg:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Ændr indeks uden for interval</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Tilvalg for forbindelser:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Ophavsret © %i-%i</translation>
</message>
@@ -3350,36 +3268,12 @@
<translation>Ødelagt blokdatabase opdaget</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Tilvalg for fejlfinding/test:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Indlæs ikke tegnebogen og deaktivér tegnebogs-RPC-kald</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Ønsker du at genopbygge blokdatabasen nu?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Aktivér offentliggørelse af hash-blok i &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Aktivér offentliggørelse af hash-transaktion i &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Aktivér offentliggørelse af rå blok i &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Aktivér offentliggørelse af rå transaktion i &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Aktivér transaktionserstatning i hukommelsespuljen (standard: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Fejl under oprettelse af %s: Du kan ikke oprette ikke-HD-tegnebøger med denne version.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3394,6 +3288,10 @@
<translation>Fejl under indlæsning af %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Fejl ved indlæsning af %s: Private nøgler kan kun deaktiveres under oprettelse</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Fejl under indlæsning af %s: Tegnebog ødelagt</translation>
</message>
@@ -3418,6 +3316,10 @@
<translation>Lytning på enhver port mislykkedes. Brug -listen=0, hvis du ønsker dette.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Genindlæsning af tegnebogen under initialisering mislykkedes</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importerer…</translation>
</message>
@@ -3427,7 +3329,7 @@
</message>
<message>
<source>Initialization sanity check failed. %s is shutting down.</source>
- <translation>Klargøring af sundhedstjek mislykkedes. %s lukker ned.</translation>
+ <translation>Sundhedstjek under initialisering mislykkedes. %s lukker ned.</translation>
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
@@ -3442,8 +3344,12 @@
<translation>Ugyldigt beløb for -fallbackfee=&lt;beløb&gt;: “%s”</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Hold hukommelsespuljen med transaktioner under &lt;n&gt; megabyte (standard: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Angivet blokmappe “%s” eksisterer ikke.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Opgraderer txindex database</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3454,26 +3360,10 @@
<translation>Indlæser bandlysningsliste…</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Placering for autentificerings-cookie (standard: datamappe)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>For få tilgængelige fildeskriptorer.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Tilslut kun til knuder i netværk &lt;net&gt; (IPv4, IPv6 eller Onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Udskriv denne hjælpetekst og afslut</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Udskriv version og afslut</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Beskæring kan ikke opsættes med en negativ værdi.</translation>
</message>
@@ -3482,14 +3372,6 @@
<translation>Beskæringstilstand er ikke kompatibel med -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Genopbyg kædetilstand og blokindeks fra blk*.dat-filerne på disken</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Genopbyg kædetilstand ud fra de aktuelt indekserede blokke</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Genafspiller blokke…</translation>
</message>
@@ -3498,14 +3380,6 @@
<translation>Spoler blokke tilbage…</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Sæt cache-størrelse for database i megabytes (%d til %d; standard: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Angiv tegnebogsfil (inden for datamappe)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Kildekoden er tilgængelig fra %s.</translation>
</message>
@@ -3518,6 +3392,10 @@
<translation>Ikke i stand til at tildele til %s på denne computer. %s kører formodentlig allerede.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>U-istand til at generere nøgler</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Argument -benchmark understøttes ikke og ignoreres; brug -debug=bench.</translation>
</message>
@@ -3538,14 +3416,6 @@
<translation>Opgraderer UTXO-database</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Brug UPnP til at konfigurere den lyttende port (standard: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Brug testkæden</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Brugeragent-kommentar (%s) indeholder usikre tegn.</translation>
</message>
@@ -3554,90 +3424,26 @@
<translation>Verificerer blokke…</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Tilvalg for fejlfinding/test af tegnebog:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Det var nødvendigt at genskrive tegnebogen: Genstart %s for at gennemføre</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Tilvalg for tegnebog:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Tillad JSON-RPC-forbindelser fra angivet kilde. Gyldig for &lt;ip&gt; er en enkelt IP (fx 1.2.3.4), et netværk/netmaske (fx 1.2.3.4/255.255.255.0) eller et netværk/CIDR (fx 1.2.3.4/24). Dette tilvalg kan angives flere gange</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Tildel given adresse og sæt andre knuder, der forbinder til den, på hvidliste. Brug [vært]:port notation for IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Opret nye filer med systemstandard for rettigheder i stedet for umask 077 (kun virksomt med tegnebogsfunktionalitet deaktiveret)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Opdag egne IP-adresser (standard: 1 under lytning og ingen -externalip eller -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Fejl: Lytning efter indkommende forbindelser mislykkedes (lytning resultarede i fejl %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Udfør kommando, når en relevant alarm modtages eller vi ser en virkelig lang udsplitning (%s i cmd erstattes af besked)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Gebyrer (i %s/kB) mindre end dette opfattes som intet gebyr for videresendelse, mining og oprettelse af transaktioner (standard: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Hvis paytxfee ikke er sat, inkluderes nok gebyr til at transaktioner begynder at blive bekræftet ingen for gennemsnitligt n blokke (standard: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Ugyldigt beløb for -maxtxfee=&lt;beløb&gt;: “%s” (skal være på mindst minrelay-gebyret på %s for at undgå hængende transaktioner)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maksimal størrelse på data i transaktioner til dataoverførsel, som vi videresender og miner (standard: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Brug tilfældige akkreditiver for hver proxy-forbindelse. Dette aktiverer strømisolation med Tor (standard: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Transaktionsbeløbet er for lille til at sende, når gebyret er trukket fra</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Andre knuder på hvidliste kan ikke DoS-bandlyses, og deres transaktioner videresendes altid, selv hvis de allerede er i hukommelsespuljen. Brugbart til fx et adgangspunkt</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Du er nødt til at genopbygge databasen ved hjælp af -reindex for at gå tilbage til ikke-beskåret tilstand. Dette vil downloade hele blokkæden igen</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(standard: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Acceptér offentlige REST-anmodninger (standard: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Opret automatisk skjult Tor-tjeneste (standard: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Forbind gennem SOCKS5-proxy</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Fejl under indlæsning af %s: Du kan ikke slå HD fra på en allerede eksisterende HD-tegnebog</translation>
</message>
@@ -3650,10 +3456,6 @@
<translation>Fejl under opgradering af kædetilstandsdatabase</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importerer blokeringer fra ekstern blk000??.dat-fil under opstart</translation>
- </message>
- <message>
<source>Information</source>
<translation>Information</translation>
</message>
@@ -3674,42 +3476,14 @@
<translation>Ugyldig netmaske angivet i -whitelist: “%s”</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Behold højest &lt;n&gt; uforbindelige transaktioner i hukommelsen (standard: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Nødt til at angive en port med -whitebinde: “%s”</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Videresendelsesvalgmuligheder for knude:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Tilvalg for RPC-server:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reducerer -maxconnections fra %d til %d på grund af systembegrænsninger.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Genindlæs blokkæden efter manglende tegnebogstransaktioner under opstart</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Send sporings-/fejlsøgningsinformation til konsollen i stedet for debug.log filen</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Vis alle tilvalg for fejlsøgning (brug: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Formindsk debug.log filen ved klientopstart (standard: 1 hvis ikke -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Signering af transaktion mislykkedes</translation>
</message>
@@ -3722,14 +3496,6 @@
<translation>Dette er eksperimentelt software.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Adgangskode for Tor kontrolport (standard: tom)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Tor kontrolport, der skal bruges, hvis onion-lytning er aktiveret (standard: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Transaktionsbeløb er for lavt</translation>
</message>
@@ -3746,18 +3512,18 @@
<translation>Ikke i stand til at tildele til %s på denne computer (bind returnerede fejl %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Opgradér tegnebog til seneste format under opstart</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Brugernavn til JSON-RPC-forbindelser</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Kan ikke generere indledningsvise nøgler</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Verificerer tegnebøger…</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Tegnebog %s findes uden for tegnebogsmappen %s</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Advarsel</translation>
</message>
@@ -3766,98 +3532,18 @@
<translation>Advarsel: Ukendte nye regler aktiveret (versionsbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Hvorvidt der skal arbejdes i kun-blokke-tilstand (standard: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Du er nødt til at genopbygge databasen ved hjælp af -reindex for at ændre -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Zapper alle transaktioner fra tegnebog…</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ-notifikationsindstillinger:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Adgangskode til JSON-RPC-forbindelser</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Udfør kommando, når den bedste blok ændres (%s i kommandoen erstattes med blokhash)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Tillad DNS-opslag for -addnode, -seednode og -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = behold metadata for transaktion, fx kontoindehaver og information om betalingsanmodning, 2 = drop metadata for transaktion)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee er sat meget højt! Gebyrer så store risikeres betalt på en enkelt transaktion.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Tildel til den givne adresse for at lytte efter JSON-RPC-forbindelser. Dette tilvalg ignoreres med mindre -rpcwallet også bruges. Port er valgfri og tilsidesætter -rpcport. Brug [vært]:port-notation for IPv6. Denne valgmulighed kan angives flere gange (standard: 127.0.0.1 og ::1, dvs. localhost, eller hvis -rpcallowip is angivet: 0.0.0.0 og ::, dvs. alle adresser)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Behold ikke transaktioner i hukommelsespuljen i mere end &lt;n&gt; timer (default: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Tilsvarende bytes pr. sigop i transaktioner, som videresendes og mines (standard: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Fejl under indlæsning af %s: Du kan ikke aktivere HD på en allerede eksisterende ikke-HD-tegnebog</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Fejl under indlæsning af tegnebog %s. “-wallet”-parameteren kan kun angive et filnavn (ikke en sti).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Gebyrer (i %s/kB) mindre end dette opfattes som intet gebyr under oprettelse af transaktioner (standard: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Gennemtving videresendelse af transaktioner fra hvidlistede knuder, selv om de overtræder lokal videresendelsespolitik (standard: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Hvor gennemarbejdet blokverificeringen for -checkblocks er (0-4; standard: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Vedligehold et komplet transaktionsindeks, der bruges af rpc-kaldet getrawtransaction (standard: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Antal sekunder, som knuder der opfører sig upassende, skal vente før reetablering (standard: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Udskriv fejlsøgningsinformation (standard: %u, angivelse af &lt;kategori&gt; er valgfri)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Indstiller serialiseringen af rå transaktioner eller blok-hex returneret i ikke-verbose tilstand, non-segwit(0) eller sigwit(1) (standard: %d)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Understøt filtrering af blokke og transaktioner med Bloom-filtre (standard: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Den gebyrsats (i %s/kB), som indikerer din tolerance for at kassere byttepenge ved at føje dem til gebyret (standard: %s). Bemærk: Et output kasseres, hvis det anses som støv ved denne rate, men der vil altid kasseres op til støvvideresendelsesgebyret, og et kasseringsgebyr derover er begrænset af gebyrestimatet for det længste mål</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Dette er transaktionsgebyret, du kan betale, når gebyrestimeringer ikke er tilgængelige.</translation>
</message>
@@ -3870,10 +3556,6 @@
<translation>Den totale længde på netværksversionsstrengen (%i) overstiger maksimallængden (%i). Reducér antaller af eller størrelsen på uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Prøver at holde udadgående traffik under det givne mål (i MiB pr. 24 timer), 0 = ingen grænse (standard: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Argument -socks understøttes ikke. Det er ikke længere muligt at sætte SOCKS-version; kun SOCKS5-proxier understøttes.</translation>
</message>
@@ -3882,10 +3564,6 @@
<translation>Argument -whitelistalwaysrelay understøttes ikke og ignoreres; brug -whitelistrelay og/eller -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Brug separat SOCS5-proxy for at nå knuder via Tors skjulte tjenester (standard: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Advarsel: Ukendte blokversioner bliver minet! Det er muligt, at ukendte regler er i brug</translation>
</message>
@@ -3894,111 +3572,18 @@
<translation>Advarsel: Tegnebogsfil ødelagt, data reddet! Oprindelig %s gemt som %s i %s; hvis din saldo eller dine transaktioner er forkert, bør du genskabe fra en sikkerhedskopi.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Sæt knuder på hvidliste, som forbinder fra den givne IP-adresse (fx 1.2.3.4) eller CIDR-noteret netværk (fx 1.2.3.0/24). Kan angives flere gange.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s er meget højt sat!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(standard: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Forespørg altid adresser på andre knuder via DNS-opslag (default: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Fejl under indlæsning af tegnebog %s. -wallet filnavn skal være en almindelig fil.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Fejl under indlæsning af tegnebog %s. -wallet filnavn angivet mere end én gang.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Fejl under indlæsning af tegnebog %s. Ugyldige tegn i -wallet filnavn.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Antal blokke som tjekkes ved opstart (standard: %u, 0 = alle)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Inkludér IP-adresser i fejlretningsoutput (standard: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Nøglepulje løb tør; kald venligst keypoolrefill først</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Lyt efter JSON-RPC-forbindelser på &lt;port&gt; (standard: %u eller testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Lyt efter forbindelser på &lt;port&gt; (standard: %u eller testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Oprethold højest &lt;n&gt; forbindelser til andre knuder (standard: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Få tegnebogen til at transmittere transaktioner</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maksimum for modtagelsesbuffer pr. forbindelse, &lt;n&gt;*1000 byte (standard: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maksimum for afsendelsesbuffer pr. forbindelse, &lt;n&gt;*1000 byte (standard: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Føj tidsstempel foran fejlsøgningsoutput (standard: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Videresend og udvind databærer-transaktioner (standard: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Videresend ikke-P2SH multisig (standard: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Sæt nøglepuljestørrelse til &lt;n&gt; (standard: %u)
-</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Sæt maksimal BIP141-blokvægt (standard: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Angiv antallet af tråde til at håndtere RPC-kald (standard: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Angiv konfigurationsfil (standard: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Angiv tilslutningstimeout i millisekunder (minimum: 1, standard: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Angiv pid-fil (standard: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Brug ubekræftede byttepenge under afsendelse af transaktioner (standard: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Starter netværkstråde…</translation>
</message>
@@ -4015,10 +3600,6 @@
<translation>Dette er transaktionsgebyret, som betaler, når du sender en transaktion.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Grænse for afbrydelse af forbindelse til knuder, der opfører sig upassende (standard: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Transaktionsbeløb må ikke være negative</translation>
</message>
@@ -4039,6 +3620,26 @@
<translation>Manglende dækning</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Kan ikke generere en bytte-adresse nøgle. Private nøgler er deaktiveret for denne tegnebog.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Kan ikke opgradere en ikke HD dele tegnebog uden opgradering til at støtte før split nøglepool. Venligst brug -upgradewallet=169900 eller -upgradewallet med ingen version specificeret.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Gebyr estimering fejlede. Tilbagefaldsgebyr er deaktiveret. Vent et par blokke eller aktiver -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Advarsel: Private nøgler opdaget i tegnebog {%s} med deaktiverede private nøgler</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Kan ikke skrive til datamappe '%s'; tjek tilladelser.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Indlæser blokindeks…</translation>
</message>
diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts
index 31e01c3916..31feaf114f 100644
--- a/src/qt/locale/bitcoin_de.ts
+++ b/src/qt/locale/bitcoin_de.ts
@@ -7,7 +7,7 @@
</message>
<message>
<source>Create a new address</source>
- <translation>Eine neue Adresse erstellen</translation>
+ <translation>Neue Adresse erstellen</translation>
</message>
<message>
<source>&amp;New</source>
@@ -30,12 +30,16 @@
<translation>Ausgewählte Adresse aus der Liste entfernen</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Zu suchende Adresse oder Bezeichnung eingeben</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Daten der aktuellen Ansicht in eine Datei exportieren</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation>E&amp;xportieren</translation>
+ <translation>&amp;Exportieren</translation>
</message>
<message>
<source>&amp;Delete</source>
@@ -55,15 +59,15 @@
</message>
<message>
<source>Sending addresses</source>
- <translation>Sender_in Addresse</translation>
+ <translation>Senderaddressen</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation>Empfangsadressen</translation>
+ <translation>Empfängeradressen</translation>
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Dies sind ihre Bitcoin-Adressen zum Tätigen von Überweisungen. Bitte prüfen Sie den Betrag und die Adresse des Empfängers, bevor Sie Bitcoins überweisen.</translation>
+ <translation>Dies sind Ihre Bitcoin-Adressen zum Tätigen von Überweisungen. Bitte prüfen Sie den Betrag und die Adresse des Empfängers, bevor Sie Bitcoins überweisen.</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
@@ -141,11 +145,11 @@
</message>
<message>
<source>Encrypt wallet</source>
- <translation>Wallet verschlüsseln</translation>
+ <translation>Brieftasche verschlüsseln</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Dieser Vorgang benötigt ihre Passphrase, um die Brieftasche zu entsperren.</translation>
+ <translation>Dieser Vorgang benötigt Ihre Passphrase, um die Brieftasche zu entsperren.</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -157,7 +161,7 @@
</message>
<message>
<source>Decrypt wallet</source>
- <translation>Brieftasche entschlüsseln</translation>
+ <translation>Wallet entschlüsseln</translation>
</message>
<message>
<source>Change passphrase</source>
@@ -322,6 +326,14 @@
<translation>&amp;URI öffnen...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Brieftasche:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Standard Brieftasche</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Klicken zum Deaktivieren der Netzwerkaktivität.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Reindiziere Blöcke auf Datenträger...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy ist &lt;b&gt;aktiviert&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Bitcoins an eine Bitcoin-Adresse überweisen</translation>
</message>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Brieftasche: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Typ: %1
@@ -730,10 +752,6 @@
<translation>&amp;Adresse</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Neue Empfangsadresse</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Neue Zahlungsadresse</translation>
</message>
@@ -750,8 +768,12 @@
<translation>Die eingegebene Adresse "%1" ist keine gültige Bitcoin-Adresse.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Die eingegebene Adresse "%1" befindet sich bereits im Adressbuch.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Die Adresse "%1" existiert bereits als Empfangsadresse mit dem Label "%2" und kann daher nicht als Sendeadresse hinzugefügt werden.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Die eingegebene Adresse "%1" befindet sich bereits im Adressbuch mit der Bezeichnung "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>Kommandozeilenoptionen</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Benutzung:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Kommandozeilenoptionen</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>UI Einstellungen:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Datenverzeichnis beim Starten auswählen (Standard: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Sprache einstellen, zum Beispiel "de_DE" (Standard: Systemgebietsschema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Minimiert starten</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>SSL-Wurzelzertifikate für Zahlungsanforderungen festlegen (Standard: Systemstandard)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Startbildschirm beim Starten anzeigen (Standard: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Setze alle Einstellungen zurück, die über die grafische Oberfläche geändert wurden.</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1064,6 +1050,22 @@
<translation>&amp;Netzwerk</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Deaktiviert einige erweiterte Funktionen, aber alle Blöcke werden trotzdem vollständig validiert. Um diese Einstellung rückgängig zu machen, muss die gesamte Blockkette erneut heruntergeladen werden. Die tatsächliche Festplattennutzung kann etwas höher sein.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>&amp;block Speicher kürzen auf</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Wenn diese Einstellung rückgängig gemacht wird, muss die komplette Blockkette erneut heruntergeladen werden.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = automatisch, &lt;0 = so viele Kerne frei lassen)</translation>
</message>
@@ -1330,6 +1332,10 @@
<translation>URI-Verarbeitung</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' ist kein gültiger URL. Bitte 'bitcoin:' nutzen.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>Abruf-URL der Zahlungsanforderung ist ungültig: %1</translation>
</message>
@@ -1418,7 +1424,7 @@
</message>
<message>
<source>NodeId</source>
- <translation>Knoten Identität</translation>
+ <translation>Knotenkennung</translation>
</message>
<message>
<source>Ping</source>
@@ -1527,12 +1533,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Fehler beim Verarbeiten von Befehlszeilenargumenten: %1</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Fehler: Angegebenes Datenverzeichnis "%1" existiert nicht.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Fehler: Konfigurationsdatei kann nicht analysiert werden: %1. Bitte nur "Schlüssel=Wert"-Syntax verwenden.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Fehler: Konfigurationsdatei konnte nicht Verarbeitet werden: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1625,6 +1635,14 @@
<translation>Speichernutzung</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Brieftasche:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(keine)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Zurücksetzen</translation>
</message>
@@ -1790,7 +1808,11 @@
</message>
<message>
<source>&amp;Unban</source>
- <translation>&amp;Node entsperren</translation>
+ <translation>K&amp;noten entsperren</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Standard Brieftasche</translation>
</message>
<message>
<source>Welcome to the %1 RPC console.</source>
@@ -1810,13 +1832,21 @@
</message>
<message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
- <translation>WARNUNG: Betrüger sind aktiv gewesen und erklären den Benutzern, hier Befehle einzugeben und ihre Brieftascheninhalte zu stehlen. Verwenden Sie diese Konsole nicht, ohne die Verzweigungen eines Befehls vollständig zu verstehen.</translation>
+ <translation>WARNUNG: Betrüger sind aktiv gewesen, die Benutzer auffordern, hier Befehle einzugeben, um Brieftascheninhalte zu stehlen. Verwenden Sie diese Konsole nicht, ohne die Auswirkungen eines Befehls vollständig zu verstehen.</translation>
</message>
<message>
<source>Network activity disabled</source>
<translation>Netzwerkaktivität deaktiviert</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Befehl wird ohne spezifizierte Brieftasche ausgeführt</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Befehl wird mit Brieftasche "%1" ausgeführt</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(Knotenkennung: %1)</translation>
</message>
@@ -1888,20 +1918,20 @@
<translation>Zurücksetzen</translation>
</message>
<message>
- <source>Requested payments history</source>
- <translation>Verlauf der angeforderten Zahlungen</translation>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Ureigene SegWit-Adressen (alias Bech32 oder BIP-173) werden Ihre Transaktionsgebühren senken und bieten besseren Tippfehlerschutz, werden jedoch von alten Brieftaschen nicht unterstützt. Wenn abgewählt, wird eine mit älteren Brieftaschen kompatible Adresse erstellt.</translation>
</message>
<message>
- <source>&amp;Request payment</source>
- <translation>&amp;Zahlung anfordern</translation>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generiere ureigene SegWit(Bech32)-Adresse</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Bech32 Adressen (BIP-173) sind günstiger zum senden und besser geschützt gegen Tippfehler. Wenn nicht gewählt wird eine P2SH verpackte SegWit Adresse generiert, kompatibel mit älteren Wallets.</translation>
+ <source>Requested payments history</source>
+ <translation>Verlauf der angeforderten Zahlungen</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Erzeuge Bech32 Adresse</translation>
+ <source>&amp;Request payment</source>
+ <translation>&amp;Zahlung anfordern</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1983,6 +2013,10 @@
<translation>Nachricht</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Wallet</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Resultierende URI ist zu lang, bitte den Text für Bezeichnung/Nachricht kürzen.</translation>
</message>
@@ -2097,12 +2131,16 @@
<translation>Transaktionsgebühreneinstellungen ausblenden</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>pro Kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Geben sie eine angepasste Gebühr pro kB (1.000 Byte) virtueller Größe der Transaktion an.
+
+Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktion von 500 Byte (einem halben kB) würde eine Gebühr von 50 Satoshis ergeben, da die Gebühr pro Byte berechnet wird.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Wenn die benutzerdefinierte Gebühr 1000 Satoshis beträgt und die Transaktion nur 250 Byte groß ist, wird bei Auswahl von "pro Kilobyte" eine Gebühr in Höhe von 250 Satoshis, bei Auswahl von "Mindestbetrag" eine Gebühr in Höhe von 1000 Satoshis bezahlt. Bei Transaktionen die Größer als ein Kilobyte sind, werden bei beiden Optionen die Gebühren pro Kilobyte bezahlt.</translation>
+ <source>per kilobyte</source>
+ <translation>pro Kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2154,7 +2192,7 @@
</message>
<message>
<source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
- <translation>Mit Replace-By-Fee (BIP-125) kann die Transaktionsgebühr nach dem senden erhöht werden. Ohne dies wird eine höhere Gebühr empfoohlen um das Risiko einer hohen Transaktionszeit zu reduzieren.</translation>
+ <translation>Mit Replace-By-Fee (BIP-125) kann die Transaktionsgebühr nach dem Senden erhöht werden. Ohne dies wird eine höhere Gebühr empfohlen, um das Risiko einer hohen Transaktionszeit zu reduzieren.</translation>
</message>
<message>
<source>Clear &amp;All</source>
@@ -2213,14 +2251,6 @@
<translation>Wollen Sie die Überweisung ausführen?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>als Transaktionsgebühr hinzugefügt</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Gesamtbetrag %1</translation>
- </message>
- <message>
<source>or</source>
<translation>oder</translation>
</message>
@@ -2229,10 +2259,26 @@
<translation>Du kannst die Gebühr später erhöhen (Zeigt Replace-By-Fee, BIP-125).</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>aus Brieftasche %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Bitte überprüfen sie ihre Transaktion. </translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaktionsgebühr</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>Replace-By-Fee, BIP-125 wird nicht angezeigt.</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>Gesamtbetrag</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Überweisung bestätigen</translation>
</message>
@@ -2574,10 +2620,6 @@
<translation>steht im Konflikt mit einer Transaktion mit %1 Bestätigungen</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>%1/unbestätigt</translation>
</message>
@@ -2606,14 +2648,6 @@
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, wurde noch nicht erfolgreich übertragen</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, verteilt durch %n Knoten</numerusform><numerusform>, verteilt durch %n Knoten</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Datum</translation>
</message>
@@ -2698,6 +2732,10 @@
<translation>Gesamte Transaktionsgröße</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Virtuelle Größe der Transaktion</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Ausgabeindex</translation>
</message>
@@ -2768,10 +2806,6 @@
<translation>Offen bis %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Unbestätigt</translation>
</message>
@@ -2796,10 +2830,6 @@
<translation>Unreif (%1 Bestätigungen, wird verfügbar sein nach %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Dieser Block wurde vom Netzwerk nicht angenommen und wird wahrscheinlich nicht bestätigt werden!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generiert, aber nicht akzeptiert</translation>
</message>
@@ -3110,38 +3140,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Speichern der Wallet-Daten nach %1 war erfolgreich.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Abbrechen</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Optionen:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Datenverzeichnis festlegen</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Mit dem angegebenen Knoten verbinden, um Adressen von Gegenstellen abzufragen, danach trennen</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Die eigene öffentliche Adresse angeben</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Kommandozeilen- und JSON-RPC-Befehle annehmen</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Veröffentlicht unter der MIT-Softwarelizenz, siehe beiligende Datei %s oder %s.</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Wenn &lt;category&gt; nicht angegeben wird oder &lt;category&gt;=1, jegliche Debugginginformationen ausgeben.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Kürzungsmodus wurde kleiner als das Minimum in Höhe von %d MiB konfiguriert. Bitte verwenden Sie einen größeren Wert.</translation>
</message>
@@ -3158,18 +3168,10 @@
<translation>Fehler: Ein schwerer interner Fehler ist aufgetreten, siehe debug.log für Details.</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Gebühr (in %s/kB), die von Ihnen gesendeten Transaktionen hinzugefügt wird (Standard: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Kürze Blockspeicher...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Als Hintergrunddienst ausführen und Befehle annehmen</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Kann HTTP Server nicht starten. Siehe debug log für Details.</translation>
</message>
@@ -3182,22 +3184,6 @@
<translation>Die %s-Entwickler</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Eine Transaktionsgebühr (in %s/kB) wird genutzt, wenn für die Gebührenschützung zu wenig Daten vorliegen (Standardwert: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Immer übermittelte Transaktionen von freigegebenen Peers akzeptieren, auch wenn keine Transaktionen übermittelt werden (Standard: %d)</translation>
- </message>
- <message>
- <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source>
- <translation>Mit dem angegebenen Knoten verbinden und versuchen die Verbindung aufrecht zu erhalten (Siehe die "addnode" RPC Kommando Hilfe für mehr Information)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>An die angegebene Adresse binden und immer abhören. Für IPv6 "[Host]:Port"-Notation verwenden</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Datenverzeichnis %s kann nicht gesperrt werden. Evtl. wurde %s bereits gestartet.</translation>
</message>
@@ -3206,40 +3192,12 @@
<translation>Kann keine Verbindungen herstellen und addrman gleichzeitig ausgehende Verbindungen suchen lassen.</translation>
</message>
<message>
- <source>Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)</source>
- <translation>Stellt lediglich die Verbindungen zum/zu den spezifischen Knoten her; -connect=0 deaktiviert die automatische Verbindungsherstellung (Die Regel für diesen Knoten ist die selbe wie für -addnode)</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Alle Wallet-Transaktionen löschen und nur diese Teilbereiche der Blockkette durch -rescan beim Starten wiederherstellen</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Lesen von %s fehlgeschlagen! Alle Schlüssel wurden korrekt gelesen, Transaktionsdaten bzw. Adressbucheinträge fehlen aber möglicherweise oder sind inkorrekt.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Debugging-Informationen für eine Kategorie ausschließen. Kann in Verbindung mit -debug = 1 verwendet werden, um Debug-Logs für alle Kategorien auszugeben, mit Ausnahme einer oder mehrerer spezifizierter Kategorien.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Befehl ausführen wenn sich eine Wallet-Transaktion verändert (%s im Befehl wird durch die Transaktions-ID ersetzt)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Zusätzliche Transaktionen für kompakten Block-Nachbau im Speicher vorhalten (default: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Sofern dieser Block Bestandteil der Blockchain ist, nehme an, dass er und seine Vorgänger gültig sind und überspringe ggf. dessen Skriptverifikation (0 um alle zu verifizieren, default: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Maximal zulässige mediane Peer-Zeit-Offset-Einstellung. Lokale Perspektive der Zeit kann von Peers vorwärts oder rückwärts um diesen Betrag beeinflusst werden. (Voreinstellung: %u Sekunden)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Maximale Gesamtgebühr (in %s) in einer Börsentransaktion; wird dies zu niedrig gesetzten können große Transaktionen abgebrochen werden (Standard: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Gruppiere Outputs mit der Auswahl von allen oder keinen Adressen, anstatt alle pro Output auszuwählen. Die Privatsphäre wurde verbessert, da eine Adresse nur einmal verwendet wird (ausser jemand sendet Coins nachdem von der Adresse ausgegeben wurde). Durch diese hinzugefügte Limitierung kann es allerdings zu leicht erhöhten Transaktionskosten kommen, da eine suboptimale Coinselektierung bei Transaktionen stattfinden kann. (Standardeinstellung: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3250,22 +3208,6 @@
<translation>Wenn sie %s nützlich finden, sind Helfer sehr gern gesehen. Besuchen Sie %s um mehr über das Softwareprojekt zu erfahren.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Adressen von Gegenstellen via DNS-Namensauflösung finden, falls zu wenige Adressen verfügbar sind (Standard: 1, außer bei -connect)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Speicherplatzanforderung durch Kürzen (Pruning) alter Blöcke reduzieren. Dies erlaubt das Aufrufen des sogenannten Pruneblockchain RPC zum Löschen spezifischer Blöcke und und aktiviert das automatische Pruning alter Blöcke, sofern eine Zielgröße in MIB angegeben wird. Dieser Modus ist nicht mit -txindex und -resacan kompatibel. Warnung: Das Rücksetzen dieser Einstellung erfordert das erneute Herunterladen der gesamten Blockchain. (Standard: 0 = deaktiviert das Pruning, 1 = erlaubt manuelles Pruning via RPC, &gt;%u = automatisches Pruning der Blockdateien, um angegebene Maximalgröße nicht zu überschreiten)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Niedrigste Gebühr (in %s/kB) für Transaktionen einstellen, die bei der Blockerzeugung berücksichtigt werden sollen. (default: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Maximale Anzahl an Skript-Verifizierungs-Threads festlegen (%u bis %d, 0 = automatisch, &lt;0 = so viele Kerne frei lassen, Standard: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Die Block-Datenbank enthält einen Block, der in der Zukunft auftaucht. Dies kann daran liegen, dass die Systemzeit Ihres Computers falsch eingestellt ist. Stellen Sie die Block-Datenbank nur wieder her, wenn Sie sich sicher sind, dass Ihre Systemzeit korrekt eingestellt ist.</translation>
</message>
@@ -3286,18 +3228,6 @@
<translation>Sie müssen die Datenbank mit Hilfe von -reindex neu aufbauen, um zum ungekürzten Modus zurückzukehren. Dies erfordert, dass die gesamte Blockkette erneut heruntergeladen wird.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>UPnP verwenden, um eine Portweiterleitung einzurichten (Standard: 1, wenn abgehört wird und -proxy nicht gesetzt ist)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Benutzername und gehashtes Passwort für JSON-RPC Verbindungen. Das Feld &lt;userpw&gt; kommt im Format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Ein kanonisches Pythonskript ist in share/rpcuser inbegriffen. Der client benutzt wie gehabt, die rpcuser/rpcpassword Parameter. Diese Option kann mehrere Male spezifiziert werden</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Das Wallet erzeugt keine Transaktionen, die das Mempool Chain Limit überschreiten (Standardeinstellung: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Warnung: Das Netzwerk scheint nicht vollständig übereinzustimmen! Einige Miner scheinen Probleme zu haben.</translation>
</message>
@@ -3306,10 +3236,6 @@
<translation>Warnung: Wir scheinen nicht vollständig mit unseren Gegenstellen übereinzustimmen! Sie oder die anderen Knoten müssen unter Umständen Ihre Client-Software aktualisieren.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Gibt an, ob der mempool beim Beenden gespeichert und beim Starten wieder geladen werden soll (Standard: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d der letzten 100 Blöcke haben eine unerwartete Version</translation>
</message>
@@ -3322,42 +3248,14 @@
<translation>-maxmempool muss mindestens %d MB betragen</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; kann sein:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Eingehende Verbindungen annehmen (Standard: 1, wenn nicht -proxy oder -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Hänge ein Kommentar zur User Agent-Zeichenkette an</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Es wird versucht, private Schlüssel beim Starten aus einem beschädigtem Wallet wiederherzustellen</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Blockerzeugungsoptionen:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Kann Adresse in -%s nicht auflösen: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Chain Auswahloptionen:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Position des Wechselgelds außerhalb des Bereichs</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Verbindungsoptionen:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3366,38 +3264,10 @@
<translation>Beschädigte Blockdatenbank erkannt</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Debugging-/Testoptionen:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Die Wallet nicht laden und Wallet-RPC-Aufrufe deaktivieren</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Möchten Sie die Blockdatenbank jetzt neu aufbauen?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Aktiviere das Veröffentlichen des Hash-Blocks in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Aktiviere das Veröffentlichen der Hash-Transaktion in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Aktiviere das Veröffentlichen des Raw-Blocks in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Aktiviere das Veröffentlichen der Roh-Transaktion in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Maximal &lt;n&gt; nicht-verbindbare Transaktionen im Speicher halten (Standard: %u)</translation>
- </message>
- <message>
<source>Error creating %s: You can't create non-HD wallets with this version.</source>
<translation>Fehler beim Laden von %s: Sie können HD nicht aktivieren da sie derzeit eine nicht HD Brieftasche besitzen.</translation>
</message>
@@ -3414,6 +3284,11 @@
<translation>Fehler beim Laden von %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Fehler beim laden von %s: Private Schlüssel können nur bei der Erstellung deaktiviert werden
+</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Fehler beim Laden von %s: Das Wallet ist beschädigt</translation>
</message>
@@ -3466,8 +3341,12 @@
<translation>Ungültiger Betrag für -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Halten Sie den Transaktionsspeicherpool unter &lt;n&gt; Megabytes (Voreinstellung: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Angegebener Blöcke-Ordner "%s" existiert nicht.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Erneuern der txindex Datenbank</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3478,26 +3357,10 @@
<translation>Lade Sperrliste...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Dateiort für das Auth-Cookie (Standard: Datenverzeichnis)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Nicht genügend Datei-Deskriptoren verfügbar.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Nur zu Knoten des Netzwerktyps &lt;net&gt; verbinden (ipv4, ipv6 oder onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Drucke diese Hilfemeldung und beende</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Gibt die Versionsnummer aus und beendet das Programm</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Kürzungsmodus kann nicht mit einem negativen Wert konfiguriert werden.</translation>
</message>
@@ -3506,14 +3369,6 @@
<translation>Kürzungsmodus ist nicht mit -txindex kompatibel.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Blockkettenindex aus aktuellen Dateien blk000??.dat beim Starten wiederaufbauen</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Blockkettenzustand aus aktuelle indizierten Blöcken wiederaufbauen</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Blöcke werden nochmal neu verarbeitet ...</translation>
</message>
@@ -3522,18 +3377,6 @@
<translation>Verifiziere Blöcke...</translation>
</message>
<message>
- <source>Send transactions with full-RBF opt-in enabled (RPC only, default: %u)</source>
- <translation>Wähle alle zu sendenden Transaktionen als full-RBF opt-in aktiviert (Ausschließlich RPC, Standard: %u)</translation>
- </message>
- <message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Größe des Datenbankcaches in Megabyte festlegen (%d bis %d, Standard: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Wallet-Datei angeben (innerhalb des Datenverzeichnisses)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Der Quellcode ist von %s verfügbar.</translation>
</message>
@@ -3546,6 +3389,10 @@
<translation>Kann auf diesem Computer nicht an %s binden. Evtl. wurde %s bereits gestartet.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Schlüssel können nicht generiert werden</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Nicht unterstütztes Argument -benchmark wurde ignoriert, bitte -debug=bench verwenden.</translation>
</message>
@@ -3559,15 +3406,7 @@
</message>
<message>
<source>Upgrading UTXO database</source>
- <translation>Aktualisierung der UTXO Datenbank</translation>
- </message>
- <message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>UPnP verwenden, um eine Portweiterleitung einzurichten (Standard: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Die Testchain verwenden</translation>
+ <translation>Aktualisierung der UTXO-Datenbank</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -3578,90 +3417,26 @@
<translation>Verifiziere Blöcke...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Wallet Debugging-/Testoptionen:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Wallet musste neu geschrieben werden: starten Sie %s zur Fertigstellung neu</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Wallet-Optionen:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>JSON-RPC-Verbindungen von der angegeben Quelle erlauben. Gültig für &lt;ip&gt; ist eine einzelne IP-Adresse (z.B. 1.2.3.4), ein Netzwerk bzw. eine Netzmaske (z.B. 1.2.3.4/255.255.255.0), oder die CIDR-Notation (z.B. 1.2.3.4/24). Kann mehrmals angegeben werden.</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>An die angegebene Adresse binden und Gegenstellen, die sich dorthin verbinden, immer zulassen. Für IPv6 "[Host]:Port"-Notation verwenden</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Neue Dateien mit Standard-Systemrechten erzeugen, anstatt mit umask 077 (nur mit deaktivierter Walletfunktion nutzbar)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Eigene IP-Adressen ermitteln (Standard: 1, wenn abgehört wird und nicht -externalip oder -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Fehler: Abhören nach eingehenden Verbindungen fehlgeschlagen (listen meldete Fehler %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Befehl ausführen wenn ein relevanter Alarm empfangen wird oder wir einen wirklich langen Fork entdecken (%s im Befehl wird durch die Nachricht ersetzt)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Niedrigere Gebühren (in %s/Kb) als diese werden bei der Transaktionserstellung als gebührenfrei angesehen (Standard: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Wenn -paytxfee nicht festgelegt wurde Gebühren einschließen, so dass mit der Bestätigung von Transaktionen im Schnitt innerhalb von n Blöcken begonnen wird (Standard: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Ungültiger Betrag für -maxtxfee=&lt;amount&gt;: '%s' (muss mindestens die minimale Weiterleitungsgebühr in Höhe von %s sein, um zu verhindern dass Transaktionen nicht bearbeitet werden)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maximale Datengröße in "Data Carrier"-Transaktionen die weitergeleitet und erarbeitet werden (Standard: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Zufällige Anmeldedaten für jede Proxyverbindung verwenden. Dies aktiviert Tor-Datenflussisolation (Standard: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Der Transaktionsbetrag ist zum senden zu niedrig, nachdem die Gebühr abgezogen wurde.</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Erlaubte Gegenstellen werden nicht für DoS-Attacken gesperrt und ihre Transkationen werden immer weitergeleitet, auch wenn sie sich bereits im Speicherpool befinden, was z.B. für Gateways sinnvoll ist.</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Sie müssen die Datenbank mit Hilfe von -reindex neu aufbauen, um zum ungekürzten Modus zurückzukehren. Dies erfordert, dass die gesamte Blockkette erneut heruntergeladen wird.</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(Standard: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Öffentliche REST-Anfragen annehmen (Standard: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Automatisch versteckten Tor-Dienst erstellen (Standard: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Über einen SOCKS5-Proxy &amp;verbinden</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Fehler beim Laden von %s: Sie können die hierarchisch deterministische Schlüsselgeneration (HD) für eine bereits existierende HD-Brieftasche nicht deaktivieren</translation>
</message>
@@ -3674,10 +3449,6 @@
<translation>Fehler bei der Aktualisierung einer Kettenstatus-Datenbank</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Blöcke beim Starten aus externer Datei blk000??.dat importieren</translation>
- </message>
- <message>
<source>Information</source>
<translation>Hinweis</translation>
</message>
@@ -3698,42 +3469,14 @@
<translation>Ungültige Netzmaske angegeben in -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Maximal &lt;n&gt; nicht-verbindbare Transaktionen im Speicher halten (Standard: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Angabe eines Ports benötigt für -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Knoten-Weiterleitungsoptionen:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC-Serveroptionen:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduziere -maxconnections von %d zu %d, aufgrund von Systemlimitierungen.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Blockkette beim Starten erneut nach fehlenden Wallet-Transaktionen durchsuchen</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Rückverfolgungs- und Debuginformationen an die Konsole senden, anstatt sie in debug.log zu schreiben</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Zeige alle Debuggingoptionen (Benutzung: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Protokolldatei debug.log beim Starten des Clients kürzen (Standard: 1, wenn kein -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Signierung der Transaktion fehlgeschlagen</translation>
</message>
@@ -3758,14 +3501,6 @@
<translation>Dies ist experimentelle Software.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>TOR Kontrollport Passwort (Standard: leer)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Zu benutzender TOR Kontrollport wenn Onion Auflistung aktiv ist (Standard: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Transaktionsbetrag zu niedrig</translation>
</message>
@@ -3786,14 +3521,6 @@
<translation>Anfänglicher Schlüssel kann nicht generiert werden.</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Wallet beim Starten auf das neueste Format aktualisieren</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Benutzername für JSON-RPC-Verbindungen</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>Verifiziere Wallet(s)...</translation>
</message>
@@ -3810,110 +3537,18 @@
<translation>Warnung: Unbekannte neue Regeln aktiviert (Versionsbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Legt fest ob nur Blöcke Modus aktiv sein soll (Standard: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Sie müssen die Datenbank mit Hilfe von -reindex neu aufbauen, um -txindex zu ändern</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Lösche alle Transaktionen aus Wallet...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ-Benachrichtigungsoptionen:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Passwort für JSON-RPC-Verbindungen</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Befehl ausführen wenn der beste Block wechselt (%s im Befehl wird durch den Hash des Blocks ersetzt)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Erlaube DNS-Abfragen für -addnode, -seednode und -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = TX-Metadaten wie z.B. Accountbesitzer und Zahlungsanforderungsinformationen behalten, 2 = TX-Metadaten verwerfen)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee ist auf einen sehr hohen Wert festgelegt! Gebühren dieser Höhe könnten für eine einzelne Transaktion bezahlt werden.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>An die angegebene Adresse binden und auf JSON-RPC-Verbindungen abhören. Diese Option wird ignoriert wenn '-rpcallowip' nicht auch angegeben ist. Die Angabe des Ports ist optional und überschreibt den Parameter '-rpcport'. Benutzen Sie die [host]:port Annotation für IPv6. Diese Option kann mehrmals angegeben werden. (Standard: 127.0.0.1 und ::1, z.B. localhost; Wenn '-rpcallowip' angegeben wurde werden alle Adressen verwendet, also 0.0.0.0 und ::)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Die Transaktion nicht länger im Speicherpool behalten als &lt;n&gt; Stunden (Standard: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Maximale Datengröße in "Data Carrier"-Transaktionen die weitergeleitet und erarbeitet werden (Standard: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Fehler beim Herunterladen von %s: Sie können keine hierarchisch deterministische Schlüsselgeneration (HD) auf eine bereits existierende nicht-HD Brieftasche (Wallet) aktivieren.</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Fehler beim Laden der Brieftasche %s. Der Parameter -wallet darf nur ein Dateiname sein (kein Dateipfad).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Niedrigere Gebühren (in %s/Kb) als diese werden bei der Transaktionserstellung als gebührenfrei angesehen (Standard: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Leite Transaktionen von Peers auf der Positivliste auf jeden Fall weiter, auch wenn sie die lokale Weiterleitungsregeln verletzen (Standardeinstellung: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Legt fest, wie gründlich die Blockverifikation von -checkblocks ist (0-4, Standard: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Einen vollständigen Transaktionsindex führen, der vom RPC-Befehl "getrawtransaction" genutzt wird (Standard: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Anzahl Sekunden, während denen sich nicht konform verhaltenden Gegenstellen die Wiederverbindung verweigert wird (Standard: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Debugginginformationen ausgeben (Standard: %u, &lt;category&gt; anzugeben ist optional)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight</source>
- <translation>Setzen von maximalem BIP141 Blockgewicht von * 4. ist veraltet, benutze blockmaxweight</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Setzt die Serialisierung von Rohtransaktionen oder Block Hex-Daten auf non-verbose mode, nicht-Segwit(0) oder Segwit(1) (default: %d)</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>Spezifiziere das Verzeichnis für das Wallet (Standard:&lt;datadir&gt;/wallets wenn es vorhanden ist, sonst &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>Verzeichniss für das Debug Logfile: Es kann sich um einen absoluten oder relativen Pfad zum Datenverzeichniss handeln (Standard: %s)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Unterstütze Blöcke und Transaktionen mit Bloomfiltern zu filtern (default: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Die Transaktionsgebührrate (in %s/kB), die die Toleranz anzeigt für das Abschreiben von Wechselgeld, durch deren Zufügung zur Transaktionsgebühr (Standard: %s). Hinweis: Eine Ausgabe wird abgeschrieben, wenn sie bei Höhe dieser Rate "Staub" ist, aber es wird immer abgeschrieben bis zur Staub-Weiterleitungsgebühr, und eine Abschreibungsgebühr darüber ist begrenzt durch die Gebührenschätzung für das längste Ziel</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Das ist die Transaktionsgebühr, welche du zahlen müsstest, wenn die Gebührenschätzungen nicht verfügbar sind.</translation>
</message>
@@ -3926,10 +3561,6 @@
<translation>Gesamtlänge des Netzwerkversionstrings (%i) erreicht die maximale Länge (%i). Reduzieren Sie die Nummer oder die Größe von uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Versucht ausgehenden Datenverkehr unter dem gegebenen Wert zu halten (in MiB pro 24h), 0 = kein Limit (default: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Nicht unterstützter Parameter -socks gefunden. Das Festlegen der SOCKS-Version ist nicht mehr möglich, nur noch SOCKS5-Proxies werden unterstützt.</translation>
</message>
@@ -3938,118 +3569,22 @@
<translation>Das Argument -whitelistalwaysrelay wird nicht unterstützt und deswegen ignoriert. Benutze -whitelistrelay und/oder -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Separaten SOCKS5-Proxy verwenden, um Gegenstellen über versteckte Tor-Dienste zu erreichen (Standard: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Warnung: Unbekannte Blockversion wird durch Mining erzeugt! Es ist möglich, dass unbekannte Regeln in Kraft sind.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Gegenstellen die sich von der angegebenen IP-Adresse (e.g. 1.2.3.4) oder CIDR Notation (eg. 1.2.3.0/24) aus verbinden immer zulassen. Kann mehrmals angegeben werden.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s wurde sehr hoch eingestellt!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(Standard: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Adressen von Gegenstellen immer über DNS-Namensauflösung abfragen (Standard: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Fehler beim Laden der Brieftasche %s. -wallet Dateiname muss eine normale Datei sein.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Fehler beim Laden der Brieftasche %s. -wallet Dateiname doppelt angegeben.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Fehler beim Laden der Brieftasche %s. -wallet Dateiname enthält ungültige Buchstaben.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Wieviele Blöcke beim Starten geprüft werden sollen (Standard: %u, 0 = alle)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>IP-Adressen in Debugausgabe einschließen (Standard: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Der Keypool ist erschöpft. Bitte rufen Sie zunächst keypoolrefill auf.</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>&lt;port&gt; nach JSON-RPC-Verbindungen abhören (Standard: %u oder Testnetz: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>&lt;port&gt; nach Verbindungen abhören (Standard: %u oder Testnetz: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Maximal &lt;n&gt; Verbindungen zu Gegenstellen aufrechterhalten (Standard: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Die Wallet soll Transaktionen übertragen/broadcasten</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximale Größe des Empfangspuffers pro Verbindung, &lt;n&gt; * 1000 Byte (Standard: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximale Größe des Sendepuffers pro Verbindung, &lt;n&gt; * 1000 Byte (Standard: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Debugausgaben einen Zeitstempel voranstellen (Standard: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>"Data Carrier"-Transaktionen weiterleiten und erarbeiten (Standard: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Nicht-"P2SH-Multisig" weiterleiten (Standard: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Größe des Schlüsselpools festlegen auf &lt;n&gt; (Standard: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Maximales BIP141 Blockgewicht festlegen (Standard: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Maximale Anzahl an Threads zur Verarbeitung von RPC-Anfragen festlegen (Standard: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Konfigurationsdatei festlegen (Standard: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Verbindungzeitüberschreitung in Millisekunden festlegen (Minimum: 1, Standard: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>PID-Datei festlegen (Standard: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Unbestätigtes Wechselgeld darf beim Senden von Transaktionen ausgegeben werden (Standard: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Netzwerk-Threads werden gestartet...</translation>
</message>
@@ -4066,10 +3601,6 @@
<translation>Dies ist die Gebühr, die beim Senden einer Transaktion fällig wird.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Schwellenwert, um Verbindungen zu sich nicht konform verhaltenden Gegenstellen zu beenden (Standard: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Transaktionsbeträge dürfen nicht negativ sein.</translation>
</message>
@@ -4090,6 +3621,26 @@
<translation>Unzureichender Kontostand</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Es kann keinen privater Schlüssel für eine Wechselgeldaddresse generiert werden. Private Schlüssel sind für diese Brieftasche deaktiviert.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Ein Wallet das kein geteiltes HD-Wallet ist, kann kein Upgrade erfahren, wenn nicht auch der Schlüsselpool vor der Teilung ein Upgrade erfahren hat. Bitte benutzen Sie upgradewallet=169900 oder -upgradewallet ohne Angabe einer Version.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Die Gebührenabschätzung schlug fehl. Fallbackfee ist deaktiviert. Warten sie ein paar Blöcke oder aktivieren sie -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Warnung: Es wurden private Schlüssel in der Brieftasche {%s} entdeckt, welche private Schlüssel jedoch deaktiviert hat.</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Es konnte nicht in das Datenverzeichnis '%s' geschrieben werden; Überprüfen sie die Berechtigungen. </translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Lade Blockindex...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_el.ts b/src/qt/locale/bitcoin_el.ts
index 62a93fa628..ee89afa6ad 100644
--- a/src/qt/locale/bitcoin_el.ts
+++ b/src/qt/locale/bitcoin_el.ts
@@ -5,6 +5,10 @@
<source>Create a new address</source>
<translation>Δημιουργία νέου λογαριασμού</translation>
</message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Αντιγραφή</translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
@@ -132,6 +136,10 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
+ <message>
+ <source>Wallet</source>
+ <translation>Πορτοφόλι</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts
index fb190a6f96..85d5c62c91 100644
--- a/src/qt/locale/bitcoin_el_GR.ts
+++ b/src/qt/locale/bitcoin_el_GR.ts
@@ -27,7 +27,11 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>Αντιγραφη της επιλεγμενης διεύθυνσης στο πρόχειρο του συστηματος</translation>
+ <translation>Διαγραφή της επιλεγμένης διεύθυνσης από τη λίστα</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Αναζήτηση με βάση τη διεύθυνση ή την επιγραφή</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
@@ -83,7 +87,7 @@
</message>
<message>
<source>Export Address List</source>
- <translation>Εξαγωγή Λίστας Διεύθυνσεων</translation>
+ <translation>Εξαγωγή Λίστας Διευθύνσεων</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
@@ -132,6 +136,10 @@
<translation>Επανέλαβε τον νέο κωδικό πρόσβασης</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Προβολή κωδικού πρόσβασης</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Εισάγετε το νέο κωδικό πρόσβασης στο πορτοφόλι. &lt;br/&gt;Παρακαλώ χρησιμοποιείστε έναν κωδικό με &lt;b&gt;δέκα ή περισσότερους τυχαίους χαρακτήρες &lt;/b&gt;, ή &lt;b&gt;οχτώ ή παραπάνω λέξεις &lt;/b&gt;.</translation>
</message>
@@ -141,15 +149,15 @@
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Αυτη η ενεργεία χρειάζεται τον κωδικό του πορτοφολιού για να ξεκλειδώσει το πορτοφόλι.</translation>
+ <translation>Αυτή η ενέργεια χρειάζεται τον κωδικό του πορτοφολιού για να ξεκλειδώσει το πορτοφόλι.</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation>Ξεκλειδωσε το πορτοφολι</translation>
+ <translation>Ξεκλείδωσε το πορτοφόλι</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Αυτη η ενεργεια χρειάζεται τον κωδικο του πορτοφολιου για να αποκρυπτογραφησειι το πορτοφόλι.</translation>
+ <translation>Αυτή η ενέργεια χρειάζεται τον κωδικό του πορτοφολιού για να αποκρυπτογραφήσει το πορτοφόλι.</translation>
</message>
<message>
<source>Decrypt wallet</source>
@@ -168,6 +176,10 @@
<translation>Επιβεβαίωσε κρυπτογράφηση πορτοφολιού</translation>
</message>
<message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Προσόχη! Εάν κρυπτογραφήσεις το πορτοφόλι σου και χάσεις τη φράση αποκατάστασης, θα &lt;b&gt; ΧΑΣΕΙΣ ΟΛΑ ΣΟΥ ΤΑ BITCOIN &lt;/b&gt;!</translation>
+ </message>
+ <message>
<source>Are you sure you wish to encrypt your wallet?</source>
<translation>Είστε σίγουρος/η ότι θέλετε να κρυπτογραφήσετε το πορτοφόλι σας;</translation>
</message>
@@ -177,25 +189,61 @@
</message>
<message>
<source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 θα κλείσει τώρα για να τελειώσει η διαδικασία κρυπτογράφησης. Να θυμάστε ότι κρυπρογραφόντας το πορτοφόλι σας δεν μπορείτε να προστατεύσετε πλήρως τα bitcoin σας απο κλοπή μέσω malware που μπορεί να προσβάλει τον υπολογιστή σας.</translation>
+ <translation>%1 θα κλείσει τώρα για να τελειώσει η διαδικασία κρυπτογράφησης. Να θυμάστε ότι κρυπτογραφόντας το πορτοφόλι σας δεν μπορείτε να προστατεύσετε πλήρως τα bitcoin σας απο κλοπή μέσω malware που μπορεί να προσβάλει τον υπολογιστή σας.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>ΣΗΜΑΝΤΙΚΟ: Τα προηγούμενα αντίγραφα ασφαλείας που έχετε κάνει από το αρχείο του πορτοφόλιου σας θα πρέπει να αντικατασταθουν με το νέο που δημιουργείται, κρυπτογραφημένο αρχείο πορτοφόλιου. Για λόγους ασφαλείας, τα προηγούμενα αντίγραφα ασφαλείας του μη κρυπτογραφημένου αρχείου πορτοφόλιου θα καταστουν άχρηστα μόλις αρχίσετε να χρησιμοποιείτε το νέο κρυπτογραφημένο πορτοφόλι. </translation>
</message>
<message>
<source>Wallet encryption failed</source>
<translation>Η κρυπτογράφηση του πορτοφολιού απέτυχε</translation>
</message>
<message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Η κρυπτογράφηση του πορτοφολιού απέτυχε λογω εσωτερικού σφάλματος. Το πορτοφολι δεν κρυπτογραφηθηκε.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Οι εισαχθέντες κωδικοί δεν ταιριάζουν.</translation>
+ </message>
+ <message>
<source>Wallet unlock failed</source>
- <translation>Το Ξεκλείδωμα του Πορτοφολιού Απέτυχε</translation>
+ <translation>Το ξεκλείδωμα του πορτοφολιού απέτυχε</translation>
</message>
- </context>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Ο κωδικος που εισήχθη για την αποκρυπτογραφηση του πορτοφολιού ήταν λαθος.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation> Η αποκρυπτογράφηση του πορτοφολιού απέτυχε </translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Η φράση πρόσβασης άλλαξε επιτυχώς</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Προσοχη: το πλήκτρο Caps Lock είναι ενεργο.</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
- </context>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Netmask</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Απαγορευμένο έως</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>Υπογραφή &amp;Μηνύματος...</translation>
+ <translation>Υπογραφή &amp;μηνύματος...</translation>
</message>
<message>
<source>Synchronizing with network...</source>
@@ -227,13 +275,17 @@
</message>
<message>
<source>Quit application</source>
- <translation>Εξοδος από την εφαρμογή</translation>
+ <translation>Έξοδος από την εφαρμογή</translation>
</message>
<message>
<source>&amp;About %1</source>
<translation>&amp;Περί %1</translation>
</message>
<message>
+ <source>Show information about %1</source>
+ <translation>Εμφάνισε πληροφορίες σχετικά με %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>Σχετικά με &amp;Qt</translation>
</message>
@@ -246,6 +298,10 @@
<translation>&amp;Επιλογές...</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Επεργασία ρυθμισεων επιλογών για το %1</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Κρυπτογράφησε το πορτοφόλι</translation>
</message>
@@ -255,7 +311,7 @@
</message>
<message>
<source>&amp;Change Passphrase...</source>
- <translation>&amp;Άλλαξε κωδικο πρόσβασης</translation>
+ <translation>&amp;Άλλαξε Φράση Πρόσβασης</translation>
</message>
<message>
<source>&amp;Sending addresses...</source>
@@ -270,8 +326,32 @@
<translation>'Ανοιγμα &amp;URI</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Πορτοφόλι</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Προεπιλεγμένο πορτοφόλι</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Κάντε κλικ για να απενεργοποιήσετε το δίκτυο.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Η δραστηριότητα δικτύου είναι απενεργοποιημένη.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Κάντε κλικ για να ενεργοποιήσετε τo δίκτυο ξανά.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Συγχρονισμός Επικεφαλίδων (%1%)...</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
- <translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο...</translation>
+ <translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρό δίσκο...</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
@@ -319,7 +399,7 @@
</message>
<message>
<source>Show or hide the main Window</source>
- <translation>Εμφάνιση ή αποκρύψη του κεντρικου παράθυρου </translation>
+ <translation>Εμφάνιση ή απόκρυψη του κεντρικού παραθύρου</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
@@ -370,6 +450,14 @@
<translation>&amp;Επιλογές γραμμής εντολών</translation>
</message>
<message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο...</translation>
+ </message>
+ <message>
<source>%1 behind</source>
<translation>%1 πίσω</translation>
</message>
@@ -379,7 +467,7 @@
</message>
<message>
<source>Transactions after this will not yet be visible.</source>
- <translation>Οι συναλλαγές μετά από αυτό δεν θα είναι ακόμη ορατες.</translation>
+ <translation>Οι συναλλαγές μετά από αυτό δεν θα είναι ακόμη ορατές.</translation>
</message>
<message>
<source>Error</source>
@@ -414,6 +502,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Πορτοφόλι: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Τύπος: %1
@@ -468,15 +562,15 @@
</message>
<message>
<source>Fee:</source>
- <translation>Ταρίφα</translation>
+ <translation>Ταρίφα:</translation>
</message>
<message>
<source>Dust:</source>
- <translation>Σκόνη</translation>
+ <translation>Σκόνη:</translation>
</message>
<message>
<source>After Fee:</source>
- <translation>Ταρίφα αλλαγής</translation>
+ <translation>Ταρίφα αλλαγής:</translation>
</message>
<message>
<source>Change:</source>
@@ -535,10 +629,30 @@
<translation>Αντιγραφή ταυτότητας συναλλαγής</translation>
</message>
<message>
+ <source>Copy quantity</source>
+ <translation>Αντιγραφή ποσότητας</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Αντιγραφή τελών</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>ναι</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>όχι</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(χωρίς ετικέτα)</translation>
</message>
- </context>
+ <message>
+ <source>(change)</source>
+ <translation>(αλλαγή)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -562,10 +676,6 @@
<translation>&amp;Διεύθυνση</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Νέα Διεύθυνση Λήψης</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Νέα Διεύθυνση Αποστολής</translation>
</message>
@@ -573,7 +683,31 @@
<source>Edit receiving address</source>
<translation>Διόρθωση Διεύθυνσης Λήψης</translation>
</message>
- </context>
+ <message>
+ <source>Edit sending address</source>
+ <translation> Επεξεργασία διεύθυνσης αποστολής</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Η διεύθυνση "%1" δεν είναι έγκυρη Bitcoin διεύθυνση.</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Η διεύθυνση "%1" υπάρχει ήδη ως διεύθυνσης λήψης με ετικέτα "%2" και γιαυτό τον λόγο δεν μπορεί να προστεθεί ως διεύθυνση αποστολής.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Η διεύθυνση "%1" βρίσκεται ήδη στο βιβλίο διευθύνσεων με ετικέτα "%2".</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Δεν είναι δυνατό το ξεκλείδωμα του πορτοφολιού.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Η δημιουργία νέου κλειδιού απέτυχε.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -608,18 +742,14 @@
<translation>(%1-bit)</translation>
</message>
<message>
- <source>Command-line options</source>
- <translation>επιλογής γραμμής εντολών</translation>
- </message>
- <message>
- <source>Usage:</source>
- <translation>Χρήση:</translation>
+ <source>About %1</source>
+ <translation>Σχετικά %1</translation>
</message>
<message>
- <source>command-line options</source>
- <translation>επιλογής γραμμής εντολών</translation>
+ <source>Command-line options</source>
+ <translation>Επιλογές γραμμής εντολών</translation>
</message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -662,6 +792,10 @@
<translation>Φόρμα</translation>
</message>
<message>
+ <source>Unknown...</source>
+ <translation>Άγνωστο...</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation>Χρόνος τελευταίου μπλοκ</translation>
</message>
@@ -674,11 +808,11 @@
<name>OpenURIDialog</name>
<message>
<source>Open URI</source>
- <translation>'Ανοιγμα &amp;URI</translation>
+ <translation>Άνοιγμα &amp;URI</translation>
</message>
<message>
<source>Open payment request from URI or file</source>
- <translation>Ανοιχτό αίτημα πληρωμής από URI ή απο αρχείο</translation>
+ <translation>Ανοιχτό αίτημα πληρωμής από URI ή από αρχείο</translation>
</message>
<message>
<source>URI:</source>
@@ -721,25 +855,33 @@
</message>
<message>
<source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
- <translation>URLs από τρίτους (π.χ. ένας εξερευνητής μπλοκ) τα οποία εμφανίζονται στην καρτέλα συναλλαγών ως στοιχεία μενού. Το %s στα URL αντικαθιστάται από την τιμή της κατατεμαχισμένης συναλλαγής.</translation>
+ <translation>URLs από τρίτους (π.χ. ένας εξερευνητής μπλοκ) τα οποία εμφανίζονται στην καρτέλα συναλλαγών ως στοιχεία μενού. Το %s στα URL αντικαθίσταται από την τιμή της κατατεμαχισμένης συναλλαγής.</translation>
</message>
<message>
<source>Active command-line options that override above options:</source>
<translation>Ενεργές επιλογές γραμμής-εντολών που παρακάμπτουν τις παραπάνω επιλογές:</translation>
</message>
<message>
+ <source>Open Configuration File</source>
+ <translation>Άνοιγμα Αρχείου Ρυθμίσεων</translation>
+ </message>
+ <message>
<source>Reset all client options to default.</source>
- <translation>Επαναφορα όλων των επιλογων του πελάτη σε default.</translation>
+ <translation>Επαναφορά όλων των επιλογών του πελάτη στις αρχικές.</translation>
</message>
<message>
<source>&amp;Reset Options</source>
- <translation>Επαναφορα ρυθμίσεων</translation>
+ <translation>Επαναφορά ρυθμίσεων</translation>
</message>
<message>
<source>&amp;Network</source>
<translation>&amp;Δίκτυο</translation>
</message>
<message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = αυτόματο, &lt;0 = ελεύθεροι πυρήνες)</translation>
</message>
@@ -753,7 +895,7 @@
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation>Επιλογή κατα πόσο να αναδείχνονται οι δυνατότητες ελέγχου κερμάτων.</translation>
+ <translation>Ενεργοποίηση δυνατοτήτων ελέγχου κερμάτων</translation>
</message>
<message>
<source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
@@ -773,7 +915,7 @@
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Σύνδεση στο Bitcoin δίκτυο μέσω διαμεσολαβητή SOCKS5 (π.χ. για σύνδεση μέσω Tor)</translation>
+ <translation>Σύνδεση στο δίκτυο Bitcoin μέσω διαμεσολαβητή SOCKS5 (π.χ. για σύνδεση μέσω Tor)</translation>
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
@@ -792,12 +934,24 @@
<translation>Θύρα διαμεσολαβητή</translation>
</message>
<message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Tor</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;Παράθυρο</translation>
</message>
<message>
<source>Show only a tray icon after minimizing the window.</source>
- <translation>Εμφάνιση μόνο εικονιδίου στην περιοχή ειδοποιήσεων κατά την ελαχιστοποίηση</translation>
+ <translation>Εμφάνιση μόνο εικονιδίου στην περιοχή ειδοποιήσεων κατά την ελαχιστοποίηση.</translation>
</message>
<message>
<source>&amp;Minimize to the tray instead of the taskbar</source>
@@ -813,7 +967,7 @@
</message>
<message>
<source>User Interface &amp;language:</source>
- <translation>Γλώσσα περιβάλλοντος εργασίας: </translation>
+ <translation>Γλώσσα περιβάλλοντος εργασίας:</translation>
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
@@ -825,8 +979,7 @@
</message>
<message>
<source>Whether to show coin control features or not.</source>
- <translation>Επιλογή κατα πόσο να αναδείχνονται οι δυνατότητες ελέγχου κερμάτων.
-</translation>
+ <translation>Επιλογή κατά πόσο να αναδείχνονται οι δυνατότητες ελέγχου κερμάτων.</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -846,7 +999,7 @@
</message>
<message>
<source>Confirm options reset</source>
- <translation>Επιβεβαιώση των επιλογων επαναφοράς </translation>
+ <translation>Επιβεβαίωση των επιλογών επαναφοράς</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
@@ -901,7 +1054,7 @@
</message>
<message>
<source>Mined balance that has not yet matured</source>
- <translation>Εξορυγμενο υπόλοιπο που δεν έχει ακόμα ωριμάσει </translation>
+ <translation>Εξορυγμένο υπόλοιπο που δεν έχει ακόμα ωριμάσει</translation>
</message>
<message>
<source>Balances</source>
@@ -942,6 +1095,26 @@
</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Σφάλμα αίτησης πληρωμής</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Δεν είναι δυνατή η εκκίνηση του bitcoin: χειριστής click-to-pay</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>URI χειριστής</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>Επεξεργασία αρχείου αίτησης πληρωμής</translation>
+ </message>
+ <message>
+ <source>Payment request rejected</source>
+ <translation>Η αίτηση πληρωμής απορρίφθηκε</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -970,11 +1143,11 @@
</message>
<message>
<source>%1 h</source>
- <translation>%1 ώ</translation>
+ <translation>%1 h</translation>
</message>
<message>
<source>%1 m</source>
- <translation>%1 λ</translation>
+ <translation>%1 m</translation>
</message>
<message>
<source>%1 s</source>
@@ -1074,6 +1247,10 @@
<translation>Τρέχον αριθμός μπλοκ</translation>
</message>
<message>
+ <source>Memory usage</source>
+ <translation>χρήση Μνήμης</translation>
+ </message>
+ <message>
<source>Received</source>
<translation>Παραλήφθησαν</translation>
</message>
@@ -1094,12 +1271,20 @@
<translation>Έκδοση</translation>
</message>
<message>
+ <source>Decrease font size</source>
+ <translation>Μείωση μεγέθους γραμματοσειράς</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>Αύξηση μεγέθους γραμματοσειράς</translation>
+ </message>
+ <message>
<source>Services</source>
<translation>Υπηρεσίες</translation>
</message>
<message>
<source>Ban Score</source>
- <translation>Σκορ αποκλησμού</translation>
+ <translation>Σκορ Aποκλεισμού</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1154,6 +1339,26 @@
<translation>Καθαρισμός κονσόλας</translation>
</message>
<message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;ώρα</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;μέρα</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;εβδομάδα</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;χρόνος</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Προεπιλεγμένο πορτοφόλι</translation>
+ </message>
+ <message>
<source>via %1</source>
<translation>μέσω %1</translation>
</message>
@@ -1170,6 +1375,14 @@
<translation>Εξερχόμενα</translation>
</message>
<message>
+ <source>Yes</source>
+ <translation>Ναι</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation>Όχι</translation>
+ </message>
+ <message>
<source>Unknown</source>
<translation>Άγνωστο(α)</translation>
</message>
@@ -1213,10 +1426,18 @@
<translation>Αφαίρεση</translation>
</message>
<message>
+ <source>Copy URI</source>
+ <translation>Αντιγραφή της επιλεγμένης διεύθυνσης στο πρόχειρο του συστήματος</translation>
+ </message>
+ <message>
<source>Copy label</source>
<translation>Αντιγραφή ετικέτας</translation>
</message>
<message>
+ <source>Copy message</source>
+ <translation>Αντιγραφή μηνύματος</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>Αντιγραφή ποσού</translation>
</message>
@@ -1229,7 +1450,7 @@
</message>
<message>
<source>Copy &amp;URI</source>
- <translation>Αντιγραφη της επιλεγμενης διεύθυνσης στο πρόχειρο του συστηματος</translation>
+ <translation>Αντιγραφή της επιλεγμένης διεύθυνσης στο πρόχειρο του συστήματος</translation>
</message>
<message>
<source>Copy &amp;Address</source>
@@ -1240,25 +1461,45 @@
<translation>&amp;Αποθήκευση εικόνας...</translation>
</message>
<message>
+ <source>Payment information</source>
+ <translation>Πληροφορίες πληρωμής</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>Διεύθυνση</translation>
</message>
<message>
+ <source>Amount</source>
+ <translation>Ποσό</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Ετικέτα</translation>
</message>
+ <message>
+ <source>Message</source>
+ <translation>Μήνυμα</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Πορτοφόλι</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
<source>Date</source>
- <translation>Ημερομήνια</translation>
+ <translation>Ημερομηνία</translation>
</message>
<message>
<source>Label</source>
<translation>Ετικέτα</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Μήνυμα</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(χωρίς ετικέτα)</translation>
</message>
@@ -1271,7 +1512,7 @@
</message>
<message>
<source>Coin Control Features</source>
- <translation>Χαρακτηρηστικά επιλογής κερμάτων</translation>
+ <translation>Χαρακτηριστικά επιλογής κερμάτων</translation>
</message>
<message>
<source>Inputs...</source>
@@ -1299,11 +1540,11 @@
</message>
<message>
<source>Fee:</source>
- <translation>Ταρίφα</translation>
+ <translation>Ταρίφα:</translation>
</message>
<message>
<source>After Fee:</source>
- <translation>Ταρίφα αλλαγής</translation>
+ <translation>Ταρίφα αλλαγής:</translation>
</message>
<message>
<source>Change:</source>
@@ -1355,7 +1596,7 @@
</message>
<message>
<source>Dust:</source>
- <translation>Σκόνη</translation>
+ <translation>Σκόνη:</translation>
</message>
<message>
<source>Clear &amp;All</source>
@@ -1371,13 +1612,29 @@
</message>
<message>
<source>S&amp;end</source>
- <translation>Αποστολη</translation>
+ <translation>Αποστολή</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Αντιγραφή ποσότητας</translation>
</message>
<message>
<source>Copy amount</source>
<translation>Αντιγραφή ποσού</translation>
</message>
<message>
+ <source>Copy fee</source>
+ <translation>Αντιγραφή τελών</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ή</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Κόστος συναλλαγής</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(χωρίς ετικέτα)</translation>
</message>
@@ -1430,7 +1687,7 @@
</message>
<message>
<source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Εισάγεται μία ετικέτα για αυτή την διεύθυνση για να προστεθεί στη λίστα με τις χρησιμοποιημένες διευθύνσεις</translation>
+ <translation>Εισάγετε μία ετικέτα για αυτή την διεύθυνση για να προστεθεί στη λίστα με τις χρησιμοποιημένες διευθύνσεις</translation>
</message>
<message>
<source>Pay To:</source>
@@ -1443,7 +1700,11 @@
</context>
<context>
<name>SendConfirmationDialog</name>
- </context>
+ <message>
+ <source>Yes</source>
+ <translation>Ναι</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
<message>
@@ -1455,7 +1716,7 @@
<name>SignVerifyMessageDialog</name>
<message>
<source>Signatures - Sign / Verify a Message</source>
- <translation>Υπογραφές - Είσοδος / Επαλήθευση μήνυματος </translation>
+ <translation>Υπογραφές - Είσοδος / Επαλήθευση Mηνύματος </translation>
</message>
<message>
<source>&amp;Sign Message</source>
@@ -1491,11 +1752,11 @@
</message>
<message>
<source>Copy the current signature to the system clipboard</source>
- <translation>Αντέγραφη της επιλεγμενης διεύθυνσης στο πρόχειρο του συστηματος</translation>
+ <translation>Αντιγραφή της επιλεγμένης υπογραφής στο πρόχειρο του συστήματος</translation>
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Υπογράψτε ένα μήνυμα για ν' αποδείξετε πως σας ανήκει μια συγκεκριμένη διεύθυνση Bitcoin</translation>
+ <translation>Υπογράψτε το μήνυμα για να αποδείξετε πως σας ανήκει η συγκεκριμένη διεύθυνση Bitcoin</translation>
</message>
<message>
<source>Sign &amp;Message</source>
@@ -1511,23 +1772,23 @@
</message>
<message>
<source>&amp;Verify Message</source>
- <translation>&amp;Επιβεβαίωση μηνύματος</translation>
+ <translation>&amp;Επιβεβαίωση Mηνύματος</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
- <translation>Διεύθυνση Bitcoin η οποία το μήνυμα έχει υπογραφεί</translation>
+ <translation>Διεύθυνση Bitcoin με την οποία έχει υπογραφεί το μήνυμα</translation>
</message>
<message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Υπογράψτε ένα μήνυμα για ν' αποδείξετε πως υπογραφθηκε απο μια συγκεκριμένη διεύθυνση Bitcoin</translation>
+ <translation>Επαληθεύστε το μήνυμα για να αποδείξετε πως υπογράφθηκε από τη συγκεκριμένη διεύθυνση Bitcoin</translation>
</message>
<message>
<source>Verify &amp;Message</source>
- <translation>Επιβεβαίωση μηνύματος</translation>
+ <translation>Επιβεβαίωση Mηνύματος</translation>
</message>
<message>
<source>Reset all verify message fields</source>
- <translation>Επαναφορά όλων επαλήθευμενων πεδίων μήνυματος </translation>
+ <translation>Επαναφορά όλων των πεδίων επαλήθευσης μηνύματος</translation>
</message>
</context>
<context>
@@ -1551,10 +1812,6 @@
<translation>Ανοιχτό μέχρι %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/αποσυνδεδεμένο</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/ανεπιβεβαίωτο, %1</translation>
</message>
@@ -1610,6 +1867,14 @@
<source>Transaction fee</source>
<translation>Κόστος συναλλαγής</translation>
</message>
+ <message>
+ <source>Message</source>
+ <translation>Μήνυμα</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Ποσό</translation>
+ </message>
</context>
<context>
<name>TransactionDescDialog</name>
@@ -1622,7 +1887,7 @@
<name>TransactionTableModel</name>
<message>
<source>Date</source>
- <translation>Ημερομήνια</translation>
+ <translation>Ημερομηνία</translation>
</message>
<message>
<source>Label</source>
@@ -1673,7 +1938,7 @@
</message>
<message>
<source>Date</source>
- <translation>Ημερομήνια</translation>
+ <translation>Ημερομηνία</translation>
</message>
<message>
<source>Label</source>
@@ -1700,119 +1965,67 @@
</context>
<context>
<name>WalletModel</name>
+ <message>
+ <source>Increase:</source>
+ <translation>Αύξηση:</translation>
+ </message>
</context>
<context>
<name>WalletView</name>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Options:</source>
- <translation>Επιλογές:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Ορισμός φακέλου δεδομένων</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Σύνδεση σε έναν κόμβο για την ανάκτηση διευθύνσεων από ομοτίμους, και αποσυνδέσh</translation>
- </message>
<message>
- <source>Specify your own public address</source>
- <translation>Διευκρινίστε τη δικιά σας δημόσια διεύθυνση.</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Αποδοχή εντολών κονσόλας και JSON-RPC</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Εκτέλεση στο παρασκήνιο κι αποδοχή εντολών</translation>
+ <source>Cancel</source>
+ <translation>Ακύρωση</translation>
</message>
+</context>
+<context>
+ <name>bitcoin-core</name>
<message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Αποθηκευση σε συγκεκριμένη διεύθυνση. Χρησιμοποιήστε τα πλήκτρα [Host] : συμβολισμός θύρα για IPv6</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Εκτέλεσε την εντολή όταν το καλύτερο μπλοκ αλλάξει(%s στην εντολή αντικαθίσταται από το hash του μπλοκ)</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Να δέχεσαι συνδέσεις από έξω(προεπιλογή:1)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Αποκλεισμός επιλογων δημιουργίας: </translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Επιλογές σύνδεσης:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
- <translation>Εντοπισθηκε διεφθαρμενη βαση δεδομενων των μπλοκ</translation>
+ <translation>Εντοπίσθηκε διεφθαρμένη βάση δεδομένων των μπλοκ</translation>
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
- <translation>Θελετε να δημιουργηθει τωρα η βαση δεδομενων του μπλοκ? </translation>
+ <translation>Θέλετε να δημιουργηθεί τώρα η βάση δεδομένων των μπλοκ;</translation>
</message>
<message>
<source>Error initializing block database</source>
- <translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων μπλοκ</translation>
+ <translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων των μπλοκ</translation>
</message>
<message>
<source>Error initializing wallet database environment %s!</source>
- <translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων πορτοφόλιου %s!</translation>
+ <translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων πορτοφολιού %s!</translation>
</message>
<message>
<source>Error loading block database</source>
- <translation>Σφάλμα φορτωσης της βασης δεδομενων των μπλοκ</translation>
+ <translation>Σφάλμα φόρτωσης της βάσης δεδομένων των μπλοκ</translation>
</message>
<message>
<source>Error opening block database</source>
- <translation>Σφάλμα φορτωσης της βασης δεδομενων των μπλοκ</translation>
+ <translation>Σφάλμα φόρτωσης της βάσης δεδομένων των μπλοκ</translation>
</message>
<message>
<source>Error: Disk space is low!</source>
- <translation>Προειδοποίηση: Χαμηλός χώρος στο δίσκο </translation>
+ <translation>Σφάλμα: Χαμηλός χώρος στο δίσκο!</translation>
</message>
<message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>ταλαιπωρηθειτε για να ακούσετε σε οποιαδήποτε θύρα. Χρήση - ακούστε = 0 , αν θέλετε αυτό.</translation>
+ <translation>Αποτυχία παρακολούθησης σε οποιαδήποτε θύρα. Χρησιμοποιήστε -listen=0 αν θέλετε αυτό.</translation>
</message>
<message>
<source>Importing...</source>
- <translation>ΕΙσαγωγή...</translation>
+ <translation>Εισαγωγή...</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
- <translation>Δεν ειναι αρκετες περιγραφες αρχείων διαθέσιμες.</translation>
- </message>
- <message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Μόνο σύνδεση σε κόμβους του δικτύου &lt;net&gt; (ipv4, ipv6 ή onion)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Επιλέξτε αρχείο πορτοφολιού (μέσα απο κατάλογο δεδομένων)</translation>
+ <translation>Δεν υπάρχουν αρκετοί περιγραφείς αρχείων διαθέσιμοι.</translation>
</message>
<message>
<source>Verifying blocks...</source>
- <translation>Επαλήθευση των μπλοκ... </translation>
- </message>
- <message>
- <source>Wallet options:</source>
- <translation>Επιλογές πορτοφολιού:</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Σύνδεση μέσω διαμεσολαβητή SOCKS5</translation>
+ <translation>Επαλήθευση των μπλοκ...</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
@@ -1823,26 +2036,6 @@
<translation>Πληροφορία</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Επιλογές αναμετάδοσης κόμβου: </translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Επιλογές διακομιστή RPC:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Αποστολή πληροφοριών εντοπισμού σφαλμάτων στην κονσόλα αντί του αρχείου debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Προβολή όλων των επιλογών εντοπισμού σφαλμάτων (χρήση: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Συρρίκνωση του αρχείο debug.log κατα την εκκίνηση του πελάτη (προεπιλογή: 1 όταν δεν-debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Η υπογραφή συναλλαγής απέτυχε </translation>
</message>
@@ -1852,15 +2045,11 @@
</message>
<message>
<source>Transaction amount too small</source>
- <translation>Το ποσό της συναλλαγής είναι πολύ μικρο </translation>
+ <translation>Το ποσό της συναλλαγής είναι πολύ μικρό</translation>
</message>
<message>
<source>Transaction too large</source>
- <translation>Η συναλλαγή ειναι πολύ μεγάλη </translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Όνομα χρήστη για τις συνδέσεις JSON-RPC</translation>
+ <translation>Η συναλλαγή είναι πολύ μεγάλη</translation>
</message>
<message>
<source>Warning</source>
@@ -1868,63 +2057,11 @@
</message>
<message>
<source>Zapping all transactions from wallet...</source>
- <translation>Μεταφορά όλων των συναλλαγών απο το πορτοφόλι</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Κωδικός για τις συνδέσεις JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Εκτέλεσε την εντολή όταν το καλύτερο μπλοκ αλλάξει(%s στην εντολή αντικαθίσταται από το hash του μπλοκ)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Να επιτρέπονται οι έλεγχοι DNS για προσθήκη και σύνδεση κόμβων</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Πόσο εξονυχιστική να είναι η επιβεβαίωση του μπλοκ (0-4, προεπιλογή: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Διατηρήση ένος πλήρες ευρετήριου συναλλαγών (προεπιλογή: %u) </translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Δευτερόλεπτα πριν επιτραπεί ξανά η σύνδεση των προβληματικών peers (προεπιλογή: %u)</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Πόσα μπλοκ να ελέγχθουν κατά την εκκίνηση (προεπιλογή: %u, 0 = όλα)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Να συμπεριληφθεί η διεύθυνση IP στην αναφορά? (προεπιλογή: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Μέγιστες αριθμός συνδέσεων με τους peers &lt;n&gt; (προεπιλογή: %u)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Ορίστε αρχείο ρυθμίσεων (προεπιλογή: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Ορισμός λήξης χρονικού ορίου σε χιλιοστά του δευτερολέπτου(προεπιλογή: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Ορίστε αρχείο pid (προεπιλογή: %s)</translation>
- </message>
- <message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Όριο αποσύνδεσης προβληματικών peers (προεπιλογή: %u)</translation>
+ <translation>Μεταφορά όλων των συναλλαγών από το πορτοφόλι</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Άγνωστo δίκτυο ορίζεται σε onlynet: '%s'</translation>
+ <translation>Έχει οριστεί άγνωστo δίκτυο στο -onlynet: '%s'</translation>
</message>
<message>
<source>Insufficient funds</source>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 1b51699b31..c6ecbc3f87 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -237,7 +237,7 @@
</message>
<message>
<location line="-56"/>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <source>Your wallet is now encrypted. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -246,32 +246,33 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+8"/>
<location line="+7"/>
- <location line="+42"/>
+ <location line="+43"/>
<location line="+6"/>
<source>Wallet encryption failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-54"/>
+ <location line="-55"/>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+7"/>
- <location line="+48"/>
+ <location line="+49"/>
<source>The supplied passphrases do not match.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-37"/>
+ <location line="-38"/>
+ <location line="+6"/>
<source>Wallet unlock failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
- <location line="+11"/>
+ <location line="-5"/>
+ <location line="+12"/>
<location line="+19"/>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
<translation type="unfinished"></translation>
@@ -309,27 +310,22 @@
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+307"/>
+ <location filename="../bitcoingui.cpp" line="+318"/>
<source>Sign &amp;message...</source>
<translation>Sign &amp;message...</translation>
</message>
<message>
- <location line="+483"/>
+ <location line="+574"/>
<source>Synchronizing with network...</source>
<translation>Synchronizing with network...</translation>
</message>
<message>
- <location line="-561"/>
+ <location line="-652"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
<message>
- <location line="-140"/>
- <source>Node</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+141"/>
+ <location line="+1"/>
<source>Show general overview of wallet</source>
<translation>Show general overview of wallet</translation>
</message>
@@ -399,32 +395,17 @@
<translation>&amp;Change Passphrase...</translation>
</message>
<message>
- <location line="+12"/>
- <source>&amp;Sending addresses...</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
- <source>&amp;Receiving addresses...</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+18"/>
<source>Open &amp;URI...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+104"/>
+ <location line="+157"/>
<source>Wallet:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+83"/>
- <source>default wallet</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+226"/>
+ <location line="+330"/>
<source>Click to disable network activity.</source>
<translation type="unfinished"></translation>
</message>
@@ -444,17 +425,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+37"/>
+ <location line="+53"/>
<source>Reindexing blocks on disk...</source>
<translation>Reindexing blocks on disk...</translation>
</message>
<message>
- <location line="+316"/>
+ <location line="+315"/>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-880"/>
+ <location line="-970"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -484,17 +465,12 @@
<translation>&amp;Verify message...</translation>
</message>
<message>
- <location line="+570"/>
+ <location line="+660"/>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
- <location line="-792"/>
- <source>Wallet</source>
- <translation>Wallet</translation>
- </message>
- <message>
- <location line="+149"/>
+ <location line="-733"/>
<source>&amp;Send</source>
<translation>&amp;Send</translation>
</message>
@@ -529,32 +505,32 @@
<translation>Verify messages to ensure they were signed with specified Bitcoin addresses</translation>
</message>
<message>
- <location line="+58"/>
+ <location line="+61"/>
<source>&amp;File</source>
<translation>&amp;File</translation>
</message>
<message>
- <location line="+14"/>
+ <location line="+11"/>
<source>&amp;Settings</source>
<translation>&amp;Settings</translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+66"/>
<source>&amp;Help</source>
<translation>&amp;Help</translation>
</message>
<message>
- <location line="+15"/>
+ <location line="+11"/>
<source>Tabs toolbar</source>
<translation>Tabs toolbar</translation>
</message>
<message>
- <location line="-158"/>
+ <location line="-211"/>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+70"/>
+ <location line="+71"/>
<source>Show the list of used sending addresses and labels</source>
<translation type="unfinished"></translation>
</message>
@@ -574,7 +550,7 @@
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location line="+410"/>
+ <location line="+484"/>
<source>%n active connection(s) to Bitcoin network</source>
<translation>
<numerusform>%n active connection to Bitcoin network</numerusform>
@@ -582,7 +558,7 @@
</translation>
</message>
<message>
- <location line="+60"/>
+ <location line="+76"/>
<source>Indexing blocks on disk...</source>
<translation type="unfinished"></translation>
</message>
@@ -600,7 +576,7 @@
</translation>
</message>
<message>
- <location line="+24"/>
+ <location line="+23"/>
<source>%1 behind</source>
<translation>%1 behind</translation>
</message>
@@ -635,22 +611,57 @@
<translation>Up to date</translation>
</message>
<message>
- <location line="-494"/>
+ <location line="-593"/>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+8"/>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+253"/>
+ <location line="+63"/>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;Window</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Minimize</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Zoom</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Restore</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Main Window</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+228"/>
<source>%1 client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+227"/>
+ <location line="+241"/>
<source>Connecting to peers...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+38"/>
+ <location line="+37"/>
<source>Catching up...</source>
<translation>Catching up...</translation>
</message>
@@ -711,6 +722,11 @@
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+0"/>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+19"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</translation>
@@ -721,7 +737,7 @@
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="+529"/>
+ <location filename="../bitcoin.cpp" line="+395"/>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
<translation type="unfinished"></translation>
</message>
@@ -814,7 +830,7 @@
<translation type="unfinished">Confirmed</translation>
</message>
<message>
- <location filename="../coincontroldialog.cpp" line="+53"/>
+ <location filename="../coincontroldialog.cpp" line="+58"/>
<source>Copy address</source>
<translation type="unfinished"></translation>
</message>
@@ -875,7 +891,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+315"/>
+ <location line="+313"/>
<source>(%1 locked)</source>
<translation type="unfinished"></translation>
</message>
@@ -959,7 +975,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+71"/>
+ <location line="+75"/>
<source>The entered address &quot;%1&quot; is not a valid Bitcoin address.</source>
<translation type="unfinished"></translation>
</message>
@@ -987,7 +1003,7 @@
<context>
<name>FreespaceChecker</name>
<message>
- <location filename="../intro.cpp" line="+77"/>
+ <location filename="../intro.cpp" line="+73"/>
<source>A new data directory will be created.</source>
<translation>A new data directory will be created.</translation>
</message>
@@ -1015,7 +1031,7 @@
<context>
<name>HelpMessageDialog</name>
<message>
- <location filename="../utilitydialog.cpp" line="+41"/>
+ <location filename="../utilitydialog.cpp" line="+44"/>
<source>version</source>
<translation type="unfinished">version</translation>
</message>
@@ -1079,7 +1095,7 @@
<translation>Use a custom data directory:</translation>
</message>
<message>
- <location filename="../intro.cpp" line="+20"/>
+ <location filename="../intro.cpp" line="+22"/>
<source>Bitcoin</source>
<translation type="unfinished">Bitcoin</translation>
</message>
@@ -1104,7 +1120,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+73"/>
+ <location line="+80"/>
<source>Error: Specified data directory &quot;%1&quot; cannot be created.</source>
<translation type="unfinished"></translation>
</message>
@@ -1252,12 +1268,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+16"/>
- <source>MB</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+27"/>
+ <location line="+43"/>
<source>Number of script &amp;verification threads</source>
<translation type="unfinished"></translation>
</message>
@@ -1301,12 +1312,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+31"/>
- <source>Active command-line options that override above options:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+45"/>
+ <location line="+76"/>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished"></translation>
</message>
@@ -1351,7 +1357,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+68"/>
+ <location line="+28"/>
+ <source>MiB</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+40"/>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished"></translation>
</message>
@@ -1509,7 +1520,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+182"/>
+ <location line="+41"/>
+ <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+141"/>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1519,17 +1535,17 @@
<translation>&amp;Cancel</translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="+92"/>
+ <location filename="../optionsdialog.cpp" line="+96"/>
<source>default</source>
<translation>default</translation>
</message>
<message>
- <location line="+52"/>
+ <location line="+63"/>
<source>none</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+77"/>
+ <location line="+93"/>
<source>Confirm options reset</source>
<translation>Confirm options reset</translation>
</message>
@@ -1672,8 +1688,8 @@
<context>
<name>PaymentServer</name>
<message>
- <location filename="../paymentserver.cpp" line="+317"/>
- <location line="+215"/>
+ <location filename="../paymentserver.cpp" line="+226"/>
+ <location line="+338"/>
<location line="+42"/>
<location line="+110"/>
<location line="+14"/>
@@ -1682,30 +1698,42 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-398"/>
+ <location line="-521"/>
<source>Cannot start bitcoin: click-to-pay handler</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+82"/>
- <location line="+21"/>
- <location line="+13"/>
+ <location line="+62"/>
+ <location line="+9"/>
+ <location line="+16"/>
+ <location line="+5"/>
+ <location line="+12"/>
<location line="+7"/>
<source>URI handling</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-41"/>
+ <location line="-49"/>
<source>&apos;bitcoin://&apos; is not a valid URI. Use &apos;bitcoin:&apos; instead.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+22"/>
+ <location line="+10"/>
+ <source>You are using a BIP70 URL which will be unsupported in the future.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+16"/>
<source>Payment request fetch URL is invalid: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+5"/>
+ <source>Cannot process payment request because BIP70 support was not compiled in.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+11"/>
<source>Invalid payment address %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1715,7 +1743,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+13"/>
+ <location line="+14"/>
<source>Payment request file handling</source>
<translation type="unfinished"></translation>
</message>
@@ -1725,7 +1753,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+61"/>
+ <location line="+195"/>
<location line="+9"/>
<location line="+31"/>
<location line="+10"/>
@@ -1796,7 +1824,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+6"/>
<source>Payment acknowledged</source>
<translation type="unfinished"></translation>
</message>
@@ -1842,12 +1870,12 @@
<translation type="unfinished">Amount</translation>
</message>
<message>
- <location filename="../guiutil.cpp" line="+124"/>
+ <location filename="../guiutil.cpp" line="+111"/>
<source>Enter a Bitcoin address (e.g. %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+722"/>
+ <location line="+687"/>
<source>%1 d</source>
<translation type="unfinished"></translation>
</message>
@@ -1957,7 +1985,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="+193"/>
+ <location filename="../bitcoin.cpp" line="+185"/>
<source>%1 didn&apos;t yet exit safely...</source>
<translation type="unfinished"></translation>
</message>
@@ -1970,12 +1998,12 @@
<context>
<name>QObject::QObject</name>
<message>
- <location filename="../bitcoin.cpp" line="-118"/>
+ <location filename="../bitcoin.cpp" line="-113"/>
<source>Error parsing command line arguments: %1.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+39"/>
+ <location line="+37"/>
<source>Error: Specified data directory &quot;%1&quot; does not exist.</source>
<translation type="unfinished"></translation>
</message>
@@ -2019,7 +2047,8 @@
<location filename="../forms/debugwindow.ui" line="+56"/>
<location line="+26"/>
<location line="+26"/>
- <location line="+23"/>
+ <location line="+26"/>
+ <location line="+29"/>
<location line="+26"/>
<location line="+36"/>
<location line="+23"/>
@@ -2027,7 +2056,7 @@
<location line="+23"/>
<location line="+36"/>
<location line="+23"/>
- <location line="+679"/>
+ <location line="+713"/>
<location line="+23"/>
<location line="+23"/>
<location line="+23"/>
@@ -2049,7 +2078,7 @@
<translation>N/A</translation>
</message>
<message>
- <location line="-1361"/>
+ <location line="-1427"/>
<source>Client version</source>
<translation>Client version</translation>
</message>
@@ -2079,7 +2108,22 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+26"/>
+ <location line="+10"/>
+ <source>To specify a non-default location of the data directory use the &apos;%1&apos; option.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Blocksdir</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>To specify a non-default location of the blocks directory use the &apos;%1&apos; option.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+19"/>
<source>Startup time</source>
<translation>Startup time</translation>
</message>
@@ -2129,7 +2173,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+11"/>
<source>(none)</source>
<translation type="unfinished"></translation>
</message>
@@ -2140,35 +2184,35 @@
</message>
<message>
<location line="+80"/>
- <location line="+558"/>
+ <location line="+589"/>
<source>Received</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-478"/>
- <location line="+455"/>
+ <location line="-509"/>
+ <location line="+486"/>
<source>Sent</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-414"/>
+ <location line="-445"/>
<source>&amp;Peers</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+53"/>
+ <location line="+67"/>
<source>Banned peers</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+60"/>
- <location filename="../rpcconsole.cpp" line="+502"/>
- <location line="+760"/>
+ <location line="+65"/>
+ <location filename="../rpcconsole.cpp" line="+501"/>
+ <location line="+754"/>
<source>Select a peer to view detailed information.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+37"/>
<source>Whitelisted</source>
<translation type="unfinished"></translation>
</message>
@@ -2198,18 +2242,18 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1095"/>
- <location line="+1003"/>
+ <location line="-1161"/>
+ <location line="+1069"/>
<source>User Agent</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-700"/>
+ <location line="-734"/>
<source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+84"/>
+ <location line="+87"/>
<source>Decrease font size</source>
<translation type="unfinished"></translation>
</message>
@@ -2219,7 +2263,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+610"/>
+ <location line="+641"/>
<source>Services</source>
<translation type="unfinished"></translation>
</message>
@@ -2269,7 +2313,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1132"/>
+ <location line="-1166"/>
<source>Last block time</source>
<translation>Last block time</translation>
</message>
@@ -2284,7 +2328,7 @@
<translation>&amp;Console</translation>
</message>
<message>
- <location line="+211"/>
+ <location line="+214"/>
<source>&amp;Network Traffic</source>
<translation type="unfinished"></translation>
</message>
@@ -2294,7 +2338,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../rpcconsole.cpp" line="-414"/>
+ <location filename="../rpcconsole.cpp" line="-411"/>
<source>In:</source>
<translation type="unfinished"></translation>
</message>
@@ -2304,17 +2348,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../forms/debugwindow.ui" line="-315"/>
+ <location filename="../forms/debugwindow.ui" line="-318"/>
<source>Debug log file</source>
<translation>Debug log file</translation>
</message>
<message>
- <location line="+152"/>
+ <location line="+155"/>
<source>Clear console</source>
<translation>Clear console</translation>
</message>
<message>
- <location filename="../rpcconsole.cpp" line="-253"/>
+ <location filename="../rpcconsole.cpp" line="-249"/>
<source>1 &amp;hour</source>
<translation type="unfinished"></translation>
</message>
@@ -2347,17 +2391,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+48"/>
+ <location line="+47"/>
<source>&amp;Unban</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+54"/>
- <source>default wallet</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+110"/>
+ <location line="+161"/>
<source>Welcome to the %1 RPC console.</source>
<translation type="unfinished"></translation>
</message>
@@ -2387,17 +2426,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+68"/>
+ <location line="+70"/>
<source>Executing command without any wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="-2"/>
<source>Executing command using &quot;%1&quot; wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+190"/>
+ <location line="+189"/>
<source>(node id: %1)</source>
<translation type="unfinished"></translation>
</message>
@@ -2626,7 +2665,7 @@
<context>
<name>RecentRequestsTableModel</name>
<message>
- <location filename="../recentrequeststablemodel.cpp" line="+27"/>
+ <location filename="../recentrequeststablemodel.cpp" line="+25"/>
<source>Date</source>
<translation type="unfinished">Date</translation>
</message>
@@ -2665,7 +2704,7 @@
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+588"/>
+ <location filename="../sendcoinsdialog.cpp" line="+593"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -2772,18 +2811,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+80"/>
- <location line="+13"/>
- <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
- <source>(read the tooltip)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+29"/>
+ <location line="+112"/>
<source>Recommended:</source>
<translation type="unfinished"></translation>
</message>
@@ -2793,12 +2821,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+52"/>
+ <location line="+49"/>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+185"/>
+ <location line="+166"/>
<source>Send to multiple recipients at once</source>
<translation>Send to multiple recipients at once</translation>
</message>
@@ -2813,17 +2841,27 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-835"/>
+ <location line="-800"/>
<source>Dust:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+696"/>
+ <location line="+543"/>
+ <source>When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+131"/>
<source>Confirmation time target:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+74"/>
+ <location line="+58"/>
<source>Enable Replace-By-Fee</source>
<translation type="unfinished"></translation>
</message>
@@ -2853,7 +2891,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>S&amp;end</translation>
</message>
<message>
- <location filename="../sendcoinsdialog.cpp" line="-504"/>
+ <location filename="../sendcoinsdialog.cpp" line="-505"/>
<source>Copy quantity</source>
<translation type="unfinished"></translation>
</message>
@@ -2888,20 +2926,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+76"/>
+ <location line="+74"/>
<source>%1 (%2 blocks)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+131"/>
- <location line="+5"/>
+ <location line="+133"/>
<location line="+5"/>
+ <location line="+6"/>
<location line="+4"/>
<source>%1 to %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+7"/>
<source>Are you sure you want to send?</source>
<translation type="unfinished"></translation>
</message>
@@ -2916,12 +2954,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-57"/>
+ <location line="-61"/>
<source>from wallet %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+36"/>
+ <location line="+40"/>
<source>Please, review your transaction.</source>
<translation type="unfinished"></translation>
</message>
@@ -2946,7 +2984,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+192"/>
+ <location line="+191"/>
<source>The recipient address is not valid. Please recheck.</source>
<translation type="unfinished"></translation>
</message>
@@ -2990,13 +3028,8 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<source>Payment request expired.</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location line="+91"/>
- <source>Pay only the required fee of %1</source>
- <translation type="unfinished"></translation>
- </message>
<message numerus="yes">
- <location line="+43"/>
+ <location line="+120"/>
<source>Estimated to begin confirmation within %n block(s).</source>
<translation>
<numerusform>Estimated to begin confirmation within %n block.</numerusform>
@@ -3138,7 +3171,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../sendcoinsentry.cpp" line="+35"/>
+ <location filename="../sendcoinsentry.cpp" line="+39"/>
<source>Enter a label for this address to add it to your address book</source>
<translation type="unfinished"></translation>
</message>
@@ -3155,7 +3188,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>ShutdownWindow</name>
<message>
- <location filename="../utilitydialog.cpp" line="+84"/>
+ <location filename="../utilitydialog.cpp" line="+83"/>
<source>%1 is shutting down...</source>
<translation type="unfinished"></translation>
</message>
@@ -3366,7 +3399,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>TransactionDesc</name>
<message numerus="yes">
- <location filename="../transactiondesc.cpp" line="+31"/>
+ <location filename="../transactiondesc.cpp" line="+35"/>
<source>Open for %n more block(s)</source>
<translation>
<numerusform>Open for %n more block</numerusform>
@@ -3414,7 +3447,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+23"/>
+ <location line="+22"/>
<source>Status</source>
<translation type="unfinished"></translation>
</message>
@@ -3473,12 +3506,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<location line="+12"/>
<location line="+54"/>
<location line="+30"/>
- <location line="+58"/>
+ <location line="+60"/>
<source>Credit</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location line="-152"/>
+ <location line="-154"/>
<source>matures in %n more block(s)</source>
<translation>
<numerusform>matures in %n more block</numerusform>
@@ -3493,12 +3526,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<message>
<location line="+60"/>
<location line="+26"/>
- <location line="+61"/>
+ <location line="+63"/>
<source>Debit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-77"/>
+ <location line="-79"/>
<source>Total debit</source>
<translation type="unfinished"></translation>
</message>
@@ -3549,12 +3582,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+18"/>
+ <location line="+19"/>
<source>Merchant</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+8"/>
<source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to &quot;not accepted&quot; and it won&apos;t be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
<translation type="unfinished"></translation>
</message>
@@ -3607,7 +3640,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>TransactionTableModel</name>
<message>
- <location filename="../transactiontablemodel.cpp" line="+226"/>
+ <location filename="../transactiontablemodel.cpp" line="+227"/>
<source>Date</source>
<translation type="unfinished">Date</translation>
</message>
@@ -3743,7 +3776,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>TransactionView</name>
<message>
- <location filename="../transactionview.cpp" line="+70"/>
+ <location filename="../transactionview.cpp" line="+71"/>
<location line="+16"/>
<source>All</source>
<translation type="unfinished"></translation>
@@ -3814,7 +3847,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+47"/>
+ <location line="+51"/>
<source>Abandon transaction</source>
<translation type="unfinished"></translation>
</message>
@@ -3864,7 +3897,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+193"/>
+ <location line="+199"/>
<source>Export Transaction History</source>
<translation type="unfinished"></translation>
</message>
@@ -3929,7 +3962,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+166"/>
+ <location line="+171"/>
<source>Range:</source>
<translation type="unfinished"></translation>
</message>
@@ -3942,7 +3975,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>UnitDisplayStatusBarControl</name>
<message>
- <location filename="../bitcoingui.cpp" line="+159"/>
+ <location filename="../bitcoingui.cpp" line="+154"/>
<source>Unit to show amounts in. Click to select another unit.</source>
<translation type="unfinished"></translation>
</message>
@@ -3958,19 +3991,19 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>WalletModel</name>
<message>
- <location filename="../walletmodel.cpp" line="+215"/>
+ <location filename="../walletmodel.cpp" line="+219"/>
<source>Send Coins</source>
<translation type="unfinished">Send Coins</translation>
</message>
<message>
- <location line="+289"/>
+ <location line="+301"/>
<location line="+39"/>
- <location line="+6"/>
+ <location line="+5"/>
<source>Fee bump error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-45"/>
+ <location line="-44"/>
<source>Increasing transaction fee failed</source>
<translation type="unfinished"></translation>
</message>
@@ -4005,10 +4038,15 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+5"/>
<source>Could not commit transaction</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location line="+35"/>
+ <source>default wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>WalletView</name>
@@ -4023,7 +4061,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished">Export the data in the current tab to a file</translation>
</message>
<message>
- <location line="+207"/>
+ <location line="+206"/>
<source>Backup Wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -4053,7 +4091,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+54"/>
+ <location line="+44"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -4066,7 +4104,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+22"/>
+ <location line="+20"/>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation type="unfinished"></translation>
</message>
@@ -4081,22 +4119,22 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+81"/>
+ <location line="+74"/>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+26"/>
<source>Pruning blockstore...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+28"/>
+ <location line="+30"/>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-178"/>
+ <location line="-172"/>
<source>Bitcoin Core</source>
<translation type="unfinished">Bitcoin Core</translation>
</message>
@@ -4116,7 +4154,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+10"/>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation type="unfinished"></translation>
</message>
@@ -4156,7 +4194,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+5"/>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation type="unfinished"></translation>
</message>
@@ -4192,6 +4230,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+1"/>
+ <source>Config setting for %s only applied on %s network when in [%s] section.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Copyright (C) %i-%i</source>
<translation type="unfinished"></translation>
</message>
@@ -4207,11 +4250,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+2"/>
- <source>Error creating %s: You can&apos;t create non-HD wallets with this version.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Error initializing block database</source>
<translation>Error initializing block database</translation>
</message>
@@ -4241,7 +4279,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
<source>Error loading block database</source>
<translation>Error loading block database</translation>
</message>
@@ -4251,7 +4289,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>Error opening block database</translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+6"/>
<source>Error: Disk space is low!</source>
<translation>Error: Disk space is low!</translation>
</message>
@@ -4296,12 +4334,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+47"/>
+ <location line="+22"/>
+ <source>Specified blocks directory &quot;%s&quot; does not exist.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+24"/>
<source>Upgrading txindex database</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-43"/>
+ <location line="-42"/>
<source>Loading P2P addresses...</source>
<translation type="unfinished"></translation>
</message>
@@ -4336,12 +4379,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+8"/>
<source>The source code is available from %s.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+9"/>
<source>Transaction fee and change calculation failed</source>
<translation type="unfinished"></translation>
</message>
@@ -4357,21 +4400,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+3"/>
- <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Unsupported argument -tor found, use -onion.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Unsupported logging category %s=%s.</source>
<translation type="unfinished"></translation>
</message>
@@ -4396,7 +4424,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-165"/>
+ <location line="-158"/>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation type="unfinished"></translation>
</message>
@@ -4411,17 +4439,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+44"/>
+ <location line="+38"/>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+22"/>
- <source>Error loading %s: You can&apos;t disable HD on an already existing HD wallet</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+4"/>
+ <location line="+25"/>
<source>Error reading from database, shutting down.</source>
<translation type="unfinished"></translation>
</message>
@@ -4431,7 +4454,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+3"/>
+ <source>Error: Disk space is low for %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
<source>Information</source>
<translation>Information</translation>
</message>
@@ -4467,6 +4495,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
</message>
<message>
<location line="+4"/>
+ <source>Section [%s] is not recognized.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Signing transaction failed</source>
<translation>Signing transaction failed</translation>
</message>
@@ -4486,13 +4519,13 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
- <source>Specified blocks directory &quot;%s&quot; does not exist.
+ <location line="+4"/>
+ <source>The specified config file %s does not exist
</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+1"/>
<source>The transaction amount is too small to pay the fee</source>
<translation type="unfinished"></translation>
</message>
@@ -4527,7 +4560,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+9"/>
<source>Verifying wallet(s)...</source>
<translation type="unfinished"></translation>
</message>
@@ -4552,17 +4585,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-191"/>
+ <location line="-182"/>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+18"/>
- <source>Error loading %s: You can&apos;t enable HD on an already existing non-HD wallet</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+40"/>
+ <location line="+56"/>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation type="unfinished"></translation>
</message>
@@ -4577,17 +4605,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+9"/>
- <source>Unsupported argument -socks found. Setting SOCKS version isn&apos;t possible anymore, only SOCKS5 proxies are supported.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
- <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+8"/>
+ <location line="+14"/>
<source>Warning: Unknown block versions being mined! It&apos;s possible unknown rules are in effect</source>
<translation type="unfinished"></translation>
</message>
@@ -4602,22 +4620,22 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+18"/>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+21"/>
+ <location line="+22"/>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+20"/>
<source>Starting network threads...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+4"/>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
<translation type="unfinished"></translation>
</message>
@@ -4652,12 +4670,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>Unknown network specified in -onlynet: &apos;%s&apos;</translation>
</message>
<message>
- <location line="-46"/>
+ <location line="-48"/>
<source>Insufficient funds</source>
<translation>Insufficient funds</translation>
</message>
<message>
- <location line="-128"/>
+ <location line="-120"/>
<source>Can&apos;t generate a change-address key. Private keys are disabled for this wallet.</source>
<translation type="unfinished"></translation>
</message>
@@ -4667,12 +4685,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+14"/>
+ <location line="+12"/>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+54"/>
+ <location line="+48"/>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
<translation type="unfinished"></translation>
</message>
@@ -4702,12 +4720,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation>Rescanning...</translation>
</message>
<message>
- <location line="-43"/>
+ <location line="-42"/>
<source>Done loading</source>
<translation>Done loading</translation>
</message>
<message>
- <location line="+14"/>
+ <location line="+12"/>
<source>Error</source>
<translation>Error</translation>
</message>
diff --git a/src/qt/locale/bitcoin_en_GB.ts b/src/qt/locale/bitcoin_en_GB.ts
index dbb6a06874..92a08280d7 100644
--- a/src/qt/locale/bitcoin_en_GB.ts
+++ b/src/qt/locale/bitcoin_en_GB.ts
@@ -30,6 +30,10 @@
<translation>Delete the currently selected address from the list</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Enter address or label to search</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Export the data in the current tab to a file</translation>
</message>
@@ -322,6 +326,14 @@
<translation>Open &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Wallet:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>default wallet</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Click to disable network activity.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Reindexing blocks on disk...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Wallet: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Type: %1
@@ -730,10 +752,6 @@
<translation>&amp;Address</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>New receiving address</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>New sending address</translation>
</message>
@@ -750,8 +768,12 @@
<translation>The entered address "%1" is not a valid Bitcoin address.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>The entered address "%1" is already in the address book.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>The entered address "%1" is already in the address book with label "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>Command-line options</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Usage:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>command-line options</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>UI Options:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Choose data directory on startup (default: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Set language, for example "de_DE" (default: system locale)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Start minimised</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Set SSL root certificates for payment request (default: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Show splash screen on startup (default: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Reset all settings changed in the GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -864,7 +850,7 @@
</message>
<message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</translation>
+ <translation>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterwards to keep your disk usage low.</translation>
</message>
<message>
<source>Use the default data directory</source>
@@ -1068,6 +1054,22 @@
<translation>&amp;Network</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Prune &amp;block storage to</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Reverting this setting requires re-downloading the entire blockchain.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt;0 = leave that many cores free)</translation>
</message>
@@ -1334,6 +1336,10 @@
<translation>URI handling</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>Payment request fetch URL is invalid: %1</translation>
</message>
@@ -1531,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Error parsing command line arguments: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Error: Specified data directory "%1" does not exist.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Error: Cannot parse configuration file: %1. Only use key=value syntax.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Error: Cannot parse configuration file: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1594,7 +1604,7 @@
</message>
<message>
<source>Startup time</source>
- <translation>Startup time</translation>
+ <translation>Start up time</translation>
</message>
<message>
<source>Network</source>
@@ -1629,6 +1639,14 @@
<translation>Memory usage</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Wallet:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(none)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Reset</translation>
</message>
@@ -1797,6 +1815,10 @@
<translation>&amp;Unban</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>default wallet</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Welcome to the %1 RPC console.</translation>
</message>
@@ -1821,6 +1843,14 @@
<translation>Network activity disabled</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Executing command without any wallet</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Executing command using "%1" wallet</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(node id: %1)</translation>
</message>
@@ -1892,20 +1922,20 @@
<translation>Clear</translation>
</message>
<message>
- <source>Requested payments history</source>
- <translation>Requested payments history</translation>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</translation>
</message>
<message>
- <source>&amp;Request payment</source>
- <translation>&amp;Request payment</translation>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generate native segwit (Bech32) address</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</translation>
+ <source>Requested payments history</source>
+ <translation>Requested payments history</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Generate Bech32 address</translation>
+ <source>&amp;Request payment</source>
+ <translation>&amp;Request payment</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1987,6 +2017,10 @@
<translation>Message</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Wallet</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Resulting URI too long, try to reduce the text for label / message.</translation>
</message>
@@ -2101,12 +2135,16 @@
<translation>collapse fee-settings</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>per kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</translation>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2217,14 +2255,6 @@
<translation>Are you sure you want to send?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>added as transaction fee</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Total Amount %1</translation>
- </message>
- <message>
<source>or</source>
<translation>or</translation>
</message>
@@ -2233,10 +2263,26 @@
<translation>You can increase the fee later (signals Replace-By-Fee, BIP-125).</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>from wallet %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Please, review your transaction.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaction fee</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>Not signalling Replace-By-Fee, BIP-125.</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>Total Amount</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirm send coins</translation>
</message>
@@ -2578,10 +2624,6 @@
<translation>conflicted with a transaction with %1 confirmations</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/unconfirmed, %1</translation>
</message>
@@ -2610,14 +2652,6 @@
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, has not been successfully broadcast yet</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, broadcast through %n node</numerusform><numerusform>, broadcast through %n nodes</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Date</translation>
</message>
@@ -2702,6 +2736,10 @@
<translation>Transaction total size</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Transaction virtual size</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Output index</translation>
</message>
@@ -2772,10 +2810,6 @@
<translation>Open until %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Unconfirmed</translation>
</message>
@@ -2800,10 +2834,6 @@
<translation>Immature (%1 confirmations, will be available after %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>This block was not received by any other nodes and will probably not be accepted!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generated but not accepted</translation>
</message>
@@ -3114,38 +3144,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>The wallet data was successfully saved to %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Cancel</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Options:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Specify data directory</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Specify your own public address</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accept command line and JSON-RPC commands</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distributed under the MIT software license, see the accompanying file %s or %s.</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Prune configured below the minimum of %d MiB. Please use a higher number.</translation>
</message>
@@ -3162,18 +3172,10 @@
<translation>Error: A fatal internal error occurred, see debug.log for details</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Fee (in %s/kB) to add to transactions you send (default: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning blockstore...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Run in the background as a daemon and accept commands</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Unable to start HTTP server. See debug log for details.</translation>
</message>
@@ -3186,22 +3188,6 @@
<translation>The %s developers</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</translation>
- </message>
- <message>
- <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source>
- <translation>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info).</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Bind to given address and always listen on it. Use [host]:port notation for IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
</message>
@@ -3210,40 +3196,12 @@
<translation>Cannot provide specific connections and have addrman find outgoing connections at the same.</translation>
</message>
<message>
- <source>Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)</source>
- <translation>Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode).</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Extra transactions to keep in memory for compact block reconstructions (default: %u).</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s).</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3254,22 +3212,6 @@
<translation>Please contribute if you find %s useful. Visit %s for further information about the software.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used).</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Set lowest fee rate (in %s/kB) for transactions to be included in block creation (default: %s).</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</translation>
</message>
@@ -3290,18 +3232,6 @@
<translation>Unable to rewind the database to a pre-fork state. You will need to re-download the blockchain</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times.</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Wallet will not create transactions that violate mempool chain limits (default: %u).</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</translation>
</message>
@@ -3310,10 +3240,6 @@
<translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Whether to save the mempool on shutdown and load on restart (default: %u).</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d of last 100 blocks have unexpected version.</translation>
</message>
@@ -3326,42 +3252,14 @@
<translation>-maxmempool must be at least %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; can be:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Append comment to the user agent string</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Attempt to recover private keys from a corrupt wallet on startup</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Block creation options:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Cannot resolve -%s address: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Chain selection options:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Change index out of range</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Connection options:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3370,38 +3268,10 @@
<translation>Corrupted block database detected</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Debugging/Testing options:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Do not load the wallet and disable wallet RPC calls</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Do you want to rebuild the block database now?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Enable publish hash block in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Enable publish hash transaction in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Enable publish raw block in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Enable publish raw transaction in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Enable transaction replacement in the memory pool (default: %u)</translation>
- </message>
- <message>
<source>Error creating %s: You can't create non-HD wallets with this version.</source>
<translation>Error creating %s: You can't create non-HD wallets with this version.</translation>
</message>
@@ -3418,6 +3288,10 @@
<translation>Error loading %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Error loading %s: Private keys can only be disabled during creation</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Error loading %s: Wallet corrupted</translation>
</message>
@@ -3470,8 +3344,12 @@
<translation>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Specified blocks directory "%s" does not exist.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Upgrading txindex database</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3482,26 +3360,10 @@
<translation>Loading banlist...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Location of the auth cookie (default: data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Not enough file descriptors available.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Print this help message and exit</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Print version and exit</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Prune cannot be configured with a negative value.</translation>
</message>
@@ -3510,14 +3372,6 @@
<translation>Prune mode is incompatible with -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Rebuild chain state and block index from the blk*.dat files on disk</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Rebuild chain state from the currently indexed blocks</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Replaying blocks...</translation>
</message>
@@ -3526,18 +3380,6 @@
<translation>Rewinding blocks...</translation>
</message>
<message>
- <source>Send transactions with full-RBF opt-in enabled (RPC only, default: %u)</source>
- <translation>Send transactions with full-RBF opt-in enabled (RPC only, default: %u).</translation>
- </message>
- <message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Set database cache size in megabytes (%d to %d, default: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Specify wallet file (within data directory)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>The source code is available from %s.</translation>
</message>
@@ -3550,6 +3392,10 @@
<translation>Unable to bind to %s on this computer. %s is probably already running.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Unable to generate keys</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Unsupported argument -benchmark ignored, use -debug=bench.</translation>
</message>
@@ -3570,14 +3416,6 @@
<translation>Upgrading UTXO database</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Use UPnP to map the listening port (default: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Use the test chain</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>User Agent comment (%s) contains unsafe characters.</translation>
</message>
@@ -3586,90 +3424,26 @@
<translation>Verifying blocks...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Wallet debugging/testing options:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Wallet needed to be rewritten: restart %s to complete</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Wallet options:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: Listening for incoming connections failed (listen returned error %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maximum size of data in data carrier transactions we relay and mine (default: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Randomise credentials for every proxy connection. This enables Tor stream isolation (default: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>The transaction amount is too small to send after the fee has been deducted</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(default: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Accept public REST requests (default: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Automatically create Tor hidden service (default: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Connect through SOCKS5 proxy</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Error loading %s: you can't disable HD on an already existing HD wallet.</translation>
</message>
@@ -3682,10 +3456,6 @@
<translation>Error upgrading chainstate database.</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Imports blocks from external blk000??.dat file on startup</translation>
- </message>
- <message>
<source>Information</source>
<translation>Information</translation>
</message>
@@ -3706,42 +3476,14 @@
<translation>Invalid netmask specified in -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Need to specify a port with -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Node relay options:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC server options:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reducing -maxconnections from %d to %d, because of system limitations.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Rescan the block chain for missing wallet transactions on startup</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Send trace/debug info to console instead of debug.log file</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Show all debugging options (usage: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Shrink debug.log file on client startup (default: 1 when no -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Signing transaction failed</translation>
</message>
@@ -3766,14 +3508,6 @@
<translation>This is experimental software.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor control port password (default: empty)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Tor control port to use if onion listening enabled (default: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Transaction amount too small</translation>
</message>
@@ -3794,14 +3528,6 @@
<translation>Unable to generate initial keys.</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Upgrade wallet to latest format on startup</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Username for JSON-RPC connections</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>Verifying wallet(s)...</translation>
</message>
@@ -3818,110 +3544,18 @@
<translation>Warning: unknown new rules activated (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Whether to operate in a blocks only mode (default: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>You need to rebuild the database using -reindex to change -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Zapping all transactions from wallet...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ notification options:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Password for JSON-RPC connections</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Allow DNS lookups for -addnode, -seednode and -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses).</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Error loading %s: you can't enable HD on an already existing non-HD wallet.</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Error loading wallet %s. The -wallet parameter must only specify a filename (not a path).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Force relay of transactions from whitelisted peers, even if they violate local relay policy (default: %d).</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>How thorough the block verification of -checkblocks is (0-4, default: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight</source>
- <translation>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight.</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Sets the serialisation of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d).</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;).</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s).</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Support filtering of blocks and transaction with bloom filters (default: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target.</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>This is the transaction fee you may pay when fee estimates are not available.</translation>
</message>
@@ -3934,22 +3568,14 @@
<translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
- <translation>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</translation>
+ <translation>Unsupported argument -socks found. Setting SOCKS version isn't possible any more, only SOCKS5 proxies are supported.</translation>
</message>
<message>
<source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
<translation>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</translation>
</message>
@@ -3958,110 +3584,18 @@
<translation>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is set very high!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(default: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Always query for peer addresses via DNS lookup (default: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Error loading wallet %s. The -wallet filename must be a regular file.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Error loading wallet %s. Duplicate -wallet filename specified.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Error loading wallet %s. Invalid characters in -wallet filename.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>How many blocks to check at startup (default: %u, 0 = all)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Include IP addresses in debug output (default: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Keypool ran out, please call keypoolrefill first.</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Maintain at most &lt;n&gt; connections to peers (default: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Make the wallet broadcast transactions</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Prepend debug output with timestamp (default: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Relay and mine data carrier transactions (default: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Relay non-P2SH multisig (default: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Set key pool size to &lt;n&gt; (default: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Set maximum BIP141 block weight (default: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Set the number of threads to service RPC calls (default: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Specify configuration file (default: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Specify connection timeout in milliseconds (minimum: 1, default: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Specify pid file (default: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Spend unconfirmed change when sending transactions (default: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Starting network threads...</translation>
</message>
@@ -4078,10 +3612,6 @@
<translation>This is the transaction fee you will pay if you send a transaction.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Threshold for disconnecting misbehaving peers (default: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Transaction amounts must not be negative.</translation>
</message>
@@ -4102,6 +3632,26 @@
<translation>Insufficient funds</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Can't generate a change-address key. Private keys are disabled for this wallet.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Warning: Private keys detected in wallet {%s} with disabled private keys</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Cannot write to data directory '%s'; check permissions.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Loading block index...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts
index 15f54db27a..550ca2a82a 100644
--- a/src/qt/locale/bitcoin_eo.ts
+++ b/src/qt/locale/bitcoin_eo.ts
@@ -30,6 +30,10 @@
<translation>Forigi la elektitan adreson el la listo</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Tajpu adreson aŭ etikedon por serĉi</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Eksporti la datumojn el la aktuala langeto al dosiero</translation>
</message>
@@ -571,19 +575,7 @@
<source>Command-line options</source>
<translation>Komandliniaj agordaĵoj</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uzado:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>komandliniaj agordaĵoj</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Uzantinterfaco ebloj:</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -1099,6 +1091,10 @@
<translation>Mesaĝo</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Monujo</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>La rezultanta URI estas tro longa. Provu malplilongigi la tekston de la etikedo / mesaĝo.</translation>
</message>
@@ -1245,18 +1241,14 @@
<translation>Ĉu vi certas, ke vi volas sendi?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>aldonita kiel krompago</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Totala sumo %1</translation>
- </message>
- <message>
<source>or</source>
<translation>aŭ</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Krompago</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Konfirmi sendon de bitmono</translation>
</message>
@@ -1498,10 +1490,6 @@
<translation>Malferma ĝis %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/senkonekte</translation>
- </message>
- <message>
<source>%1/unconfirmed</source>
<translation>%1/nekonfirmite</translation>
</message>
@@ -1514,10 +1502,6 @@
<translation>Stato</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, ankoraŭ ne elsendita sukcese</translation>
- </message>
- <message>
<source>Date</source>
<translation>Dato</translation>
</message>
@@ -1640,10 +1624,6 @@
<translation>Malferma ĝis %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Senkonekte</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Nekonfirmita</translation>
</message>
@@ -1652,10 +1632,6 @@
<translation>Konfirmita (%1 konfirmoj)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Tiun ĉi blokon ne ricevis ajna alia nodo, kaj ĝi verŝajne ne akceptiĝos!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Kreita sed ne akceptita</translation>
</message>
@@ -1866,42 +1842,10 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Agordoj:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Specifi dosieron por datumoj</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Konekti al nodo por ricevi adresojn de samtavolanoj, kaj malkonekti</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Specifi vian propran publikan adreson</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Akcepti komandojn JSON-RPC kaj el komandlinio</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Ruli fone kiel demono kaj akcepti komandojn</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Kerno de Bitmono</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Bindi al donita adreso kaj ĉiam aŭskulti per ĝi. Uzu la formaton [gastigo]:pordo por IPv6</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Plenumi komandon kiam monuja transakcio ŝanĝiĝas (%s en cmd anstataŭiĝas per TxID)</translation>
- </message>
- <message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
<translation>Tiu ĉi estas antaŭeldona testa versio - uzu laŭ via propra risko - ne uzu por minado aŭ por aplikaĵoj por vendistoj</translation>
</message>
@@ -1914,18 +1858,6 @@
<translation>Averto: ŝajne ni ne tute konsentas kun niaj samtavolanoj! Eble vi devas ĝisdatigi vian klienton, aŭ eble aliaj nodoj faru same.</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; povas esti:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Akcepti konektojn el ekstere (defaŭlte: 1 se ne estas -proxy nek -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Blok-kreaj agordaĵoj:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>Difektita blokdatumbazo trovita</translation>
</message>
@@ -1966,34 +1898,14 @@
<translation>Nesufiĉa nombro de dosierpriskribiloj disponeblas.</translation>
</message>
<message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Specifi monujan dosieron (ene de dosierujo por datumoj)</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>Kontrolado de blokoj...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Monujaj opcioj:</translation>
- </message>
- <message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Plenumi komandon kiam rilata alerto riceviĝas, aŭ kiam ni vidas tre longan forkon (%s en cms anstataŭiĝas per mesaĝo)</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informoj</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Sendi spurajn/sencimigajn informojn al la konzolo anstataŭ al dosiero debug.log</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Malpligrandigi la sencimigan protokol-dosieron kiam kliento lanĉiĝas (defaŭlte: 1 kiam mankas -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Subskriba transakcio fiaskis</translation>
</message>
@@ -2010,30 +1922,10 @@
<translation>Transakcio estas tro granda</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Salutnomo por konektoj JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Averto</translation>
</message>
<message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Vi devas rekontrui la datumbazon kun -reindex por ŝanĝi -txindex</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Pasvorto por konektoj JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Plenumi komandon kiam plej bona bloko ŝanĝiĝas (%s en cmd anstataŭiĝas per bloka haketaĵo)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permesi DNS-elserĉojn por -addnote, -seednote kaj -connect</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>Nekonata reto specifita en -onlynet: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts
index 3a5f442957..7b07380606 100644
--- a/src/qt/locale/bitcoin_es.ts
+++ b/src/qt/locale/bitcoin_es.ts
@@ -30,6 +30,10 @@
<translation>Eliminar la dirección seleccionada de la lista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduzca una dirección o etiqueta que buscar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar los datos en la ficha actual a un archivo</translation>
</message>
@@ -322,6 +326,14 @@
<translation>Abrir &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Monedero</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>monedero predeterminado</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Pulsar para deshabilitar la actividad de red.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Reindexando bloques en disco...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy está&lt;b&gt;habilitado&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Enviar bitcoins a una dirección Bitcoin</translation>
</message>
@@ -510,6 +526,11 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Monedero: %1</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Tipo: %1
@@ -576,7 +597,7 @@
</message>
<message>
<source>Fee:</source>
- <translation>Tasa:</translation>
+ <translation>Comisión:</translation>
</message>
<message>
<source>Dust:</source>
@@ -660,7 +681,7 @@
</message>
<message>
<source>Copy after fee</source>
- <translation>Copiar después de couta</translation>
+ <translation>Copiar después de comisión</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -688,7 +709,7 @@
</message>
<message>
<source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Esta etiqueta se vuelve roja si algún destinatario recibe una cantidad inferior a la actual puerta polvorienta.</translation>
+ <translation>Esta etiqueta se vuelve roja si algún destinatario recibe una cantidad inferior al actual umbral de polvo.</translation>
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
@@ -730,16 +751,12 @@
<translation>&amp;Dirección</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nueva dirección de recivimiento</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nueva dirección de envío</translation>
</message>
<message>
<source>Edit receiving address</source>
- <translation>Editar dirección de recivimiento</translation>
+ <translation>Editar dirección de recepción</translation>
</message>
<message>
<source>Edit sending address</source>
@@ -750,12 +767,16 @@
<translation>La dirección introducida "%1" no es una dirección Bitcoin válida.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>La dirección introducida "%1" está ya en la agenda.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>La dirección "%1" ya existe como dirección de recepción con la etiqueta "%2" y, por lo tanto, no se puede agregar como dirección de envío.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>La dirección ingresada "%1" ya está en la libreta de direcciones con la etiqueta "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation>Podría no desbloquear el monedero.</translation>
+ <translation>No se pudo desbloquear el monedero.</translation>
</message>
<message>
<source>New key generation failed.</source>
@@ -797,47 +818,11 @@
</message>
<message>
<source>About %1</source>
- <translation>Acerda de %1</translation>
+ <translation>Acerca de %1</translation>
</message>
<message>
<source>Command-line options</source>
- <translation>Opciones de la línea de órdenes</translation>
- </message>
- <message>
- <source>Usage:</source>
- <translation>Uso:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opciones de la consola de comandos</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opciones de interfaz de usuario:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Elegir directorio de datos al iniciar (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Establecer el idioma, por ejemplo, "es_ES" (predeterminado: configuración regional del sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Arrancar minimizado</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Establecer los certificados raíz SSL para solicitudes de pago (predeterminado: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Mostrar pantalla de bienvenida en el inicio (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Reiniciar todos los ajustes modificados en el GUI</translation>
+ <translation>Opciones de la línea de comandos</translation>
</message>
</context>
<context>
@@ -852,7 +837,7 @@
</message>
<message>
<source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
- <translation>Al ser la primera vez que se ejecuta el programa, puede elegir donde %1 almacenará sus datos.</translation>
+ <translation>Al ser la primera vez que se ejecuta el programa, puede elegir dónde %1 almacenará sus datos.</translation>
</message>
<message>
<source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
@@ -966,7 +951,7 @@
<name>OpenURIDialog</name>
<message>
<source>Open URI</source>
- <translation>Abrir URI...</translation>
+ <translation>Abrir URI</translation>
</message>
<message>
<source>Open payment request from URI or file</source>
@@ -978,7 +963,7 @@
</message>
<message>
<source>Select payment request file</source>
- <translation>Seleccionar archivo de sulicitud de pago</translation>
+ <translation>Seleccionar archivo de solicitud de pago</translation>
</message>
<message>
<source>Select payment request file to open</source>
@@ -1068,6 +1053,22 @@
<translation>&amp;Red</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Desactiva algunas características avanzadas, pero todos los bloques se validarán por completo. Revertir esta configuración requiere volver a descargar todo el blockchain. El uso real del disco puede ser algo mayor.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Podar el almacenamiento de &amp;bloques para</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Revertir estas configuraciones requiere re-descargar el blockchain entero.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = automático, &lt;0 = dejar libres ese número de núcleos)</translation>
</message>
@@ -1101,7 +1102,7 @@
</message>
<message>
<source>Accept connections from outside.</source>
- <translation>Aceptar conexiones externas.</translation>
+ <translation>Aceptar conexiones desde el exterior.</translation>
</message>
<message>
<source>Allow incomin&amp;g connections</source>
@@ -1129,7 +1130,7 @@
</message>
<message>
<source>Used for reaching peers via:</source>
- <translation>Usado para alcanzar compañeros via:</translation>
+ <translation>Usado para alcanzar pares via:</translation>
</message>
<message>
<source>IPv4</source>
@@ -1205,7 +1206,7 @@
</message>
<message>
<source>none</source>
- <translation>Ninguna</translation>
+ <translation>ninguna</translation>
</message>
<message>
<source>Confirm options reset</source>
@@ -1225,7 +1226,7 @@
</message>
<message>
<source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
- <translation>El fichero de configuración se utiliza para especificar opciones de usuario avanzadas que reemplazar las configuraciones de la interfaz gráfica de usuario. Adicionalmente, se reemplazará cualquier opción introducida en la línea de órdenes.</translation>
+ <translation>El fichero de configuración se utiliza para especificar opciones de usuario avanzadas que reemplazar las configuraciones de la interfaz gráfica de usuario. Adicionalmente, cualquier opción introducida en la línea de comandos reemplazará a este fichero de configuración.</translation>
</message>
<message>
<source>Error</source>
@@ -1256,7 +1257,7 @@
</message>
<message>
<source>Watch-only:</source>
- <translation>De observación:</translation>
+ <translation>Solo observación:</translation>
</message>
<message>
<source>Available:</source>
@@ -1296,7 +1297,7 @@
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>Su saldo actual en direcciones watch-only</translation>
+ <translation>Su saldo actual en direcciones watch-only (solo-observación)</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1308,7 +1309,7 @@
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Transacciones sin confirmar en direcciones watch-only</translation>
+ <translation>Transacciones sin confirmar en direcciones watch-only (solo-observación)</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
@@ -1316,7 +1317,7 @@
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation>Saldo total en las direcciones watch-only</translation>
+ <translation>Saldo total en las direcciones watch-only (solo-observación)</translation>
</message>
</context>
<context>
@@ -1334,6 +1335,10 @@
<translation>Manejo de URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin: //' no es un URI válido. Use 'bitcoin:' en su lugar.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>La búsqueda de solicitud de pago URL es válida: %1</translation>
</message>
@@ -1359,7 +1364,7 @@
</message>
<message>
<source>Payment request network doesn't match client network.</source>
- <translation>La red de solicitud de pago no cimbina la red cliente.</translation>
+ <translation>La red de solicitud de pago no coincide con la red cliente.</translation>
</message>
<message>
<source>Payment request expired.</source>
@@ -1426,7 +1431,7 @@
</message>
<message>
<source>Ping</source>
- <translation>Sonido</translation>
+ <translation>Ping</translation>
</message>
<message>
<source>Sent</source>
@@ -1531,12 +1536,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Error al parsear los argumentos de la línea de comando: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Error: El directorio de datos «%1» especificado no existe.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Error: No se puede analizar el archivo de configuración: %1. Utilice únicamente la sintaxis clave=valor.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Error: No se puede analizar/parsear el archivo de configuración: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1629,6 +1638,14 @@
<translation>Uso de memoria</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Monedero:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(ninguno)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Reiniciar</translation>
</message>
@@ -1646,7 +1663,7 @@
</message>
<message>
<source>Banned peers</source>
- <translation>Peers Bloqueados</translation>
+ <translation>Pares bloqueados</translation>
</message>
<message>
<source>Select a peer to view detailed information.</source>
@@ -1670,7 +1687,7 @@
</message>
<message>
<source>Synced Headers</source>
- <translation>Sincronizar Cabeceras</translation>
+ <translation>Cabeceras Sincronizadas</translation>
</message>
<message>
<source>Synced Blocks</source>
@@ -1706,15 +1723,15 @@
</message>
<message>
<source>Last Send</source>
- <translation>Ultimo envío</translation>
+ <translation>Último envío</translation>
</message>
<message>
<source>Last Receive</source>
- <translation>Ultima recepción</translation>
+ <translation>Última recepción</translation>
</message>
<message>
<source>Ping Time</source>
- <translation>Ping</translation>
+ <translation>Tiempo de Ping</translation>
</message>
<message>
<source>The duration of a currently outstanding ping.</source>
@@ -1726,7 +1743,7 @@
</message>
<message>
<source>Min Ping</source>
- <translation>Sonido Mínimo</translation>
+ <translation>Min Ping</translation>
</message>
<message>
<source>Time Offset</source>
@@ -1794,7 +1811,11 @@
</message>
<message>
<source>&amp;Unban</source>
- <translation>&amp;Unbano</translation>
+ <translation>&amp;Unban</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Monedero predeterminado</translation>
</message>
<message>
<source>Welcome to the %1 RPC console.</source>
@@ -1821,6 +1842,14 @@
<translation>Actividad de red deshabilitada</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Ejecutar comando sin monedero</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Ejecutar comando usando "%1" monedero</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(nodo: %1)</translation>
</message>
@@ -1892,20 +1921,20 @@
<translation>Vaciar</translation>
</message>
<message>
- <source>Requested payments history</source>
- <translation>Historial de pagos solicitados</translation>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Las direcciones segwit nativas (también conocidas como Bech32 o BIP-173) reducen las comisiones de transacción más adelante y ofrecen una mejor protección contra errores tipográficos, pero las billeteras antiguas no las admiten. Cuando no está marcada, se creará una dirección compatible con billeteras más antiguas.</translation>
</message>
<message>
- <source>&amp;Request payment</source>
- <translation>&amp;Solicitar pago</translation>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generar dirección segwit nativa (Bech32)</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Las direcciones Bech32 (BIP-173) son mas baratas al gastar y ofrecen mejor proteción contra errores de tipeo. Cuando no se marque una dirección SegWit envuelta en P2SH será creada, compatible con monederos antiguos. </translation>
+ <source>Requested payments history</source>
+ <translation>Historial de pagos solicitados</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Generar dirección Bech32</translation>
+ <source>&amp;Request payment</source>
+ <translation>&amp;Solicitar pago</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1917,7 +1946,7 @@
</message>
<message>
<source>Remove the selected entries from the list</source>
- <translation>Borrar de la lista las direcciónes actualmente seleccionadas</translation>
+ <translation>Borrar las entradas seleccionadas de la lista</translation>
</message>
<message>
<source>Remove</source>
@@ -1929,7 +1958,7 @@
</message>
<message>
<source>Copy label</source>
- <translation>Copiar capa</translation>
+ <translation>Copiar etiqueta</translation>
</message>
<message>
<source>Copy message</source>
@@ -1987,6 +2016,10 @@
<translation>Mensaje</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Monedero</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultante demasiado grande, trate de reducir el texto de etiqueta / mensaje.</translation>
</message>
@@ -2042,7 +2075,7 @@
</message>
<message>
<source>automatically selected</source>
- <translation>Seleccionado automáticamente</translation>
+ <translation>seleccionado automáticamente</translation>
</message>
<message>
<source>Insufficient funds!</source>
@@ -2062,11 +2095,11 @@
</message>
<message>
<source>Fee:</source>
- <translation>Tasa:</translation>
+ <translation>Comisión:</translation>
</message>
<message>
<source>After Fee:</source>
- <translation>Después de tasas:</translation>
+ <translation>Después de comisión:</translation>
</message>
<message>
<source>Change:</source>
@@ -2094,19 +2127,23 @@
</message>
<message>
<source>Warning: Fee estimation is currently not possible.</source>
- <translation>Advertencia: En este momento no se puede estimar la cuota.</translation>
+ <translation>Advertencia: En este momento no se puede estimar la comisión.</translation>
</message>
<message>
<source>collapse fee-settings</source>
<translation>Colapsar ajustes de comisión.</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>por kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Especifique una comisión personalizada por kB (1,000 bytes) del tamaño virtual de la transacción.
+
+Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis por kB" para un tamaño de transacción de 500 bytes (la mitad de 1 kB) finalmente generará una comisión de solo 50 satoshis.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Si la comisión se establece en 1000 satoshis y la transacción está a sólo 250 bytes, entonces "por kilobyte" sólo paga 250 satoshis de cuota, mientras que "el mínimo total" pagaría 1.000 satoshis. Para las transacciones más grandes que un kilobyte ambos pagan por kilobyte</translation>
+ <source>per kilobyte</source>
+ <translation>por kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2190,7 +2227,7 @@
</message>
<message>
<source>Copy after fee</source>
- <translation>Copiar después de couta</translation>
+ <translation>Copiar después de comisión</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -2217,14 +2254,6 @@
<translation>¿Seguro que quiere enviar?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>añadido como comisión de transacción</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Cantidad total %1</translation>
- </message>
- <message>
<source>or</source>
<translation>o</translation>
</message>
@@ -2233,10 +2262,26 @@
<translation>Puede incrementar la comisión más tarde (usa Replace-By-Fee, BIP-125).</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>de monedero %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Por favor, revisa tu transacción</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Comisión de transacción</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>No usa Replace-By-Fee, BIP-125.</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>Monto total</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirmar enviar monedas</translation>
</message>
@@ -2270,7 +2315,7 @@
</message>
<message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation>Una comisión mayor que %1 se considera una cuota irracionalmente alta.</translation>
+ <translation>Una comisión mayor que %1 se considera una comisión irracionalmente alta.</translation>
</message>
<message>
<source>Payment request expired.</source>
@@ -2290,7 +2335,7 @@
</message>
<message>
<source>Warning: Unknown change address</source>
- <translation>Alerta: dirección cambiada desconocida</translation>
+ <translation>Alerta: dirección de cambio desconocida</translation>
</message>
<message>
<source>Confirm custom change address</source>
@@ -2575,11 +2620,7 @@
</message>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
- <translation>Hay un conflicto con la traducción de las confirmaciones %1</translation>
- </message>
- <message>
- <source>%1/offline</source>
- <translation>%1/sin conexión</translation>
+ <translation>Hay un conflicto con una transacción con %1 confirmaciones</translation>
</message>
<message>
<source>0/unconfirmed, %1</source>
@@ -2587,11 +2628,11 @@
</message>
<message>
<source>in memory pool</source>
- <translation>en el equipo de memoria</translation>
+ <translation>en el pool de memoria</translation>
</message>
<message>
<source>not in memory pool</source>
- <translation>no en el equipo de memoria</translation>
+ <translation>no en el pool de memoria</translation>
</message>
<message>
<source>abandoned</source>
@@ -2610,14 +2651,6 @@
<translation>Estado</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, no ha sido emitido con éxito aún</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, transmitir a través de %n nodo</numerusform><numerusform>, transmitir a través de %n nodos</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Fecha</translation>
</message>
@@ -2702,6 +2735,10 @@
<translation>Tamaño total de transacción</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Tamaño virtual de transacción</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Indice de salida</translation>
</message>
@@ -2723,7 +2760,7 @@
</message>
<message>
<source>Inputs</source>
- <translation>entradas</translation>
+ <translation>Entradas</translation>
</message>
<message>
<source>Amount</source>
@@ -2772,10 +2809,6 @@
<translation>Abierto hasta %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Sin conexion</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Sin confirmar</translation>
</message>
@@ -2800,10 +2833,6 @@
<translation>No disponible (%1 confirmaciones. Estarán disponibles al cabo de %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Este bloque no ha sido recibido por otros nodos y probablemente no sea aceptado!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generado pero no aceptado</translation>
</message>
@@ -2936,7 +2965,7 @@
</message>
<message>
<source>Copy label</source>
- <translation>Copiar capa</translation>
+ <translation>Copiar etiqueta</translation>
</message>
<message>
<source>Copy amount</source>
@@ -3045,19 +3074,19 @@
</message>
<message>
<source>Fee bump error</source>
- <translation>Error de incremento de cuota</translation>
+ <translation>Error de incremento de comisión</translation>
</message>
<message>
<source>Increasing transaction fee failed</source>
- <translation>Ha fallado el incremento de la cuota de transacción.</translation>
+ <translation>Ha fallado el incremento de la comisión de transacción.</translation>
</message>
<message>
<source>Do you want to increase the fee?</source>
- <translation>¿Desea incrementar la cuota?</translation>
+ <translation>¿Desea incrementar la comisión?</translation>
</message>
<message>
<source>Current fee:</source>
- <translation>Cuota actual:</translation>
+ <translation>Comisión actual:</translation>
</message>
<message>
<source>Increase:</source>
@@ -3065,11 +3094,11 @@
</message>
<message>
<source>New fee:</source>
- <translation>Nueva cuota:</translation>
+ <translation>Nueva comisión:</translation>
</message>
<message>
<source>Confirm fee bump</source>
- <translation>Confirmar incremento de cuota.</translation>
+ <translation>Confirmar incremento de comisión.</translation>
</message>
<message>
<source>Can't sign transaction.</source>
@@ -3114,42 +3143,20 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Los datos del monedero se han guardado con éxito en %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Cancelar</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opciones:
-</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Especificar directorio para los datos</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Conectar a un nodo para obtener direcciones de pares y desconectar</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especifique su propia dirección pública</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aceptar comandos consola y JSON-RPC
-</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distribuido bajo la licencia de software MIT, vea el archivo adjunto %s o %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Si &lt;category&gt; no es proporcionado o si &lt;category&gt; =1, muestra toda la información de depuración.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>La Poda se ha configurado por debajo del minimo de %d MiB. Por favor utiliza un valor mas alto.</translation>
+ <translation>La Poda se ha configurado por debajo del minimo de %d MiB. Por favor utiliza un valor más alto.</translation>
</message>
<message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
@@ -3164,19 +3171,10 @@
<translation>Un error interno fatal ocurrió, ver debug.log para detalles</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Comisión (en %s/KB) para agregar a las transacciones que envíe (por defecto: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Poda blockstore ...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Ejecutar en segundo plano como daemon y aceptar comandos
-</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>No se ha podido comenzar el servidor HTTP. Ver debug log para detalles.</translation>
</message>
@@ -3189,22 +3187,6 @@
<translation>Los desarrolladores de %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Una comision (en %s/kB) que sera usada cuando las estimacion de comision no disponga de suficientes datos (predeterminado: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Aceptar transacciones retransmitidas recibidas desde nodos en la lista blanca incluso cuando no estés retransmitiendo transacciones (predeterminado: %d)</translation>
- </message>
- <message>
- <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source>
- <translation>Agregue un nodo para conectars e intentar mantener una conexión abierta (véase el comando de ayuda RPC "addnode" para mas información)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Vincular a la dirección dada y escuchar siempre en ella. Utilice la notación [host]:port para IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>No se puede bloquear el directorio %s. %s ya se está ejecutando.</translation>
</message>
@@ -3213,40 +3195,12 @@
<translation>No es posible mostrar las conexiones indicadas y tener addrman buscando conexiones al mismo tiempo.</translation>
</message>
<message>
- <source>Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)</source>
- <translation>Conectar solo al nodo(s) especificado(s); -connect=0 deshabilita conexiones automáticas (las reglas para este nodo son las mismas que para -addnode)</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Borrar todas las transacciones del monedero y sólo recuperar aquellas partes de la cadena de bloques por medio de -rescan on startup.</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Error leyendo %s!. Todas las claves se han leido correctamente, pero los datos de transacciones o la libreta de direcciones pueden faltar o ser incorrectos.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Descartar información de depuración para una categoría. Puede utilizarse simultáneamente con -debug=1 para escribir información de depuración de todas las categorías a excepción de una o más categorías. </translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Ejecutar comando cuando una transacción del monedero cambia (%s en cmd se remplazará por TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Transacciones extra a mantener en la memoria para reconstrucciones de bloque compacto (predeterminado: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Si este bloque está en la cadena asuma que sus predecesores y él son válidos y potencialmente se saltan su script de verificación (0 para verificar todo, predeterminado: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Ajuste máximo permitido del tiempo offset medio de pares. La perspectiva local de tiempo se verá influenciada por los pares anteriores y posteriores a esta cantidad. (Por defecto: %u segundos)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Máximas comisiones totales (en %s) para utilizar en una sola transacción del monedero; establecer esto demasiado bajo puede abortar grandes transacciones (predeterminado: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Grupo de salida por dirección, seleccionando todo o nada, en lugar de seleccionar en una base para salida. La privacidad se mejora como una dirección utilizada una sola vez (a menos que alguien lo envíe después de gastarlo), a menos que alguien envíe una solicitud, pero puede resultar en tarifas ligeramente más altas ya que la selección de la moneda puede ser inferior a la óptima debido a la limitación adicional después de gastarla. (por defecto, predeterminado %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3257,22 +3211,6 @@
<translation>Contribuya si encuentra %s de utilidad. Visite %s para mas información acerca del programa.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Consultar las direcciones de pares mediante búsqueda DNS, si existen pocas direcciones (por defecto: 1 excepto si se está usando -connect)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Reducir los requerimientos de almacenamiento habilitando la poda (eliminación) de los bloques viejos. Esto permite que la cadena de bloqueo RPC sea llamada para eliminar bloques específicos, y habilita la poda automática de bloques viejos si se provee el tamaño de un objetivo en MiB. Este modo es incompatible con -txindex and -rescan. Precaución: Revertir este ajuste requiere volver a descargar la cadena de bloqueo completa. (predefinido: 0 = deshabilita bloques de poda, 1 = permite la poda manual mediante RPC, &gt;%u = elimina automáticamente los archivos de bloqueo para permanecer bajo el tamaño del objetivo especificado en MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Establecer la tasa más baja (en %s/kB) por transacciones para incluirse en la creación de bloque. (predeterminado: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Establecer el número de hilos (threads) de verificación de scripts (entre %u y %d, 0 = automático, &lt;0 = dejar libres ese número de núcleos; predeterminado: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>La base de datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de tu ordenador están mal ajustados. Reconstruye la base de datos de bloques solo si estas seguro de que la fecha y hora de tu ordenador estan ajustados correctamente.</translation>
</message>
@@ -3293,18 +3231,6 @@
<translation>No es posible reconstruir la base de datos a un estado anterior. Debe descargar de nuevo la cadena de bloques.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Nombre de usuario y contraseña numerada para conexiones JSON-RPC. El campo &lt;userpw&gt; viene en el formato: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Un script canónico de python está incluído en compartir/usuario rpc. Entonces el cliente se conecta normalmente utilizando la pareja de argumentos usuario rpc=&lt;USERNAME&gt;/contraseña rpc=&lt;PASSWORD&gt;. Esta opción puede ser especificada múltiples veces</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>El monedero no creará transacciones que violen los límites de la cadena mempool (predeterminado: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Advertencia: ¡La red no parece coincidir del todo! Algunos mineros parecen estar experimentando problemas.</translation>
</message>
@@ -3313,10 +3239,6 @@
<translation>Advertencia: ¡No parecemos estar del todo con nuestros pares! Puede que necesite actualizarse, o puede que otros nodos necesiten actualizarse.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Indica si guardar el mempool al cerrar y cargar al reiniciar (por defecto: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d de los últimos 100 bloques tienen versión no esperada</translation>
</message>
@@ -3329,42 +3251,14 @@
<translation>-maxmempool debe ser por lo menos de %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; puede ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Adjunta un comentario a la linea de agente de usuario</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Intento de recuperar claves privadas de un monedero corrupto en arranque</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opciones de creación de bloques:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>No se puede resolver -%s direccion: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Opciones de selección en cadena:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Cambio de indice fuera de rango</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Opciones de conexión:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3373,38 +3267,10 @@
<translation>Corrupción de base de datos de bloques detectada.</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opciones de depuración/pruebas:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>No cargar el monedero y desactivar las llamadas RPC del monedero</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>¿Quieres reconstruir la base de datos de bloques ahora?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Activar publicar bloque .hash en &lt;.Address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Activar publicar transacción .hash en &lt;.Address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Habilita la publicacion de bloques en bruto en &lt;direccion&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Habilitar publicar transacción en rama en &lt;dirección&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Habilita el reemplazamiento de transacciones en la piscina de memoria (predeterminado: %u)</translation>
- </message>
- <message>
<source>Error creating %s: You can't create non-HD wallets with this version.</source>
<translation>Error generando %s: Con esta versin no puede crear monederos no-HD.</translation>
</message>
@@ -3421,6 +3287,10 @@
<translation>Error cargando %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Error cargando %s: las claves privadas solo pueden ser deshabilitado durante la creación</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Error cargando %s: Monedero dañado</translation>
</message>
@@ -3473,8 +3343,12 @@
<translation>Cantidad inválida para -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Mantener la memoria de transacciones por debajo de &lt;n&gt; megabytes (predeterminado: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>El directorio de bloques «%s» especificado no existe.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Actualización de la base de datos txindex</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3485,26 +3359,10 @@
<translation>Cargando banlist...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Ubicación de la cookie de autenticación (default: data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>No hay suficientes descriptores de archivo disponibles. </translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Sólo conectar a nodos en redes &lt;net&gt; (ipv4, ipv6 o onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Imprimir este mensaje de ayuda y salir</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Imprimir versión y salir</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Pode no se puede configurar con un valor negativo.</translation>
</message>
@@ -3513,14 +3371,6 @@
<translation>El modo recorte es incompatible con -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Reconstruir el estado de la cadena e indice de bloques a partir de los ficheros blk*.dat en disco</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Reconstruir el estado de la cadena a partir de los bloques indexados</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Reproduciendo bloques ...</translation>
</message>
@@ -3529,14 +3379,6 @@
<translation>Verificando bloques...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Asignar tamaño del cache en megabytes (entre %d y %d; predeterminado: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especificar archivo de monedero (dentro del directorio de datos)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>El código fuente esta disponible desde %s.</translation>
</message>
@@ -3549,6 +3391,10 @@
<translation>No se ha podido conectar con %s en este equipo. %s es posible que este todavia en ejecución.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Incapaz de generar claves</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>El argumento -benchmark no es soportado y ha sido ignorado, utiliza -debug=bench</translation>
</message>
@@ -3569,14 +3415,6 @@
<translation>Actualizando la base de datos UTXO</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Usar UPnP para asignar el puerto de escucha (predeterminado:: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Utilice la cadena de prueba</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>El comentario del Agente de Usuario (%s) contiene caracteres inseguros.</translation>
</message>
@@ -3585,90 +3423,26 @@
<translation>Verificando bloques...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opciones de depuración/pruebas de monedero:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Es necesario reescribir el monedero: reiniciar %s para completar</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opciones de monedero:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permitir conexiones JSON-RPC de origen especificado. Válido para son una sola IP (por ejemplo 1.2.3.4), una red/máscara de red (por ejemplo 1.2.3.4/255.255.255.0) o una red/CIDR (e.g. 1.2.3.4/24). Esta opción se puede especificar varias veces</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Ligar a las direcciones especificadas y poner en lista blanca a los equipos conectados a ellas. Usar la notación para IPv6 [host]:puerto.</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Crear nuevos archivos con permisos por defecto del sistema, en lugar de umask 077 (sólo efectivo con la funcionalidad de monedero desactivada)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Descubra direcciones IP propias (por defecto: 1 cuando se escucha y nadie -externalip o -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: la escucha para conexiones entrantes falló (la escucha regresó el error %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Ejecutar un comando cuando se reciba una alerta importante o cuando veamos un fork demasiado largo (%s en cmd se reemplazará por el mensaje)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Las comisiones (en %s/kB) mas pequeñas que esto se consideran como cero comisión para la retransmisión, minería y creación de la transacción (predeterminado: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Si el pago de comisión no está establecido, incluir la cuota suficiente para que las transacciones comiencen la confirmación en una media de n bloques ( por defecto :%u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Cantidad no válida para -maxtxfee=&lt;amount&gt;: '%s' (debe ser por lo menos la comisión mínima de %s para prevenir transacciones atascadas)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>El tamaño máximo de los datos en las operaciones de transporte de datos que transmitimos y el mio (default: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Aleatorizar las credenciales para cada conexión proxy. Esto habilita la Tor stream isolation (por defecto: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Monto de transacción muy pequeña luego de la deducción por comisión</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>A los equipos en lista blanca no se les pueden prohibir los ataques DoS y sus transacciones siempre son retransmitidas, incluso si ya están en el mempool, es útil por ejemplo para un gateway.</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Necesitas reconstruir la base de datos utilizando -reindex para volver al modo sin recorte. Esto volverá a descargar toda la cadena de bloques</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(por defecto: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Aceptar solicitudes públicas en FERIADOS (por defecto: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Automáticamente crea el servicio Tor oculto (por defecto: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Conectar usando SOCKS5 proxy</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Error cargando %s: No puedes deshabilitar HD en un monedero HD ya existente</translation>
</message>
@@ -3681,10 +3455,6 @@
<translation>Error actualizando la base de datos chainstate</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importa los bloques desde un archivo externo blk000?.dat</translation>
- </message>
- <message>
<source>Information</source>
<translation>Información</translation>
</message>
@@ -3705,42 +3475,14 @@
<translation>Máscara de red inválida especificada en -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Mantener como máximo &lt;n&gt; transacciones no conectables en memoria (por defecto: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Necesita especificar un puerto con -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opciones de nodos de retransmisión:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opciones de servidor RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduciendo -maxconnections de %d a %d, debido a limitaciones del sistema.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Rescanea la cadena de bloques para buscar transacciones perdidas del monedero</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Enviar información de trazas/depuración a la consola en lugar de al archivo debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Muestra todas las opciones de depuración (uso: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Reducir el archivo debug.log al iniciar el cliente (predeterminado: 1 sin -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Transacción falló</translation>
</message>
@@ -3765,20 +3507,12 @@
<translation>Este software es experimental.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Contraseña del puerto de control de Tor (predeterminado: vacio)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Puerto de control de Tor a utilizar si la escucha de onion esta activada (predeterminado: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Cantidad de la transacción demasiado pequeña</translation>
</message>
<message>
<source>Transaction too large for fee policy</source>
- <translation>Operación demasiado grande para la política de tasas</translation>
+ <translation>Transacción demasiado grande para la política de comisiones</translation>
</message>
<message>
<source>Transaction too large</source>
@@ -3793,15 +3527,6 @@
<translation>No es posible generar llaves iniciales</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Actualizar el monedero al último formato al inicio</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nombre de usuario para las conexiones JSON-RPC
-</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>Verificando monedero(s)...</translation>
</message>
@@ -3818,115 +3543,20 @@
<translation>Advertencia: nuevas reglas desconocidas activadas (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Si se debe o no operar en un modo de solo bloques (predeterminado: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Necesita reconstruir las bases de datos con la opción -reindex para modificar -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Eliminando todas las transacciones del monedero...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Opciones de notificación ZeroQM:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Contraseña para las conexiones JSON-RPC
-</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Ejecutar un comando cuando cambia el mejor bloque (%s en cmd se sustituye por el hash de bloque)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permitir búsquedas DNS para -addnode, -seednode y -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = mantener los meta datos de transacción, por ejemplo: propietario e información de pago, 2 = omitir los metadatos)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee tiene un ajuste muy elevado! Comisiones muy grandes podrían ser pagadas en una única transaccion.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Vincular a la dirección dada para escuchar las conexiones JSON-RPC. Esta opción se ignora a menos que también se pase -rpcallowip. El puerto es opcional y reemplaza -rpcport. Utiliza la notación [host]:puerto para IPv6. Esta opción se puede especificar varias veces (por defecto: 127.0.0.1 y :: 1 es decir, localhost o si se ha especificado -rpcallowip, 0.0.0.0 y :: es decir, todas las direcciones)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>No mantener transacciones en la memoria mas de &lt;n&gt; horas (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Bytes equivalentes por sigop en transacciones para retrasmisión y minado (predeterminado: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Error cargando %s: No puedes habilitar HD en un monedero no HD ya existente</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Error cargando monedero %s. El parámetro -wallet solo debe indicar un nombre de fichero (no una ruta).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Las comisiones (en %s/kB) menores que esto son consideradas de cero comision para la creacion de transacciones (predeterminado: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Fuerza la retransmisión de transacciones desde nodos en la lista blanca incluso si violan la política de retransmisiones local (predeterminado: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Nivel de rigor en la verificación de bloques de -checkblocks (0-4; predeterminado: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Mantener el índice completo de transacciones, usado por la llamada rpc de getrawtransaction (por defecto: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Número de segundos en que se evita la reconexión de pares con mal comportamiento (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Mostrar depuración (por defecto: %u, proporcionar &lt;category&gt; es opcional)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight</source>
- <translation>Configurar máximo peso de bloque BIP141 a este * 4.
-Descontinuado, use blockmaxweight</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>https://www.transifex.com/joyful-world/breaking-english/
-Establecer la serialización de las transacciones sin procesar o el bloque hex devuelto en non-verbose mode, non-segwit(O) o segwit(1) (default: %d)</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>Indique directorio para guardar monederos (por defecto: &lt;datadir&gt;/monederos si existe, sino &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>Indique ubicación del archivo de registro de depuración: este puede estar en un camino absoluto o un camino relativo del directorio de datos (por defecto: %s)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Admite filtrado de bloques, y transacciones con filtros Bloom. Reduce la carga de red. ( por defecto :%u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>La comisión (en %s/kB) que indica tu tolerancia para descartar el cambio y añadirlo a la comisión (por defecto: %s). Nota: Una salida se descarta si es polvo a esa tasa, pero solo se desechará hasta la comisión de reenvío de polvo y una comisión de descarte por encima de eso está limitada por la estimación de la comisión para el objetivo más largo</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>Esta es la tarifa de cuota que debe pagar cuando las estimaciones de tarifas no estén disponibles.</translation>
+ <translation>Esta es la comisión de transacción que debe pagar cuando las estimaciones de comisión no estén disponibles.</translation>
</message>
<message>
<source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
@@ -3937,10 +3567,6 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d
<translation>La longitud total de la cadena de versión de red ( %i ) supera la longitud máxima ( %i ) . Reducir el número o tamaño de uacomments .</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Intenta de mantener el Tráfico de salida , bajo el Objetivo Determinado (en MiB por 24h) , 0 = sin limite (Por Defecto :%d )</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Error: argumento -socks encontrado. El ajuste de la versión SOCKS ya no es posible, sólo proxies SOCKS5 son compatibles.</translation>
</message>
@@ -3949,10 +3575,6 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d
<translation>El argumento no soportado -whitelistalwaysrelay ha sido ignorado, utiliza -whitelistrelay y/o -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Usar distintos proxys SOCKS5 para comunicarse vía Tor de forma anónima (Por defecto: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Advertencia: Se están minando versiones de bloques desconocidas! Es posible que normas desconocidas estén activas</translation>
</message>
@@ -3961,110 +3583,18 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d
<translation>Aviso: fichero de monedero corrupto, datos recuperados! Original %s guardado como %s en %s; si su balance de transacciones es incorrecto, debe restaurar desde una copia de seguridad.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Los pares de listas blancas que se conectan desde la dirección IP dada (por ejemplo, 1.2.3.4) o la red marcada CIDR (por ejemplo, 1.2.3.0/24). Se puede especificar varias veces.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>¡%s se establece muy alto!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(predeterminado: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Siempre consultar direcciones de otros equipos por medio de DNS lookup (por defecto: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Error cargando el monedero %s. El nombre de fichero -wallet debe ser un fichero normal.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Error cargando el monedero %s. Se ha especificado un nombre de fichero -wallet duplicado.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Error cargando el monedero %s. Caracteres inválidos en el nombre de fichero -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Cuántos bloques comprobar al iniciar (predeterminado: %u, 0 = todos)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Incluir direcciones IP en la salida de depuración (por defecto: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Keypool se ha agotado, llame a keypoolrefill primero</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escuchar conexiones JSON-RPC en &lt;puerto&gt; (predeterminado: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escuchar conexiones en &lt;puerto&gt; (predeterminado: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Mantener como máximo &lt;n&gt; conexiones a pares (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Realiza las operaciones de difusión del monedero</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Búfer de recepción máximo por conexión, &lt;n&gt;*1000 bytes (por defecto: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Búfer de recepción máximo por conexión, , &lt;n&gt;*1000 bytes (por defecto: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Anteponer marca temporal a la información de depuración (por defecto: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Retransmitir y minar transacciones de transporte de datos (por defecto: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Relay non-P2SH multisig (default: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Ajustar el número de claves en reserva &lt;n&gt; (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Establecer peso máximo bloque BIP141 (predeterminado: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Establecer el número de procesos para llamadas del servicio RPC (por defecto: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Especificar archivo de configuración (por defecto: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Especificar tiempo de espera de la conexión (mínimo: 1, por defecto: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Especificar archivo pid (predeterminado: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Usar cambio aún no confirmado al enviar transacciones (predeterminado: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Iniciando funciones de red...</translation>
</message>
@@ -4074,15 +3604,11 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d
</message>
<message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Esta es la tarifa mínima de transacción que usted paga en cada transacción.</translation>
+ <translation>Esta es la comisión mínima de transacción que usted paga en cada transacción.</translation>
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Esta es la cuota de transacción que pagará si envía una transacción.</translation>
- </message>
- <message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Umbral para la desconexión de pares con mal comportamiento (predeterminado: %u)</translation>
+ <translation>Esta es la comisión de transacción que pagará si envía una transacción.</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
@@ -4105,6 +3631,26 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d
<translation>Fondos insuficientes</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>No se puede generar una clave de cambio de dirección. Las claves privadas están deshabilitadas para este monedero.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>No se puede actualizar un monedero dividido sin HD sin actualizar para admitir el keypool pre dividido. Utilice -upgradewallet = 169900 o -upgradewallet sin una versión especificada.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Estimación de la comisión fallida. Fallbackfee está deshabilitado. Espere unos pocos bloques o habilite -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Advertencia: claves privadas detectadas en el monedero {%s} con claves privadas deshabilitadas</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>No se puede escribir en el directorio de datos '%s'; verificar permisos.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Cargando el índice de bloques...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts
index 48acd165d5..f8b13e398f 100644
--- a/src/qt/locale/bitcoin_es_CL.ts
+++ b/src/qt/locale/bitcoin_es_CL.ts
@@ -30,6 +30,10 @@
<translation>Eliminar la dirección seleccionada de la lista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduce una dirección o etiqueta para buscar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar los datos de la pestaña actual a un archivo</translation>
</message>
@@ -41,13 +45,85 @@
<source>&amp;Delete</source>
<translation>&amp;Borrar</translation>
</message>
- </context>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Selecciones la dirección para enviar monedas a</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Selecciona la dirección para recibir monedas con</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>Seleccione</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Enviando direcciones</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Recibiendo direcciones</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Estas son tus direcciones de Bitcoin para recibir pagos. Siempre revise el monto y la dirección de envío antes de enviar criptomonedas.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Estas son tus direcciones para recibir pagos. Es recomendable utilizar una nueva dirección para cada transacción.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>Copiar dirección</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>Editar</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Exportar lista de direcciones</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Archivos separados por coma (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Exportación fallida</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Había un error intentando guardar la lista de direcciones en %1. Por favor inténtelo de nuevo.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
- </context>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Dirección</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(sin etiqueta)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
+ <source>Passphrase Dialog</source>
+ <translation>Dialogo de contraseña</translation>
+ </message>
+ <message>
<source>Enter passphrase</source>
<translation>Introduce contraseña actual </translation>
</message>
@@ -59,10 +135,110 @@
<source>Repeat new passphrase</source>
<translation>Repite nueva contraseña</translation>
</message>
- </context>
+ <message>
+ <source>Show password</source>
+ <translation>Mostrar contraseña</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Introduce la nueva contraseña para la billetera.&lt;br/&gt;Por favor utiliza una contraseña de&lt;b&gt;10 o más caracteres aleatorios&lt;/b&gt;, u &lt;b&gt;ocho o más palabras&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Codificar billetera</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Esta operación necesita la contraseña para desbloquear la billetera.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Desbloquea billetera</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Esta operación necesita la contraseña para decodificar la billetara.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Decodificar cartera</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Cambia contraseña</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Introduzca la contraseña antigua y la nueva para la billetera.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Confirmar cifrado del monedero</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Advertencia: Si encriptas tu billetera y pierdes tu contraseña, vas a perder&lt;b&gt;TODOS TUS BITCOINS&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>¿Seguro que quieres seguir codificando la billetera?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Billetera codificada</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 se cerrará para finalizar el proceso de encriptación. Recuerda que encriptar tu billetera no protege completamente a tus bitcoins de ser robados por virus y malwares en tu computadora.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>IMPORTANTE: Cualquier respaldo anterior que hayas hecho del archivo de tu billetera debe ser reemplazado por el nuevo archivo encriptado que has generado. Por razones de seguridad, todos los respaldos realizados anteriormente serán inutilizables al momento de que utilices tu nueva billetera encriptada.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Falló la codificación de la billetera</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>El proceso de encriptación de la billetera fallo por culpa de un problema interno. Tu billetera no fue encriptada.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>La contraseña introducida no coincide.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Ha fallado el desbloqueo de la billetera</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>La contraseña introducida para el cifrado del monedero es incorrecta.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Ha fallado la decodificación de la billetera</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>La contraseña del monedero ha sido cambiada con éxito.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Precaucion: Mayúsculas Activadas</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
- </context>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Máscara</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Suspendido hasta</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
@@ -78,6 +254,10 @@
<translation>&amp;Vista general</translation>
</message>
<message>
+ <source>Node</source>
+ <translation>Nodo</translation>
+ </message>
+ <message>
<source>Show general overview of wallet</source>
<translation>Muestra una vista general de la billetera</translation>
</message>
@@ -102,6 +282,10 @@
<translation>S&amp;obre %1</translation>
</message>
<message>
+ <source>Show information about %1</source>
+ <translation>Mostrar Información sobre %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>Acerca de</translation>
</message>
@@ -114,6 +298,10 @@
<translation>&amp;Opciones</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Modificar las opciones de configuración para %1</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Codificar la billetera...</translation>
</message>
@@ -138,6 +326,22 @@
<translation>Abrir y url...</translation>
</message>
<message>
+ <source>Click to disable network activity.</source>
+ <translation>Click para deshabilitar la actividad de red.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Actividad de red deshabilitada</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Click para volver a habilitar la actividad de red.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Sincronizando cabeceras (%1%)...</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>Cargando el index de bloques...</translation>
</message>
@@ -186,10 +390,22 @@
<translation>&amp;Mostrar/Ocultar</translation>
</message>
<message>
+ <source>Show or hide the main Window</source>
+ <translation>Mostrar u ocultar la ventana principal</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Cifrar las claves privadas de su monedero</translation>
+ </message>
+ <message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
<translation>Firmar un mensaje para provar que usted es dueño de esta dirección</translation>
</message>
<message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Verificar mensajes comprobando que están firmados con direcciones Bitcoin concretas</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Archivo</translation>
</message>
@@ -210,6 +426,50 @@
<translation>Pide pagos (genera codigos QR and bitcoin: URls)</translation>
</message>
<message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Mostrar la lista de direcciones de envío y etiquetas</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Mostrar la lista de direcciones de recepción y etiquetas</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI or payment request</source>
+ <translation>Abrir un identificador URI bitcoin o una petición de pago</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>&amp;Opciones de linea de comando</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n conexión activa hacia la red Bitcoin</numerusform><numerusform>%n conexiones activas hacia la red Bitcoin</numerusform></translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Indexando bloques en disco...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Procesando bloques en disco...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>%n bloque procesado del historial de transacciones.</numerusform><numerusform>%n bloques procesados del historial de transacciones.</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 atrás</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>El último bloque recibido fue generado hace %1</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Las transacciones posteriores aún no están visibles.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Error</translation>
</message>
@@ -226,10 +486,52 @@
<translation>Actualizado</translation>
</message>
<message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Mostrar el mensaje de ayuda %1 para obtener una lista de los posibles comandos de Bitcoin</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 cliente</translation>
+ </message>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Conectando a pares...</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Recuperando...</translation>
</message>
<message>
+ <source>Date: %1
+</source>
+ <translation>Fecha: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Cantidad: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Tipo: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Etiqueta %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Dirección %1
+</translation>
+ </message>
+ <message>
<source>Sent transaction</source>
<translation>Transacción enviada</translation>
</message>
@@ -238,6 +540,14 @@
<translation>Transacción entrante</translation>
</message>
<message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>La generación de clave HD está &lt;b&gt;habilitada&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>La generación de clave HD está &lt;b&gt;deshabilitada&lt;/b&gt;</translation>
+ </message>
+ <message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>La billetera esta &lt;b&gt;codificada&lt;/b&gt; y actualmente &lt;b&gt;desbloqueda&lt;/b&gt;</translation>
</message>
@@ -245,10 +555,26 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>La billetera esta &lt;b&gt;codificada&lt;/b&gt; y actualmente &lt;b&gt;bloqueda&lt;/b&gt;</translation>
</message>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Ha ocurrido un error fatal. Bitcoin no puede seguir seguro y se cerrará.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation>Selección de moneda</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Cantidad:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bytes:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>Cantidad:</translation>
</message>
@@ -258,10 +584,42 @@
</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>Polvo:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Después de aplicar la comisión:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Cambio:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>(des)marcar todos</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Modo árbol</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Modo lista</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Cantidad</translation>
</message>
<message>
+ <source>Received with label</source>
+ <translation>Recibido con etiqueta</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Recibido con dirección</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Fecha</translation>
</message>
@@ -273,7 +631,87 @@
<source>Confirmed</source>
<translation>Confirmado</translation>
</message>
- </context>
+ <message>
+ <source>Copy address</source>
+ <translation>Copiar dirección</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar Cantidad</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copiar ID de transacción</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Bloquear lo no gastado</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Desbloquear lo no gastado</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Copiar comisión</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Copiar después de la comisión</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Copiar bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Copiar polvo</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Copiar cambio</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 bloqueado)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>si</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>no</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Está etiqueta se vuelve roja si algún receptor recibe una cantidad inferior al límite actual establecido para el polvo.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Puede variar +/- %1 satoshi(s) por entrada.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(sin etiqueta)</translation>
+ </message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>cambia desde %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(cambio)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -285,17 +723,65 @@
<translation>&amp;Etiqueta</translation>
</message>
<message>
+ <source>The label associated with this address list entry</source>
+ <translation>La etiqueta asociada con esta entrada de la lista de direcciones</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>La dirección asociada con esta entrada en la libreta de direcciones. Solo puede ser modificada para direcciones de envío.</translation>
+ </message>
+ <message>
<source>&amp;Address</source>
<translation>&amp;Dirección</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Nueva dirección para enviar</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Editar dirección de recepción</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Editar dirección de envio</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>La dirección introducida "%1" no es una dirección Bitcoin valida.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se pudo desbloquear la billetera.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>La generación de nueva clave falló.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
+ <source>A new data directory will be created.</source>
+ <translation>Un nuevo directorio de datos será creado.</translation>
+ </message>
+ <message>
<source>name</source>
<translation>Nombre</translation>
</message>
- </context>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>El directorio ya existe. Agrega %1 si deseas crear un nuevo directorio aquí.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>Ruta de acceso existente, pero no es un directorio.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>Es imposible crear la carpeta de datos aquí.</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
<message>
@@ -303,14 +789,18 @@
<translation>versión</translation>
</message>
<message>
- <source>Command-line options</source>
- <translation>opciones de linea de comando</translation>
+ <source>(%1-bit)</source>
+ <translation>(%1-bit)</translation>
</message>
<message>
- <source>Usage:</source>
- <translation>Uso:</translation>
+ <source>About %1</source>
+ <translation>Sobre %1</translation>
</message>
- </context>
+ <message>
+ <source>Command-line options</source>
+ <translation>opciones de linea de comando</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
<message>
@@ -318,28 +808,140 @@
<translation>bienvenido</translation>
</message>
<message>
+ <source>Welcome to %1.</source>
+ <translation>Bienvenido a %1.</translation>
+ </message>
+ <message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation>Al ser la primera vez que se ejecuta el programa, puede elegir donde %1 almacenará sus datos.</translation>
+ </message>
+ <message>
+ <source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
+ <translation>El primer proceso de sincronización consume muchos recursos, y es posible que puedan ocurrir problemas de hardware que anteriormente no hayas notado. Cada vez que ejecutes %1 automáticamente se reiniciará el proceso de sincronización desde el punto que lo dejaste anteriormente.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>Si elegiste la opción de limitar el tamaño del blockchain (pruning), de igual manera será descargada y procesada la información histórica, pero será eliminada al finalizar este proceso para disminuir el uso del disco duro.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>Usar el directorio de datos predeterminado</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>usar un directorio de datos personalizado:</translation>
+ </message>
+ <message>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>Al menos %1 GB de información será almacenado en este directorio, y seguirá creciendo a través del tiempo.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>Aproximadamente %1 GB de información será almacenado en este directorio.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>%1 descargará y almacenará una copia del blockchain de Bitcoin.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>El monedero también será almacenado en este directorio.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>Error: El directorio de datos especificado "%1" no pudo ser creado.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Error</translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>%n GB de espacio libre disponible</numerusform><numerusform>%n GB de espacio libre disponible</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(de %n GB requerido)</numerusform><numerusform>(de %n GB requeridos)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
<source>Form</source>
<translation>Formulario</translation>
</message>
- </context>
+ <message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation>Las transacciones recientes aún no pueden ser visibles, y por lo tanto el saldo de su monedero podría ser incorrecto. Esta información será correcta cuando su monedero haya terminado de sincronizarse con la red de bitcoin, como se detalla abajo.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation>La red no aceptará el intentar gastar bitcoins que están afectados por transacciones aún no mostradas.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Número de bloques restantes</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Desconocido...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Hora del último bloque</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>Progreso</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>Avance del progreso por hora</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>calculando...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Tiempo estimado restante hasta la sincronización</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Ocultar</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1)...</source>
+ <translation>Desconocido. Sincronizando cabeceras (%1)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
+ <source>Open URI</source>
+ <translation>Abrir URI</translation>
+ </message>
+ <message>
+ <source>Open payment request from URI or file</source>
+ <translation>Abrir solicitud de pago desde URI o un archivo</translation>
+ </message>
+ <message>
<source>URI:</source>
<translation>url:</translation>
</message>
- </context>
+ <message>
+ <source>Select payment request file</source>
+ <translation>Seleccionar archivo de solicitud de pago</translation>
+ </message>
+ <message>
+ <source>Select payment request file to open</source>
+ <translation>Seleccionar archivo de solicitud de pago para abrir</translation>
+ </message>
+</context>
<context>
<name>OptionsDialog</name>
<message>
@@ -351,10 +953,62 @@
<translation>&amp;Principal</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Iniciar automáticamente %1 al inicial el sistema.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Iniciar %1 al iniciar el sistema</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Tamaño del caché de la base de &amp;datos</translation>
+ </message>
+ <message>
+ <source>MB</source>
+ <translation>MB</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>Número de hilos de &amp;verificación de scripts</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>Dirección IP del proxy (Ejemplo. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ </message>
+ <message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation>Muestra si el proxy SOCKS5 por defecto se utiliza para conectarse a pares a través de este tipo de red.</translation>
+ </message>
+ <message>
+ <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
+ <translation>Minimizar en vez de salir de la aplicación cuando la ventana está cerrada. Cuando se activa esta opción, la aplicación sólo se cerrará después de seleccionar Salir en el menú.</translation>
+ </message>
+ <message>
+ <source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
+ <translation>URLs de terceros (por ejemplo, un explorador de bloques) que aparecen en la pestaña de transacciones como elementos del menú contextual. El %s en la URL es reemplazado por el valor hash de la transacción. Se pueden separar múltiples URLs por una barra vertical |.</translation>
+ </message>
+ <message>
+ <source>Active command-line options that override above options:</source>
+ <translation>Opciones activas de la terminal que tienen preferencia sobre las opciones anteriores:</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Abrir el archivo de configuración %1 en el directorio de trabajo.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Abrir archivo de configuración</translation>
+ </message>
+ <message>
<source>Reset all client options to default.</source>
<translation>Reestablece todas las opciones.</translation>
</message>
<message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;Restablecer opciones</translation>
+ </message>
+ <message>
<source>&amp;Network</source>
<translation>&amp;Red</translation>
</message>
@@ -367,6 +1021,14 @@
<translation>experto</translation>
</message>
<message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Habilitar opciones de &amp;control de monedero</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation>Gastar cambio sin confirmar</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation>Abre automáticamente el puerto del cliente Bitcoin en el router. Esto funciona solo cuando tu router es compatible con UPnP y está habilitado.</translation>
</message>
@@ -375,6 +1037,14 @@
<translation>Direcciona el puerto usando &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Aceptar conexiones externas.</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>Conectar a la red de Bitcoin a través de un proxy SOCKS5</translation>
+ </message>
+ <message>
<source>Proxy &amp;IP:</source>
<translation>&amp;IP Proxy:</translation>
</message>
@@ -387,6 +1057,26 @@
<translation>Puerto del servidor proxy (ej. 9050)</translation>
</message>
<message>
+ <source>Used for reaching peers via:</source>
+ <translation>Usado para alcanzar compañeros vía:</translation>
+ </message>
+ <message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Tor</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>Conectar a la red de Bitcoin a través de un proxy SOCKS5 diferente para los servicios anónimos de Tor.</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>y windows
</translation>
@@ -408,6 +1098,10 @@
<translation>&amp;Mostrado</translation>
</message>
<message>
+ <source>User Interface &amp;language:</source>
+ <translation>&amp;Lenguaje de la interfaz:</translation>
+ </message>
+ <message>
<source>&amp;Unit to show amounts in:</source>
<translation>&amp;Unidad en la que mostrar cantitades:</translation>
</message>
@@ -416,6 +1110,10 @@
<translation>Elige la subdivisión por defecto para mostrar cantidaded en la interfaz cuando se envien monedas</translation>
</message>
<message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>Mostrar o no funcionalidad de Coin Control</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -428,14 +1126,46 @@
<translation>predeterminado</translation>
</message>
<message>
+ <source>none</source>
+ <translation>Nada</translation>
+ </message>
+ <message>
<source>Confirm options reset</source>
<translation>Confirmar reestablecimiento de las opciones</translation>
</message>
<message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Es necesario reiniciar el cliente para activar los cambios.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>El cliente se cerrará. Desea proceder?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Opciones de configuración</translation>
+ </message>
+ <message>
+ <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
+ <translation>El archivo de configuración es utilizado para especificar opciones avanzadas del usuario, que invalidan los ajustes predeterminados. Adicionalmente, cualquier opción ingresada por la línea de comandos invalidará este archivo de configuración.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Error</translation>
</message>
- </context>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation>El archivo de configuración no pudo ser abierto.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Estos cambios requieren el reinicio del cliente.</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>El proxy ingresado es inválido. </translation>
+ </message>
+</context>
<context>
<name>OverviewPage</name>
<message>
@@ -443,16 +1173,156 @@
<translation>Formulario</translation>
</message>
<message>
+ <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
+ <translation>La información entregada puede estar desactualizada. Tu billetera se sincroniza automáticamente con la red de Bitcoin después de establecer una conexión, pero este proceso aún no se ha completado.</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>Solo observación:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Disponible:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>Tu saldo disponible para gastar</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>Pendiente:</translation>
+ </message>
+ <message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation>Total de transacciones que aún no se han sido confirmadas, y que no son contabilizadas dentro del saldo disponible para gastar</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation>Inmaduro:</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>Saldo minado que no ha madurado</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>Saldos</translation>
+ </message>
+ <message>
<source>Total:</source>
<translation>Total:</translation>
</message>
+ <message>
+ <source>Your current total balance</source>
+ <translation>Saldo total actual</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Utilizable:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Transacciones recientes</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
- </context>
+ <message>
+ <source>Payment request error</source>
+ <translation>Error en la solicitud de pago</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>Manejo de URI</translation>
+ </message>
+ <message>
+ <source>Payment request fetch URL is invalid: %1</source>
+ <translation>Lectura de URL para la solicitud de pagos es invalida: %1</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Dirección de pago inválida %1</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>Manejo del archivo de solicitud de pago</translation>
+ </message>
+ <message>
+ <source>Payment request rejected</source>
+ <translation>Solicitud de pago rechazada</translation>
+ </message>
+ <message>
+ <source>Payment request network doesn't match client network.</source>
+ <translation>Red de solicitud de pagos no coincide con la red del cliente.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Solicitud de pago expirada</translation>
+ </message>
+ <message>
+ <source>Payment request is not initialized.</source>
+ <translation>La solicitud de pago no se ha iniciado.</translation>
+ </message>
+ <message>
+ <source>Invalid payment request.</source>
+ <translation>Solicitud de pago invalida.</translation>
+ </message>
+ <message>
+ <source>Requested payment amount of %1 is too small (considered dust).</source>
+ <translation>El monto para la solicitud de pago de %1 es muy pequeño (considera el dust).</translation>
+ </message>
+ <message>
+ <source>Refund from %1</source>
+ <translation>Reembolsar desde %1</translation>
+ </message>
+ <message>
+ <source>Error communicating with %1: %2</source>
+ <translation>Fallo al comunicar con %1: %2</translation>
+ </message>
+ <message>
+ <source>Payment request cannot be parsed!</source>
+ <translation>La solicitud de pago no puede ser analizada!</translation>
+ </message>
+ <message>
+ <source>Bad response from server %1</source>
+ <translation>Mala respuesta desde el servidor %1</translation>
+ </message>
+ <message>
+ <source>Network request error</source>
+ <translation>Error en petición de la red</translation>
+ </message>
+ <message>
+ <source>Payment acknowledged</source>
+ <translation>Pago declarado</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
- </context>
+ <message>
+ <source>User Agent</source>
+ <translation>User Agent</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>Nodo/Servicio</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>ID del nodo</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>Ping</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Enviado</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Recibido</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
@@ -460,24 +1330,96 @@
<translation>Cantidad</translation>
</message>
<message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Ingresa una dirección de Bitcoin (Ejemplo: %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 d</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 h</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 m</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 s</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>Nada</translation>
+ </message>
+ <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
<message>
+ <source>%1 ms</source>
+ <translation>%1 ms</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation><numerusform>%n segundo</numerusform><numerusform>%n segundos</numerusform></translation>
+ </message>
+ <message>
<source>%1 and %2</source>
<translation>%1 y %2</translation>
</message>
<message>
+ <source>%1 B</source>
+ <translation>%1 B</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 MB</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 GB</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation>%1 aun no se ha cerrado de forma segura...</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>desconocido</translation>
</message>
</context>
<context>
<name>QObject::QObject</name>
- </context>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>Error: El directorio de datos "%1" especificado no existe.</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>Error: %1</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
- </context>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>Guardar imagen...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Copiar imagen</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Guardar código QR</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>Imagen PNG (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -501,6 +1443,14 @@
<translation>General</translation>
</message>
<message>
+ <source>Using BerkeleyDB version</source>
+ <translation>Utilizando la versión de BerkeleyDB</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>Datadir</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>Tiempo de inicio</translation>
</message>
@@ -521,11 +1471,123 @@
<translation>Bloquea cadena</translation>
</message>
<message>
+ <source>Current number of blocks</source>
+ <translation>Cantidad de bloques actual</translation>
+ </message>
+ <message>
+ <source>Memory Pool</source>
+ <translation>Memory Pool</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>Numero total de transacciones</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>Memoria utilizada</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Reestablecer</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Recibido</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Enviado</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation>&amp;Peers</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation>Peers baneados</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>Selecciona un peer para ver la información detallada.</translation>
+ </message>
+ <message>
+ <source>Whitelisted</source>
+ <translation>En la lista blanca</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Dirección</translation>
+ </message>
+ <message>
<source>Version</source>
<translation>version
</translation>
</message>
<message>
+ <source>Starting Block</source>
+ <translation>Bloque de inicio</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation>Cabeceras sincronizadas</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>Bloques sincronizados</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>User Agent</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>Disminuir tamaño de fuente</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>Aumentar tamaño de fuente</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>Servicios</translation>
+ </message>
+ <message>
+ <source>Ban Score</source>
+ <translation>Puntuación de bloqueo</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>Duración de la conexión</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation>Ultimo envío</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>Ultima recepción</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>Tiempo de Ping</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>Espera de Ping</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>Ping minimo</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation>Desplazamiento de tiempo</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Hora del último bloque</translation>
+ </message>
+ <message>
<source>&amp;Open</source>
<translation>&amp;Abrir</translation>
</message>
@@ -534,14 +1596,106 @@
<translation>&amp;Consola</translation>
</message>
<message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;Tráfico de Red</translation>
+ </message>
+ <message>
<source>Totals</source>
<translation>Total:</translation>
</message>
<message>
+ <source>In:</source>
+ <translation>Entrada:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Salida:</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation>Archivo del registro de depuración</translation>
+ </message>
+ <message>
<source>Clear console</source>
<translation>Limpiar Consola</translation>
</message>
- </context>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;hora</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;día</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 semana</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 año</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Desconectar</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>Prohibir para</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;Desbloquear</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Bienvenido a la consola RPC %1.</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>Usa las flechas (arriba y abajo) para navegar por el historial, y %1 para limpiar la consola.</translation>
+ </message>
+ <message>
+ <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
+ <translation>ADVERTENCIA: No uses esta consola sin comprender las consecuencias de la ejecución de cada comando.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Actividad de red desactivada</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(identificador del nodo: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>via %1</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>nunca</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>Entrante</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>Saliente</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation>Si</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation>No</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>Desconocido</translation>
+ </message>
+</context>
<context>
<name>ReceiveCoinsDialog</name>
<message>
@@ -556,7 +1710,63 @@
<source>&amp;Message:</source>
<translation>&amp;mensaje</translation>
</message>
- </context>
+ <message>
+ <source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
+ <translation>Mensaje opcional adjunto a la solicitud de pago, que será mostrado cuando la solicitud sea abierta. Nota: Este mensaje no será enviado con el pago a través de la red Bitcoin.</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>Usa este formulario para solicitar un pago. Todos los campos son &lt;b&gt;opcionales&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation>Monto opcional a solicitar. Deja este campo vacío o en cero si no quieres definir un monto específico.</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Limpiar todos los campos del formulario.</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>Limpiar</translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation>Historial de pagos solicitados</translation>
+ </message>
+ <message>
+ <source>&amp;Request payment</source>
+ <translation>Solicitud de pago</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>Mostrar</translation>
+ </message>
+ <message>
+ <source>Remove the selected entries from the list</source>
+ <translation>Borrar de la lista las direcciones seleccionadas</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Eliminar</translation>
+ </message>
+ <message>
+ <source>Copy URI</source>
+ <translation>Copiar URI</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Copiar mensaje</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar Cantidad</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -564,6 +1774,10 @@
<translation>Código QR </translation>
</message>
<message>
+ <source>Copy &amp;URI</source>
+ <translation>Copiar &amp;URI</translation>
+ </message>
+ <message>
<source>Copy &amp;Address</source>
<translation>&amp;Copia dirección</translation>
</message>
@@ -571,10 +1785,74 @@
<source>&amp;Save Image...</source>
<translation>Guardar imagen...</translation>
</message>
- </context>
+ <message>
+ <source>Request payment to %1</source>
+ <translation>Solicitar pago a %1</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>Información del pago</translation>
+ </message>
+ <message>
+ <source>URI</source>
+ <translation>URI</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Dirección</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Cantidad</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Cartera</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Fallo al codificar URI en código QR.</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
- </context>
+ <message>
+ <source>Date</source>
+ <translation>Fecha</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(sin etiqueta)</translation>
+ </message>
+ <message>
+ <source>(no message)</source>
+ <translation>(sin mensaje)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(no existe monto solicitado)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Solicitado</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -582,10 +1860,30 @@
<translation>Enviar monedas</translation>
</message>
<message>
+ <source>Coin Control Features</source>
+ <translation>Características de Coin Control</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>Entradas...</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>Seleccionado automaticamente</translation>
+ </message>
+ <message>
<source>Insufficient funds!</source>
<translation>Fondos insuficientes</translation>
</message>
<message>
+ <source>Quantity:</source>
+ <translation>Cantidad:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bytes:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>Cantidad:</translation>
</message>
@@ -595,10 +1893,54 @@
</translation>
</message>
<message>
+ <source>After Fee:</source>
+ <translation>Después de aplicar la comisión:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Cambio:</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation>Dirección de cambio personalizada</translation>
+ </message>
+ <message>
<source>Transaction Fee:</source>
<translation>Comisión transacción:</translation>
</message>
<message>
+ <source>Choose...</source>
+ <translation>Seleccione</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Advertencia: En este momento no se puede estimar la cuota.</translation>
+ </message>
+ <message>
+ <source>collapse fee-settings</source>
+ <translation>Colapsar ajustes de comisión.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>por kilobyte</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Ocultar</translation>
+ </message>
+ <message>
+ <source>(read the tooltip)</source>
+ <translation>(leer la sugerencia)</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>Recomendado:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>Personalizado:</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>Enviar a múltiples destinatarios</translation>
</message>
@@ -607,6 +1949,18 @@
<translation>&amp;Agrega destinatario</translation>
</message>
<message>
+ <source>Clear all fields of the form.</source>
+ <translation>Limpiar todos los campos del formulario.</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Polvo:</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>Objetivo de tiempo de confirmación</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>&amp;Borra todos</translation>
</message>
@@ -622,7 +1976,115 @@
<source>S&amp;end</source>
<translation>&amp;Envía</translation>
</message>
- </context>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar Cantidad</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Copiar comisión</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Copiar después de la comisión</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Copiar bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Copiar polvo</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Copiar cambio</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 bloques)</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 a %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>¿Seguro que quiere enviar?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Comisión de transacción</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Confirmar el envió de monedas</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>La dirección de envío no es válida. Por favor revisala.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>La cantidad por pagar tiene que ser mayor que 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>El monto sobrepasa tu saldo.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>El total sobrepasa tu saldo cuando se incluyen %1 como comisión de envió.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>¡Fallo al crear la transacción!</translation>
+ </message>
+ <message>
+ <source>The transaction was rejected with the following reason: %1</source>
+ <translation>Se ha rechazado la transacción por la siguiente razón: %1</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>Una comisión mayor que %1 se considera como una comisión absurda-mente alta.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Solicitud de pago expirada</translation>
+ </message>
+ <message>
+ <source>Pay only the required fee of %1</source>
+ <translation>Pagar únicamente la comisión requerida de %1</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Peligro: Dirección de Bitcoin inválida</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Peligro: Dirección de cambio desconocida</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>Confirma dirección de cambio personalizada</translation>
+ </message>
+ <message>
+ <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
+ <translation>La dirección de cambio que ingresaste no es parte de tu monedero. Parte de tus fondos serán enviados a esta dirección. ¿Estás seguro?</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(sin etiqueta)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
<message>
@@ -638,6 +2100,18 @@
<translation>&amp;Etiqueta:</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation>Seleccionar dirección usada anteriormente</translation>
+ </message>
+ <message>
+ <source>This is a normal payment.</source>
+ <translation>Este es un pago normal</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>Dirección Bitcoin a enviar el pago</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -650,27 +2124,79 @@
<translation>Alt+P</translation>
</message>
<message>
+ <source>Remove this entry</source>
+ <translation>Quitar esta entrada</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>Restar comisiones del monto.</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Mensaje:</translation>
</message>
<message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>Esta es una petición de pago no autentificada.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>Esta es una petición de pago autentificada.</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <translation>Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
+ </message>
+ <message>
<source>Pay To:</source>
<translation>Pagar a:</translation>
</message>
- </context>
+ <message>
+ <source>Memo:</source>
+ <translation>Memo:</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to your address book</source>
+ <translation>Introduce una etiqueta a esta dirección para añadirla a tu guía</translation>
+ </message>
+</context>
<context>
<name>SendConfirmationDialog</name>
- </context>
+ <message>
+ <source>Yes</source>
+ <translation>Si</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
- </context>
+ <message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 se esta cerrando...</translation>
+ </message>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation>No apague el equipo hasta que desaparezca esta ventana.</translation>
+ </message>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>Firmas - Firmar / verificar un mensaje</translation>
+ </message>
+ <message>
<source>&amp;Sign Message</source>
<translation>&amp;Firmar Mensaje</translation>
</message>
<message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>Dirección Bitcoin con la que firmar el mensaje</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Seleccionar dirección usada anteriormente</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -691,6 +2217,10 @@
<translation>Firma</translation>
</message>
<message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>Copiar la firma actual al portapapeles del sistema</translation>
+ </message>
+ <message>
<source>Sign the message to prove you own this Bitcoin address</source>
<translation>Firmar un mensjage para probar que usted es dueño de esta dirección</translation>
</message>
@@ -699,6 +2229,10 @@
<translation>Firmar Mensaje</translation>
</message>
<message>
+ <source>Reset all sign message fields</source>
+ <translation>Limpiar todos los campos de la firma de mensaje</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>&amp;Borra todos</translation>
</message>
@@ -707,10 +2241,74 @@
<translation>&amp;Firmar Mensaje</translation>
</message>
<message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>La dirección Bitcoin con la que se firmó el mensaje</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>Verifica el mensaje para asegurar que fue firmado con la dirección de Bitcoin especificada.</translation>
+ </message>
+ <message>
<source>Verify &amp;Message</source>
<translation>&amp;Firmar Mensaje</translation>
</message>
- </context>
+ <message>
+ <source>Reset all verify message fields</source>
+ <translation>Limpiar todos los campos de la verificación de mensaje</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Click en "Firmar mensaje" para generar una firma</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>La dirección ingresada es inválida</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Por favor, revisa la dirección e intenta nuevamente.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>La dirección ingresada no corresponde a una llave válida.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>El desbloqueo del monedero fue cancelado.</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>La llave privada para la dirección introducida no está disponible.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Falló la firma del mensaje.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Mensaje firmado.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>La firma no pudo decodificarse.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Por favor compruebe la firma e intente de nuevo.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>La firma no se combinó con el mensaje.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Falló la verificación del mensaje.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Mensaje verificado.</translation>
+ </message>
+</context>
<context>
<name>SplashScreen</name>
<message>
@@ -727,92 +2325,829 @@
</context>
<context>
<name>TransactionDesc</name>
- </context>
+ <message>
+ <source>Open until %1</source>
+ <translation>Abierto hasta %1</translation>
+ </message>
+ <message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>Hay un conflicto con la traducción de las confirmaciones %1</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, %1</source>
+ <translation>0/no confirmado, %1</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>en el equipo de memoria</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>no en el equipo de memoria</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>abandonado</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/no confirmado</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>confirmaciones %1</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Estado</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Fecha</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>Fuente</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Generado</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>Desde</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>desconocido</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>Para</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>dirección personal</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>Solo observación</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>etiqueta</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Credito</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>no aceptada</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Débito</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>Total enviado</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Crédito total</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Comisión de transacción</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation>Cantidad total</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mensaje</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Comentario</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>Identificador de transacción (ID)</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>Tamaño total de transacción</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>Indice de salida</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Vendedor</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Información de depuración</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transacción</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>Entradas</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Cantidad</translation>
+ </message>
+ <message>
+ <source>true</source>
+ <translation>verdadero</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>falso</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
<source>This pane shows a detailed description of the transaction</source>
<translation>Esta ventana muestra información detallada sobre la transacción</translation>
</message>
- </context>
+ <message>
+ <source>Details for %1</source>
+ <translation>Detalles para %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
- </context>
+ <message>
+ <source>Date</source>
+ <translation>Fecha</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Tipo</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Open until %1</source>
+ <translation>Abierto hasta %1</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>Sin confirmar</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>Abandonado</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>Confirmando (%1 de %2 confirmaciones recomendadas)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Confirmado (%1 confirmaciones)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>En conflicto</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>Inmaduro (%1 confirmación(es), Estarán disponibles después de %2)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Generado pero no aceptado</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Recibido con</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Recibido de</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Enviado a</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Pago a ti mismo</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minado</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>Solo observación</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(sin etiqueta)</translation>
+ </message>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Estado de transacción. Pasa el ratón sobre este campo para ver el numero de confirmaciones.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Fecha y hora cuando se recibió la transacción</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Tipo de transacción.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Cantidad restada o añadida al balance</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
- </context>
+ <message>
+ <source>All</source>
+ <translation>Todo</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Hoy</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Esta semana</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Este mes</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Mes pasado</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Este año</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Rango...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Recibido con</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Enviado a</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>A ti mismo</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Minado</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Otra</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Cantidad mínima</translation>
+ </message>
+ <message>
+ <source>Abandon transaction</source>
+ <translation>Transacción abandonada</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>Incrementar cuota de transacción</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copiar dirección</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copiar etiqueta</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copiar Cantidad</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copiar ID de transacción</translation>
+ </message>
+ <message>
+ <source>Copy raw transaction</source>
+ <translation>Copiar transacción bruta</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>Copiar todos los detalles de la transacción</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Editar etiqueta</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Mostrar detalles de la transacción</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Exportar historial de transacciones</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Archivos separados por coma (*.csv)</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Archivo separado de coma (*.csv)</translation>
+ </message>
+ <message>
+ <source>Watch-only</source>
+ <translation>Solo observación</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Fecha</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Tipo</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Dirección</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Exportación fallida</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Exportación exitosa</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>La transacción ha sido guardada en %1.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Rango:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>para</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>Unidad en la que se muestran las cantidades. Haga clic para seleccionar otra unidad.</translation>
+ </message>
+</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>No se ha cargado ningún monedero</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
- </context>
+ <message>
+ <source>Send Coins</source>
+ <translation>Enviar monedas</translation>
+ </message>
+ <message>
+ <source>Fee bump error</source>
+ <translation>Error de incremento de cuota</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Ha fallado el incremento de la cuota de transacción.</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>¿Desea incrementar la cuota?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>Comisión actual:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>Incremento:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>Nueva comisión:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>Confirmar incremento de comisión</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>No se ha podido firmar la transacción.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>No se pudo confirmar la transacción</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>Exportar</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Exportar los datos de la pestaña actual a un archivo</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Respaldar monedero</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Archivo de respaldo (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Ha fallado el respaldo</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>Ha habido un error al intentar guardar los datos del monedero a %1.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Respaldo exitoso</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>Los datos del monedero se han guardado con éxito en %1.</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opciones:
-</translation>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation>Distribuido bajo la licencia de software MIT, vea el archivo adjunto %s o %s</translation>
</message>
<message>
- <source>Specify data directory</source>
- <translation>Especifica directorio para los datos
-</translation>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation>La Poda se ha configurado por debajo del mínimo de %d MiB. Por favor utiliza un valor mas alto.</translation>
</message>
<message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aceptar comandos consola y JSON-RPC
-</translation>
+ <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
+ <translation>No es es posible re-escanear en modo prune. Debes usar -reindex el cual descargara toda la blockchain de nuevo.</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Correr como demonio y acepta comandos
-</translation>
+ <source>Error: A fatal internal error occurred, see debug.log for details</source>
+ <translation>Error: Un error interno fatal ha ocurrido, ver debug.log para detalles</translation>
+ </message>
+ <message>
+ <source>Pruning blockstore...</source>
+ <translation>Poda blockstore...</translation>
+ </message>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>No se ha podido iniciar el servidor HTTP. Ver debug log para detalles.</translation>
</message>
<message>
<source>Bitcoin Core</source>
<translation>bitcoin core</translation>
</message>
<message>
+ <source>The %s developers</source>
+ <translation>Los desarrolladores de %s</translation>
+ </message>
+ <message>
+ <source>%d of last 100 blocks have unexpected version</source>
+ <translation>%d de los últimos 100 bloques tienen una versión no esperada</translation>
+ </message>
+ <message>
+ <source>%s corrupt, salvage failed</source>
+ <translation>%s corrupto. Fracasó la recuperación</translation>
+ </message>
+ <message>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation>-maxmempool debe ser por lo menos de %d MB</translation>
+ </message>
+ <message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>No se puede resolver -%s direccion: '%s'</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>Cambio de indice fuera de rango</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Copyright (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation>Corrupción de base de datos de bloques detectada.</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>¿Quieres reconstruir la base de datos de bloques ahora?</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation>Error al inicializar la base de datos de bloques</translation>
+ </message>
+ <message>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation>Error al iniciar el entorno de la base de datos del monedero %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>Error cargando %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Error cargando %s: Monedero corrupto</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Error cargando %s: Monedero requiere una versión mas reciente de %s</translation>
+ </message>
+ <message>
<source>Error loading block database</source>
<translation>Error cargando blkindex.dat</translation>
</message>
<message>
+ <source>Error opening block database</source>
+ <translation>Error cargando base de datos de bloques</translation>
+ </message>
+ <message>
<source>Error: Disk space is low!</source>
<translation>Atención: Poco espacio en el disco duro</translation>
</message>
<message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation>Ha fallado la escucha en todos los puertos. Usa -listen=0 si desea esto.</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>Importando...</translation>
+ </message>
+ <message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>Incorrecto o bloque de génesis no encontrado. ¿datadir equivocada para la red?</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>La inicialización de la verificación de validez falló. Se está apagando %s.</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>Monto invalido para -%s=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>Monto invalido para -discardfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>Monto invalido para -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>Cargando direcciones P2P...</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>Cargando banlist...</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation>No hay suficientes descriptores de archivo disponibles.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>Reproduciendo bloques...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>Rebobinando bloques...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>El código fuente esta disponible desde %s.</translation>
+ </message>
+ <message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>El cálculo de la comisión de transacción y del cambio han fallado</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
+ <translation>El argumento -benchmark no es soportado y ha sido ignorado, usa -debug=bench</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
+ <translation>El argumento -debugnet no es soportado, usa -debug=ned.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -tor found, use -onion.</source>
+ <translation>El argumento -tor no es soportado, usa -onion.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>Actualizando la base de datos UTXO</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>Verificando bloques...</translation>
+ </message>
+ <message>
+ <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
+ <translation>Error cargando %s: No puedes deshabilitar HD en un monedero HD ya existente</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation>Error al leer la base de datos, cerrando aplicación.</translation>
+ </message>
+ <message>
+ <source>Error upgrading chainstate database</source>
+ <translation>Error actualizando la base de datos chainstate</translation>
+ </message>
+ <message>
<source>Information</source>
<translation>Información</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Enviar informacion de seguimiento a la consola en vez del archivo debug.log</translation>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Dirección de -onion o dominio '%s' inválido</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Usuario para las conexiones JSON-RPC
-</translation>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation>Máscara de red inválida especificada en -whitelist: '%s'</translation>
+ </message>
+ <message>
+ <source>Need to specify a port with -whitebind: '%s'</source>
+ <translation>Necesita especificar un puerto con -whitebind: '%s'</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation>Reduciendo -maxconnections de %d a %d, debido a limitaciones del sistema.</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation>Firma de transacción fallida</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>El monto a transferir es muy pequeño para pagar el impuesto</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>Este es un software experimental.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>Monto a transferir muy pequeño</translation>
+ </message>
+ <message>
+ <source>Transaction too large for fee policy</source>
+ <translation>Operación demasiado grande para la política de comision</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>Transacción muy grande</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation>No es posible conectar con %s en este sistema (bind ha devuelto el error %s)</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>Verificando billetera(s)...</translation>
</message>
<message>
<source>Warning</source>
<translation>Atención</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Contraseña para las conexiones JSON-RPC
-</translation>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <translation>Advertencia: nuevas reglas desconocidas activadas (versionbit %i)</translation>
</message>
<message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permite búsqueda DNS para addnode y connect
-</translation>
+ <source>Zapping all transactions from wallet...</source>
+ <translation>Eliminando todas las transacciones del monedero...</translation>
+ </message>
+ <message>
+ <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
+ <translation>-maxtxfee tiene un valor muy elevado! Comisiones muy grandes podrían ser pagadas en una única transacción.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
+ <translation>Error cargando %s: No puedes habilitar HD en un monedero no HD ya existente</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>Impuesto por transacción que pagarás cuando la estimación de impuesto no esté disponible.</translation>
+ </message>
+ <message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation>La longitud total de la cadena de versión de red ( %i ) supera la longitud máxima ( %i ) . Reducir el número o tamaño de uacomments .</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
+ <translation>Argumento -socks no soportado. La configuración de la versión SOCKS ya no es posible, sólo los proxies SOCKS5 son compatibles.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
+ <translation>Argumento -whitelistalwaysrelay no soportado ha sido ignorado, utiliza -whitelistrelay y/o -whitelistforcerelay</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
+ <translation>Advertencia: Se están minando versiones de bloques desconocidas! Es posible que reglas desconocidas estén activas</translation>
+ </message>
+ <message>
+ <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
+ <translation>Advertencia: Archivo de monedero corrupto, datos recuperados! Original %s guardado como %s en %s; si su balance de transacciones es incorrecto, debe restaurar desde una copia de seguridad.</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation>¡%s esta configurado muy alto!</translation>
+ </message>
+ <message>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>Error cargando el monedero %s. Se ha especificado un nombre de fichero -wallet duplicado.</translation>
+ </message>
+ <message>
+ <source>Keypool ran out, please call keypoolrefill first</source>
+ <translation>Keypool se ha agotado, llame a keypoolrefill primero</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>Iniciando procesos de red...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>La billetera no permitirá pagar menos que la fee de transmisión mínima (relay fee).</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>Mínimo de impuesto que pagarás con cada transacción.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>Impuesto por transacción a pagar si envías una transacción.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>El monto de la transacción no puede ser negativo</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>La transacción tiene demasiado tiempo de una cadena de mempool</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>La transacción debe incluir al menos un destinatario.</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation>La red especificada en -onlynet: '%s' es desconocida</translation>
</message>
<message>
<source>Insufficient funds</source>
diff --git a/src/qt/locale/bitcoin_es_CO.ts b/src/qt/locale/bitcoin_es_CO.ts
index 9c6bcdff72..812d5ac70f 100644
--- a/src/qt/locale/bitcoin_es_CO.ts
+++ b/src/qt/locale/bitcoin_es_CO.ts
@@ -502,6 +502,10 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Comisión:</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>Polvo:</translation>
+ </message>
+ <message>
<source>After Fee:</source>
<translation>Después de comisión:</translation>
</message>
@@ -510,6 +514,10 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Cambio:</translation>
</message>
<message>
+ <source>(un)select all</source>
+ <translation>(de)seleccionar todo</translation>
+ </message>
+ <message>
<source>Tree mode</source>
<translation>Modo árbol</translation>
</message>
@@ -582,6 +590,10 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Copiar bytes</translation>
</message>
<message>
+ <source>Copy dust</source>
+ <translation>Copiar polvo</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation>Copiar cambio</translation>
</message>
@@ -594,6 +606,10 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>no</translation>
</message>
<message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Está etiqueta se vuelve roja si algún receptor recibe una cantidad inferior al límite actual establecido para el polvo.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(no etiqueta)</translation>
</message>
@@ -625,10 +641,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Y dirección</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nueva dirección de recepción</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nueva dirección de envío</translation>
</message>
@@ -686,34 +698,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<source>Command-line options</source>
<translation>Opciones de línea de comando</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uso:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opciones de línea de comando</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opciones de UI:</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Establecer el idioma, por ejemplo "de_DE" (predeterminado: configuración regional del sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Iniciar minimizado</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Establecer certificados raíz SSL para solicitud de pago (predeterminado: -sistema-)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Restablecer todas las configuraciones modificadas en la GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1631,14 +1615,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Solicitar pago</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Las direcciones Bech32 (BIP-173) son más baratas para gastar y ofrecen una mejor protección contra los errores tipográficos. Cuando no se selecciona, se creará una dirección SegWit envuelta en P2SH, compatible con monederos más antiguos.</translation>
- </message>
- <message>
- <source>Generate Bech32 address</source>
- <translation>Generar dirección Bech32</translation>
- </message>
- <message>
<source>Show the selected request (does the same as double clicking an entry)</source>
<translation>Mostrar la solicitud seleccionada (hace lo mismo que hacer doble clic en una entrada)</translation>
</message>
@@ -1701,6 +1677,10 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<source>Label</source>
<translation>Etiqueta</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Billetera</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1752,6 +1732,10 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Borre todos los campos del formulario.</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>Polvo:</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation>Cantidad de copia</translation>
</message>
@@ -1773,6 +1757,10 @@ Tarifa de copia</translation>
<translation>Copiar bytes</translation>
</message>
<message>
+ <source>Copy dust</source>
+ <translation>Copiar polvo</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation>Copiar cambio</translation>
</message>
@@ -1911,6 +1899,10 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Bitcoin Core</translation>
</message>
<message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>Esta es la cuota de transacción que puede descartar si el cambio es más pequeño que el polvo a este nivel.</translation>
+ </message>
+ <message>
<source>Information</source>
<translation>Información</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts
index 59ed82943f..387a3ef540 100644
--- a/src/qt/locale/bitcoin_es_DO.ts
+++ b/src/qt/locale/bitcoin_es_DO.ts
@@ -2,6 +2,10 @@
<context>
<name>AddressBookPage</name>
<message>
+ <source>Right-click to edit address or label</source>
+ <translation>Haga clic con el botón derecho para editar una dirección o etiqueta</translation>
+ </message>
+ <message>
<source>Create a new address</source>
<translation>Crear una nueva dirección</translation>
</message>
@@ -26,6 +30,10 @@
<translation>Borrar de la lista la dirección seleccionada</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduzca una dirección o etiqueta que buscar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar a un archivo los datos de esta pestaña</translation>
</message>
@@ -37,9 +45,57 @@
<source>&amp;Delete</source>
<translation>&amp;Eliminar</translation>
</message>
- </context>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Escoja la dirección a la que se enviarán monedas</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Escoja la dirección donde quiere recibir monedas</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Direcciones de envío</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Direcciones de recepción</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Estas son sus direcciones Bitcoin para enviar pagos. Compruebe siempre la cantidad y la dirección de recibo antes de transferir monedas.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Estas son sus direcciones de Bitcoin para recibir pagos. Se recomienda utilizar una nueva dirección de recepción para cada transacción.</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Exportar la Lista de Direcciones </translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Archivo de columnas separadas por coma (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>La exportación falló</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Hubo un error al intentar guardar la lista de direcciones a %1. Por favor trate de nuevo.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Dirección</translation>
+ </message>
</context>
<context>
<name>AskPassphraseDialog</name>
@@ -59,6 +115,58 @@
<source>Repeat new passphrase</source>
<translation>Repita la nueva contraseña</translation>
</message>
+ <message>
+ <source>Show password</source>
+ <translation>Mostrar contraseña</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Introduzca la nueva contraseña para el monedero. &lt;br/&gt;Por favor use una contraseña de &lt;b&gt;diez o más caracteres aleatorios&lt;/b&gt;, u &lt;b&gt;ocho o más palabras&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Cifrar monedero</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Esta operación requiere su contraseña para desbloquear el monedero.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Desbloquear monedero</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Esta operación requiere su contraseña para descifrar el monedero.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Descifrar monedero</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Introduzca la contraseña anterior y la contraseña nueva para este monedero.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Confirme cifrado del monedero</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Atención: Si cifra su monedero y pierde la contraseña, perderá ¡&lt;b&gt;TODOS SUS BITCOINS&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>¿Está seguro que desea cifrar su monedero?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Monedero cifrado</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 se cerrará ahora para finalizar el proceso de cifrado. Recuerde que el cifrado de su monedero no puede proteger de manera completa su Bitcoin de robo por malware que esté infectando su sistema.</translation>
+ </message>
</context>
<context>
<name>BanTableModel</name>
@@ -397,15 +505,7 @@
<source>Command-line options</source>
<translation>Opciones de la línea de órdenes</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uso:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opciones de la línea de órdenes</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -820,9 +920,25 @@
<source>&amp;Save Image...</source>
<translation>Guardar Imagen...</translation>
</message>
+ <message>
+ <source>Address</source>
+ <translation>Dirección</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Monedero</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -910,6 +1026,10 @@
<source>S&amp;end</source>
<translation>&amp;Enviar</translation>
</message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Comisión de transacción</translation>
+ </message>
</context>
<context>
<name>SendCoinsEntry</name>
@@ -1069,9 +1189,29 @@
</context>
<context>
<name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Archivo de columnas separadas por coma (*.csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Dirección</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>La exportación falló</translation>
+ </message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
@@ -1088,57 +1228,10 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opciones:
-</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Especificar directorio para los datos</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Conectar a un nodo para obtener direcciones de pares y desconectar</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especifique su propia dirección pública</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aceptar comandos consola y JSON-RPC
-</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Ejecutar en segundo plano como daemon y aceptar comandos
-</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Núcleo de Bitcoin</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Vincular a la dirección dada y escuchar siempre en ella. Utilice la notación [host]:port para IPv6</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Ejecutar comando cuando una transacción del monedero cambia (%s en cmd se remplazará por TxID)</translation>
- </message>
- <message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; puede ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opciones de creación de bloques:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>Corrupción de base de datos de bloques detectada.</translation>
</message>
@@ -1179,38 +1272,14 @@
<translation>No hay suficientes descriptores de archivo disponibles. </translation>
</message>
<message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especificar archivo de monedero (dentro del directorio de datos)</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>Verificando bloques...</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Ejecutar un comando cuando se reciba una alerta importante o cuando veamos un fork demasiado largo (%s en cmd se reemplazará por el mensaje)</translation>
- </message>
- <message>
<source>Information</source>
<translation>Información</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>Opciones del sservidor RPC:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Enviar información de trazas/depuración a la consola en lugar de al archivo debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Mostrar todas las opciones de depuración (uso: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Reducir el archivo debug.log al iniciar el cliente (predeterminado: 1 sin -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Transacción falló</translation>
</message>
@@ -1223,28 +1292,10 @@
<translation>Transacción demasiado grande</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nombre de usuario para las conexiones JSON-RPC
-</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Aviso</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Contraseña para las conexiones JSON-RPC
-</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Ejecutar un comando cuando cambia el mejor bloque (%s en cmd se sustituye por el hash de bloque)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permitir búsquedas DNS para -addnode, -seednode y -connect</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>La red especificada en -onlynet '%s' es desconocida</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_ES.ts b/src/qt/locale/bitcoin_es_ES.ts
index f79940e812..1b196cb13f 100644
--- a/src/qt/locale/bitcoin_es_ES.ts
+++ b/src/qt/locale/bitcoin_es_ES.ts
@@ -30,6 +30,10 @@
<translation>Eliminar la dirección seleccionada de la lista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduzca una dirección o etiqueta que buscar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar los datos en la ficha actual a un archivo</translation>
</message>
@@ -726,10 +730,6 @@
<translation>&amp;Dirección</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nueva dirección de recivimiento</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nueva dirección de envío</translation>
</message>
@@ -746,10 +746,6 @@
<translation>La dirección introducida "%1" no es una dirección Bitcoin válida.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>La dirección introducida "%1" está ya en la agenda.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Podría no desbloquear el monedero.</translation>
</message>
@@ -799,42 +795,6 @@
<source>Command-line options</source>
<translation>Opciones de la línea de órdenes</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uso:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opciones de la consola de comandos</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opciones de interfaz de usuario:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Elegir directorio de datos al iniciar (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Establecer el idioma, por ejemplo, "es_ES" (predeterminado: configuración regional del sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Arrancar minimizado</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Establecer los certificados raíz SSL para solicitudes de pago (predeterminado: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Mostrar pantalla de bienvenida en el inicio (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Reiniciar todos los ajustes modificados en el GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1431,10 +1391,6 @@
<translation>Error: directorio especificado "%1" no existe.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Error: no se puede interpretar el archivo de configuración: %1. Utilize exclusivamente sintaxis clave=valor.</translation>
- </message>
- <message>
<source>Error: %1</source>
<translation>Error: %1</translation>
</message>
@@ -1855,6 +1811,10 @@
<translation>Mensaje</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Monedero</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultante demasiado grande, trate de reducir el texto de etiqueta / mensaje.</translation>
</message>
@@ -1965,10 +1925,6 @@
<translation>por kilobyte</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Si la tarifa de aduana se establece en 1000 satoshis y la transacción está a sólo 250 bytes, entonces "por kilobyte" sólo paga 250 satoshis de cuota, mientras que "el mínimo total" pagaría 1.000 satoshis. Para las transacciones más grandes que un kilobyte ambos pagan por kilobyte</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Ocultar</translation>
</message>
@@ -2065,18 +2021,14 @@
<translation>¿Seguro que quiere enviar?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>añadido como transacción de cuota</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Cantidad total %1</translation>
- </message>
- <message>
<source>or</source>
<translation>o</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Comisión de transacción</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirmar enviar monedas</translation>
</message>
@@ -2406,10 +2358,6 @@
<translation>Hay un conflicto con la traducción de las confirmaciones %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/sin conexión</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/no confirmado, %1</translation>
</message>
@@ -2438,10 +2386,6 @@
<translation>Estado</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, no ha sido emitido con éxito aún</translation>
- </message>
- <message>
<source>Date</source>
<translation>Fecha</translation>
</message>
@@ -2588,10 +2532,6 @@
<translation>Abierto hasta %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Sin conexion</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Sin confirmar</translation>
</message>
@@ -2616,10 +2556,6 @@
<translation>No disponible (%1 confirmaciones. Estarán disponibles al cabo de %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Este bloque no ha sido recibido por otros nodos y probablemente no sea aceptado!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generado pero no aceptado</translation>
</message>
@@ -2886,36 +2822,10 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Los datos del monedero se han guardado con éxito en %1.</translation>
</message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opciones:
-</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Especificar directorio para los datos</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Conectar a un nodo para obtener direcciones de pares y desconectar</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especifique su propia dirección pública</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aceptar comandos consola y JSON-RPC
-</translation>
- </message>
- <message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Si &lt;category&gt; no es proporcionado o si &lt;category&gt; =1, muestra toda la información de depuración.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>La Poda se ha configurado por debajo del minimo de %d MiB. Por favor utiliza un valor mas alto.</translation>
</message>
@@ -2932,19 +2842,10 @@
<translation>Un error interno fatal ocurrió, ver debug.log para detalles</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Comisión (en %s/KB) para agregar a las transacciones que envíe (por defecto: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Poda blockstore ...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Ejecutar en segundo plano como daemon y aceptar comandos
-</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>No se ha podido comenzar el servidor HTTP. Ver debug log para detalles.</translation>
</message>
@@ -2957,42 +2858,14 @@
<translation>Los %s desarrolladores</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Una comision (en %s/kB) que sera usada cuando las estimacion de comision no disponga de suficientes datos (predeterminado: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Aceptar transacciones retransmitidas recibidas desde nodos en la lista blanca incluso cuando no estés retransmitiendo transacciones (predeterminado: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Vincular a la dirección dada y escuchar siempre en ella. Utilice la notación [host]:port para IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>No se puede bloquear el directorio %s. %s ya se está ejecutando.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Borrar todas las transacciones del monedero y sólo recuperar aquellas partes de la cadena de bloques por medio de -rescan on startup.</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Error leyendo %s!. Todas las claves se han leido correctamente, pero los datos de transacciones o la libreta de direcciones pueden faltar o ser incorrectos.</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Ejecutar comando cuando una transacción del monedero cambia (%s en cmd se remplazará por TxID)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Ajuste máximo permitido del tiempo offset medio de pares. La perspectiva local de tiempo se verá influenciada por los pares anteriores y posteriores a esta cantidad. (Por defecto: %u segundos)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Máximas comisiones totales (en %s) para utilizar en una sola transacción de la cartera; establecer esto demasiado bajo puede abortar grandes transacciones (predeterminado: %s)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>Por favor, compruebe si la fecha y hora en su computadora son correctas! Si su reloj esta mal, %s no trabajara correctamente. </translation>
</message>
@@ -3001,10 +2874,6 @@
<translation>Contribuya si encuentra %s de utilidad. Visite %s para mas información acerca del programa.</translation>
</message>
<message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Establecer el número de hilos (threads) de verificación de scripts (entre %u y %d, 0 = automático, &lt;0 = dejar libres ese número de núcleos; predeterminado: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>La base de datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de tu ordenador están mal ajustados. Reconstruye la base de datos de bloques solo si estas seguro de que la fecha y hora de tu ordenador estan ajustados correctamente.</translation>
</message>
@@ -3013,14 +2882,6 @@
<translation>No es posible reconstruir la base de datos a un estado anterior. Debe descargar de nuevo la cadena de bloques.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy)</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>La cartera no creara transacciones que violan los limites de memoria de la cadena (por defecto: %u)</translation>
- </message>
- <message>
<source>%s corrupt, salvage failed</source>
<translation>%s corrupto. Fracasó la recuperacion</translation>
</message>
@@ -3029,42 +2890,14 @@
<translation>-maxmempool debe ser por lo menos de %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; puede ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Adjunta un comentario a la linea de agente de usuario</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Intento de recuperar claves privadas de un monedero corrupto en arranque</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opciones de creación de bloques:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>No se puede resolver -%s direccion: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Opciones de selección de cadena:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Cambio de indice fuera de rango</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Opciones de conexión:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3073,38 +2906,10 @@
<translation>Corrupción de base de datos de bloques detectada.</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opciones de depuración/pruebas:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>No cargar el monedero y desactivar las llamadas RPC del monedero</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>¿Quieres reconstruir la base de datos de bloques ahora?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Activar publicar bloque .hash en &lt;.Address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Activar publicar transacción .hash en &lt;.Address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Habilita la publicacion de bloques en bruto en &lt;direccion&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Habilitar publicar transacción en rama en &lt;dirección&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Habilita el reemplazamiento de transacciones en la piscina de memoria (predeterminado: %u)</translation>
- </message>
- <message>
<source>Error initializing block database</source>
<translation>Error al inicializar la base de datos de bloques</translation>
</message>
@@ -3161,34 +2966,14 @@
<translation>Cantidad inválida para -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Mantener la memoria de transacciones por debajo de &lt;n&gt; megabytes (predeterminado: %u)</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Cargando banlist...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Ubicación de la cookie de autenticación (default: data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>No hay suficientes descriptores de archivo disponibles. </translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Sólo conectar a nodos en redes &lt;net&gt; (ipv4, ipv6 o onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Imprimir este mensaje de ayuda y salir</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Imprimir versión y salir</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Pode no se puede configurar con un valor negativo.</translation>
</message>
@@ -3197,26 +2982,10 @@
<translation>El modo recorte es incompatible con -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Reconstruir el estado de la cadena e indice de bloques a partir de los ficheros blk*.dat en disco</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Reconstruir el estado de la cadena a partir de los bloques indexados</translation>
- </message>
- <message>
<source>Rewinding blocks...</source>
<translation>Verificando bloques...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Asignar tamaño de cache en megabytes (entre %d y %d; predeterminado: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especificar archivo de monedero (dentro del directorio de datos)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>El código fuente esta disponible desde %s.</translation>
</message>
@@ -3237,14 +3006,6 @@
<translation>Parámetros no compatibles -tor encontrados, use -onion .</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Usar UPnP para asignar el puerto de escucha (predeterminado:: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Utilizar la cadena de test</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>El comentario del Agente de Usuario (%s) contiene caracteres inseguros.</translation>
</message>
@@ -3253,98 +3014,30 @@
<translation>Verificando bloques...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opciones de depuración/pruebas de monedero:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Es necesario reescribir el monedero: reiniciar %s para completar</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opciones de monedero:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permitir conexiones JSON-RPC de origen especificado. Válido para son una sola IP (por ejemplo 1.2.3.4), una red/máscara de red (por ejemplo 1.2.3.4/255.255.255.0) o una red/CIDR (e.g. 1.2.3.4/24). Esta opción se puede especificar varias veces</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Ligar a las direcciones especificadas y poner en lista blanca a los equipos conectados a ellas. Usar la notación para IPv6 [host]:puerto.</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Crear nuevos archivos con permisos por defecto del sistema, en lugar de umask 077 (sólo efectivo con la funcionalidad de monedero desactivada)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Descubra direcciones IP propias (por defecto: 1 cuando se escucha y nadie -externalip o -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: la escucha para conexiones entrantes falló (la escucha regresó el error %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Ejecutar un comando cuando se reciba una alerta importante o cuando veamos un fork demasiado largo (%s en cmd se reemplazará por el mensaje)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Las comisiones (en %s/kB) mas pequeñas que esto se consideran como cero comisión para la retransmisión, minería y creación de la transacción (predeterminado: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Si el pago de comisión no está establecido, incluir la cuota suficiente para que las transacciones comiencen la confirmación en una media de n bloques ( por defecto :%u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Cantidad no válida para -maxtxfee=&lt;amount&gt;: '%s' (debe ser por lo menos la cuota de comisión mínima de %s para prevenir transacciones atascadas)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>El tamaño máximo de los datos en las operaciones de transporte de datos que transmitimos y el mio (default: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Aleatorizar las credenciales para cada conexión proxy. Esto habilita la Tor stream isolation (por defecto: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Monto de transacción muy pequeña luego de la deducción por comisión</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>A los equipos en lista blanca no se les pueden prohibir los ataques DoS y sus transacciones siempre son retransmitidas, incluso si ya están en el mempool, es útil por ejemplo para un gateway.</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Necesitas reconstruir la base de datos utilizando -reindex para volver al modo sin recorte. Esto volverá a descargar toda la cadena de bloques</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(por defecto: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Aceptar solicitudes públicas en FERIADOS (por defecto: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Automáticamente crea el servicio Tor oculto (por defecto: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Conectar usando SOCKS5 proxy</translation>
- </message>
- <message>
<source>Error reading from database, shutting down.</source>
<translation>Error al leer la base de datos, cerrando.</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importa los bloques desde un archivo externo blk000?.dat</translation>
- </message>
- <message>
<source>Information</source>
<translation>Información</translation>
</message>
@@ -3357,42 +3050,14 @@
<translation>Máscara de red inválida especificada en -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Mantener como máximo &lt;n&gt; transacciones no conectables en memoria (por defecto: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Necesita especificar un puerto con -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opciones de nodos de retransmisión:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opciones de servidor RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduciendo -maxconnections de %d a %d, debido a limitaciones del sistema.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Rescanea la cadena de bloques para transacciones perdidas de la cartera</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Enviar información de trazas/depuración a la consola en lugar de al archivo debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Muestra todas las opciones de depuración (uso: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Reducir el archivo debug.log al iniciar el cliente (predeterminado: 1 sin -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Transacción falló</translation>
</message>
@@ -3405,14 +3070,6 @@
<translation>Este software es experimental.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Contraseña del puerto de control de Tor (predeterminado: vacio)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Puerto de control de Tor a utilizar si la escucha de onion esta activada (predeterminado: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Cantidad de la transacción demasiado pequeña</translation>
</message>
@@ -3429,15 +3086,6 @@
<translation>No es posible conectar con %s en este sistema (bind ha dado el error %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Actualizar el monedero al último formato al inicio</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nombre de usuario para las conexiones JSON-RPC
-</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Aviso</translation>
</message>
@@ -3446,75 +3094,14 @@
<translation>Advertencia: nuevas reglas desconocidas activadas (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Si se debe o no operar en un modo de solo bloques (predeterminado: %u)</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Eliminando todas las transacciones del monedero...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Opciones de notificación ZeroQM:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Contraseña para las conexiones JSON-RPC
-</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Ejecutar un comando cuando cambia el mejor bloque (%s en cmd se sustituye por el hash de bloque)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permitir búsquedas DNS para -addnode, -seednode y -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = mantener los meta datos de transacción, por ejemplo: propietario e información de pago, 2 = omitir los metadatos)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee tiene un ajuste muy elevado! Comisiones muy grandes podrían ser pagadas en una única transaccion.</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>No mantener transacciones en la memoria mas de &lt;n&gt; horas (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Bytes equivalentes por sigop en transacciones para retrasmisión y minado (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Las comisiones (en %s/kB) menores que esto son consideradas de cero comision para la creacion de transacciones (predeterminado: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Fuerza la retransmisión de transacciones desde nodos en la lista blanca incluso si violan la política de retransmisiones local (predeterminado: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Nivel de rigor en la verificación de bloques de -checkblocks (0-4; predeterminado: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Mantener el índice completo de transacciones, usado por la llamada rpc de getrawtransaction (por defecto: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Número de segundos en que se evita la reconexión de pares con mal comportamiento (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Mostrar depuración (por defecto: %u, proporcionar &lt;category&gt; es opcional)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Admite filtrado de bloques, y transacciones con filtros Bloom. Reduce la carga de red. ( por defecto :%u)</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Esta es la comisión que debe pagar cuando la estimación de comisión no esta disponible.</translation>
</message>
@@ -3531,10 +3118,6 @@
<translation>El argumento no soportado -whitelistalwaysrelay ha sido ignorado, utiliza -whitelistrelay y/o -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Usar distintos proxys SOCKS5 para comunicarse vía Tor de forma anónima (Por defecto: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Advertencia: Se están minando versiones de bloques desconocidas! Es posible que normas desconocidas estén activas</translation>
</message>
@@ -3547,86 +3130,6 @@
<translation>%s es demasiado alto!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(predeterminado: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Siempre consultar direcciones de otros equipos por medio de DNS lookup (por defecto: %u)</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Cuántos bloques comprobar al iniciar (predeterminado: %u, 0 = todos)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Incluir direcciones IP en la salida de depuración (por defecto: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escuchar conexiones JSON-RPC en &lt;puerto&gt; (predeterminado: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escuchar conexiones en &lt;puerto&gt; (predeterminado: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Mantener como máximo &lt;n&gt; conexiones a pares (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Realiza las operaciones de difusión del monedero</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Búfer de recepción máximo por conexión, &lt;n&gt;*1000 bytes (por defecto: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Búfer de recepción máximo por conexión, , &lt;n&gt;*1000 bytes (por defecto: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Anteponer marca temporal a la información de depuración (por defecto: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Retransmitir y minar transacciones de transporte de datos (por defecto: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Relay non-P2SH multisig (default: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Ajustar el número de claves en reserva &lt;n&gt; (predeterminado: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Establecer peso máximo bloque BIP141 (predeterminado: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Establecer el número de procesos para llamadas del servicio RPC (por defecto: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Especificar archivo de configuración (por defecto: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Especificar tiempo de espera de la conexión (mínimo: 1, por defecto: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Especificar archivo pid (predeterminado: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Usar cambio aún no confirmado al enviar transacciones (predeterminado: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Iniciando funciones de red...</translation>
</message>
@@ -3639,10 +3142,6 @@
<translation>Esta es la comisión que pagará si envia la transacción.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Umbral para la desconexión de pares con mal comportamiento (predeterminado: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Las cantidades de las transacciones no pueden ser negativas.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts
index d4ca4aa587..e1f79c5056 100644
--- a/src/qt/locale/bitcoin_es_MX.ts
+++ b/src/qt/locale/bitcoin_es_MX.ts
@@ -30,6 +30,10 @@
<translation>Eliminar la dirección actualmente seleccionada de la lista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Ingrese dirección o capa a buscar </translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar la información en la tabla actual a un archivo</translation>
</message>
@@ -66,9 +70,25 @@
<translation>Estas son tus direcciones de Bitcoin para enviar pagos. Siempre revisa el monto y la dirección de envío antes de enviar monedas.</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Estas son sus direcciones de Bitcoin para recibir pagos. Se recomienda utilizar una nueva dirección de recepción para cada transacción.</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Copiar dirección</translation>
</message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>copiar y etiquetar</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>Editar</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Exportar lista de direcciones </translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
@@ -353,15 +373,7 @@
<source>Command-line options</source>
<translation>opciones de la Linea de comandos</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uso:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Opciones de comando de lineas</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -476,6 +488,10 @@
<source>Copy &amp;Address</source>
<translation>&amp;Copiar dirección</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Cartera</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -640,26 +656,14 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opciones:</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>nucleo Bitcoin</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;categoria&gt; puede ser:</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>Verificando bloques...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opciones de cartera:</translation>
- </message>
- <message>
<source>Information</source>
<translation>Información </translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_UY.ts b/src/qt/locale/bitcoin_es_UY.ts
index 05549ad7da..32524b45e7 100644
--- a/src/qt/locale/bitcoin_es_UY.ts
+++ b/src/qt/locale/bitcoin_es_UY.ts
@@ -30,6 +30,10 @@
<translation>Eliminar la dirección seleccionada de la lista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Ingresar la dirección o etiqueta para buscar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar los datos en la pestaña actual a un archivo</translation>
</message>
@@ -335,6 +339,10 @@
<source>Copy &amp;Address</source>
<translation>Copiar Dirección</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Billetera</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -467,10 +475,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opciones:</translation>
- </message>
- <message>
<source>Information</source>
<translation>Información</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_VE.ts b/src/qt/locale/bitcoin_es_VE.ts
index 81058c615a..b500c16352 100644
--- a/src/qt/locale/bitcoin_es_VE.ts
+++ b/src/qt/locale/bitcoin_es_VE.ts
@@ -42,10 +42,18 @@
<translation>&amp;Borrar</translation>
</message>
<message>
+ <source>Choose the address to send coins to</source>
+ <translation>Escoja la direccion a enviar las monedas</translation>
+ </message>
+ <message>
<source>Choose the address to receive coins with</source>
<translation>Elige la dirección para recibir monedas</translation>
</message>
<message>
+ <source>C&amp;hoose</source>
+ <translation>Escoger</translation>
+ </message>
+ <message>
<source>Sending addresses</source>
<translation>Envío de direcciones</translation>
</message>
@@ -54,6 +62,18 @@
<translation>Direcciones de recepción</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Estas son tus direcciones Bitcoin para realizar pagos. Verifica siempre el monto y la dirección de recepción antes de enviar monedas. </translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Estas son tus direcciones Bitcoin para recibir pagos. Es recomendable usar una nueva dirección de recibo para cada transacción.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>Copiar dirección</translation>
+ </message>
+ <message>
<source>Copy &amp;Label</source>
<translation>Copiar &amp;Etiqueta</translation>
</message>
@@ -65,10 +85,30 @@
<source>Export Address List</source>
<translation>Exportar lista de direcciones</translation>
</message>
- </context>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Separar los archivos con comas (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Error al exportar</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Tuvimos un problema al guardar la dirección en la lista %1. Intenta de Nuevo.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
<message>
+ <source>Label</source>
+ <translation>Nombre</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Direccion</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
@@ -91,6 +131,40 @@
<source>Repeat new passphrase</source>
<translation>Repetir nueva frase de contraseña</translation>
</message>
+ <message>
+ <source>Show password</source>
+ <translation>Mostrar contraseña</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Cifrar monedero</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Esta operación necesita su frase de contraseña de la billetera para desbloquearla.
+</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Desbloquear monedero</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Esta operación necesita su frase de contraseña de la billetera para descifrar la billetera.
+</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Descifrar monedero</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Cambiar frase secreta</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Confirmar cifrado de billetera</translation>
+ </message>
</context>
<context>
<name>BanTableModel</name>
@@ -409,15 +483,7 @@
<source>Command-line options</source>
<translation>Opciones de línea de comandos</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uso:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opciones de línea de comandos</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -572,10 +638,26 @@
<source>Copy &amp;Address</source>
<translation>&amp;Copiar Dirección</translation>
</message>
+ <message>
+ <source>Address</source>
+ <translation>Direccion</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Nombre</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Billetera</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Label</source>
+ <translation>Nombre</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
@@ -662,12 +744,32 @@
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Label</source>
+ <translation>Nombre</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
</context>
<context>
<name>TransactionView</name>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Separar los archivos con comas (*.csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Nombre</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Direccion</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Error al exportar</translation>
+ </message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
@@ -684,64 +786,64 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opciones:</translation>
+ <source>Bitcoin Core</source>
+ <translation>Bitcoin Core</translation>
</message>
<message>
- <source>Specify data directory</source>
- <translation>Especifique directorio de datos</translation>
+ <source>Information</source>
+ <translation>Información</translation>
</message>
<message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Conecte un nodo para recuperar direcciones pares, y desconecte</translation>
+ <source>Transaction amount too small</source>
+ <translation>Transacción muy pequeña</translation>
</message>
<message>
- <source>Specify your own public address</source>
- <translation>Especifique su propia dirección pública</translation>
+ <source>Transaction too large</source>
+ <translation>Transacción muy grande</translation>
</message>
<message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aceptar linea de comando y comandos JSON-RPC</translation>
+ <source>Warning</source>
+ <translation>Advertencia</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Correr en segundo plano como daemon y aceptar comandos</translation>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>Esta es la tarifa mínima a pagar en cada transacción.</translation>
</message>
<message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>Esta es la tarifa a pagar si realizas una transacción.</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Enlazar dirección dada y siempre escuchar en ella. Usar [host]:port notación para IPv6</translation>
+ <source>Transaction amounts must not be negative</source>
+ <translation>Los montos de la transacción no debe ser negativo</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Borrar todas las transacciones de la billetera y solo recuperar aquellas partes de la cadena de bloques a través de -rescan en el inicio del sistema.</translation>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>La transacción tiene largo tiempo en una cadena mempool</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Ejecutar comando cuando una transacción de la billetera cambia (%s en cmd es reemplazado por TxID)</translation>
+ <source>Transaction must have at least one recipient</source>
+ <translation>La transacción debe tener al menos un destinatario</translation>
</message>
<message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Fija el número de verificación de hilos de script (%u a %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</translation>
+ <source>Insufficient funds</source>
+ <translation>Fondos insuficientes</translation>
</message>
<message>
- <source>Information</source>
- <translation>Información</translation>
+ <source>Loading wallet...</source>
+ <translation>Cargando monedero...</translation>
</message>
<message>
- <source>Transaction amount too small</source>
- <translation>Transacción muy pequeña</translation>
+ <source>Cannot downgrade wallet</source>
+ <translation>No se puede rebajar monedero</translation>
</message>
<message>
- <source>Transaction too large</source>
- <translation>Transacción muy grande</translation>
+ <source>Rescanning...</source>
+ <translation>Escaneando...</translation>
</message>
<message>
- <source>Warning</source>
- <translation>Advertencia</translation>
+ <source>Done loading</source>
+ <translation>Carga lista</translation>
</message>
<message>
<source>Error</source>
diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts
index 408d6eb840..8291a50b1c 100644
--- a/src/qt/locale/bitcoin_et.ts
+++ b/src/qt/locale/bitcoin_et.ts
@@ -30,6 +30,10 @@
<translation>Kustuta märgistatud aadress loetelust</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Otsimiseks sisesta märgis või aadress</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Ekspordi kuvatava vahelehe sisu faili</translation>
</message>
@@ -610,10 +614,6 @@
<translation>&amp;Aadress</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Uus vastu võttev aadress</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Uus saatev aadress</translation>
</message>
@@ -630,10 +630,6 @@
<translation>Sisestatud aadress "%1" ei ole korrektne Bitcoin aadress.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Sisestatud aadress "%1" on juba aadressi raamatus.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Rahakoti lahtilukustamine ebaõnnestus.</translation>
</message>
@@ -659,23 +655,7 @@
<source>Command-line options</source>
<translation>Käsurea valikud</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Kasutus:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>käsurea valikud</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Kasutajaliidese Suvandid:</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Käivitamisel kuva laadimisekraani (vaikimisi %u)</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -1175,6 +1155,10 @@
<translation>Sõnum</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Rahakott</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI liiga pikk, proovi vähendada märke / sõnumi pikkust.</translation>
</message>
@@ -1329,14 +1313,14 @@
<translation>Oled kindel, et soovid saata?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>lisatud kui tehingutasu</translation>
- </message>
- <message>
<source>or</source>
<translation>või</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Tehingutasu</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Müntide saatmise kinnitamine</translation>
</message>
@@ -1586,10 +1570,6 @@
<translation>Avatud kuni %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline'is</translation>
- </message>
- <message>
<source>%1/unconfirmed</source>
<translation>%1/kinnitamata</translation>
</message>
@@ -1602,10 +1582,6 @@
<translation>Olek</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, veel esitlemata</translation>
- </message>
- <message>
<source>Date</source>
<translation>Kuupäev</translation>
</message>
@@ -1732,10 +1708,6 @@
<translation>Kinnitatud (%1 kinnitust)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Antud klotsi pole saanud ükski osapool ning tõenäoliselt seda ei aktsepteerita!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Loodud, kuid aktsepteerimata</translation>
</message>
@@ -1946,54 +1918,14 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Valikud:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Täpsusta andmekataloog</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Peeri aadressi saamiseks ühendu korraks node'iga</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Täpsusta enda avalik aadress</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Luba käsurea ning JSON-RPC käsklusi</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Tööta taustal ning aktsepteeri käsklusi</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoini tuumik</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Määratud aadressiga sidumine ning sellelt kuulamine. IPv6 jaoks kasuta vormingut [host]:port</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Käivita käsklus, kui rahakoti tehing muutub (%s cmd's muudetakse TxID'ks)</translation>
- </message>
- <message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
<translation>See on test-versioon - kasutamine omal riisikol - ära kasuta mining'uks ega kaupmeeste programmides</translation>
</message>
<message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Luba välisühendusi (vaikeväärtus: 1 kui puudub -proxy või -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Blokeeri loomise valikud:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>Tuvastati vigane bloki andmebaas</translation>
</message>
@@ -2030,30 +1962,10 @@
<translation>Kontrollin blokke...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Rahakoti valikud:</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(vaikimisi: %u)</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informatsioon</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>RPC serveri valikud:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Saada jälitus/debug, debug.log faili asemel, konsooli</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Kahanda programmi käivitamisel debug.log faili (vaikeväärtus: 1, kui ei ole -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Tehingu allkirjastamine ebaõnnestus</translation>
</message>
@@ -2070,30 +1982,10 @@
<translation>Tehing liiga suur</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC ühenduste kasutajatunnus</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Hoiatus</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC ühenduste salasõna</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Käivita käsklus, kui parim plokk muutub (käskluse %s asendatakse ploki hash'iga)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>-addnode, -seednode ja -connect tohivad kasutada DNS lookup'i</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(vaikimisi: %s)</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>Kirjeldatud tundmatu võrgustik -onlynet'is: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_et_EE.ts b/src/qt/locale/bitcoin_et_EE.ts
index fb7c0ee3e4..4778e9492b 100644
--- a/src/qt/locale/bitcoin_et_EE.ts
+++ b/src/qt/locale/bitcoin_et_EE.ts
@@ -257,15 +257,7 @@
<source>Command-line options</source>
<translation>Käsurea valikud</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Kasutus:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>käsurea valikud</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -508,6 +500,10 @@
<source>Message</source>
<translation>Sõnum</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Rahakott</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -764,10 +760,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Valikud:</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
diff --git a/src/qt/locale/bitcoin_eu_ES.ts b/src/qt/locale/bitcoin_eu_ES.ts
index d890d7ed22..e266621d16 100644
--- a/src/qt/locale/bitcoin_eu_ES.ts
+++ b/src/qt/locale/bitcoin_eu_ES.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Klikatu eskuinean helbidea edo etiketa aldatzeko</translation>
+ <translation>Klikatu eskuinarekin helbidea edo etiketa aldatzeko</translation>
</message>
<message>
<source>Create a new address</source>
@@ -30,6 +30,10 @@
<translation>Ezabatu aukeratutako helbideak listatik</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Bilatzeko, helbide edo etiketa sartu</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Uneko fitxategian datuak esportatu</translation>
</message>
@@ -132,6 +136,14 @@
<translation>Pasahitz berria errepiikatu</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Erakutsi pasahitza</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Sartu pasaesaldi bat diru-zorrorako. Mesedez erabili ausazko hamar edo gehiago karaktere edo zortzi edo gehiago hitz.</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Diruzorroa enkriptatu</translation>
</message>
@@ -270,6 +282,10 @@
<translation>Fitxen tresna-barra</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Akatsa</translation>
+ </message>
+ <message>
<source>Up to date</source>
<translation>Eguneratua</translation>
</message>
@@ -336,10 +352,6 @@
<translation>&amp;Helbidea</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Jasotzeko helbide berria</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Bidaltzeko helbide berria</translation>
</message>
@@ -352,10 +364,6 @@
<translation>Bidaltzeko helbidea editatu</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Sartu berri den helbidea, "%1", helbide-liburuan dago jadanik.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Ezin da diruzorroa desblokeatu.</translation>
</message>
@@ -372,6 +380,10 @@
</context>
<context>
<name>Intro</name>
+ <message>
+ <source>Error</source>
+ <translation>Akatsa</translation>
+ </message>
</context>
<context>
<name>ModalOverlay</name>
@@ -389,6 +401,10 @@
<source>Options</source>
<translation>Aukerak</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Akatsa</translation>
+ </message>
</context>
<context>
<name>OverviewPage</name>
@@ -604,10 +620,6 @@
<translation>%1 konfirmazio</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, ez da oraindik arrakastaz igorri</translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -658,10 +670,6 @@
<translation>Konfirmatuta (%1 konfirmazio)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Bloke hau ez du beste inongo nodok jaso, eta seguruenik ez da onartuko!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Sortua, baina ez onartua</translation>
</message>
@@ -820,8 +828,8 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Aukerak:</translation>
+ <source>Loading wallet...</source>
+ <translation>Diru-zorroa kargatzen</translation>
</message>
<message>
<source>Rescanning...</source>
@@ -831,5 +839,9 @@
<source>Done loading</source>
<translation>Zamaketa amaitua</translation>
</message>
- </context>
+ <message>
+ <source>Error</source>
+ <translation>Akatsa</translation>
+ </message>
+</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts
index 1e27c1cf97..c2f2930a08 100644
--- a/src/qt/locale/bitcoin_fa.ts
+++ b/src/qt/locale/bitcoin_fa.ts
@@ -3,11 +3,11 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>برای تغییر آدرس و یا برچسب کلیک راست کنید.</translation>
+ <translation>برای تغییر آدرس و یا برچسب کلیک راست کنید</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>ایجاد نشانی جدید</translation>
+ <translation>ایجاد آدرس جدید</translation>
</message>
<message>
<source>&amp;New</source>
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>کپی نشانی انتخاب شده کنونی به حافظه‌ی سیستم</translation>
+ <translation>کپی‌برداری از آدرس منتخب به حافظهٔ سیستم</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -27,11 +27,15 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>حذف نشانی انتخاب‌شده کنونی از لیست</translation>
+ <translation>حذف آدرس منتخب از لیست</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>برای جست‌‌وجو نشانی یا برچسب را وارد کنید</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>خروجی گرفتن داده‌های برگه‌ی فعلی به یک فایل</translation>
+ <translation>صدور داده‌های برگهٔ فعلی به یک پرونده</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -43,35 +47,35 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>آدرس مورد نظر برای ارسال کوین ها را انتخاب کنید</translation>
+ <translation>آدرس مورد نظر برای ارسال سکه‌ها را انتخاب کنید</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>آدرس موردنظر برای دریافت کوین ها را انتخاب کنید.</translation>
+ <translation>آدرس موردنظر برای دریافت سکه‌ها را انتخاب کنید</translation>
</message>
<message>
<source>C&amp;hoose</source>
- <translation>انتخاب</translation>
+ <translation>ان&amp;تخاب</translation>
</message>
<message>
<source>Sending addresses</source>
- <translation>آدرس های فرستنده</translation>
+ <translation>آدرس‌های ارسالی</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation>آدرس های گیرنده</translation>
+ <translation>آدرس‌های دریافتی</translation>
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>اینها آدرس های شما برای فرستادن پرداخت هاست. همیشه قبل از فرستادن سکه ها مقدار و آدرس دریافت کننده را چک کنید.</translation>
+ <translation>این‌ها آدرس‌های بیتکوین برای پرداخت‌ها هستند. همیشه قبل از فرستادن سکه‌ها مقدار و آدرس دریافت‌کننده را بررسی نمایید.</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>این ها آدرس های بیت کوین شما برای دریافت پرداخت ها می باشد. توصیه میشود برای هر تراکنش از یک آدرس دریافت جدید استفاده کنید.</translation>
+ <translation>این‌ها آدرس‌های بیتکوین شما برای دریافت مبالغ می‌باشد. توصیه می‌شود برای هر تراکنش از یک آدرس جدید استفاده کنید.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>کپی کردن آدرس</translation>
+ <translation>کپ&amp;ی کردن آدرس</translation>
</message>
<message>
<source>Copy &amp;Label</source>
@@ -93,7 +97,11 @@
<source>Exporting Failed</source>
<translation>صدور موفق نبود</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>خطا در ذخیره‌سازی لیست آدرس‌ها در %1.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
<message>
@@ -128,12 +136,16 @@
<translation>تکرار گذرواژهٔ جدید</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>نمایش گذرواژه</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>رمزنگاری کیف پول</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>این عملیات نیاز به عبارت کیف پول شما برای بازگشایی کیف پول دارد</translation>
+ <translation>این عملیات نیاز به عبارت کیف پول شما برای بازگشایی کیف پول دارد.</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -403,7 +415,7 @@
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n ارتباط فعال با شبکهٔ بیت‌کوین</numerusform></translation>
+ <translation><numerusform>%n ارتباط فعال با شبکهٔ بیت‌کوین</numerusform><numerusform>%n ارتباط فعال با شبکهٔ بیت‌کوین</numerusform></translation>
</message>
<message>
<source>Processing blocks on disk...</source>
@@ -411,7 +423,7 @@
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>پردازش %n بلاک از تاریخچه ی تراکنش ها </numerusform></translation>
+ <translation><numerusform>پردازش %n بلاک از تاریخچه ی تراکنش ها </numerusform><numerusform>پردازش %n بلاک از تاریخچه ی تراکنش ها </numerusform></translation>
</message>
<message>
<source>%1 behind</source>
@@ -634,10 +646,6 @@
<translation>&amp;نشانی</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>نشانی گیرنده جدید</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>نشانی فرستنده جدید</translation>
</message>
@@ -654,14 +662,14 @@
<translation>نشانی وارد شده "%1" یک نشانی معتبر بیت‌کوین نیست.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>نشانی وارد شده «%1» در حال حاضر در دفترچه وجود دارد.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>نمی‌توان کیف پول را رمزگشایی کرد.</translation>
</message>
- </context>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>تولید کلید جدید ناموفق بود.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
@@ -703,35 +711,7 @@
<source>Command-line options</source>
<translation>گزینه‌های خط‌فرمان</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>استفاده:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>گزینه‌های خط فرمان</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>گزینه‌های رابط کاربری:</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>زبان را تنظیم کنید؛ برای مثال «de_DE» (پیشفرض: زبان سیستم)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>شروع برنامه به صورت کوچک‌شده</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>تنظیم گواهی ریشه SSl برای درخواست پرداخت (پیشفرض: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>نمایش پنجرهٔ خوشامدگویی در ابتدای اجرای برنامه (پیش‌فرض: %u)</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -760,7 +740,7 @@
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>%n گیگابایت فضا موجود است</numerusform></translation>
+ <translation><numerusform>%n گیگابایت فضا موجود است</numerusform><numerusform>%n گیگابایت فضا موجود است</numerusform></translation>
</message>
</context>
<context>
@@ -1017,6 +997,10 @@
<context>
<name>PeerTableModel</name>
<message>
+ <source>Ping</source>
+ <translation>پینگ</translation>
+ </message>
+ <message>
<source>Sent</source>
<translation>ارسال شده</translation>
</message>
@@ -1145,6 +1129,10 @@
<translation>استخر حافظه</translation>
</message>
<message>
+ <source>Current number of transactions</source>
+ <translation>تعداد تراکنش های فعلی</translation>
+ </message>
+ <message>
<source>Memory usage</source>
<translation>مصرف حافظه</translation>
</message>
@@ -1296,6 +1284,10 @@
<translation>کپی برچسب</translation>
</message>
<message>
+ <source>Copy message</source>
+ <translation>کپی پیام</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>کپی مقدار</translation>
</message>
@@ -1322,17 +1314,37 @@
<source>Label</source>
<translation>برچسب</translation>
</message>
+ <message>
+ <source>Message</source>
+ <translation>پیام</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>کیف پول</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation>تاریخ</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>برچسب</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>پیام</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(بدون برچسب)</translation>
</message>
+ <message>
+ <source>(no message)</source>
+ <translation>(بدون پیام)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -1449,6 +1461,14 @@
<translation>کپی کردن تغییر</translation>
</message>
<message>
+ <source>or</source>
+ <translation>یا</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>هزینهٔ تراکنش</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(بدون برچسب)</translation>
</message>
@@ -1613,21 +1633,85 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message>
+ <source>Status</source>
+ <translation>وضعیت</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>تاریخ</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>منبع</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>تولید شده</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>از</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>به</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>اعتبار</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>پیام</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>تراکنش</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>ورودی ها</translation>
+ </message>
</context>
<context>
<name>TransactionDescDialog</name>
<message>
<source>This pane shows a detailed description of the transaction</source>
- <translation>این پانل شامل توصیف کاملی از جزئیات تراکنش است</translation>
+ <translation>این پنل شامل توصیف کاملی از جزئیات تراکنش است</translation>
</message>
</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation>تاریخ</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>نوع</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>برچسب</translation>
</message>
<message>
+ <source>Received with</source>
+ <translation>دریافت شد با</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>دریافت شد از</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>فرستاده شد به</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(نامعلوم)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(بدون برچسب)</translation>
</message>
@@ -1635,6 +1719,38 @@
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>همه</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>امروز</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>این هفته</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>این ماه</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>ماه قبل</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>امسال</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>دریافت شد با</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>فرستاده شد به</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>کپی ادرس</translation>
</message>
@@ -1651,10 +1767,30 @@
<translation>کپی شناسهٔ تراکنش</translation>
</message>
<message>
+ <source>Edit label</source>
+ <translation>ویرایش برچسب</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>نمایش جزئیات تراکنش</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>استخراج تاریخچه تراکنش ها</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>فایل جدا شده با ویرگول(*.csv)</translation>
</message>
<message>
+ <source>Date</source>
+ <translation>تاریخ</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>نوع</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>برچسب</translation>
</message>
@@ -1666,7 +1802,11 @@
<source>Exporting Failed</source>
<translation>صدور موفق نبود</translation>
</message>
- </context>
+ <message>
+ <source>to</source>
+ <translation>به</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -1675,61 +1815,41 @@
</context>
<context>
<name>WalletModel</name>
- </context>
-<context>
- <name>WalletView</name>
- </context>
-<context>
- <name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>گزینه‌ها:</translation>
+ <source>Send Coins</source>
+ <translation>فرستادن سکه ها</translation>
</message>
<message>
- <source>Specify data directory</source>
- <translation>مشخص کردن دایرکتوری داده‌ها</translation>
+ <source>Current fee:</source>
+ <translation>دستمزد فعلی</translation>
</message>
<message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>اتصال به یک گره برای دریافت آدرس‌های همتا و قطع اتصال پس از اتمام عملیات</translation>
+ <source>Increase:</source>
+ <translation>افزایش</translation>
</message>
<message>
- <source>Specify your own public address</source>
- <translation>آدرس عمومی خود را مشخص کنید</translation>
+ <source>New fee:</source>
+ <translation>تعرفه جدید</translation>
</message>
+ </context>
+<context>
+ <name>WalletView</name>
<message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>پذیرش دستورات خط فرمان و دستورات JSON-RPC</translation>
+ <source>&amp;Export</source>
+ <translation>و صدور</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>اجرا در پشت زمینه به‌صورت یک سرویس و پذیرش دستورات</translation>
+ <source>Export the data in the current tab to a file</source>
+ <translation>صدور داده‌های برگهٔ فعلی به یک پرونده</translation>
</message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
<message>
<source>Bitcoin Core</source>
<translation> هسته Bitcoin </translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>مقید به نشانی داده شده باشید و همیشه از آن پیروی کنید. از نشانه گذاری استاندار IPv6 به صورت Host]:Port] استفاده کنید.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>هنگامی که یک تراکنش در کیف پولی رخ می دهد، دستور را اجرا کن(%s در دستورات بوسیله ی TxID جایگزین می شود)</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>پذیرش اتصالات از بیرون (پیش فرض:1 بدون پراکسی یا اتصال)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>بستن گزینه ایجاد</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>گزینه‌های اتصال:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>حق تألیف (C) %i-%i</translation>
</message>
@@ -1774,36 +1894,16 @@
<translation>بارگذاری لیست‌سیاه...</translation>
</message>
<message>
- <source>Print this help message and exit</source>
- <translation>چاپ ایت پیام کمک و خروج</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>چاپ نسخه و خروج</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>در حال بازبینی بلوک‌ها...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>گزینه‌های کیف پول:</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(پیش‌فرض %u)</translation>
- </message>
- <message>
<source>Information</source>
<translation>اطلاعات</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>اطلاعات ردگیری/اشکال‌زدایی را به جای فایل لاگ اشکال‌زدایی به کنسول بفرستید</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>فایل debug.log را در startup مشتری کوچک کن (پیش فرض:1 اگر اشکال زدایی روی نداد)</translation>
+ <source>This is experimental software.</source>
+ <translation>این یک نرم افزار آزمایشی است.</translation>
</message>
<message>
<source>Transaction amount too small</source>
@@ -1814,10 +1914,6 @@
<translation>تراکنش بسیار بزرگ است</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC شناسه برای ارتباطات</translation>
- </message>
- <message>
<source>Warning</source>
<translation>هشدار</translation>
</message>
@@ -1826,22 +1922,6 @@
<translation>هشدار: قوانین جدید ناشناخته‌ای فعال شده‌اند (نسخه‌بیت %i)</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC عبارت عبور برای ارتباطات</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>زمانی که بهترین بلاک تغییر کرد، دستور را اجرا کن (%s در cmd با block hash جایگزین شده است)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>به DNS اجازه بده تا برای addnode ، seednode و اتصال جستجو کند</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(پیش‌فرض %s)</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>شبکه مشخص شده غیرقابل شناسایی در onlynet: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts
index 77b0046a34..be00b00656 100644
--- a/src/qt/locale/bitcoin_fa_IR.ts
+++ b/src/qt/locale/bitcoin_fa_IR.ts
@@ -30,6 +30,10 @@
<translation>حذف آدرس های انتخاب شده از لیست</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>آدرس یا برچسب را برای جستجو وارد کنید</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>صدور داده نوار جاری به یک فایل</translation>
</message>
@@ -132,6 +136,10 @@
<translation>رمز/پَس فرِیز را دوباره وارد کنید</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>نمایش گذرواژه</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>رمز جدید را در کیف‌پول وارد کنید. &lt;br/&gt;لطفا از رمزی استفاده کنید که&lt;b&gt; حداقل ۱۰ کاراکتر راندوم&lt;/b&gt;یا&lt;b&gt;حداقل ۸ کلمه داشته باشد&lt;/b&gt;.</translation>
</message>
@@ -223,6 +231,10 @@
<context>
<name>BanTableModel</name>
<message>
+ <source>IP/Netmask</source>
+ <translation>آی پی/نت ماسک</translation>
+ </message>
+ <message>
<source>Banned Until</source>
<translation>مسدودشده تا</translation>
</message>
@@ -231,7 +243,7 @@
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>امضا و پیام</translation>
+ <translation>ثبت &amp;پیام</translation>
</message>
<message>
<source>Synchronizing with network...</source>
@@ -242,6 +254,10 @@
<translation>بازبینی</translation>
</message>
<message>
+ <source>Node</source>
+ <translation>گره</translation>
+ </message>
+ <message>
<source>Show general overview of wallet</source>
<translation>نمای کلی از wallet را نشان بده</translation>
</message>
@@ -306,6 +322,18 @@
<translation>دریافت آدرس ها</translation>
</message>
<message>
+ <source>Open &amp;URI...</source>
+ <translation>بازکردن آدرس...</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>کیف پول:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>کیف پول پیش‌فرض</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>برای غیرفعال‌کردن فعالیت شبکه کلیک کنید.</translation>
</message>
@@ -342,6 +370,10 @@
<translation>پنجره دیباگ</translation>
</message>
<message>
+ <source>Open debugging and diagnostic console</source>
+ <translation>باز کردن کنسول دی باگ و تشخیص</translation>
+ </message>
+ <message>
<source>&amp;Verify message...</source>
<translation>تایید پیام</translation>
</message>
@@ -358,6 +390,10 @@
<translation>ارسال</translation>
</message>
<message>
+ <source>&amp;Receive</source>
+ <translation>دریافت</translation>
+ </message>
+ <message>
<source>&amp;Show / Hide</source>
<translation>نمایش/ عدم نمایش</translation>
</message>
@@ -409,9 +445,13 @@
<source>Open a bitcoin: URI or payment request</source>
<translation>بازکردن بیت‌کوین: آدرس یا درخواست پرداخت</translation>
</message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>گزینه های خط فرمان</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n ارتباط فعال به شبکه بیت‌کوین</numerusform></translation>
+ <translation><numerusform>%n ارتباط فعال به شبکه بیت‌کوین</numerusform><numerusform>%n ارتباط فعال به شبکه بیت‌کوین</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
@@ -423,21 +463,53 @@
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>%n بلاک از تاریخچه تراکنش، پردازش شد.</numerusform></translation>
+ <translation><numerusform>%n بلاک از تاریخچه تراکنش، پردازش شد.</numerusform><numerusform>%n بلاک از تاریخچه تراکنش، پردازش شد.</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 قبل</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>تراکنش‌های بعد از این تراکنش هنوز در دسترس نیستند.</translation>
</message>
<message>
<source>Error</source>
<translation>خطا</translation>
</message>
<message>
+ <source>Warning</source>
+ <translation>هشدار</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>اطلاعات</translation>
+ </message>
+ <message>
<source>Up to date</source>
<translation>به روز</translation>
</message>
<message>
+ <source>Connecting to peers...</source>
+ <translation>در حال اتصال به همتاهای شبکه...</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>در حال روزآمد سازی..</translation>
</message>
<message>
+ <source>Amount: %1
+</source>
+ <translation>مبلغ: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>آدرس: %1
+</translation>
+ </message>
+ <message>
<source>Sent transaction</source>
<translation>تراکنش ارسالی</translation>
</message>
@@ -453,7 +525,11 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>wallet رمزگذاری شد و در حال حاضر قفل است</translation>
</message>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>خطای بحرانی رخ داده است. بیتکوین دیگر به صورت ایمن قادر به ادامه دادن نمی‌باشد و خارج خواهد شد.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -465,6 +541,10 @@
<translation>مقدار</translation>
</message>
<message>
+ <source>Bytes:</source>
+ <translation>بایت ها:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>میزان وجه:</translation>
</message>
@@ -473,6 +553,14 @@
<translation>هزینه</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>گرد و غبار با داست:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>بعد از احتساب کارمزد</translation>
+ </message>
+ <message>
<source>Change:</source>
<translation>تغییر</translation>
</message>
@@ -481,6 +569,14 @@
<translation>(عدم)انتخاب همه</translation>
</message>
<message>
+ <source>Tree mode</source>
+ <translation>حالت درختی</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>حالت لیستی</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>میزان</translation>
</message>
@@ -529,6 +625,22 @@
<translation>کپی هزینه</translation>
</message>
<message>
+ <source>Copy after fee</source>
+ <translation>کپی کردن بعد از احتساب کارمزد</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>کپی کردن بایت ها</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>کپی کردن داست:</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>کپی کردن تغییر</translation>
+ </message>
+ <message>
<source>yes</source>
<translation>بله</translation>
</message>
@@ -540,7 +652,11 @@
<source>(no label)</source>
<translation>(برچسب ندارد)</translation>
</message>
- </context>
+ <message>
+ <source>(change)</source>
+ <translation>(تغییر)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -556,10 +672,6 @@
<translation>آدرس</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>آدرس دریافتی جدید</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>آدرس ارسالی جدید</translation>
</message>
@@ -571,14 +683,34 @@
<source>Edit sending address</source>
<translation>ویرایش آدرس ارسالی</translation>
</message>
- </context>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>آدرس وارد شده "%1" آدرس معتبر بیت کوین نیست.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>نمیتوان کیف پول را باز کرد.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>تولید کلید جدید به خطا انجامید.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
<message>
+ <source>A new data directory will be created.</source>
+ <translation>پوشه داده جدید ساخته خواهد شد</translation>
+ </message>
+ <message>
<source>name</source>
<translation>نام</translation>
</message>
- </context>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>نمیتوان در اینجا پوشه داده ساخت.</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
<message>
@@ -586,10 +718,10 @@
<translation>نسخه</translation>
</message>
<message>
- <source>Usage:</source>
- <translation>میزان استفاده:</translation>
+ <source>Command-line options</source>
+ <translation>گزینه های خط-فرمان </translation>
</message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -597,10 +729,26 @@
<translation>خوش آمدید</translation>
</message>
<message>
+ <source>Welcome to %1.</source>
+ <translation>به %1 خوش آمدید.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>استفاده کردن از پوشه داده پیشفرض</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>استفاده کردن از پوشه داده مخصوص:</translation>
+ </message>
+ <message>
<source>Bitcoin</source>
<translation>بیت کوین</translation>
</message>
<message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>کیف پول هم در همین دایرکتوری ذخیره می‌شود.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>خطا</translation>
</message>
@@ -612,10 +760,26 @@
<translation>فرم</translation>
</message>
<message>
+ <source>Number of blocks left</source>
+ <translation>تعداد بلوک‌های باقیمانده</translation>
+ </message>
+ <message>
<source>Unknown...</source>
<translation>ناشناس...</translation>
</message>
<message>
+ <source>Last block time</source>
+ <translation>زمان آخرین بلوک</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>پیشرفت</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>سرعت افزایش پیشرفت بر ساعت</translation>
+ </message>
+ <message>
<source>calculating...</source>
<translation>در حال محاسبه...</translation>
</message>
@@ -626,7 +790,27 @@
</context>
<context>
<name>OpenURIDialog</name>
- </context>
+ <message>
+ <source>Open URI</source>
+ <translation>باز کردن آدرس URL</translation>
+ </message>
+ <message>
+ <source>Open payment request from URI or file</source>
+ <translation>بازکردن درخواست پرداخت از آدرس URL یا فایل</translation>
+ </message>
+ <message>
+ <source>URI:</source>
+ <translation>آدرس:</translation>
+ </message>
+ <message>
+ <source>Select payment request file</source>
+ <translation>انتخاب فایل درخواست وجه (Payment Request)</translation>
+ </message>
+ <message>
+ <source>Select payment request file to open</source>
+ <translation>انتخاب فایل درحواست وجه برای باز کردن</translation>
+ </message>
+</context>
<context>
<name>OptionsDialog</name>
<message>
@@ -634,10 +818,26 @@
<translation>گزینه ها</translation>
</message>
<message>
+ <source>&amp;Main</source>
+ <translation>&amp;اصلی</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>اندازه کش پایگاه داده.</translation>
+ </message>
+ <message>
<source>MB</source>
<translation>مگابایت</translation>
</message>
<message>
+ <source>Open Configuration File</source>
+ <translation>بازکردن فایل پیکربندی</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>ریست تمامی تنظیمات کلاینت به پیشفرض</translation>
+ </message>
+ <message>
<source>&amp;Reset Options</source>
<translation>تنظیم مجدد گزینه ها</translation>
</message>
@@ -646,14 +846,50 @@
<translation>شبکه</translation>
</message>
<message>
+ <source>GB</source>
+ <translation>گیگابایت</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation>کیف پول</translation>
</message>
<message>
+ <source>Expert</source>
+ <translation>حرفه‌ای</translation>
+ </message>
+ <message>
+ <source>Accept connections from outside.</source>
+ <translation>پذیرفتن اتصال شدن از بیرون</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>اجازه دادن به ارتباطات ورودی</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>پراکسی و آی‌پی:</translation>
+ </message>
+ <message>
<source>&amp;Port:</source>
<translation>پورت:</translation>
</message>
<message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>شبکه Tor</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>اتصال به شبکه بیت کوین با استفاده از پراکسی SOCKS5 برای استفاده از سرویس مخفی تور</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>پنجره</translation>
</message>
@@ -662,6 +898,18 @@
<translation>نمایش</translation>
</message>
<message>
+ <source>User Interface &amp;language:</source>
+ <translation>زبان واسط کاربری:</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>واحد نمایشگر مقادیر:</translation>
+ </message>
+ <message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>URLهای تراکنش شخص ثالث</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>تایید</translation>
</message>
@@ -674,10 +922,42 @@
<translation>پیش فرض</translation>
</message>
<message>
+ <source>none</source>
+ <translation>خالی</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>تایید ریست تنظیمات</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>کلاینت نیازمند ریست شدن است برای فعال کردن تغییرات</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>کلاینت خاموش خواهد شد.آیا میخواهید ادامه دهید؟</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>تنظیمات پیکربندی</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>خطا</translation>
</message>
- </context>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation>فایل پیکربندی قادر به بازشدن نبود.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>تغییرات منوط به ریست کاربر است.</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>آدرس پراکسی ارائه شده نامعتبر است.</translation>
+ </message>
+</context>
<context>
<name>OverviewPage</name>
<message>
@@ -689,18 +969,46 @@
<translation>اطلاعات نمایش داده شده ممکن است روزآمد نباشد. wallet شما به صورت خودکار بعد از برقراری اتصال با شبکه bitcoin به روز می شود اما این فرایند هنوز تکمیل نشده است.</translation>
</message>
<message>
+ <source>Watch-only:</source>
+ <translation>فقط قابل-مشاهده:</translation>
+ </message>
+ <message>
<source>Available:</source>
<translation>در دسترس:</translation>
</message>
<message>
+ <source>Your current spendable balance</source>
+ <translation>موجودی قابل خرج در الان</translation>
+ </message>
+ <message>
<source>Pending:</source>
<translation>در حال انتظار:</translation>
</message>
<message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation>تعداد تراکنشهایی که نیاز به تایید دارند و هنوز در مانده حساب جاری شما به حساب نیامده اند</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>موجودی استخراج شده هنوز کامل نشده است</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>موجودی ها</translation>
+ </message>
+ <message>
<source>Total:</source>
<translation>کل:</translation>
</message>
<message>
+ <source>Your current total balance</source>
+ <translation>موجودی شما در همین لحظه</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>موجودی شما در همین لحظه در آدرس های Watch only Addresses </translation>
+ </message>
+ <message>
<source>Spendable:</source>
<translation>قابل مصرف:</translation>
</message>
@@ -708,13 +1016,65 @@
<source>Recent transactions</source>
<translation>تراکنش های اخیر</translation>
</message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>تراکنش های تایید نشده به آدرس های فقط قابل مشاهده watch-only</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>موجودی استخراج شده در آدرس های فقط قابل مشاهده هنوز کامل نشده است</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>درخواست پرداخت با خطا مواجه شد</translation>
+ </message>
+ <message>
+ <source>Payment request rejected</source>
+ <translation>درخواست پرداخت رد شد</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>درخواست پرداخت منقضی شد یا تاریخ آن گذشت.</translation>
+ </message>
+ <message>
+ <source>Payment request is not initialized.</source>
+ <translation>درخواست پرداخت, با مقداردهی اولیه یکسان نبود.</translation>
+ </message>
+ <message>
+ <source>Invalid payment request.</source>
+ <translation>درخواست پرداخت نامعتبر بود.</translation>
+ </message>
+ <message>
+ <source>Network request error</source>
+ <translation>درخواست از شبکه با خطا مواجه شد</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
- </context>
+ <message>
+ <source>Node/Service</source>
+ <translation>گره/خدمت</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>شناسه گره</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>پینگ</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>فرستاده شد</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>دریافت شد</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
@@ -722,6 +1082,14 @@
<translation>میزان</translation>
</message>
<message>
+ <source>None</source>
+ <translation>هیچ کدام</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>موجود نیست</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>ناشناس</translation>
</message>
@@ -731,18 +1099,58 @@
</context>
<context>
<name>QRImageWidget</name>
- </context>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;ذخیره کردن Image...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;کپی کردن image</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>ذحیره کردن Qr Code</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>تصویر با فرمت PNG انتخاب(*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
+ <source>N/A</source>
+ <translation>موجود نیست</translation>
+ </message>
+ <message>
<source>Client version</source>
<translation>ویرایش کنسول RPC</translation>
</message>
<message>
+ <source>&amp;Information</source>
+ <translation>&amp;اطلاعات</translation>
+ </message>
+ <message>
+ <source>Debug window</source>
+ <translation>پنجره یا صفحه دی باگ</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>عمومی</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>پوشه داده Datadir</translation>
+ </message>
+ <message>
<source>Network</source>
<translation>شبکه</translation>
</message>
<message>
+ <source>Name</source>
+ <translation>نام</translation>
+ </message>
+ <message>
<source>Number of connections</source>
<translation>تعداد اتصال</translation>
</message>
@@ -754,7 +1162,175 @@
<source>Current number of blocks</source>
<translation>تعداد زنجیره های حاضر</translation>
</message>
- </context>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>تعداد تراکنش ها در حال حاضر</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>حافظه استفاده شده</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation>کیف پول:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(هیچ کدام)</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;ریست کردن</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>دریافت شد</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>فرستاده شد</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation>&amp;همتاها</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation>همتاهای بن شده</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>انتخاب همتا یا جفت برای جزییات اطلاعات</translation>
+ </message>
+ <message>
+ <source>Whitelisted</source>
+ <translation>لیست سفید شده یا لیست سالم WhiteList</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>مسیر</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>نسخه</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>کاهش دادن اندازه فونت</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>افزایش دادن اندازه فونت</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>خدمات</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>زمان اتصال</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation>آخرین ارسال</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>آخرین دریافت</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>مدت زمان پینگ</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>انتظار پینگ</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>حداقل پینگ</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>زمان آخرین بلوک</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>&amp;بازکردن</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;شلوغی شبکه</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation>جمع کل ها</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>به یا داخل:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>خارج شده:</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation>پاک کردن کنسول</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;ساعت</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;روز</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;هفته</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;سال</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;قطع شدن</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>بن یا بن شده برای</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;خارج کردن از بن</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>کیف پول پیش‌فرض</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>فعالیت شبکه غیر فعال شد</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>هیچ وقت</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation>بله</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation>خیر</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>ناشناس یا نامعلوم</translation>
+ </message>
+</context>
<context>
<name>ReceiveCoinsDialog</name>
<message>
@@ -770,14 +1346,46 @@
<translation>پیام:</translation>
</message>
<message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>از این فرم استفاده کنید برای درخواست پرداخت ها.تمامی گزینه ها &lt;b&gt;اختیاری&lt;/b&gt;هستند.</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>پاک کردن تمامی گزینه های این فرم</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>پاک کردن</translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation>تاریخچه پرداخت های درخواست شده</translation>
+ </message>
+ <message>
+ <source>&amp;Request payment</source>
+ <translation>&amp;درخواست پرداخت</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>نمایش</translation>
+ </message>
+ <message>
<source>Remove</source>
<translation>حذف</translation>
</message>
<message>
+ <source>Copy URI</source>
+ <translation>کپی کردن آدرس URL</translation>
+ </message>
+ <message>
<source>Copy label</source>
<translation>کپی برچسب</translation>
</message>
<message>
+ <source>Copy message</source>
+ <translation>کپی کردن پیام</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>کپی مقدار</translation>
</message>
@@ -785,29 +1393,81 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>QR Code</source>
+ <translation>کی یو آر کد Qr Code</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation>کپی کردن &amp;آدرس URL</translation>
+ </message>
+ <message>
<source>Copy &amp;Address</source>
<translation>کپی آدرس</translation>
</message>
<message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;ذخیره کردن تصویر...</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>اطلاعات پرداخت</translation>
+ </message>
+ <message>
+ <source>URI</source>
+ <translation>آدرس URL</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>آدرس</translation>
</message>
<message>
+ <source>Amount</source>
+ <translation>میزان وجه:</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>برچسب</translation>
</message>
+ <message>
+ <source>Message</source>
+ <translation>پیام</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>کیف پول</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation>تاریخ</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>برچسب</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>پیام</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(برچسب ندارد)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation>(بدون پیام)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(هیچ درخواست پرداخت وجود ندارد)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>درخواست شده</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -815,6 +1475,14 @@
<translation>سکه های ارسالی</translation>
</message>
<message>
+ <source>Coin Control Features</source>
+ <translation>قابلیت های کنترل کوین</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>به صورت خودکار انتخاب شده</translation>
+ </message>
+ <message>
<source>Insufficient funds!</source>
<translation>وجوه ناکافی</translation>
</message>
@@ -823,6 +1491,10 @@
<translation>مقدار</translation>
</message>
<message>
+ <source>Bytes:</source>
+ <translation>بایت ها:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>میزان وجه:</translation>
</message>
@@ -831,18 +1503,86 @@
<translation>هزینه</translation>
</message>
<message>
+ <source>After Fee:</source>
+ <translation>بعد از احتساب کارمزد</translation>
+ </message>
+ <message>
<source>Change:</source>
<translation>تغییر</translation>
</message>
<message>
+ <source>Custom change address</source>
+ <translation>تغییر آدرس مخصوص</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>کارمزد تراکنش:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>انتخاب...</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>هشدار:تخمین کارمزد در حال حاضر امکان پذیر نیست.</translation>
+ </message>
+ <message>
+ <source>collapse fee-settings</source>
+ <translation>تنظیمات کاهش کارمزد</translation>
+ </message>
+ <message>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>مشخص کردن هزینه کارمزد مخصوص به ازاری کیلوبایت(1,000 بایت) حجم مجازی تراکنش
+
+توجه: از آن جایی که کارمزد بر اساس هر بایت محاسبه میشود,هزینه کارمزد"100 ساتوشی بر کیلو بایت"برای تراکنش با حجم 500 بایت(نصف 1 کیلوبایت) کارمزد فقط اندازه 50 ساتوشی خواهد بود.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>به ازای هر کیلوبایت</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation>پنهان کردن</translation>
</message>
<message>
+ <source>Recommended:</source>
+ <translation>پیشنهاد شده:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>سفارشی:</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(مقداردهی کارمزد هوشمند هنوز مشخص نشده است.این کارمزد معمولا به اندازه چند بلاک طول میکشد...) </translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>ارسال همزمان به گیرنده های متعدد</translation>
</message>
<message>
+ <source>Add &amp;Recipient</source>
+ <translation>اضافه کردن &amp;گیرنده</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>پاک کردن تمامی گزینه های این فرم</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>گرد و غبار یا داست:</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>هدف زمانی تایید شدن:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>فعال کردن جایگذاری دوباره از کارمزد</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>پاک کردن همه</translation>
</message>
@@ -871,6 +1611,90 @@
<translation>کپی هزینه</translation>
</message>
<message>
+ <source>Copy after fee</source>
+ <translation>کپی کردن بعد از احتساب کارمزد</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>کپی کردن بایت ها</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>کپی کردن داست:</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>کپی کردن تغییر</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>آیا برای ارسال کردن یا فرستادن مطمئن هستید؟</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>یا</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>تو میتوانی بعدا هزینه کارمزد را افزایش بدی(signals Replace-By-Fee, BIP-125)</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>لطفا,تراکنش خود را بازبینی کنید.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>کارمزد تراکنش</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>میزان کل</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>تایید کردن ارسال کوین ها</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>آدرس گیرنده نامعتبر است.لطفا دوباره چک یا بررسی کنید.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>میزان پولی کخ پرداخت می کنید باید بزرگتر از 0 باشد.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>این میزان پول بیشتر از موجودی شما است.</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>آدرس تکراری یافت شد:آدرس ها باید فقط یک بار استفاده شوند.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>ایجاد تراکنش با خطا مواجه شد!</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>درخواست پرداخت منقضی شد یا تاریخ آن گذشت.</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>هشدار: آدرس بیت کوین نامعتبر</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>هشدار:تغییر آدرس نامعلوم</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>تایید کردن تغییر آدرس سفارشی</translation>
+ </message>
+ <message>
+ <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
+ <translation>این آدرس که شما انتخاب کرده اید بخشی از کیف پول شما نیست.هر یا همه دارایی های شما در این کیف پول به این آدرس ارسال خواهد شد.آیا مطمئن هستید؟</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(برچسب ندارد)</translation>
</message>
@@ -890,10 +1714,38 @@
<translation>برچسب:</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation>انتخاب آدرس قبلا استفاده شده</translation>
+ </message>
+ <message>
+ <source>This is a normal payment.</source>
+ <translation>این پرداحت,عادی هست.</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>آدرس بیت کوین برای ارسال پرداحت به آن</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
<source>Paste address from clipboard</source>
<translation>استفاده از آدرس کلیپ بورد</translation>
</message>
<message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation>پاک کردن این ورودی</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>استفاده از موجودی حساب</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>پیام:</translation>
</message>
@@ -908,7 +1760,11 @@
</context>
<context>
<name>SendConfirmationDialog</name>
- </context>
+ <message>
+ <source>Yes</source>
+ <translation>بله</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
<message>
@@ -919,14 +1775,30 @@
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>امضاها -ثبت/تایید پیام</translation>
+ </message>
+ <message>
<source>&amp;Sign Message</source>
- <translation>امضای پیام </translation>
+ <translation>&amp;ثبت پیام </translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>انتخاب آدرس قبلا استفاده شده</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
</message>
<message>
<source>Paste address from clipboard</source>
<translation>آدرس را بر کلیپ بورد کپی کنید</translation>
</message>
<message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
<source>Enter the message you want to sign here</source>
<translation>پیامی که می خواهید امضا کنید را اینجا وارد کنید</translation>
</message>
@@ -936,7 +1808,7 @@
</message>
<message>
<source>Sign &amp;Message</source>
- <translation>امضای پیام </translation>
+ <translation>ثبت &amp;پیام</translation>
</message>
<message>
<source>Clear &amp;All</source>
@@ -951,10 +1823,30 @@
<translation>تایید پیام</translation>
</message>
<message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>برای تولید امضا "Sign Message" و یا "ثبت پیام" را کلیک کنید</translation>
+ </message>
+ <message>
<source>The entered address is invalid.</source>
<translation>آدرس وارد شده نامعتبر است.</translation>
</message>
- </context>
+ <message>
+ <source>Message signed.</source>
+ <translation>پیام ثبت شده</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>این امضا با حرفو پیام همخوانی ندارد</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>پیام شما با خطا مواجه شد</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>پیام شما تایید شد</translation>
+ </message>
+</context>
<context>
<name>SplashScreen</name>
<message>
@@ -964,7 +1856,11 @@
</context>
<context>
<name>TrafficGraphWidget</name>
- </context>
+ <message>
+ <source>KB/s</source>
+ <translation>کیلو بایت بر ثانیه</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
@@ -972,6 +1868,10 @@
<translation>وضعیت</translation>
</message>
<message>
+ <source>Date</source>
+ <translation>تاریخ</translation>
+ </message>
+ <message>
<source>Source</source>
<translation>منبع</translation>
</message>
@@ -984,10 +1884,86 @@
<translation>از</translation>
</message>
<message>
+ <source>unknown</source>
+ <translation>ناشناس</translation>
+ </message>
+ <message>
<source>To</source>
<translation>به</translation>
</message>
- </context>
+ <message>
+ <source>own address</source>
+ <translation>آدرس خود</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>فقط-با قابلیت دیدن</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>برچسب</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>اعتبار</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>قبول نشده</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>تمامی اعتبار</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>کارمزد تراکنش</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation>میزان وجه دقیق</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>پیام</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>کامنت</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>شناسه تراکنش</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>حجم کل تراکنش</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>اطلاعات دی باگ Debug</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>تراکنش</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>ورودی ها</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>میزان وجه:</translation>
+ </message>
+ <message>
+ <source>true</source>
+ <translation>درست</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>نادرست</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
@@ -998,6 +1974,14 @@
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation>تاریخ</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>نوع</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>برچسب</translation>
</message>
@@ -1006,6 +1990,14 @@
<translation>تایید نشده</translation>
</message>
<message>
+ <source>Generated but not accepted</source>
+ <translation>تولید شده ولی هنوز قبول نشده است</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>دریافت شده با</translation>
+ </message>
+ <message>
<source>Received from</source>
<translation>دریافت شده از</translation>
</message>
@@ -1014,25 +2006,101 @@
<translation>ارسال شده به</translation>
</message>
<message>
+ <source>Payment to yourself</source>
+ <translation>پرداخت به خود</translation>
+ </message>
+ <message>
<source>Mined</source>
<translation>استخراج شده</translation>
</message>
<message>
+ <source>watch-only</source>
+ <translation>فقط-با قابلیت دیدن</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(موجود نیست)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(برچسب ندارد)</translation>
</message>
- </context>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>تاریخ و زمان تراکنش دریافت شده است</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>نوع تراکنش.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation> میزان وجه کم شده یا اضافه شده به حساب</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>همه</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>امروز</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>این هفته</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>این ماه</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>ماه گذشته</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>امسال یا این سال</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>دامنه...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>گرفته شده با</translation>
+ </message>
+ <message>
<source>Sent to</source>
<translation>ارسال شده به</translation>
</message>
<message>
+ <source>To yourself</source>
+ <translation>به خودت</translation>
+ </message>
+ <message>
<source>Mined</source>
<translation>استخراج شده</translation>
</message>
<message>
+ <source>Other</source>
+ <translation>بقیه</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>وارد کردن آدرس,شناسه تراکنش, یا برچسب برای جست و جو</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>حداقل میزان وجه</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>افزایش کارمزد تراکنش</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>کپی آدرس</translation>
</message>
@@ -1049,10 +2117,38 @@
<translation>کپی شناسه تراکنش</translation>
</message>
<message>
+ <source>Copy full transaction details</source>
+ <translation>کپی کردن تمامی اطلاعات تراکنش</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>ویرایش کردن برچسب</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>نشان دادن جرییات تراکنش</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>خارج کردن یا بالا بردن سابقه تراکنش ها</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>فایل سی اس وی (*.csv)</translation>
</message>
<message>
+ <source>Confirmed</source>
+ <translation>تایید شده</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>تاریخ</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>نوع</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>برچسب</translation>
</message>
@@ -1061,10 +2157,26 @@
<translation>آدرس</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>شناسه</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>گرفتن خروجی به مشکل خورد</translation>
</message>
- </context>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>خارج کردن موفقیت آمیز بود Exporting</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>دامنه:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>به</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
</context>
@@ -1073,69 +2185,209 @@
</context>
<context>
<name>WalletModel</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>ارسال کوین ها یا سکه ها</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>افزایش کارمزد تراکنش با خطا مواجه شد</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>آیا میخواهید اندازه کارمزد را افزایش دهید؟</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>کارمزد الان:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>افزایش دادن:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>کارمزد جدید:</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>نمیتوان تراکنش را ثبت کرد</translation>
+ </message>
</context>
<context>
<name>WalletView</name>
- </context>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;صدور</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>بازیابی یا پشتیبان گیری کیف پول</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>بازیابی یا پشتیبان گیری با خطا مواجه شد</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>بازیابی یا پشتیبان گیری موفقیت آمیز بود.</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>لغو</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>انتخابها:</translation>
+ <source>Bitcoin Core</source>
+ <translation>هسته بیت کوین</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>تغییر دادن اندیس خارج از دامنه</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>کپی رایت (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>آیا میخواهید الان پایگاه داده بلاک را بازسازی کنید؟</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>خطا در بارگذاری پایگاه داده بلاک block</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation>خطا در بازکردن پایگاه داده بلاک block</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low!</source>
+ <translation>حطا:فضای دیسک کم است!</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>در حال وارد کردن...</translation>
</message>
<message>
- <source>Specify data directory</source>
- <translation>دایرکتوری داده را مشخص کن</translation>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>میزان نامعتبر برای -%s=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>command line و JSON-RPC commands را قبول کنید</translation>
+ <source>Upgrading txindex database</source>
+ <translation>ارتقا دادن پایگاه داده اندیس تراکنش ها یا txindex</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>به عنوان daemon بک گراند را اجرا کنید و دستورات را قبول نمایید</translation>
+ <source>Loading P2P addresses...</source>
+ <translation>در حال بارگذاری آدرس های همتا-به-همتا یا P2P</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>در حال بارگذاری لیست بن...</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation>نمیتوان کلید ها را تولید کرد</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>ارتقا دادن پایگاه داده UTXO</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>در حال تایید کردن بلاک ها...</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>مبلغ تراکنش کمتر از آن است که پس از کسر هزینه تراکنش قابل ارسال باشد</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>گزینه های سرویس دهنده RPC:</translation>
+ <source>Error reading from database, shutting down.</source>
+ <translation>خواندن از پایگاه داده با خطا مواجه شد,در حال خاموش شدن.</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>ارسال اطلاعات پیگیری/خطایابی به کنسول به جای ارسال به فایل debug.log</translation>
+ <source>Information</source>
+ <translation>اطلاعات</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>شناسه کاربری برای ارتباطاتِ JSON-RPC</translation>
+ <source>Signing transaction failed</source>
+ <translation>ثبت تراکنش با خطا مواجه شد</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>رمز برای ارتباطاتِ JSON-RPC</translation>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>حجم تراکنش بسیار کم است برای پرداخت کارمزد</translation>
</message>
<message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>دستور را وقتی بهترین بلاک تغییر کرد اجرا کن (%s در دستور توسط block hash جایگزین شده است)</translation>
+ <source>This is experimental software.</source>
+ <translation>این یک نرم افزار تجربی است.</translation>
</message>
<message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>تنظیم تعداد ریسمان ها برای سرویس دهی فراخوانی های RPC (پیش فرض: %d)</translation>
+ <source>Transaction amount too small</source>
+ <translation>حجم تراکنش خیلی کم است</translation>
</message>
<message>
- <source>Specify configuration file (default: %s)</source>
- <translation>فایل تنظیمات را مشخص کنید (پیش فرض: %s)</translation>
+ <source>Transaction too large for fee policy</source>
+ <translation>حجم تراکنش خیلی زیاد است به خاطر سیاست های کارمزدی بیت کوین</translation>
</message>
<message>
- <source>Specify pid file (default: %s)</source>
- <translation>فایل pid را مشخص کنید (پیش فرض: %s)</translation>
+ <source>Transaction too large</source>
+ <translation>حجم تراکنش خیلی زیاد است</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>نمیتوان کلید های اولیه را تولید کرد.</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>در حال تایید شدن کیف پول(ها)...</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>هشدار</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>این هزینه تراکنشی است که در صورت عدم وجود هزینه تخمینی، پرداخت می کنید.</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
+ <translation>هشدار:یک بلاک از یک نسخه ناشناس در حال ماین شدن است.در این اتفاق ممکن است قوانین ناشناسی اثرات نامعلوم بگذارند.</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation>%s بسیار بزرگ انتخاب شده است.</translation>
+ </message>
+ <message>
+ <source>Keypool ran out, please call keypoolrefill first</source>
+ <translation>کلید استخر تمام شده است، لطفاً درخواست کلید استخر را پرنمایید.</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>ایجاد نخ‌های شبکه ...</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>این کمترین فی تراکنش است که در هر تراکنش پرداخت می‌نمایید.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>مقدار تراکنش نمی‌تواند منفی باشد.</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>تراکنش باید حداقل یک دریافت کننده داشته باشد</translation>
</message>
<message>
<source>Insufficient funds</source>
<translation>وجوه ناکافی</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>نمیتوان تغییر-آدرس کلید را تولید کرد.کلید های خصوصی در این کیف پول غیر فعال شده اند.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>لود شدن نمایه بلاکها..</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts
index cf8610c345..71832200df 100644
--- a/src/qt/locale/bitcoin_fi.ts
+++ b/src/qt/locale/bitcoin_fi.ts
@@ -30,6 +30,10 @@
<translation>Poista valittu osoite listalta</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Anna etsittävä osoite tai tunniste</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Vie auki olevan välilehden tiedot tiedostoon</translation>
</message>
@@ -322,6 +326,14 @@
<translation>Avaa &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Lompakko:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>oletuslompakko</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Paina poistaaksesi verkkoyhteysilmaisin käytöstä.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Ladataan lohkoindeksiä...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Välipalvelin on &lt;b&gt;käytössä&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Lähetä kolikoita Bitcoin-osoitteeseen</translation>
</message>
@@ -437,6 +453,10 @@
<source>&amp;Command-line options</source>
<translation>&amp;Komentorivin valinnat</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n aktiivinen yhteys Bitcoin-verkkoon</numerusform><numerusform>%n aktiivista yhteyttä Bitcoin-verkkoon</numerusform></translation>
+ </message>
<message>
<source>Indexing blocks on disk...</source>
<translation>Ladataan lohkoindeksiä...</translation>
@@ -445,6 +465,10 @@
<source>Processing blocks on disk...</source>
<translation>Käsitellään lohkoja levyllä...</translation>
</message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Käsitelty %n lohko rahansiirtohistoriasta.</numerusform><numerusform>Käsitelty %n lohkoa rahansiirtohistoriasta.</numerusform></translation>
+ </message>
<message>
<source>%1 behind</source>
<translation>%1 jäljessä</translation>
@@ -722,10 +746,6 @@
<translation>&amp;Osoite</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Uusi vastaanotto-osoite</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Uusi lähetysosoite</translation>
</message>
@@ -742,8 +762,12 @@
<translation>Antamasi osoite "%1" ei ole kelvollinen Bitcoin-osoite.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Antamasi osoite "%1" on jo osoitekirjassa</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Osoite "%1" on jo vastaanotto-osoitteena nimellä "%2", joten sitä ei voi lisätä lähetysosoitteeksi.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Syötetty osoite "%1" on jo osoitekirjassa nimellä "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -795,42 +819,6 @@
<source>Command-line options</source>
<translation>Komentorivi parametrit</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Käyttö:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>komentorivi parametrit</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Käyttöliittymän asetukset:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Valitse datahakemisto käynnistyksen yhteydessä (oletus: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Aseta kieli, esimerkiksi "de_DE" (oletus: järjestelmän kieli)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Käynnistä pienennettynä</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Aseta maksupyynnöille SSL-juurivarmenteet (oletus: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Näytä aloitusruutu käynnistyksen yhteydessä (oletus: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Nollaa kaikki graafisen käyttöliittymän kautta tehdyt muutokset</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -894,7 +882,15 @@
<source>Error</source>
<translation>Virhe</translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>%n GB tilaa vapaana</numerusform><numerusform>%n GB tilaa vapaana</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(tarvitaan %n GB)</numerusform><numerusform>(tarvitaan %n GB)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -997,7 +993,7 @@
</message>
<message>
<source>Number of script &amp;verification threads</source>
- <translation>Script &amp;varmistuksen threadien määrä</translation>
+ <translation>Säikeiden määrä skriptien &amp;varmistuksessa</translation>
</message>
<message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
@@ -1008,6 +1004,18 @@
<translation>Ilmoittaa, mikäli oletetettua SOCKS5-välityspalvelinta käytetään vertaisten tavoittamiseen tämän verkkotyypin kautta.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Käytä SOCKS&amp;5-välityspalvelinta tavoittamaan Tor-verkon piilotetut palvelut:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Piilota kuvake järjestelmäpalkista.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Piilota tehtäväpalkin kuvake</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Minimoi ikkuna ohjelman sulkemisen sijasta kun ikkuna suljetaan. Kun tämä asetus on käytössä, ohjelma suljetaan vain valittaessa valikosta Poistu.</translation>
</message>
@@ -1040,6 +1048,18 @@
<translation>&amp;Verkko</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Jättää pois joitain edistyneitä ominaisuuksia, mutta silti varmistaa kaikki lohkot kokonaan. Tämän asetuksen muutto vaatii koko lohkoketjun uudelleen lataamisen. Levyn käyttöaste saattaa olla hiukan suurempaa.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Karsi lohkovaraston kooksi</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Tämän asetuksen muuttaminen vaatii koko lohkoketjun uudelleenlataamista.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt;0 = jätä näin monta ydintä vapaaksi)</translation>
</message>
@@ -1072,6 +1092,14 @@
<translation>Portin uudelleenohjaus &amp;UPnP:llä</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Hyväksy yhteysiä ulkopuolelta</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Hyväksy sisääntulevia yhteyksiä</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Yhdistä Bitcoin-verkkoon SOCKS5-välityspalvelimen kautta.</translation>
</message>
@@ -1152,6 +1180,10 @@
<translation>Näytetäänkö kolikkokontrollin ominaisuuksia vai ei</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;Kolmannen osapuolen rahansiirto URL:t</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1294,6 +1326,10 @@
<translation>URI käsittely</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' ei ole kelvollinen URI. Käytä 'bitcoin:' sen sijaan.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>Maksupyynnön haku URL on virheellinen: %1</translation>
</message>
@@ -1381,6 +1417,10 @@
<translation>Noodi/Palvelu</translation>
</message>
<message>
+ <source>NodeId</source>
+ <translation>NodeId</translation>
+ </message>
+ <message>
<source>Ping</source>
<translation>Vasteaika</translation>
</message>
@@ -1463,12 +1503,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Virhe käsitellessä komentorivin valintaa: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Virhe: Annettua data-hakemistoa "%1" ei ole olemassa.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Virhe: asetustiedostoa %1 ei voida jäsentää. Käytä vain avain=arvo merkintätapaa.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Virhe: Asetustiedostoa ei voida käsitellä: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1729,6 +1773,10 @@
<translation>&amp;Poista esto</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>oletuslompakko</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Tervetuloa %1 RPC-konsoliin.</translation>
</message>
@@ -1737,6 +1785,10 @@
<translation>Käytä nuolia ylös ja alas selataksesi historiaa, sekä %1 tyhjentääkseksi ruudun.</translation>
</message>
<message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Lisätietoja konsolin käytöstä saat kirjoittamalla %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>VAROITUS: aktiiviset huijarit neuvovat kirjoittamaan komentoja tähän komentoriviin, varastaen lompakkosi sisällön. Älä käytä komentoriviä ilman täyttä ymmärrystä kirjoittamasi komennon toiminnasta.</translation>
</message>
@@ -1816,6 +1868,10 @@
<translation>Tyhjennä</translation>
</message>
<message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Luo natiivi segwit (Bech32) -osoite</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Pyydettyjen maksujen historia</translation>
</message>
@@ -1824,10 +1880,6 @@
<translation>&amp;Vastaanota maksu</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Luo Bech32-osoite</translation>
- </message>
- <message>
<source>Show the selected request (does the same as double clicking an entry)</source>
<translation>Näytä valittu pyyntö (sama toiminta kuin alkion tuplaklikkaus)</translation>
</message>
@@ -1907,6 +1959,10 @@
<translation>Viesti</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Lompakko</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Tuloksen URI on liian pitkä, yritä lyhentää otsikon tai viestin tekstiä.</translation>
</message>
@@ -2025,14 +2081,14 @@
<translation>per kilotavu</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Jos määritelty palkkio on asetettu 1000 satoshiin ja siirto on vain 250 tavua, niin "kilotavua kohti" maksaa vain 250 satoshin palkkion, kun "vähintään" maksaa 1000 satoshia. Kilotavua suuremmilla siirroilla molemmat maksavat jokaista kilotavua kohti.</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Piilota</translation>
</message>
<message>
+ <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
+ <translation>Vähimmäispalkkion maksaminen käy hyvin, kunhan verkossa on vähemmän siirtotapahtumia kuin lohkoissa on tilaa. Huomaa, että tämä saattaa johtaa ei-koskaan-vahvistuvaan siirtoon, jos verkon käsittelykyky ylittyy.</translation>
+ </message>
+ <message>
<source>(read the tooltip)</source>
<translation>(lue työkaluvinkki)</translation>
</message>
@@ -2069,6 +2125,14 @@
<translation>Vahvistusajan tavoite:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Käytä Replace-By-Fee:tä</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Replace-By-Fee:tä (BIP-125) käyttämällä voit korottaa siirtotapahtuman palkkiota sen lähettämisen jälkeen. Ilman tätä saatetaan suositella käyttämään suurempaa palkkiota kompensoimaan viiveen kasvamisen riskiä.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>&amp;Tyhjennnä Kaikki</translation>
</message>
@@ -2125,16 +2189,20 @@
<translation>Oletko varma, että haluat lähettää?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>lisätty rahansiirtomaksuna</translation>
+ <source>or</source>
+ <translation>tai</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Kokonaismäärä %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Voit korottaa palkkiota myöhemmin (osoittaa Replace-By-Fee:tä, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>tai</translation>
+ <source>Please, review your transaction.</source>
+ <translation>Tarkistathan siirtosi.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Siirtokulu</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2180,6 +2248,10 @@
<source>Pay only the required fee of %1</source>
<translation>Maksa vain vaadittu kulu %1 </translation>
</message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>Vahvistuminen alkaa arviolta %n lohkon sisällä.</numerusform><numerusform>Vahvistuminen alkaa arviolta %n lohkon sisällä.</numerusform></translation>
+ </message>
<message>
<source>Warning: Invalid Bitcoin address</source>
<translation>Varoitus: Virheellinen Bitcoin-osoite </translation>
@@ -2252,6 +2324,10 @@
<translation>V&amp;ähennä maksukulu määrästä</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>Käytä saatavilla oleva saldo</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Viesti:</translation>
</message>
@@ -2457,6 +2533,10 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Avoinna vielä %n lohkon ajan</numerusform><numerusform>Avoinna vielä %n lohkon ajan</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Avoinna %1 asti</translation>
@@ -2466,10 +2546,6 @@
<translation>ristiriidassa maksutapahtumalle, jolla on %1 varmistusta</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/ei linjalla</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/varmistamaton, %1</translation>
</message>
@@ -2498,10 +2574,6 @@
<translation>Tila</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, ei ole vielä onnistuneesti kuulutettu</translation>
- </message>
- <message>
<source>Date</source>
<translation>Aika</translation>
</message>
@@ -2639,15 +2711,15 @@
<source>Label</source>
<translation>Nimike</translation>
</message>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Avoinna vielä %n lohkon ajan</numerusform><numerusform>Avoinna vielä %n lohkon ajan</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Avoinna %1 asti</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Ei yhteydessä</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Varmistamaton</translation>
</message>
@@ -2672,10 +2744,6 @@
<translation>Epäkypsä (%1 varmistusta, saatavilla %2 jälkeen)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Tätä lohkoa ei vastaanotettu mistään muusta solmusta ja sitä ei mahdollisesti hyväksytä!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Luotu, mutta ei hyäksytty</translation>
</message>
@@ -2787,6 +2855,10 @@
<translation>Muu</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Kirjoita osoite, siirron tunniste tai nimiö etsiäksesi</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Minimimäärä</translation>
</message>
@@ -2912,6 +2984,10 @@
<translation>Lähetä kolikoita</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>Virhe nostaessa palkkiota.</translation>
+ </message>
+ <message>
<source>Increasing transaction fee failed</source>
<translation>Siirtokulun nosto epäonnistui</translation>
</message>
@@ -2924,10 +3000,18 @@
<translation>Nykyinen palkkio:</translation>
</message>
<message>
+ <source>Increase:</source>
+ <translation>Korota:</translation>
+ </message>
+ <message>
<source>New fee:</source>
<translation>Uusi palkkio:</translation>
</message>
<message>
+ <source>Confirm fee bump</source>
+ <translation>Vahvista palkkion korotus</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Siirtoa ei voida allekirjoittaa.</translation>
</message>
@@ -2970,38 +3054,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Lompakko tallennettiin onnistuneesti tiedostoon %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Peruuta</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Asetukset:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Määritä data-hakemisto</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Yhdistä noodiin hakeaksesi naapurien osoitteet ja katkaise yhteys</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Määritä julkinen osoitteesi</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Hyväksy merkkipohjaiset- ja JSON-RPC-käskyt</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Jaettu MIT -ohjelmistolisenssin alaisuudessa, katso mukana tuleva %s tiedosto tai %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Jos &lt;category&gt; on toimittamatta tai jos &lt;category&gt; = 1, tulosta kaikki debug-tieto.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Karsinta konfiguroitu alle minimin %d MiB. Käytä surempaa numeroa.</translation>
</message>
@@ -3018,18 +3082,10 @@
<translation>Virhe: Kriittinen sisäinen virhe kohdattiin, katso debug.log lisätietoja varten</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Kulu (muodossa %s/kB) joka lisätään rahansiirtoihin joita lähetät (oletus: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Karsitaan lohkovarastoa...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Aja taustalla daemonina ja hyväksy komennot</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>HTTP-palvelinta ei voitu käynnistää. Katso debug-lokista lisätietoja.</translation>
</message>
@@ -3042,42 +3098,14 @@
<translation>%s kehittäjät</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Kulusuhde (%s/kt) jota käytetään, kun kulun arviointiin tarvittava tietomäärä ei riitä (oletus: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Hyväksy valkolistatuilta vertaisilta vastaanotetut, välitetyt siirrot silloinkin, kun siirtojen välitys ei ole käytössä (oletus: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Kytkeydy annettuun osoitteeseen ja pidä linja aina auki. Käytä [host]:portin merkintätapaa IPv6:lle.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Ei voida lukita data-hakemistoa %s. %s on luultavasti jo käynnissä.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Poista kaikki lompakon rahasiirrot ja palauta vain määrätyt osat lohkoketjusta -rescan -valitsimella käynnistyksen yhteydessä.</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Virhe luettaessa %s! Avaimet luetttiin oikein, mutta rahansiirtotiedot tai osoitekirjan sisältö saattavat olla puutteellisia tai vääriä.</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Suorita käsky kun lompakossa rahansiirto muuttuu (%s cmd on vaihdettu TxID kanssa)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Muistissa pidettävien rahansiirtojen määrä tiiviiden lohkojen muodostusta varten (oletus: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Jos tämä lohko on ketjussa, oleta lohkon sekä sen edeltäjien olevan kelvollisia ja mahdollisesti ohita niiden skriptin vahvistus (0 vahvistaa kaiken, oletus: %s, testnet: %s)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>Tarkistathan että tietokoneesi päivämäärä ja kellonaika ovat oikeassa! Jos kellosi on väärässä, %s ei toimi oikein.</translation>
</message>
@@ -3086,18 +3114,6 @@
<translation>Ole hyvä ja avusta, jos %s on mielestäsi hyödyllinen. Vieraile %s saadaksesi lisää tietoa ohjelmistosta.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Pyydä vertaisten osoitteita DNS-kyselyjen avulla, mikäli osoitteita on vähän (oletus: 1, ellei -connect valitsinta käytetä)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Aseta lohkon luonnissa lisättävien siirtojen vähimmäispalkkion suhde (%s/kt) (oletus: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Aseta script varmistuksen threadien lukumäärä (%u - %d, 0= auto, &lt;0 = jätä näin monta ydintä vapaaksi, oletus: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Lohkotietokanta sisältää lohkon, joka vaikuttaa olevan tulevaisuudesta. Tämä saattaa johtua tietokoneesi virheellisesti asetetuista aika-asetuksista. Rakenna lohkotietokanta uudelleen vain jos olet varma, että tietokoneesi päivämäärä ja aika ovat oikein.</translation>
</message>
@@ -3114,10 +3130,6 @@
<translation>Tietokantaa ei onnistuttu palauttamaan tilaan ennen haarautumista. Lohkoketju pitää ladata uudestaan.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Käytä UPnP:ta kuuntelevan portin kartoitukseen (oletus: 1 kun kuunnellaan ja -proxy ei käytössä)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Varoitus: Tietoverkko ei ole sovussa! Luohijat näyttävät kokevan virhetilanteita.</translation>
</message>
@@ -3126,10 +3138,6 @@
<translation>Varoitus: Olemme ristiriidassa vertaisten kanssa! Sinun tulee päivittää tai toisten solmujen tulee päivitää.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Tallennetaanko muistivaranto sulkemisen yhteydessä ja ladataanko se käynnistyksessä (oletus: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d viimeisestä 100 lohkosta sisälsi odottamattoman versiotiedon</translation>
</message>
@@ -3142,30 +3150,10 @@
<translation>-maxmempool on oltava vähintään %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; voi olla:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Hyväksy yhteyksiä ulkopuolelta (vakioasetus: 1 jos -proxy tai -connect ei määritelty)</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Yritä palauttaa yksityiset avaimet korruptoituneesta lompakosta käynnistyksen yhteydessä</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Lohkon luonnin asetukset:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>-%s -osoitteen '%s' selvittäminen epäonnistui</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Yhteyden valinnat:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Tekijänoikeus (C) %i-%i</translation>
</message>
@@ -3174,24 +3162,12 @@
<translation>Vioittunut lohkotietokanta havaittu</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Debuggaus/Testauksen valinnat:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Älä lataa lompakkoa ja poista lompakon RPC kutsut</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Haluatko uudelleenrakentaa lohkotietokannan nyt?</translation>
</message>
<message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Ota rahansiirtojen raakavedosten julkaisu käyttöön osoitteessa &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Ota rahansiirron korvaaminen käyttöön muistivarannossa (oletus: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Virhe luodessa %s: Et voi luoda ei-HD lompakkoja tällä versiolla.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3254,8 +3230,12 @@
<translation>Virheellinen määrä -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Pidä siirtojen muistivaranto alle &lt;n&gt; megatavun (oletus: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Määrättyä lohkohakemistoa "%s" ei ole olemassa.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Päivitetään txindex -tietokantaa</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3266,26 +3246,10 @@
<translation>Ladataan kieltolistaa...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Todennusevästeen sijainti (oletus: datahakemisto)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Ei tarpeeksi tiedostomerkintöjä vapaana.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Yhdistä vain solmukohtiin &lt;net&gt;-verkossa (ipv4, ipv6 tai onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Näytä tämä ohjeviesti ja poistu</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Näytä versio ja poistu.</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Karsintaa ei voi toteuttaa negatiivisella arvolla.</translation>
</message>
@@ -3294,26 +3258,14 @@
<translation>Karsittu tila ei ole yhteensopiva -txindex:n kanssa.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Muodosta ketjun tila ja lohkoindeksi levyllä olevista blk*.dat -tiedostoista</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Muodosta ketjun tila tällä hetkellä indeksoiduista lohkoista</translation>
+ <source>Replaying blocks...</source>
+ <translation>Tarkastetaan lohkoja..</translation>
</message>
<message>
<source>Rewinding blocks...</source>
<translation>Varmistetaan lohkoja...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Aseta tietokannan välimuistin koko megatavuissa (%d - %d, oletus: %d</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Aseta lompakkotiedosto (data-hakemiston sisällä)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Lähdekoodi löytyy %s.</translation>
</message>
@@ -3326,6 +3278,10 @@
<translation>Kytkeytyminen kohteeseen %s ei onnistu tällä tietokoneella. %s on luultavasti jo käynnissä.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Avaimia ei voitu luoda</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Argumenttia -benchmark ei tueta, käytä -debug=bench.</translation>
</message>
@@ -3346,98 +3302,26 @@
<translation>Päivitetään UTXO-tietokantaa</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Käytä UPnP:ta kuuntelevan portin kartoittamiseen (oletus: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Käytä testiketjua</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>Varmistetaan lohkoja...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Lompakon debug- ja testausvalinnat:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Lompakko tarvitsee uudelleenkirjoittaa: käynnistä %s uudelleen</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Lompakon valinnat:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Salli JSON-RPC-yhteydet määritetystä lähteestä. Kelvolliset arvot &lt;ip&gt; ovat yksittäinen IP (esim. 1.2.3.4), verkko/verkkomaski (esim. 1.2.3.4/255.255.255.0) tai verkko/luokaton reititys (esim. 1.2.3.4/24). Tätä valintatapaa voidaan käyttää useita kertoja</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Kytkeydy osoitteeseen ja valkolistaa siihen yhdistävät vertaiset. Käytä [isäntä]:portti -merkintätapaa IPv6:lle</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Luo uudet tiedostot järjestelmän oletusoikeuksilla, älä umask 077:llä (toimii vain, jos lompakkotoiminto on poissa käytöstä)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Paljasta omat IP-osoitteet (oletus: 1 kun kuunnellaan ja -externalip tai -proxy ei ole käytössä)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Virhe: Saapuvien yhteyksien kuuntelu epäonnistui (kuuntelu palautti virheen %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Aja komento kun olennainen hälytys vastaanotetaan tai nähdään todella pitkä haara (%s komennossa korvataan viestillä)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Tätä pienempiä palkkioita (%s/kt) kohdellaan väittäessä, louhittaessa ja siirtoja luodessa nollana (oletus: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Mikäli paytxfee -valitsinta ei ole asetettu, sisällytä riittävä maksu, jotta siirron vahvistus alkaa keskimäärin n lohkon sisällä (oletus: %u)</translation>
- </message>
- <message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Suurin tietoa kantavien rahasiirtojen tietomäärä, joita välitetään ja louhitaan (oletus: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Satunnaista tunnisteet jokaiselle välityspalvelinyhteydelle. Tämä mahdollistaa Tor -virran eristämisen (oletus: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Siirtomäärä on liian pieni lähetettäväksi kulun vähentämisen jälkeen.</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Valkolistattuja vertaisia eivät voi DoS -estää, joten niiden siirrot välitetään aina, myös silloin, kun ne ovat jo muistivarannossa. Hyödyllinen esim. yhdyskäytävälle</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Palataksesi karsimattomaan tilaan joudut uudelleenrakentamaan tietokannan -reindex -valinnalla. Tämä lataa koko lohkoketjun uudestaan.</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(oletus: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Hyväksy julkisia REST-pyyntöjä (oletus: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Luo Tor-salattu palvelu automaattisesti (oletus: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Yhdistä SOCKS5 proxin kautta</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Virhe ladattaessa %s: Et voi poistaa HD-ominaisuutta jo olemassa olevasta HD-lompakosta.</translation>
</message>
@@ -3446,8 +3330,8 @@
<translation>Virheitä tietokantaa luettaessa, ohjelma pysäytetään.</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Tuo lohkot ulkoisesta blk000??.dat -tiedostosta käynnistettäessä</translation>
+ <source>Error upgrading chainstate database</source>
+ <translation>Virhe päivittäessä chainstate-tietokantaa</translation>
</message>
<message>
<source>Information</source>
@@ -3470,44 +3354,24 @@
<translation>Kelvoton verkkopeite määritelty argumentissa -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Pidä enimmillään &lt;n&gt; yhdistämiskelvotonta rahansiirtoa muistissa (oletus: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Pitää määritellä portti argumentilla -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Välityssolmukohdan asetukset:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC-palvelimen valinnat:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Vähennetään -maxconnections arvoa %d:stä %d:hen järjestelmän rajoitusten vuoksi.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Uudelleenskannaa lohkoketju käynnistyksen yhteydessä puuttuvien lompakon rahansiirtojen vuoksi</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Lähetä jäljitys/debug-tieto konsoliin, debug.log-tiedoston sijaan</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Näytä kaikki debuggaus valinnat: (käyttö: --help -help-debug)</translation>
+ <source>Signing transaction failed</source>
+ <translation>Siirron vahvistus epäonnistui</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Pienennä debug.log tiedosto käynnistyksen yhteydessä (vakioasetus: 1 kun ei -debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Määriteltyä lompakon hakemistoa "%s" ei ole olemassa.</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>Siirron vahvistus epäonnistui</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Määritelty lompakkohakemisto "%s" sijaitsee suhteellisessa polussa</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3518,14 +3382,6 @@
<translation>Tämä on ohjelmistoa kokeelliseen käyttöön.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor-hallintaportin salasana (oletus: tyhjä)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Tor-hallintaportti jota käytetään jos onion-kuuntelu on käytössä (oletus: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Siirtosumma liian pieni</translation>
</message>
@@ -3542,18 +3398,14 @@
<translation>Kytkeytyminen kohteeseen %s ei onnistunut tällä tietokonella (kytkeytyminen palautti virheen %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Päivitä lompakko viimeisimpään formaattiin käynnistyksen yhteydessä</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Käyttäjätunnus JSON-RPC-yhteyksille</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>Varmistetaan lompakko(ja)...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Lompakko %s sijaitsee lompakkohakemiston %s ulkopuolella.</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Varoitus</translation>
</message>
@@ -3562,68 +3414,20 @@
<translation>Varoitus: tuntemattomia uusia sääntöjä aktivoitu (versiobitti %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Toimitaanko tilassa jossa ainoastaan lohkot sallitaan (oletus: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Sinun tulee uudelleenrakentaa tietokanta -reindex -valitsimella vaihtaaksesi -txindex -arvoa</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Tyhjennetään kaikki rahansiirrot lompakosta....</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ-ilmoitusasetukset:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Salasana JSON-RPC-yhteyksille</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Suorita käsky kun paras lohko muuttuu (%s cmd on vaihdettu block hashin kanssa)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Salli DNS kyselyt -addnode, -seednode ja -connect yhteydessä</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee on asetettu erittäin suureksi! Tämänkokoisia kuluja saatetaan maksaa yhdessä rahansiirrossa.</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Älä pidä rahansiirtoja muistivarannoissa kauemmin kuin &lt;n&gt; tuntia (oletus: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Virhe ladattaessa %s: Et voi ottaa HD:ta käyttöön jo olemassa olevalle ei-HD -lompakolle.</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Virhe ladattaessa lompakkoa %s. -wallet -valitsimen pitää osoittaa tiedostonimeen (ei polkuun).</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Pakota rahansiirtojen välitys valkolistatuilta vertaisilta, vaikka ne rikkoisivatkin paikallisia välitysmääräyksiä (oletus: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Kuinka läpikäyvä lohkojen -checkblocks -todennus on (0-4, oletus: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Kuinka monta sekuntia huonosti käyttäytyviä vertaisia estetään yhdistämästä (oletus: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Tulosta debuggaustieto (oletus: %u, annettu &lt;category&gt; valinnainen)</translation>
- </message>
- <message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Pyrkii pitämään lähtevän liikenteen alle annetun tavoitetteen (megatavuina 24 tunnissa). 0 = ei rajaa (oletus: %d)</translation>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>Tämän siirtomaksun maksat, kun siirtomaksun arviointi ei ole käytettävissä.</translation>
</message>
<message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
@@ -3634,10 +3438,6 @@
<translation>Argumenttia -whitelistalwaysrelay ei tueta ja se ohitettiin. Käytä -whitelistrelay ja/tai -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Käytä erillistä SOCKS5-proxyä tavoittaaksesi vertaisia Tor-piilopalveluiden kautta (oletus: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Varoitus: Tuntemattomia lohkoversioita louhitaan! Tuntemattomia sääntöjä saattaa olla voimassa</translation>
</message>
@@ -3646,106 +3446,22 @@
<translation>%s on asetettu todella korkeaksi!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(oletus: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Pyydä vertaisten osoitteita aina DNS-kyselyjen avulla (oletus: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Virhe ladattaessa lompakkoa %s. -wallet tiedostonimen pitää osoittaa tavalliseen tiedostoon.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Virhe ladattaessa lompakkoa %s. -wallet -tiedostonimi esiintyy useaan kertaan.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Virhe ladattaessa lompakkoa %s. -wallet tiedostonimi sisältää virheellisiä merkkejä.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Kuinka monta lohkoa tarkistetaan käynnistyksessä (oletus: %u, 0 = kaikki)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Sisällytä IP-osoitteet virheenkorjauslokissa (oletus: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Avainallas tyhjentyi, ole hyvä ja kutsu keypoolrefill ensin</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Kuuntele JSON-RPC-yhteyksiä portissa &lt;port&gt; (oletus: %u tai testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Kuuntele yhteyksiä portissa &lt;port&gt; (oletus: %u tai testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Ylläpidä enimmillään &lt;n&gt; yhteyttä vertaisiin (oletus: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Aseta lompakko kuuluttamaan rahansiirtoja</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maksimi yhteyttä kohden käytettävä vastaanottopuskurin koko, &lt;n&gt;*1000 tavua (oletus: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maksimi yhteyttä kohden käytettävä lähetyspuskurin koko, &lt;n&gt;*1000 tavua (oletus: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Lisää debug-tietojen alkuun aikaleimat (oletus: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Välitä ja louhi dataa kantavia rahansiirtoja (oletus: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Välitä ei-P2SH-multisig (oletus: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Aseta avainaltaan kooksi &lt;n&gt; (oletus: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Aseta suurin BIP141-lohkopaino (oletus: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Aseta RPC-kutsujen palvelemiseen tarkoitettujen säikeiden lukumäärä (oletus: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Määritä asetustiedosto (oletus: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Määritä yhteyden aikakatkaisu millisekunneissa (minimi: 1, oletus: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Määritä pid-tiedosto (oletus: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Käytä vahvistamattomia vaihtorahoja lähetettäessä rahansiirtoja (oletus: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Käynnistetään verkkoa...</translation>
</message>
<message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>Lompakko välttää maksamasta alle vähimmäisen välityskulun.</translation>
+ </message>
+ <message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
<translation>Tämä on jokaisesta siirrosta maksettava vähimmäismaksu.</translation>
</message>
@@ -3754,10 +3470,6 @@
<translation>Tämä on lähetyksestä maksettava maksu jonka maksat</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Aikaväli sopimattomien vertaisten yhteyksien katkaisuun (oletus: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Lähetyksen siirtosumman tulee olla positiivinen</translation>
</message>
@@ -3778,6 +3490,14 @@
<translation>Lompakon saldo ei riitä</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Vaihtorahaosoitetteen avainta ei voitu luoda. Yksityisavaimet on poistettu käytöstä tässä lompakossa.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Siirtomaksun arviointi epäonnistui. Odota muutama lohko tai käytä -fallbackfee -valintaa..</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Ladataan lohkoindeksiä...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts
index 22a98e132f..046972360e 100644
--- a/src/qt/locale/bitcoin_fr.ts
+++ b/src/qt/locale/bitcoin_fr.ts
@@ -11,7 +11,7 @@
</message>
<message>
<source>&amp;New</source>
- <translation>&amp;Nouveau</translation>
+ <translation>&amp;Nouvelle</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
@@ -30,6 +30,10 @@
<translation>Supprimer de la liste l’adresse sélectionnée actuellement</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Saisir une adresse ou une étiquette à rechercher</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exporter les données de l’onglet actuel vers un fichier</translation>
</message>
@@ -322,6 +326,14 @@
<translation>Ouvrir une &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Porte-monnaie :</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>porte-monnaie par défaut</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Cliquer pour désactiver l’activité réseau.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Réindexation des blocs sur le disque...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Le serveur mandataire est &lt;b&gt;activé&lt;/b&gt; : %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Envoyer des pièces à une adresse Bitcoin</translation>
</message>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Porte-monnaie : %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Type : %1
@@ -730,10 +752,6 @@
<translation>&amp;Adresse</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nouvelle adresse de réception</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nouvelle adresse d’envoi</translation>
</message>
@@ -750,8 +768,12 @@
<translation>L’adresse saisie « %1 » n’est pas une adresse Bitcoin valide.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>L’adresse saisie « %1 » est déjà présente dans le carnet d’adresses.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>L’adresse « %1 » existe déjà en tant qu’adresse de réception avec l’étiquette « %2 » et ne peut donc pas être ajoutée en tant qu’adresse d’envoi.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>L’adresse saisie « %1 » est déjà présente dans le carnet d’adresses avec l’étiquette « %2 ».</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>Options de ligne de commande</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Utilisation :</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>options de ligne de commande</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Options de l’IU :</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Choisir un répertoire de données au démarrage (par défaut : %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Définir la langue, par exemple « fr_CH » (par défaut : la langue du système)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Démarrer minimisé</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Définir les certificats SSL racine pour les requêtes de paiement (par défaut : -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Afficher l’écran d’accueil au démarrage (par défaut : %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Réinitialiser tous les paramètres changés dans l’IUG</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -856,7 +842,7 @@
</message>
<message>
<source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation>Lorsque vous cliquez sur OK, %1 commence à télécharger et à traiter l’intégralité de la chaîne de blocs %4 (%2 Go) en débutant avec les transactions les plus anciennes de %3, quand %4 a été lancé initialement.</translation>
+ <translation>Quand vous cliquerez sur Valider, %1 commencera à télécharger et à traiter l’intégralité de la chaîne de blocs %4 (%2 Go) en débutant avec les transactions les plus anciennes de %3, quand %4 a été lancé initialement.</translation>
</message>
<message>
<source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
@@ -896,7 +882,7 @@
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Erreur : le répertoire de données indiqué « %1 » ne peut pas être créé.</translation>
+ <translation>Erreur : Le répertoire de données indiqué « %1 » ne peut pas être créé.</translation>
</message>
<message>
<source>Error</source>
@@ -1029,7 +1015,7 @@
</message>
<message>
<source>Hide the icon from the system tray.</source>
- <translation>Masquer l'icône dans la zone de notification.</translation>
+ <translation>Cacher l’icône dans la zone de notification.</translation>
</message>
<message>
<source>&amp;Hide tray icon</source>
@@ -1037,7 +1023,7 @@
</message>
<message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
- <translation>Minimiser au lieu de quitter l’application lorsque la fenêtre est fermée. Si cette option est activée, l’application ne sera fermée qu’en sélectionnant Quitter dans le menu.</translation>
+ <translation>Quand la fenêtre est fermée, réduire au lieu de quitter l’application. Si cette option est activée, l’application ne sera fermée qu’en sélectionnant Quitter dans le menu.</translation>
</message>
<message>
<source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
@@ -1068,6 +1054,22 @@
<translation>&amp;Réseau</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Désactive certaines fonctions avancées, mais tous les blocs seront quand même validés entièrement. Changer ce paramètre à sa valeur antérieure exige de retélécharger la chaîne de blocs dans son intégralité. L’espace disque utilisé pourrait être un peu plus élevé.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Élaguer l’espace de stockage des &amp;blocs jusqu’à</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>Go</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Changer ce paramètre à sa valeur antérieure exige de retélécharger la chaîne de blocs dans son intégralité.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt; 0 = laisser ce nombre de cœurs inutilisés)</translation>
</message>
@@ -1157,11 +1159,11 @@
</message>
<message>
<source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Minimiser dans la zone de notification au lieu de la barre des tâches</translation>
+ <translation>&amp;Réduire dans la zone de notification au lieu de la barre des tâches</translation>
</message>
<message>
<source>M&amp;inimize on close</source>
- <translation>M&amp;inimiser lors de la fermeture</translation>
+ <translation>Ré&amp;duire lors de la fermeture</translation>
</message>
<message>
<source>&amp;Display</source>
@@ -1193,7 +1195,7 @@
</message>
<message>
<source>&amp;OK</source>
- <translation>&amp;OK</translation>
+ <translation>&amp;Valider</translation>
</message>
<message>
<source>&amp;Cancel</source>
@@ -1252,7 +1254,7 @@
</message>
<message>
<source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
- <translation>Les informations affichées peuvent être obsolètes. Votre porte-monnaie est automatiquement synchronisé avec le réseau Bitcoin lorsque la connexion s’établit, or ce processus n’est pas encore terminé.</translation>
+ <translation>Les informations affichées peuvent être obsolètes. Votre porte-monnaie se synchronise automatiquement avec le réseau Bitcoin dès qu’une connexion est établie, mais ce processus n’est pas encore achevé.</translation>
</message>
<message>
<source>Watch-only:</source>
@@ -1334,6 +1336,10 @@
<translation>Gestion des URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' n’est pas une URI valide. Utilisez plutôt 'bitcoin:'.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>L’URL de récupération de la demande de paiement est invalide : %1</translation>
</message>
@@ -1531,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Erreur d’analyse des arguments de ligne de commande : %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Erreur : le répertoire de données indiqué « %1 » n’existe pas.</translation>
+ <translation>Erreur : Le répertoire de données indiqué « %1 » n’existe pas.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Erreur : impossible d’analyser le fichier de configuration : %1. N’utiliser que la syntaxe clef=valeur.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Erreur : Impossible d’analyser le fichier de configuration : %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1629,6 +1639,14 @@
<translation>Utilisation de la mémoire</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Porte-monnaie :</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(aucun)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Réinitialiser</translation>
</message>
@@ -1797,6 +1815,10 @@
<translation>&amp;Réhabiliter</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>porte-monnaie par défaut</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Bienvenue sur la console RPC de %1.</translation>
</message>
@@ -1821,6 +1843,14 @@
<translation>L’activité réseau est désactivée.</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Exécution de la commande sans aucun porte-monnaie</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Exécution de la commande en utilisant le porte-monnaie « %1 »</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(ID de nœud : %1)</translation>
</message>
@@ -1892,20 +1922,20 @@
<translation>Effacer</translation>
</message>
<message>
- <source>Requested payments history</source>
- <translation>Historique des paiements demandés</translation>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Les adresses SegWit natives (aussi appelées Bech32 ou BIP-173) réduisent vos frais de transaction ultérieurs et offrent une meilleure protection contre les erreurs de frappe, mais les anciens porte-monnaie ne les prennent pas en charge. Si cette option n’est pas cochée, une adresse compatible avec les anciens porte-monnaie sera plutôt créée.</translation>
</message>
<message>
- <source>&amp;Request payment</source>
- <translation>&amp;Demander un paiement</translation>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Générer une adresse SegWit native (Bech32)</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Il est moins coûteux de dépenser à partir d’adresses Bech32 (BIP-173). Elles offrent aussi une meilleure protection contre les fautes de frappe. Si cette option n’est pas cochée, une adresse SegWit enveloppée dans un P2SH sera créée, compatible avec les anciens porte-monnaie.</translation>
+ <source>Requested payments history</source>
+ <translation>Historique des paiements demandés</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Générer une adresse Bech32</translation>
+ <source>&amp;Request payment</source>
+ <translation>&amp;Demander un paiement</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1987,6 +2017,10 @@
<translation>Message</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Porte-monnaie</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>L’URI résultante est trop longue. Essayez de réduire le texte de l’étiquette ou du message.</translation>
</message>
@@ -2101,12 +2135,16 @@
<translation>réduire les paramètres des frais</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>par kilo-octet</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Déterminer des frais personnalisés par Ko (1 000 octets) de la taille virtuelle de la transaction.
+
+Note : Les frais étant calculés par octet, des frais de « 100 satoshis par Ko » pour une transaction d’une taille de 500 octets (la moitié de 1 Ko) donneront des frais de seulement 50 satoshis.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Si les frais personnalisés sont définis à 1 000 satoshis et que la transaction est seulement de 250 octets, le « par kilo-octet » ne paiera donc que 250 satoshis de frais, alors que le « total au moins » paiera 1 000 satoshis. Pour des transactions supérieures à un kilo-octet, les deux paieront par kilo-octet.</translation>
+ <source>per kilobyte</source>
+ <translation>par kilo-octet</translation>
</message>
<message>
<source>Hide</source>
@@ -2217,14 +2255,6 @@
<translation>Voulez-vous vraiment envoyer ?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>ajoutés comme frais de transaction</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Montant total %1</translation>
- </message>
- <message>
<source>or</source>
<translation>ou</translation>
</message>
@@ -2233,10 +2263,26 @@
<translation>Vous pouvez augmenter les frais ultérieurement (signale Remplacer-par-des-frais, BIP-125).</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>du porte-monnaie %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Veuillez vérifier votre transaction.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Frais de transaction</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>Ne signale pas Remplacer-par-des-frais, BIP-125.</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>Montant total</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirmer l’envoi de pièces</translation>
</message>
@@ -2254,7 +2300,7 @@
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>Le montant dépasse votre solde lorsque les frais de transaction de %1 sont inclus.</translation>
+ <translation>Le montant dépasse votre solde quand les frais de transaction de %1 sont inclus.</translation>
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
@@ -2578,10 +2624,6 @@
<translation>est en conflit avec une transaction ayant %1 confirmations</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/hors ligne</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/non confirmées, %1</translation>
</message>
@@ -2610,14 +2652,6 @@
<translation>État</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, n’a pas encore été diffusée avec succès</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, diffusée par %n nœud</numerusform><numerusform>, diffusée par %n nœuds</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Date</translation>
</message>
@@ -2702,8 +2736,12 @@
<translation>Taille totale de la transaction</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Taille virtuelle de la transaction</translation>
+ </message>
+ <message>
<source>Output index</source>
- <translation>Index de sorties</translation>
+ <translation>Index des sorties</translation>
</message>
<message>
<source>Merchant</source>
@@ -2711,7 +2749,7 @@
</message>
<message>
<source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation>Les pièces générées doivent mûrir pendant %1 blocs avant de pouvoir être dépensées. Lorsque ce bloc a été généré, il a été diffusé sur le réseau pour être ajouté à la chaîne de blocs. Si son intégration à la chaîne échoue, son état sera modifié en « refusée » et il ne sera pas possible de le dépenser. Cela peut arriver occasionnellement si un autre nœud génère un bloc à quelques secondes du vôtre.</translation>
+ <translation>Les pièces générées doivent mûrir pendant %1 blocs avant de pouvoir être dépensées. Quand vous avez généré ce bloc, il a été diffusé sur le réseau pour être ajouté à la chaîne de blocs. Si son intégration à la chaîne échoue, son état sera modifié en « refusée » et il ne sera pas possible de le dépenser. Cela peut arriver occasionnellement si un autre nœud génère un bloc à quelques secondes du vôtre.</translation>
</message>
<message>
<source>Debug information</source>
@@ -2772,10 +2810,6 @@
<translation>Ouvert jusqu’à %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Hors ligne</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Non confirmée</translation>
</message>
@@ -2800,10 +2834,6 @@
<translation>Immature (%1 confirmations, sera disponible après %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Ce bloc n’a été reçu par aucun autre nœud et ne sera probablement pas accepté !</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Générée mais refusée</translation>
</message>
@@ -2916,7 +2946,7 @@
</message>
<message>
<source>Enter address, transaction id, or label to search</source>
- <translation>Saisir l'adresse, l’ID de transaction ou l'étiquette à chercher</translation>
+ <translation>Saisir l’adresse, l’ID de transaction ou l’étiquette à chercher</translation>
</message>
<message>
<source>Min amount</source>
@@ -3114,38 +3144,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Les données du porte-monnaie ont été enregistrées avec succès vers %1</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Annuler</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Options :</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Indiquer le répertoire de données</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Se connecter à un nœud pour obtenir des adresses de pairs puis se déconnecter</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Indiquer votre propre adresse publique</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accepter les commandes JSON-RPC et en ligne de commande</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distribué sous la licence MIT d’utilisation d’un logiciel. Consulter le fichier joint %s ou %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Si &lt;category&gt; n’est pas indiqué ou si &lt;category&gt; = 1, extraire toutes les données de débogage.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>L’élagage est configuré au-dessous du minimum de %d Mio. Veuillez utiliser un nombre plus élevé.</translation>
</message>
@@ -3159,21 +3169,13 @@
</message>
<message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Erreur : une erreur interne fatale s’est produite. Voir debug.log pour plus de détails</translation>
- </message>
- <message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Les frais (en %s/ko) à ajouter aux transactions que vous envoyez (par défaut : %s)</translation>
+ <translation>Erreur : Une erreur interne fatale s’est produite. Voir debug.log pour plus de détails</translation>
</message>
<message>
<source>Pruning blockstore...</source>
<translation>Élagage du magasin de blocs...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Fonctionner en arrière-plan en tant que démon et accepter les commandes</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Impossible de démarrer le serveur HTTP. Voir le journal de débogage pour plus de détails.</translation>
</message>
@@ -3186,22 +3188,6 @@
<translation>Les développeurs de %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Un taux de frais (en %s/Ko) qui sera utilisé si l’estimation de frais ne possède pas suffisamment de données (par défaut : %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Accepter les transactions relayées reçues de pairs de la liste blanche même si le nœud ne relaie pas les transactions (par défaut : %d)</translation>
- </message>
- <message>
- <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source>
- <translation>Ajouter un nœud auquel se connecter et tenter de garder la connexion ouverte (voir l’aide de la commande RPC « addnode » pour plus d’infos)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Se lier à l’adresse donnée et toujours l’écouter. Utiliser la notation [host]:port pour l’IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Impossible d’obtenir un verrou sur le répertoire de données %s. %s fonctionne probablement déjà.</translation>
</message>
@@ -3210,36 +3196,12 @@
<translation>Il est impossible de fournir des connexions particulières et en même temps demander à addrman de trouver les connexions sortantes.</translation>
</message>
<message>
- <source>Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)</source>
- <translation>Se connecter seulement aux nœuds précisés ; -connect=0 désactive les connexions automatiques (les règles pour ce pair sont identiques à celles de -addnode)</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Supprimer toutes les transactions du porte-monnaie et ne récupérer que ces parties de la chaîne de blocs avec -rescan au démarrage</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Erreur de lecture de %s ! Toutes les clés ont été lues correctement, mais les données transactionnelles ou les entrées du carnet d’adresses sont peut-être manquantes ou incorrectes.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Exclure les informations de débogage pour une catégorie. Peut être utilisé en combinaison avec -debug=1 pour sortir les journaux de débogage pour toutes les catégories sauf une ou plusieurs particulières.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Exécuter la commande lorsqu’une transaction de porte-monnaie change (%s dans la commande est remplacée par TxID)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Si ce bloc est dans la chaîne, supposer qu’il est valide, ainsi que ces ancêtres, et ignorer potentiellement la vérification de leur script (0 pour tout vérifier, valeur par défaut : %s, réseau de test : %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Réglage moyen maximal autorisé de décalage de l’heure d’un pair. La perspective locale du temps peut être influencée par les pairs, en avance ou en retard, de cette valeur. (Par défaut : %u secondes)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Frais totaux maximaux (en %s) à utiliser en une seule transaction de porte-monnaie ou transaction brute ; les définir trop bas pourrait interrompre les grosses transactions (par défaut : %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Grouper les sorties par adresse, les sélectionnant toutes ou n’en sélectionnant aucune, au lieu d’une sélection par sortie. La confidentialité est améliorée dans la mesure où une adresse n’est utilisée qu’une fois (à moins que quelqu’un envoie à adresse après l’avoir utilisée pour une dépense). Cela pourrait entraîner des frais légèrement plus élevés, car une sélection sous-optimale des pièces pourrait en résulter en raison de la restriction supplémentaire (par défaut : %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3250,22 +3212,6 @@
<translation>Si vous trouvez %s utile, vous pouvez y contribuer. Vous trouverez davantage d’informations à propos du logiciel sur %s.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Demander les adresses de pairs par consultation DNS si l’on manque d’adresses (par défaut : 1 sauf si -connect est utilisé)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Réduire les exigences de stockage en activant l’élagage (suppression) des anciens blocs. Cela permet d’appeler le RPC « pruneblockchain » pour supprimer des blocs précis et active l’élagage automatique des anciens blocs si une taille cible en Mio est fournie. Ce mode n’est pas compatible avec -txindex et -rescan. Avertissement : ramener ce paramètre à sa valeur antérieure exige de retélécharger l’intégralité de la chaîne de blocs (par défaut : 0 = désactiver l’élagage des blocs, 1 = permettre l’élagage manuel par RPC, &gt;%u = élaguer automatiquement les fichiers de blocs pour rester en deçà de la taille cible précisée en Mio).</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Définir le taux minimal de frais (en %s/Ko) pour les transactions à inclure dans la création de blocs (par défaut : %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Définir le nombre de fils de vérification des scripts (%u à %d, 0 = auto, &lt; 0 = laisser ce nombre de cœurs inutilisés, par défaut : %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>La base de données de blocs contient un bloc qui semble provenir du futur. Cela pourrait être causé par la date et l’heure erronées de votre ordinateur. Ne reconstruisez la base de données de blocs que si vous êtes certain que la date et l’heure de votre ordinateur sont justes.</translation>
</message>
@@ -3286,18 +3232,6 @@
<translation>Impossible de rebobiner la base de données à un état préfourche. Vous devrez retélécharger la chaîne de blocs</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Utiliser l’UPnP pour mapper le port d’écoute (par défaut : 1 en écoute et sans -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Nom d’utilisateur et mot de passe haché pour les connexions JSON-RPC. Le champ &lt;userpw&gt; est au format : &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Un script python canonique est inclus dans share/rpcuser. Le client se connecte ensuite normalement en utilisant la paire d’arguments rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt;. Cette option peut être précisée plusieurs fois.</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Un porte-monnaie ne créera aucune transaction qui enfreint les limites de chaîne de la réserve de mémoire (par défaut : %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Avertissement : le réseau ne semble pas totalement d’accord ! Certains mineurs semblent éprouver des problèmes.</translation>
</message>
@@ -3306,10 +3240,6 @@
<translation>Avertissement : nous ne semblons pas être en accord complet avec nos pairs ! Une mise à niveau pourrait être nécessaire pour vous ou pour d’autres nœuds du réseau.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Enregistrer ou non la réserve de mémoire lors de la fermeture et la charger ou non lors du redémarrage (par défaut : %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d des 100 derniers blocs ont une version inattendue</translation>
</message>
@@ -3322,42 +3252,14 @@
<translation>-maxmempool doit être d’au moins %d Mo</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; peut être :</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accepter les connexions entrantes (par défaut : 1 si aucun -proxy ou -connect )</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Ajouter un commentaire à la chaîne d’agent utilisateur</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Tenter de récupérer les clés privées d’un porte-monnaie corrompu lors du démarrage</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Options de création de blocs :</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Impossible de résoudre l’adresse -%s : « %s »</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Options de sélection de la chaîne :</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>L’index de changement est hors échelle</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Options de connexion :</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Tous droits réservés (C) %i-%i</translation>
</message>
@@ -3366,38 +3268,10 @@
<translation>Une base de données de blocs corrompue a été détectée</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Options de débogage/de test :</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Ne pas charger le porte-monnaie et désactiver les appels RPC</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Voulez-vous reconstruire la base de données de blocs maintenant ?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Activer la publication du bloc de hachage dans &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Activer la publication de la transaction de hachage dans &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Activer la publication du bloc brut dans &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Activer la publication de la transaction brute dans &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Activer le remplacement de transactions dans la réserve de mémoire (par défaut : %u)</translation>
- </message>
- <message>
<source>Error creating %s: You can't create non-HD wallets with this version.</source>
<translation>Erreur de création de %s : vous ne pouvez pas créer de porte-monnaie non HD avec cette version.</translation>
</message>
@@ -3414,6 +3288,10 @@
<translation>Erreur de chargement de %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Erreur de chargement de %s : les clés privées ne peuvent être désactivées qu’à la création.</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Erreur de chargement de %s : porte-monnaie corrompu</translation>
</message>
@@ -3431,7 +3309,7 @@
</message>
<message>
<source>Error: Disk space is low!</source>
- <translation>Erreur : l’espace disque est faible !</translation>
+ <translation>Erreur : Il reste peu d’espace disque !</translation>
</message>
<message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
@@ -3466,8 +3344,12 @@
<translation>Montant invalide pour -fallbackfee=&lt;amount&gt; : « %s »</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Garder la réserve de mémoire transactionnelle sous &lt;n&gt; mégaoctets (par défaut : %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Le répertoire des blocs indiqué « %s » n’existe pas.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Mise à niveau de la base de données txindex</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3478,26 +3360,10 @@
<translation>Chargement de la liste d’interdiction...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Emplacement du fichier témoin auth (par défaut : data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Pas assez de descripteurs de fichiers proposés.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Seulement se connecter aux nœuds du réseau &lt;net&gt; (IPv4, IPv6 ou oignon)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Imprimer ce message d’aide et quitter</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Imprimer la version et quitter</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>L’élagage ne peut pas être configuré avec une valeur négative.</translation>
</message>
@@ -3506,14 +3372,6 @@
<translation>Le mode élagage n’est pas compatible avec -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Reconstruire l’état de la chaîne et l’index des blocs à partir des fichiers blk*.dat sur le disque</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Reconstruire l’état de la chaîne à partir des blocs indexés actuellement</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Relecture des blocs...</translation>
</message>
@@ -3522,18 +3380,6 @@
<translation>Rebobinage des blocs...</translation>
</message>
<message>
- <source>Send transactions with full-RBF opt-in enabled (RPC only, default: %u)</source>
- <translation>Envoyer les transactions avec « full-RBF opt-in » activé (RPC seulement, par défaut : %u)</translation>
- </message>
- <message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Définir la taille du cache de la base de données en mégaoctets (%d à %d, default: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Indiquer le fichier de porte-monnaie (dans le répertoire de données)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Le code source se trouve sur %s.</translation>
</message>
@@ -3546,6 +3392,10 @@
<translation>Impossible de se lier à %s sur cet ordinateur. %s fonctionne probablement déjà.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Impossible de générer les clés</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Argument non pris en charge -benchmark ignoré, utiliser -debug=bench.</translation>
</message>
@@ -3566,14 +3416,6 @@
<translation>Mise à niveau de la base de données UTXO</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Utiliser l’UPnP pour mapper le port d’écoute (par défaut : %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Utiliser la chaîne de test</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Le commentaire d’agent utilisateur (%s) contient des caractères dangereux.</translation>
</message>
@@ -3582,90 +3424,26 @@
<translation>Vérification des blocs... </translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Options de débogage/de test du porte-monnaie :</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Le porte-monnaie devait être réécrit : redémarrer %s pour terminer l’opération.</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Options du porte-monnaie :</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permettre les connexions JSON-RPC de sources spécifiques. Valide pour &lt;ip&gt; qui sont une IP simple (p. ex. 1.2.3.4), un réseau/masque réseau (p. ex. 1.2.3.4/255.255.255.0) ou un réseau/CIDR (p. ex. 1.2.3.4/24). Cette option peut être être précisée plusieurs fois</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Se lier à l’adresse donnée et aux pairs s’y connectant. Utiliser la notation [host]:port pour l’IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Créer de nouveaux fichiers avec les permissions système par défaut, au lieu de umask 077 (effectif seulement avec la fonction du porte-monnaie désactivée)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Découvrir ses propres adresses (par défaut : 1 en écoute et sans externalip ou -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Erreur : l’écoute des connexions entrantes a échoué (l’écoute a retourné l’erreur %s)</translation>
- </message>
- <message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Exécuter une commande lorsqu’une alerte pertinente est reçue, ou si nous voyons une bifurcation vraiment étendue (%s dans la commande est remplacé par le message)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Les frais (en %s/Ko) inférieurs à ce seuil sont considérés comme étant nuls pour le relais, le minage et la création de transactions (par défaut : %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Si paytxfee n’est pas défini, inclure suffisamment de frais afin que les transactions commencent la confirmation en moyenne avant n blocs (par défaut : %u)</translation>
+ <translation>Erreur : L’écoute des connexions entrantes a échoué (l’écoute a retourné l’erreur %s)</translation>
</message>
<message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Montant invalide pour -maxtxfee=&lt;amount&gt; : « %s » (doit être au moins les frais minrelay de %s pour prévenir le blocage des transactions)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Quantité maximale de données dans les transactions du porteur de données que nous relayons et minons (par défaut : %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Aléer les authentifiants pour chaque connexion mandataire. Cela active l’isolement de flux de Tor (par défaut : %u) </translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Le montant de la transaction est trop bas pour être envoyé une fois que les frais ont été déduits</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Les pairs de la liste blanche ne peuvent pas être bannis DoS et leurs transactions sont toujours relayées, même si elles sont déjà dans le mempool, utile p. ex. pour une passerelle</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Vous devez reconstruire la base de données en utilisant -reindex afin de revenir au mode sans élagage. Cela retéléchargera complètement la chaîne de blocs.</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(par défaut : %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Accepter les demandes REST publiques (par défaut : %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Créer automatiquement un service caché Tor (par défaut : %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Se connecter par un mandataire SOCKS5</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Erreur de chargement de %s : vous ne pouvez pas désactiver HD sur un porte-monnaie HD existant</translation>
</message>
@@ -3678,10 +3456,6 @@
<translation>Erreur de mise à niveau de la base de données d’état de la chaîne</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importe des blocs à partir d’un fichier blk000??.dat externe lors du démarrage</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informations</translation>
</message>
@@ -3702,42 +3476,14 @@
<translation>Masque réseau invalide indiqué dans -whitelist : « %s »</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Garder au plus &lt;n&gt; transactions non connectables en mémoire (par défaut : %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Un port doit être précisé avec -whitebind : « %s »</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Options de relais du nœud :</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Options du serveur RPC :</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Réduction de -maxconnections de %d à %d, due aux restrictions du système</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Réanalyser la chaîne de blocs au démarrage, à la recherche de transactions de porte-monnaie manquantes</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Envoyer les infos de débogage/trace à la console au lieu du fichier debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Montrer toutes les options de débogage (utilisation : --help --help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Réduire le fichier debug.log lors du démarrage du client (par défaut : 1 sans -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Échec de signature de la transaction</translation>
</message>
@@ -3750,14 +3496,6 @@
<translation>Ceci est un logiciel expérimental.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Mot de passe du port de contrôle Tor (par défaut : vide)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Port de contrôle Tor à utiliser si l’écoute onion est activée (par défaut :%s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Le montant de la transaction est trop bas</translation>
</message>
@@ -3778,14 +3516,6 @@
<translation>Impossible de générer les clés initiales</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Mettre à niveau le porte-monnaie au démarrage vers le format le plus récent</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nom d’utilisateur pour les connexions JSON-RPC</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>Vérification des porte-monnaie...</translation>
</message>
@@ -3802,106 +3532,18 @@
<translation>Avertissement : nouvelles règles inconnues activées (bit de version %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Fonctionner ou non en mode blocs seulement (par défaut : %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Vous devez reconstruire la base de données en utilisant -reindex afin de modifier -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Supprimer toutes les transactions du porte-monnaie...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Options de notification ZeroMQ</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Mot de passe pour les connexions JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Exécuter la commande lorsque le meilleur bloc change (%s dans cmd est remplacé par le hachage du bloc)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Autoriser les recherches DNS pour -addnode, -seednode et -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = conserver les métadonnées de transmission, p. ex. les informations du propriétaire du compte et de demande de paiement, 2 = abandonner les métadonnées de transmission)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>La valeur -maxtxfee est très élevée ! Des frais aussi élevés pourraient être payés en une seule transaction.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Se lier à l’adresse donnée pour écouter des connexions JSON-RPC. Cette option est ignorée à moins que -rpcallowip soit aussi passé. Le port est facultatif et remplace -rpcport. Utiliser la notation [host]:port pour l’IPv6. Cette option peut être précisée plusieurs fois (par défaut : 127.0.0.1 et ::1 c.-à-d. l’hôte local ou si -rpcallowip a été précisé, 0.0.0.0 et :: c.-à-d. toutes les adresses)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Ne pas conserver de transactions dans la réserve de mémoire plus de &lt;n&gt; heures (par défaut : %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Octets équivalents par sigop dans les transactions pour relayer et miner (par défaut : %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Erreur de chargement de %s : vous ne pouvez pas activer HD sur un porte-monnaie non HD existant</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Erreur de chargement du porte-monnaie %s. Le paramètre -wallet ne doit indiquer qu’un nom de fichier (pas un chemin).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Les frais (en %s/Ko) inférieurs à ce seuil sont considérés comme étant nuls pour la création de transactions (par défaut : %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Forcer le relais de transactions des pairs de la liste blanche même s’ils transgressent la politique locale de relais (par défaut : %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Degré de profondeur de la vérification des blocs -checkblocks (0-4, par défaut : %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Maintenir un index complet des transactions, utilisé par l’appel RPC getrawtransaction (obtenir la transaction brute) (par défaut : %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Délai en secondes de refus de reconnexion pour les pairs présentant un mauvais comportement (par défaut : %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Extraire les informations de débogage (par défaut : %u, fournir &lt;category&gt; est facultatif)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Définit la sérialisation de la transaction brute ou les données hexa de bloc retournées en mode non-verbose, non-segwit(0) ou segwit(1) (par défaut : %d)</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>Indiquer le répertoire où placer les porte-monnaie (par défaut : &lt;datadir&gt;/wallets s’il existe, autrement &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>Indiquer l’emplacement du fichier journal de débogage : ce peut être un chemin absolu ou un chemin relatif au répertoire de données (par défaut : %s)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Prendre en charge le filtrage des blocs et des transactions avec les filtres bloom (par défaut : %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Le taux de frais (en %s/Ko) qui indique votre tolérance à renoncer à la monnaie en l’ajoutant aux frais (par défaut : %s). Note : une sortie est rejetée si elle est considérée comme poussière pour ce taux, mais nous rejetterons toujours jusqu’aux frais de relais poussière et des frais de rejet par delà cette valeur qui sont limités par l’estimation de frais pour la cible la plus longue </translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Il s’agit des frais de transaction que vous pourriez payer si aucune estimation de frais n’est proposée.</translation>
</message>
@@ -3914,10 +3556,6 @@
<translation>La taille totale de la chaîne de version de réseau (%i) dépasse la longueur maximale (%i). Réduire le nombre ou la taille des commentaires uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Tente de garder le trafic sortant sous la cible donnée (en Mio par 24 h), 0 = sans limite (par défaut : %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>L’argument non pris en charge -socks a été trouvé. Il n’est plus possible de définir la version de SOCKS, seuls les mandataires SOCKS5 sont pris en charge.</translation>
</message>
@@ -3926,10 +3564,6 @@
<translation>Argument non pris charge -whitelistalwaysrelay ignoré, utiliser -whitelistrelay et/ou -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Utiliser un serveur mandataire SOCKS5 séparé pour atteindre les pairs par les services cachés de Tor (par défaut : %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Avertissement : des versions de blocs inconnues sont minées ! Il est possible que des règles inconnues soient en vigueur</translation>
</message>
@@ -3938,110 +3572,18 @@
<translation>Avertissement : le fichier du porte-monnaie est corrompu, les données ont été récupérées ! Le fichier %s original a été enregistré en tant que %s dans %s ; si votre solde ou vos transactions sont incorrects, vous devriez restaurer une sauvegarde.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Pairs de la liste blanche se connectant à partir de l’adresse IP donnée (p. ex. 1.2.3.4) ou du réseau noté CIDR (p. ex. 1.2.3.0/24). Peut être précisé plusieurs fois.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>La valeur %s est très élevée !</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(par défaut : %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Toujours demander les adresses des pairs par recherche DNS (par défaut : %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Erreur de chargement du porte-monnaie %s. Le paramètre -wallet doit être un fichier ordinaire.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Erreur de chargement du porte-monnaie %s. Le nom de fichier -wallet indiqué est un doublon.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Erreur de chargement du porte-monnaie %s. Il y a des caractères invalides dans le nom de fichier -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Nombre de blocs à vérifier au démarrage (par défaut : %u, 0 = tous)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Inclure les adresses IP à la sortie de débogage (par défaut : %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>La réserve de clés est épuisée, veuillez d’abord appeler « keypoolrefill »</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Écouter les connexions JSON-RPC sur &lt;port&gt; (par défaut : %u ou tesnet : %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Écouter les connexions sur &lt;port&gt; (par défaut : %u ou tesnet : %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Garder au plus &lt;n&gt; connexions avec les pairs (par défaut : %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Obliger le porte-monnaie à diffuser les transactions</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Tampon maximal de réception par connexion, &lt;n&gt;*1000 octets (par défaut : %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Tampon maximal d’envoi par connexion », &lt;n&gt;*1000 octets (par défaut : %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Ajouter l’estampille temporelle au début de la sortie de débogage (par défaut : %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Relayer et miner les transactions du porteur de données (par défaut : %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Relayer les multisignatures non-P2SH (par défaut : %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Définir la taille de la réserve de clés à &lt;n&gt; (par défaut : %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Définir le poids maximal de bloc BIP141 (par défaut : %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Définir le nombre de fils pour les appels RPC (par défaut : %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Indiquer le fichier de configuration (par défaut : %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Indiquer le délai d’expiration de la connexion en millisecondes (minimum : 1, par défaut : %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Indiquer le fichier pid (par défaut : %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Dépenser la monnaie non confirmée lors de l’envoi de transactions (par défaut : %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Démarrage des processus réseau...</translation>
</message>
@@ -4058,10 +3600,6 @@
<translation>Il s’agit des frais minimaux que vous payez si vous envoyez une transaction.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Seuil de déconnexion des pairs présentant un mauvais comportement (par défaut : %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Les montants transactionnels ne doivent pas être négatifs</translation>
</message>
@@ -4082,6 +3620,26 @@
<translation>Fonds insuffisants</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Impossible de générer une clé d’adresse de monnaie. Les clés privées sont désactivées pour ce porte-monnaie.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Impossible de mettre à niveau un porte-monnaie divisé non-HD sans mettre à niveau pour prendre en charge la réserve de clés antérieure à la division. Veuillez utiliser -upgradewallet=169900 ou -upgradewallet sans indiquer de version.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Échec d’estimation des frais. L’option de frais de repli est désactivée. Attendez quelques blocs ou activez -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Avertissement : Des clés privées ont été détectées dans le porte-monnaie {%s} dont les clés privées sont désactivées.</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Impossible d’écrire dans le répertoire de données '%s' ; veuillez vérifier les droits.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Chargement de l’index des blocs…</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fr_FR.ts b/src/qt/locale/bitcoin_fr_FR.ts
index 147c388832..10582127c4 100644
--- a/src/qt/locale/bitcoin_fr_FR.ts
+++ b/src/qt/locale/bitcoin_fr_FR.ts
@@ -30,6 +30,10 @@
<translation>Supprimer l'adresse sélectionnée de la liste</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Entrez une adresse ou une étiquette à rechercher</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exporter les données de l'onglet courant vers un fichier</translation>
</message>
@@ -326,6 +330,14 @@
<translation>Cliquez pour désactiver l'activité du réseau.</translation>
</message>
<message>
+ <source>Network activity disabled.</source>
+ <translation>Activité réseau désactivée</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Cliquez pour réactiver l'activité réseau</translation>
+ </message>
+ <message>
<source>Syncing Headers (%1%)...</source>
<translation>Synchronisation des entêtes (%1%)...</translation>
</message>
@@ -390,6 +402,10 @@
<translation>Signer vos messages avec vos adresses Bitcoin pour prouver que vous les détenez</translation>
</message>
<message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Vérifier les messages pour s'assurer qu'ils soient signés avec les adresses Bitcoin spécifiées</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Fichier</translation>
</message>
@@ -414,6 +430,10 @@
<translation>Montrer la liste des adresses d'envois utilisées et les étiquettes</translation>
</message>
<message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Afficher la liste des labels et adresses de réception utilisées</translation>
+ </message>
+ <message>
<source>Open a bitcoin: URI or payment request</source>
<translation>Ouvrir un bitcoin: URI ou demande de paiement</translation>
</message>
@@ -421,11 +441,19 @@
<source>&amp;Command-line options</source>
<translation>&amp;Options de ligne de commande</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n connexion active avec le réseau Bitcoin</numerusform><numerusform>%n connexions actives avec le réseau Bitcoin</numerusform></translation>
+ </message>
<message>
<source>Indexing blocks on disk...</source>
<translation>Indexation des blocs sur le disque...</translation>
</message>
<message>
+ <source>Processing blocks on disk...</source>
+ <translation>Traitement des blocs sur le disque</translation>
+ </message>
+ <message>
<source>%1 behind</source>
<translation>en retard de %1</translation>
</message>
@@ -454,10 +482,18 @@
<translation>À jour</translation>
</message>
<message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Afficher le %1 message d'aide pour récupérer une liste des options de ligne de commande Bitcoin</translation>
+ </message>
+ <message>
<source>%1 client</source>
<translation>%1 client</translation>
</message>
<message>
+ <source>Connecting to peers...</source>
+ <translation>Connexion au pairs...</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Rattrapage...</translation>
</message>
@@ -500,6 +536,14 @@
<translation>Transaction entrante</translation>
</message>
<message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>Génération de clé HD &lt;b&gt;activée&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Génération de clé HD &lt;b&gt;désactivée&lt;/b&gt;</translation>
+ </message>
+ <message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>Le porte-monnaie est &lt;b&gt;chiffré&lt;/b&gt; et est actuellement &lt;b&gt;déverrouillé&lt;/b&gt;</translation>
</message>
@@ -507,7 +551,11 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Le porte-monnaie est &lt;b&gt;chiffré&lt;/b&gt; et est actuellement &lt;b&gt;verrouillé&lt;/b&gt;</translation>
</message>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Une erreur fatale a eu lieu. Bitcoin ne peut plus continuer en toute sécurité et va s'éteindre</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -639,6 +687,10 @@
<translation>non</translation>
</message>
<message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Cette étiquette devient rouge si un bénéficiaire reçoit une somme plus basse que la limite actuelle de poussière.</translation>
+ </message>
+ <message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
<translation>Peut varier de +/- %1 satoshi(s) par entrée.</translation>
</message>
@@ -666,12 +718,16 @@
<translation>&amp;Étiquette</translation>
</message>
<message>
- <source>&amp;Address</source>
- <translation>&amp;Adresse</translation>
+ <source>The label associated with this address list entry</source>
+ <translation>L'étiquette associée à cette entrée du carnet d'adresses</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nouvelle adresse de réception</translation>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>L'adresse associée avec cette entrée du carnet d'adresses. Ne peut être modifiée que pour les adresses d'envoi.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;Adresse</translation>
</message>
<message>
<source>New sending address</source>
@@ -690,10 +746,6 @@
<translation>L'adresse entrée "%1" n'est pas une adresse Bitcoin valide.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>L'adresse fournie « %1 » est déjà présente dans le carnet d'adresses.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Impossible de déverrouiller le porte-monnaie.</translation>
</message>
@@ -713,6 +765,10 @@
<translation>nom</translation>
</message>
<message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Le répertoire existe déjà. Ajouter %1 si vous voulez créer un nouveau répertoire ici.</translation>
+ </message>
+ <message>
<source>Path already exists, and is not a directory.</source>
<translation>Le chemin existe déjà et ce n'est pas un répertoire. </translation>
</message>
@@ -739,23 +795,7 @@
<source>Command-line options</source>
<translation>Options de ligne de commande</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Utilisation :</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Options de ligne de commande</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Options interface graphique:</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Démarrer sous forme minimisée</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -779,6 +819,18 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>Environ %1 GB de données seront stockées dans ce répertoire, et cela augmentera au cours du temps.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>Environ %1 GB de données seront stockées dans ce répertoire.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Le porte-monnaie sera aussi stocké dans ce répertoire.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" cannot be created.</source>
<translation>Erreur: Le répertoire de données "%1" n'a pas pu être créé. </translation>
</message>
@@ -1434,6 +1486,10 @@
<source>Message</source>
<translation>Message</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Portefeuille</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1589,18 +1645,14 @@
<translation>Êtes-vous sûr de vouloir envoyer ?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>Ajoute en tant que frais de transaction</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Montant Total %1</translation>
- </message>
- <message>
<source>or</source>
<translation>ou</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Frais de transaction</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirmer l'envoi des pièces</translation>
</message>
@@ -1810,10 +1862,6 @@
<translation>État</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, n'a pas encore été diffusée avec succès</translation>
- </message>
- <message>
<source>Date</source>
<translation>Date</translation>
</message>
@@ -1944,10 +1992,6 @@
<translation>Ouvert jusqu'à %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Hors ligne</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Non Confirmé</translation>
</message>
@@ -1960,10 +2004,6 @@
<translation>Confirmée (%1 confirmations)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Ce bloc n'a été reçu par aucun autre nœud et ne sera probablement pas accepté !</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Généré mais pas accepté</translation>
</message>
@@ -2190,26 +2230,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Options :</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Spécifier le répertoire de données</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Spécifier votre adresse publique </translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accepter les commandes de JSON-RPC et de la ligne de commande</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Fonctionner en arrière-plan en tant que démon et accepter les commandes</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Impossible de démarrer le serveur HTTP. Voir le journal de débogage pour plus de détails.</translation>
</message>
@@ -2218,22 +2238,6 @@
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; peut être:</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Options de création de bloc:</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Options de connexion:</translation>
- </message>
- <message>
- <source>Debugging/Testing options:</source>
- <translation>Options de débogage/test </translation>
- </message>
- <message>
<source>Importing...</source>
<translation>
Importation ...</translation>
@@ -2243,32 +2247,16 @@ Importation ...</translation>
<translation>Vérifications des blocs...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Options du portefeuille:</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(défaut: %u)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Connecté au travers du proxy SOCKS5</translation>
- </message>
- <message>
<source>Information</source>
<translation>Information</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Options du relais de nœud: </translation>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Adresse ou nom d'hôte -onion invalide: '%s'</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>Options de serveur RPC:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Envoyer les informations de débogage/trace à la console au lieu du fichier debug.log</translation>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Adresse -proxy invalide: '%s'</translation>
</message>
<message>
<source>Signing transaction failed</source>
@@ -2291,26 +2279,10 @@ Importation ...</translation>
<translation>Transaction trop grande</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nom d'utilisateur pour les connexions JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Attention</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Mot de passe pour les connexions JSON-RPC</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(défaut: %s)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Spécifier le pid du fichier (défaut: %s)</translation>
- </message>
- <message>
<source>Insufficient funds</source>
<translation>Fonds insuffisants</translation>
</message>
diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts
index f241ae6384..b1a5cd7b64 100644
--- a/src/qt/locale/bitcoin_gl.ts
+++ b/src/qt/locale/bitcoin_gl.ts
@@ -26,6 +26,10 @@
<translation>Borrar a dirección actualmente seleccionada da listaxe</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduce dirección ou etiqueta para buscar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar os datos da pestaña actual a un arquivo.</translation>
</message>
@@ -381,15 +385,7 @@
<source>Command-line options</source>
<translation>Opcións da liña de comandos</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Emprego:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opcións da liña de comandos</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -752,6 +748,10 @@
<source>&amp;Save Image...</source>
<translation>&amp;Gardar Imaxe...</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Moedeiro</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -818,6 +818,10 @@
<source>S&amp;end</source>
<translation>&amp;Enviar</translation>
</message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Tarifa de transacción</translation>
+ </message>
</context>
<context>
<name>SendCoinsEntry</name>
@@ -996,54 +1000,10 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opcións:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Especificar directorio de datos</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Conectar a nodo para recuperar direccións de pares, e desconectar</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especificar a túa propia dirección pública</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aceptar liña de comandos e comandos JSON-RPC</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Executar no fondo como un demo e aceptar comandos</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Core de Bitcoin</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Enlazar a unha dirección dada e escoitar sempre nela. Emprega a notación [host]:post para IPv6</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Executar comando cando unha transacción do moedeiro cambia (%s no comando é substituído por TxID)</translation>
- </message>
- <message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;categoría&gt; pode ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Aceptar conexións de fóra (por defecto: 1 se non -proxy ou -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opcións de creación de bloque:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>Detectada base de datos de bloques corrupta.</translation>
</message>
@@ -1084,30 +1044,14 @@
<translation>Non hai suficientes descritores de arquivo dispoñibles.</translation>
</message>
<message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especificar arquivo do moedeiro (dentro do directorio de datos)</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>Verificando bloques...</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Executar comando cando se recibe unha alerta relevante ou vemos un fork realmente longo (%s no cmd é substituído pola mensaxe)</translation>
- </message>
- <message>
<source>Information</source>
<translation>Información</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Enviar traza/información de depuración á consola en lugar de ao arquivo debug.log</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Recortar o arquivo debug.log ao arrancar o cliente (por defecto: 1 cando no-debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Fallou a sinatura da transacción</translation>
</message>
@@ -1120,30 +1064,10 @@
<translation>A transacción é demasiado grande</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nome de usuario para conexións JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Precaución</translation>
</message>
<message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Precisas reconstruír a base de datos empregando -reindex para cambiar -txindex</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Contrasinal para conexións JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Executar comando cando o mellor bloque cambie (%s no comando é sustituído polo hash do bloque)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permitir lookup de DNS para -addnote, -seednote e -connect</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>Rede descoñecida especificada en -onlynet: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts
index bae077056a..c8088da4e2 100644
--- a/src/qt/locale/bitcoin_he.ts
+++ b/src/qt/locale/bitcoin_he.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>לחץ מקש ימני כדי לערוך כתובת או תווית</translation>
+ <translation>לחץ על הכפתור הימני בעכבר כדי לערוך את הכתובת או התווית</translation>
</message>
<message>
<source>Create a new address</source>
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>העתקת הכתובת המסומנת ללוח הגזירים</translation>
+ <translation>העתק את הכתובת המסומנת ללוח העריכה</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -30,6 +30,10 @@
<translation>מחיקת הכתובת שנבחרה מהרשימה</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>נא להזין כתובת או תווית לחיפוש</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>יצוא הנתונים מהלשונית הנוכחית לקובץ</translation>
</message>
@@ -75,7 +79,7 @@
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>העתקת &amp;תוית</translation>
+ <translation>העתקת &amp;תווית</translation>
</message>
<message>
<source>&amp;Edit</source>
@@ -132,6 +136,10 @@
<translation>נא לחזור על מילת הצופן החדשה</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>הצג סיסמא</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>נא להזין את מילת הצופן לארנק.&lt;br/&gt;נא להשתמש במילת צופן המורכבת מ&lt;b&gt;עשרה או יותר תווים אקראיים&lt;/b&gt;, או &lt;b&gt;שמונה מילים ומעלה&lt;/b&gt;.</translation>
</message>
@@ -271,19 +279,19 @@
</message>
<message>
<source>&amp;About %1</source>
- <translation>על &amp;אודות %1</translation>
+ <translation>&amp;אודות %1</translation>
</message>
<message>
<source>Show information about %1</source>
- <translation>הצגת מידע על %1</translation>
+ <translation>הצג מידע על %1</translation>
</message>
<message>
<source>About &amp;Qt</source>
- <translation>על אודות Qt</translation>
+ <translation>אודות &amp;Qt</translation>
</message>
<message>
<source>Show information about Qt</source>
- <translation>הצגת מידע על Qt</translation>
+ <translation>הצג מידע על Qt</translation>
</message>
<message>
<source>&amp;Options...</source>
@@ -318,6 +326,14 @@
<translation>פתיחת &amp;כתובת משאב…</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>ארנק:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>ארנק בררת מחדל</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>יש ללחוץ כדי לנטרל פעילות רשת.</translation>
</message>
@@ -338,6 +354,10 @@
<translation>המקטעים נוספים למפתח בכונן…</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>שרת הפרוקסי &lt;b&gt;פעיל&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>שליחת מטבעות לכתובת ביטקוין</translation>
</message>
@@ -435,11 +455,11 @@
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>חיבור אחד פעיל לרשת ביטקוין</numerusform><numerusform>%n חיבורים פעילים לרשת ביטקוין</numerusform></translation>
+ <translation><numerusform>חיבור אחד פעיל לרשת ביטקוין</numerusform><numerusform>%n חיבורים פעילים לרשת ביטקוין</numerusform><numerusform>%n חיבורים פעילים לרשת ביטקוין</numerusform><numerusform>%n חיבורים פעילים לרשת ביטקוין</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
- <translation>מאנדקס את הבלוקים על הכונן...</translation>
+ <translation>המקטעים על הכונן מסודרים באינדקס…</translation>
</message>
<message>
<source>Processing blocks on disk...</source>
@@ -502,6 +522,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>ארנק: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>סוג: %1
@@ -722,10 +748,6 @@
<translation>&amp;כתובת</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>כתובת קבלה חדשה</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>כתובת שליחה חדשה</translation>
</message>
@@ -742,8 +764,12 @@
<translation>הכתובת שהוקלדה „%1” היא אינה כתובת ביטקוין תקנית.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>הכתובת שהוקלדה „%1” כבר נמצאת בספר הכתובות.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>כתובת "%1" כבר קיימת ככתובת מקבלת עם תווית "%2" ולכן לא ניתן להוסיף אותה ככתובת שולחת</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>הכתובת שהוכנסה "%1" כבר נמצאת בפנקס הכתובות עם התווית "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -789,48 +815,12 @@
</message>
<message>
<source>About %1</source>
- <translation>על אודות %1</translation>
+ <translation>אודות %1</translation>
</message>
<message>
<source>Command-line options</source>
<translation>אפשרויות שורת פקודה</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>שימוש:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>אפשרויות שורת פקודה</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>אפשרויות ממשק</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>נא לבחור תיקיית נתונים עם הפתיחה (בררת מחדל: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>הגדרת השפה, לדוגמה „he_IL” (בררת מחדל: שפת העמרכת)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>התחלה במצב ממוזער</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>הגדרת אישורי בסיס SSL לבקשות תשלומים (בררת מחדל: -מערכת-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>הצגת מסך פתיחה בעת הפעלה (בררת מחדל: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>איפוס כל שינויי הגדרות התצוגה</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -896,11 +886,11 @@
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>ג״ב של מקום פנוי זמין</numerusform><numerusform>%n ג״ב של מקום פנוי זמינים</numerusform></translation>
+ <translation><numerusform>ג״ב של מקום פנוי זמין</numerusform><numerusform>%n ג״ב של מקום פנוי זמינים</numerusform><numerusform>%n ג״ב של מקום פנוי זמינים</numerusform><numerusform>%n ג״ב של מקום פנוי זמינים</numerusform></translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
- <translation><numerusform>(מתוך %n ג״ב נדרשים)</numerusform><numerusform>(מתוך %n ג״ב נדרשים)</numerusform></translation>
+ <translation><numerusform>(מתוך %n ג״ב נדרשים)</numerusform><numerusform>(מתוך %n ג״ב נדרשים)</numerusform><numerusform>(מתוך %n ג״ב נדרשים)</numerusform><numerusform>(מתוך %n ג״ב נדרשים)</numerusform></translation>
</message>
</context>
<context>
@@ -1012,6 +1002,18 @@
<translation>כתובת ה־IP של המתווך (לדוגמה IPv4: 127.0.0.1‏ / IPv6: ::1)</translation>
</message>
<message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation>מראה אם פרוקסי SOCKS5 המסופק כבררת מחדל משמש להתקשרות עם עמיתים באמצעות סוג רשת זה.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>השתמשו בפרוקסי SOCKS&amp;5 נפרד כדי להתקשר עם עמיתים באמצעות שירותים חבויים ברשת Tor:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>הסתר את סמל מגש המערכת</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>מזער ואל תצא מהאפליקציה עם סגירת החלון. כאשר אפשרות זו דלוקה, האפליקציה תיסגר רק בבחירת ״יציאה״ בתפריט.</translation>
</message>
@@ -1044,6 +1046,18 @@
<translation>&amp;רשת</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>משבית מספר תכונות מתקדמות אבל כל הבלוקים עדיין יעברו אימות מלא. שינוי של הגדרה זו מצריך הורדה מחדש של הבלוקצ'יין. נצילות הדיסק עלולה לעלות.</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>ג״ב</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>שינוי הגדרה זו מצריך הורדה מחדש של הבלוקצ'יין</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = אוטומטי, &lt;0 = להשאיר כזאת כמות של ליבות חופשיות)</translation>
</message>
@@ -1076,10 +1090,22 @@
<translation>מיפוי פתחה באמצעות UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>אשר חיבורים חיצוניים</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>לאפשר חיבורים &amp;נכנסים</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>התחבר לרשת הביטקוין דרך פרוקסי SOCKS5.</translation>
</message>
<message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>להתחבר &amp;דרך מתווך SOCKS5 (מתווך בררת מחדל):</translation>
+ </message>
+ <message>
<source>Proxy &amp;IP:</source>
<translation>כתובת ה־IP של המ&amp;תווך:</translation>
</message>
@@ -1108,6 +1134,10 @@
<translation>Tor</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>התחברות לרשת ביטקוין דרך מתווך SOCKS5 נפרד לשירותי Tor נסתרים.</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;חלון</translation>
</message>
@@ -1290,6 +1320,14 @@
<translation>טיפול בכתובות</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'//:bitcoin' אינה כתובת URI תקינה. השתמשו במקום ב ':bitcoin'.</translation>
+ </message>
+ <message>
+ <source>Payment request fetch URL is invalid: %1</source>
+ <translation>כתובת ה URL של בקשת התשלום אינה תקינה : %1</translation>
+ </message>
+ <message>
<source>Invalid payment address %1</source>
<translation>כתובת תשלום שגויה %1</translation>
</message>
@@ -1338,6 +1376,10 @@
<translation>זיכוי מאת %1</translation>
</message>
<message>
+ <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
+ <translation>בקשת התשלום %1 גדולה מדי (%2 בתים, מורשה %3 בתים).</translation>
+ </message>
+ <message>
<source>Error communicating with %1: %2</source>
<translation>שגיאה בעת יצירת קשר עם %1:‏ %2</translation>
</message>
@@ -1425,23 +1467,23 @@
</message>
<message numerus="yes">
<source>%n second(s)</source>
- <translation><numerusform>שנייה אחת</numerusform><numerusform>%n שניות</numerusform></translation>
+ <translation><numerusform>שנייה אחת</numerusform><numerusform>%n שניות</numerusform><numerusform>%n שניות</numerusform><numerusform>%n שניות</numerusform></translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
- <translation><numerusform>דקה אחת</numerusform><numerusform>%n דקות</numerusform></translation>
+ <translation><numerusform>דקה אחת</numerusform><numerusform>%n דקות</numerusform><numerusform>%n דקות</numerusform><numerusform>%n דקות</numerusform></translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
- <translation><numerusform>שעה אחת</numerusform><numerusform>%n שעות</numerusform></translation>
+ <translation><numerusform>שעה אחת</numerusform><numerusform>%n שעות</numerusform><numerusform>%n שעות</numerusform><numerusform>%n שעות</numerusform></translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
- <translation><numerusform>יום אחד</numerusform><numerusform>%n ימים</numerusform></translation>
+ <translation><numerusform>יום אחד</numerusform><numerusform>%n ימים</numerusform><numerusform>%n ימים</numerusform><numerusform>%n ימים</numerusform></translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
- <translation><numerusform>שבוע אחד</numerusform><numerusform>%n שבועות</numerusform></translation>
+ <translation><numerusform>שבוע אחד</numerusform><numerusform>%n שבועות</numerusform><numerusform>%n שבועות</numerusform><numerusform>%n שבועות</numerusform></translation>
</message>
<message>
<source>%1 and %2</source>
@@ -1449,7 +1491,7 @@
</message>
<message numerus="yes">
<source>%n year(s)</source>
- <translation><numerusform>שנה אחת</numerusform><numerusform>%n שנים</numerusform></translation>
+ <translation><numerusform>שנה אחת</numerusform><numerusform>%n שנים</numerusform><numerusform>%n שנים</numerusform><numerusform>%n שנים</numerusform></translation>
</message>
<message>
<source>%1 B</source>
@@ -1479,12 +1521,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>שגיאה בפענוח ארגומנטים בשורת הפקודה: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>שגיאה: תיקיית הנתונים שצוינה „%1” אינה קיימת.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>שגיאה: לא ניתן לפענח את התצורה: %1. יש להשתמש אך ורק בתחביר מפתח=ערך.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>שגיאה: כשל בפענוח קובץ הקונפיגורציה: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1518,7 +1564,7 @@
</message>
<message>
<source>Client version</source>
- <translation>גרסת מנשק</translation>
+ <translation>גרסה</translation>
</message>
<message>
<source>&amp;Information</source>
@@ -1534,7 +1580,7 @@
</message>
<message>
<source>Using BerkeleyDB version</source>
- <translation>שימוש ב־BerkeleyDB גרסה</translation>
+ <translation>גרסת BerkeleyDB</translation>
</message>
<message>
<source>Datadir</source>
@@ -1570,11 +1616,19 @@
</message>
<message>
<source>Current number of transactions</source>
- <translation>מספר הפעולה הנוכחי</translation>
+ <translation>מספר עסקאות נוכחי</translation>
</message>
<message>
<source>Memory usage</source>
- <translation>שימוש בזכרון</translation>
+ <translation>ניצול זכרון</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation>ארנק:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(אין)</translation>
</message>
<message>
<source>&amp;Reset</source>
@@ -1629,6 +1683,10 @@
<translation>סוכן משתמש</translation>
</message>
<message>
+ <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation>פתחו את לוג ניפוי השגיאות ה%1 מתיקיית הנתונים הנוכחית. עבור קבצי לוג גדולים ייתכן זמן המתנה של מספר שניות.</translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation>הקטן גודל גופן</translation>
</message>
@@ -1665,6 +1723,10 @@
<translation>פינג</translation>
</message>
<message>
+ <source>Min Ping</source>
+ <translation>פינג מינימלי</translation>
+ </message>
+ <message>
<source>Time Offset</source>
<translation>הפרש זמן</translation>
</message>
@@ -1733,6 +1795,10 @@
<translation>&amp;שחרור חסימה</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>ארנק בררת מחדל</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>ברוך בואך למסוף ה־RPC של %1.</translation>
</message>
@@ -1741,6 +1807,14 @@
<translation>יש להשתמש בחצים למעלה ומלטה כדי לנווט בהסיטוריה וב־%1 כדי לנקות את המסך.</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>הקלידו %1 לקבלת סקירה של הפקודות הזמינות.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>למידע נוסף על שימוש במסוף בקרה מסוג זה %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>אזהרה! ישנם רמאים הנוהגים לשכנע משתמשים להקליד פקודות כאן ועל ידי כך לגנוב את תכולת הארנק שלהם. אל תשתמש במסוף הבקרה מבלי שאתה מבין באופן מלא את המשמעות של הפקודה!</translation>
</message>
@@ -1749,6 +1823,14 @@
<translation>פעילות הרשת נוטרלה</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>מבצע פקודה ללא כל ארנק</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>מבצע פקודה באמצעות ארנק "%1" </translation>
+ </message>
+ <message>
<source>via %1</source>
<translation>דרך %1</translation>
</message>
@@ -1816,6 +1898,14 @@
<translation>ניקוי</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>כתובות segwit טבעיות (כלומר Bech32 או BIP-173) מפחיתות את עמלת העסקה שלכם בהמשך ומציעות הגנה נגד שגיאות כתיב, אך ארנקים ישנים לא תומכים בהן. אם לא סומן, כתובת תאימה לארנקים ישנים תיווצר במקום.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>הפקת כתובת segwit טבעית (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>היסטוריית בקשות תשלום</translation>
</message>
@@ -1903,10 +1993,18 @@
<translation>הודעה</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>ארנק</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>הכתובת שנוצרה ארוכה מדי, כדאי לנסות לקצר את הטקסט של התווית / הודעה.</translation>
</message>
- </context>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>שגיאה בקידוד ה URI לברקוד.</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -2001,6 +2099,10 @@
<translation>בחר...</translation>
</message>
<message>
+ <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
+ <translation>שימוש בעמלת בררת המחדל עלול לגרום לשליחת עסקה שתכלל בבלוק עוד מספר שעות או ימים (או לעולם לא). נא שקלו בחירה ידנית של העמלה או המתינו לאימות מלא של הבלוקצ'יין.</translation>
+ </message>
+ <message>
<source>Warning: Fee estimation is currently not possible.</source>
<translation>אזהרה</translation>
</message>
@@ -2009,6 +2111,14 @@
<translation>צמצום הגדרות עמלה</translation>
</message>
<message>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>ציינו עמלה מותאמת אישית פר קילובייט (1000 בתים) של הגודל הוירטואלי של העסקה.
+
+לתשומת לבכם: מאחר והעמלה מחושבת על בסיס פר-בית, עמלה של "100 סטושי פר קילובייט" עבור עסקה בגודל 500 בתים (חצי קילובייט) תפיק בסופו של דבר עמלה של 50 סטושי בלבד.</translation>
+ </message>
+ <message>
<source>per kilobyte</source>
<translation>עבור קילו-בית</translation>
</message>
@@ -2017,6 +2127,10 @@
<translation>הסתר</translation>
</message>
<message>
+ <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
+ <translation>זה בסדר לשלם את העמלה המינימלית כל עוד נפח הטרנזקציות קטן מנפח הבלוקים. אבל יש להיזהר כיוון שבמידה והעומס ברשת גדל, העיסקה עלולה לא להיות מאושרת לעולם.</translation>
+ </message>
+ <message>
<source>Recommended:</source>
<translation>מומלץ:</translation>
</message>
@@ -2025,6 +2139,10 @@
<translation>מותאם אישית:</translation>
</message>
<message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(שירות עמלה חכמה לא אותחל עדיין. יש להמתין מספר בלוקים...)</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>שליחה למספר מוטבים בו־זמנית</translation>
</message>
@@ -2041,6 +2159,18 @@
<translation>אבק:</translation>
</message>
<message>
+ <source>Confirmation time target:</source>
+ <translation>זמן לקבלת אישור:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>אפשר ״החלפה-על ידי עמלה״</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>באמצעות עמלה-ניתנת-לשינוי (BIP-125) תוכלו להגדיל עמלת עסקה גם לאחר שליחתה. ללא אפשרות זו, עמלה גבוהה יותר יכולה להיות מומלצת כדי להקטין את הסיכון בעיכוב אישור העסקה.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>&amp;ניקוי הכול</translation>
</message>
@@ -2085,20 +2215,32 @@
<translation>העתקת השינוי</translation>
</message>
<message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 בלוקים)</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<translation>לשלוח?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>נוספה עמלת העברה</translation>
+ <source>or</source>
+ <translation>או</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>סכום כולל %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>תוכלו להגדיל את העמלה מאוחר יותר (איתות Replace-By-Fee, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>או</translation>
+ <source>Please, review your transaction.</source>
+ <translation>אנא עברו שוב על העסקה שלכם.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>עמלת העברה</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>סכום כולל</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2117,6 +2259,10 @@
<translation>הסכום חורג מהמאזן שלך.</translation>
</message>
<message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>הסכום גבוה מהמאזן שלכם לאחר כלילת עמלת עסקה %1.</translation>
+ </message>
+ <message>
<source>Duplicate address found: addresses should only be used once each.</source>
<translation>נמצאה כתובת כפולה: יש להשתמש בכל כתובת פעם אחת בלבד.</translation>
</message>
@@ -2212,6 +2358,10 @@
<translation>ה&amp;חסרת העמלה מהסכום</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>השתמש בכלל היתרה</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>הודעה:</translation>
</message>
@@ -2418,6 +2568,10 @@
<translation>פתוחה עד %1</translation>
</message>
<message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>ישנה סתירה עם עסקה שעברה %1 אימותים</translation>
+ </message>
+ <message>
<source>in memory pool</source>
<translation>במאגר הזיכרון</translation>
</message>
@@ -2430,6 +2584,10 @@
<translation>ננטש</translation>
</message>
<message>
+ <source>%1 confirmations</source>
+ <translation>%1 אימותים</translation>
+ </message>
+ <message>
<source>Status</source>
<translation>מצב</translation>
</message>
@@ -2473,6 +2631,10 @@
<source>Credit</source>
<translation>אשראי</translation>
</message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>הבשלה בעוד בלוק %n</numerusform><numerusform>הבשלה בעוד %n בלוקים</numerusform><numerusform>הבשלה בעוד %n בלוקים</numerusform><numerusform>הבשלה בעוד %n בלוקים</numerusform></translation>
+ </message>
<message>
<source>not accepted</source>
<translation>לא התקבל</translation>
@@ -2514,6 +2676,10 @@
<translation>גודל ההעברה הכללי</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>גודל וירטואלי של עסקה</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>מפתח פלט</translation>
</message>
@@ -2522,6 +2688,10 @@
<translation>סוחר</translation>
</message>
<message>
+ <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation>מטבעות מופקים חייבים להבשיל במשך %1 בלוקים לפני שניתן לבזבזם. כשהפקתם בלוק זה, הבלוק שודר לרשת לצורך הוספה לבלוקצ'יין. אם הבלוק לא יתווסף לבלוקצ'יין, מצב הבלוק ישונה ל "לא התקבל" ולא יהיה ניתן לבזבזו. מצב זה עלול לקרות כאשר שרת ביטקוין אחר מפיק בלוק בהפרש של כמה שניות משלכם.</translation>
+ </message>
+ <message>
<source>Debug information</source>
<translation>פרטי ניפוי שגיאות</translation>
</message>
@@ -2573,17 +2743,13 @@
</message>
<message numerus="yes">
<source>Open for %n more block(s)</source>
- <translation><numerusform>פתוחה למשך בלוק אחד נוסף</numerusform><numerusform>פתוחה למשך %n בלוקים נוספים</numerusform></translation>
+ <translation><numerusform>פתוחה למשך בלוק אחד נוסף</numerusform><numerusform>פתוחה למשך %n בלוקים נוספים</numerusform><numerusform>פתוחה למשך %n בלוקים נוספים</numerusform><numerusform>פתוחה למשך %n בלוקים נוספים</numerusform></translation>
</message>
<message>
<source>Open until %1</source>
<translation>פתוחה עד %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>לא מקוונת</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>לא מאושרת</translation>
</message>
@@ -2608,10 +2774,6 @@
<translation>צעירה (%1 אישורים, תהיה זמינה לאחר %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>בלוק זה לא התקבל על ידי אף צומת אחר וככל הנראה לא יאושר!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>הבלוק יוצר אך לא אושר</translation>
</message>
@@ -2659,7 +2821,15 @@
<source>Type of transaction.</source>
<translation>סוג ההעברה.</translation>
</message>
- </context>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>ייעוד/תכלית מגדר ע"י המשתמש של העסקה.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>סכום ירד או התווסף למאזן</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
@@ -2711,6 +2881,10 @@
<translation>אחר</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>הכנס כתובת, מזהה העברה, או תווית לחיפוש</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>סכום מזערי</translation>
</message>
@@ -2719,6 +2893,10 @@
<translation>נטישת העברה</translation>
</message>
<message>
+ <source>Increase transaction fee</source>
+ <translation>הגדל עמלת העברה</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>העתקת הכתובת</translation>
</message>
@@ -2832,6 +3010,10 @@
<translation>שליחת מטבעות</translation>
</message>
<message>
+ <source>Increasing transaction fee failed</source>
+ <translation>כשל בהעלאת עמלת עסקה</translation>
+ </message>
+ <message>
<source>Do you want to increase the fee?</source>
<translation>להגדיל את העמלה?</translation>
</message>
@@ -2890,36 +3072,20 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>נתוני הארנק נשמרו בהצלחה אל %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>ביטול</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>אפשרויות:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>ציון תיקיית נתונים</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>יש להתחבר למפרק כדי לדלות כתובות עמיתים ואז להתנתק</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>נא לציין את הכתובת הפומבית שלך</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>קבלת פקודות משורת הפקודה ומ־JSON-RPC</translation>
- </message>
- <message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>שגיאה: סניה קלמה קריטית פנימית קרטה, פנה ל debug.log לפרטים</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>ריצה כסוכן ברקע וקבלת פקודות</translation>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>שרת ה HTTP לא עלה. ראו את ה debug לוג לפרטים.</translation>
</message>
<message>
<source>Bitcoin Core</source>
@@ -2930,58 +3096,42 @@
<translation>ה %s מפתחים</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>להתאגד לכתובת נתונה להאזין לה תמיד. יש להשתמש בצורה ‎[host]:port עבור IPv6.</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>מחיקת כל העברות הארנק ולשחזר רק את החלקים המסוימים בשרשרת המקטעים באמצעות ‎-rescan עם ההפעלה</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>ביצוע פקודה כאשר העברה בארנק משתנה (%s ב־cmd יוחלף ב־TxID)</translation>
+ <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
+ <translation>נא בדקו שהתאריך והשעה במחשב שלכם נכונים! אם השעון שלכם לא מסונכרן, %s לא יעבוד כהלכה.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>שימוש ב־UPnP כדי למפות את הפתחה להאזנה (בררת מחדל: 1 בעת האזנה ובלי ‎-proxy)</translation>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>אנא שקלו תרומה אם מצאתם את %s שימושי. בקרו ב %s למידע נוסף על התוכנה.</translation>
</message>
<message>
- <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>אזהרה: נראה כי הרשת אינה מסכימה באופן מלא! חלק מהכורים חווים תקלות.</translation>
- </message>
- <message>
- <source>-maxmempool must be at least %d MB</source>
- <translation>‎-maxmempool חייב להיות לפחות %d מ״ב</translation>
+ <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
+ <translation>מאגר נתוני הבלוקים מכיל בלוק עם תאריך עתידי. הדבר יכול להיגרם מתאריך ושעה שגויים במחשב שלכם. בצעו בנייה מחדש של מאגר נתוני הבלוקים רק אם אתם בטוחים שהתאריך והשעה במחשבכם נכונים</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;קטגוריה&gt; יכולה להיות:</translation>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation>קוד זה הינו גרסת טסט טרום-פרסומית. *שימוש על אחריותכם בלבד* אין לעשות שימוש בקוד לצרכי כריית בלוקים או אפליקציות מסחר.</translation>
</message>
<message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>קבלת חיבורים מבחוץ (בררת מחדל: 1 ללא ‎-proxy או ‎-connect)</translation>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation> שידור-חוזר של הבלוקים לא הצליח. תצטרכו לבצע בנייה מחדש של מאגר הנתונים באמצעות הדגל reindex-chainstate-.</translation>
</message>
<message>
- <source>Append comment to the user agent string</source>
- <translation>הוספת הערה למחרוזת סוכן המשתמש</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>הרצה-לאחור של מאגר הנתונים למצב טרום-פיצולי לא הצליחה. תצטרכו להוריד מחדש את הבלוקצ'יין.</translation>
</message>
<message>
- <source>Block creation options:</source>
- <translation>אפשרויות יצירת מקטע:</translation>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>אזהרה: נראה כי הרשת אינה מסכימה באופן מלא! חלק מהכורים חווים תקלות.</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>אפשרויות בחירת שרשרת:</translation>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation>‎-maxmempool חייב להיות לפחות %d מ״ב</translation>
</message>
<message>
<source>Change index out of range</source>
<translation>אינדקס העודף מחוץ לתחום</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>הגדרות חיבור:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>כל הזכויות שמורות (C) %i-‏%i</translation>
</message>
@@ -2990,18 +3140,14 @@
<translation>התגלה מסד נתוני מקטעים לא תקין</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>אפשרויות ניפוי/בדיקה:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>לא לטעון את הארנק ולנטרל קריאות RPC</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>האם לבנות מחדש את מסד נתוני המקטעים?</translation>
</message>
<message>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>שגיאה ביצירת %s: אין אפשרות ליצור ארנקים שאינם HD בגרסה זו.</translation>
+ </message>
+ <message>
<source>Error initializing block database</source>
<translation>שגיאה באתחול מסד נתוני המקטעים</translation>
</message>
@@ -3030,6 +3176,10 @@
<translation>האזנה נכשלה בכל פורט. השתמש ב- -listen=0 אם ברצונך בכך.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>כשל בסריקה מחדש של הארנק בזמן האתחול</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>מתבצע יבוא…</translation>
</message>
@@ -3046,6 +3196,14 @@
<translation>סכום שגוי עבור ‎-fallbackfee=&lt;amount&gt;:‏ '%s'</translation>
</message>
<message>
+ <source>Upgrading txindex database</source>
+ <translation>שדרוג מאגר נתוני txindex </translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>טעינת כתובות P2P...</translation>
+ </message>
+ <message>
<source>Loading banlist...</source>
<translation>טוען רשימת חסומים...</translation>
</message>
@@ -3054,58 +3212,34 @@
<translation>אין מספיק מידע על הקובץ</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>תמיד להתחבר למפרקים ברשת &lt;net&gt;‏ (ipv4,‏ ipv6 או onion)</translation>
+ <source>The source code is available from %s.</source>
+ <translation>קוד המקור זמין ב %s.</translation>
</message>
<message>
- <source>Print this help message and exit</source>
- <translation>להדפיס הודעת עזרה זו ולצאת</translation>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>החישוב עבור עמלת העיסקה והעודף נכשל</translation>
</message>
<message>
- <source>Print version and exit</source>
- <translation>הדפס גירסא וצא</translation>
+ <source>Unable to generate keys</source>
+ <translation>כשל בהפקת מפתחות</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>הגדרת גודל מטמון מסדי הנתונים במגה בתים (%d עד %d, בררת מחדל: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>ציון קובץ ארנק (בתוך תיקיית הנתונים)</translation>
+ <source>Upgrading UTXO database</source>
+ <translation>שדרוג מאגר נתוני UTXO </translation>
</message>
<message>
<source>Verifying blocks...</source>
<translation>המקטעים מאומתים…</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>אפשרות דיבוג/בדיקת ארנק:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>יש לכתוב את הארנק מחדש: יש להפעיל את %s כדי להמשיך</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>אפשרויות הארנק:</translation>
- </message>
- <message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>הרץ פקודה כאשר ההתראה הרלוונטית מתקבלת או כשאנחנו עדים לפיצול ארוך מאוד (%s בשורת הפקודה יוחלף ע"י ההודעה)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>סכום העברה נמוך מדי לשליחה אחרי גביית העמלה</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(בררת מחדל: %u)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>התחברות דרך מתווך SOCKS5</translation>
- </message>
- <message>
<source>Information</source>
<translation>מידע</translation>
</message>
@@ -3122,26 +3256,6 @@
<translation>עליך לציין פתחה עם ‎-whitebind:‏ '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>אפשרויות ממסר מפרק:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>הגדרות שרת RPC</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>שלח מידע דיבאג ועקבה לקונסולה במקום לקובץ debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>הצגת כל אפשרויות הניפוי (שימוש: ‎--help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>כיווץ הקובץ debug.log בהפעלת הלקוח (בררת מחדל: 1 ללא ‎-debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>החתימה על ההעברה נכשלה</translation>
</message>
@@ -3170,86 +3284,14 @@
<translation>לא ניתן להתאגד עם הפתחה %s במחשב זה (פעולת האיגוד החזירה את השגיאה %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>עדכן ארק לפורמט העדכני בהפעלה</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>שם משתמש לחיבורי JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>אזהרה</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>ססמה לחיבורי JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>יש לבצע פקודה זו כשהמקטע הטוב ביותר משתנה (%s בפקודה יוחלף בגיבוב המקטע)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>הפעלת בדיקת DNS עבור ‎-addnode,‏ ‎-seednode ו־‎-connect</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>המשתנה ‎-socks נמצא אך אין בו תמיכה עוד. הגדרת גרסת SOCKS אינה אפשרית עוד, קיימת תמיכה רק ב־SOCKS5.</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(ברירת מחדל: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>תמיד לתשאל את כתובת העמיתים באמצעות חיפוש DNS (בררת מחדל: %u)</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>כמה מקטעים לבדוק עם ההפעלה (בררת מחדל: %u,‏ 0 = הכול)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>לכלול את כתובת ה־IP בפלט ניפוי השגיאות (בררת מחדל: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>האזנה לחיבורי JSON-RPC דרך &lt;port&gt; (בררת מחדל: %u או ברשת הבדיקה: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>האזנה לחיבורים על גבי &lt;port&gt; (בררת מחדל: %u או לרשת הבדיקה: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>לשמור על &lt;n&gt; חיבורים לעמיתים לכל היותר (בררת מחדל: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>להגדיר את הארנק להפצת העברות</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>הגדרת גודל מאגר המפתחות לכדי &lt;n&gt; (בררת מחדל: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>הגדרת משקל מרבי למקטע BIP141 (בררת מחדל: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>הגדרת קובץ תצורה (בררת מחדל: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>ציון תפוגת זמן ההמתנה לחיבור במילישניות (מינימום: 1, בררת מחדל: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>ציון קובץ pid (בררת מחדל: %s)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>תהליכי הרשת מופעלים…</translation>
</message>
@@ -3262,10 +3304,6 @@
<translation>זו עמלת ההעברה שתיגבה ממך במידה של שליחת העברה.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>סף לניתוק עמיתים סוררים (בררת מחדל: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>סכומי ההעברה לא יכולים להיות שליליים</translation>
</message>
@@ -3282,6 +3320,14 @@
<translation>אין מספיק כספים</translation>
</message>
<message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>אזהרה: זוהו מפתחות פרטיים בארנק {%s} עם מפתחות פרטיים מושבתים</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>לא ניתן לכתוב אל תיקיית הנתונים ‚%s’, נא לבדוק את ההרשאות.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>מפתח המקטעים נטען…</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hi_IN.ts b/src/qt/locale/bitcoin_hi_IN.ts
index 62b46f40ac..cf969b67db 100644
--- a/src/qt/locale/bitcoin_hi_IN.ts
+++ b/src/qt/locale/bitcoin_hi_IN.ts
@@ -7,7 +7,7 @@
</message>
<message>
<source>Create a new address</source>
- <translation>नया पता लिखिए !</translation>
+ <translation>एक नया पता बनाएं</translation>
</message>
<message>
<source>&amp;New</source>
@@ -18,10 +18,26 @@
<translation>चुनिन्दा पते को सिस्टम क्लिपबोर्ड पर कापी करे !</translation>
</message>
<message>
+ <source>&amp;Copy</source>
+ <translation>&amp;कॉपी </translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>सी&amp;लूज़ </translation>
+ </message>
+ <message>
<source>Delete the currently selected address from the list</source>
<translation>सूची से वर्तमान में चयनित पता हटाएं</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>ढूँदने के लिए कृपा करके पता या लेबल टाइप करे !</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>डेटा को मौजूदा टैब से एक फ़ाइल में निर्यात करें</translation>
+ </message>
+ <message>
<source>&amp;Export</source>
<translation>&amp;निर्यात</translation>
</message>
@@ -49,13 +65,53 @@
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
<translation>ये भुगतान भेजने के लिए ये आपके बिटकॉइन पते हैं। हमेशा सिक्के भेजने से पहले राशि और प्राप्तकर्ता पते की जांच करें।</translation>
</message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>भुगतान प्राप्त करने के लिए ये आपके बीटकोइन पते हैं प्रत्येक लेनदेन के लिए एक नया प्राप्त पता उपयोग करने की सिफारिश की जाती है।</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;पता कॉपी करें </translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;संशोधित करें </translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>निर्यात पता सूची</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>कोमा द्वारा अलग की गई फ़ाइल (* .csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>निर्यात विफल रहा</translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
- </context>
+ <message>
+ <source>Label</source>
+ <translation>परचा</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>पता </translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(कोई परचा नहीं )</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
+ <source>Passphrase Dialog</source>
+ <translation>पासफ़्रेज़ डायलॉग</translation>
+ </message>
+ <message>
<source>Enter passphrase</source>
<translation>पहचान शब्द/अक्षर डालिए !</translation>
</message>
@@ -67,6 +123,18 @@
<source>Repeat new passphrase</source>
<translation>दोबारा नया पहचान शब्द/अक्षर डालिए !</translation>
</message>
+ <message>
+ <source>Show password</source>
+ <translation>पासवर्ड दिखाए</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>वॉलेट एन्क्रिप्ट करें</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>पासफ़्रेज़ बदलें</translation>
+ </message>
</context>
<context>
<name>BanTableModel</name>
@@ -193,6 +261,10 @@
<source>Confirmed</source>
<translation>पक्का</translation>
</message>
+ <message>
+ <source>(no label)</source>
+ <translation>(कोई परचा नहीं )</translation>
+ </message>
</context>
<context>
<name>EditAddressDialog</name>
@@ -218,10 +290,6 @@
<source>version</source>
<translation>संस्करण</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>खपत :</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -331,9 +399,29 @@
<source>Copy &amp;Address</source>
<translation>&amp;पता कॉपी करे</translation>
</message>
+ <message>
+ <source>Address</source>
+ <translation>पता </translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>परचा</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>वॉलेट</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>परचा</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(कोई परचा नहीं )</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -357,7 +445,11 @@
<source>Confirm the send action</source>
<translation>भेजने की पुष्टि करें</translation>
</message>
- </context>
+ <message>
+ <source>(no label)</source>
+ <translation>(कोई परचा नहीं )</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
<message>
@@ -436,9 +528,33 @@
</context>
<context>
<name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>परचा</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(कोई परचा नहीं )</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>कोमा द्वारा अलग की गई फ़ाइल (* .csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>परचा</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>पता </translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>निर्यात विफल रहा</translation>
+ </message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
@@ -455,22 +571,14 @@
<source>&amp;Export</source>
<translation>&amp;निर्यात</translation>
</message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>डेटा को मौजूदा टैब से एक फ़ाइल में निर्यात करें</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>विकल्प:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>डेटा डायरेक्टरी बताएं </translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>बैकग्राउंड में डेमॉन बन कर रन करे तथा कमांड्स स्वीकार करें </translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>ब्लॉक्स जाँचे जा रहा है...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts
index 8595068422..381c99946b 100644
--- a/src/qt/locale/bitcoin_hr.ts
+++ b/src/qt/locale/bitcoin_hr.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Desni klik za uređivanje adresa i oznaka</translation>
+ <translation>Desni klik za uređivanje adrese ili oznake</translation>
</message>
<message>
<source>Create a new address</source>
@@ -15,51 +15,55 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>Kopiraj trenutno odabranu adresu u međuspremnik</translation>
+ <translation>Kopirajte trenutno odabranu adresu u međuspremnik</translation>
</message>
<message>
<source>&amp;Copy</source>
- <translation>&amp;Kopiraj</translation>
+ <translation>&amp;Kopirajte</translation>
</message>
<message>
<source>C&amp;lose</source>
- <translation>&amp;Zatvori</translation>
+ <translation>&amp;Zatvorite</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>Brisanje trenutno odabrane adrese s popisa.</translation>
+ <translation>Obrišite trenutno odabranu adresu s popisa.</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Unesite adresu ili oznaku za pretraživanje</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>Izvoz podataka iz trenutnog lista u datoteku</translation>
+ <translation>Izvezite podatke iz trenutne kartice u datoteku</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation>&amp;Izvozi</translation>
+ <translation>&amp;Izvezite</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation>Iz&amp;briši</translation>
+ <translation>Iz&amp;brišite</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Odaberi adresu na koju šalješ novac</translation>
+ <translation>Odaberite adresu na koju ćete poslati novac</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>Odaberi adresu na koju primaš novac</translation>
+ <translation>Odaberite adresu na koju ćete primiti novac</translation>
</message>
<message>
<source>C&amp;hoose</source>
- <translation>&amp;Odaberi</translation>
+ <translation>&amp;Odaberite</translation>
</message>
<message>
<source>Sending addresses</source>
- <translation>Adresa pošiljatelja</translation>
+ <translation>Adrese pošiljatelja</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation>Adresa primatelja</translation>
+ <translation>Adrese primatelja</translation>
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
@@ -67,23 +71,23 @@
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Ovo su vaše Bitcoin adrese za primanje novca. Preporučamo da koristite novu adresu za primanje za svaku transakciju.</translation>
+ <translation>Ovo su vaše Bitcoin adrese za primanje novca. Preporučeno je da koristite novu primateljsku adresu za svaku transakciju.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>&amp;Kopiraj adresu</translation>
+ <translation>&amp;Kopirajte adresu</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>Kopiraj i označi</translation>
+ <translation>Kopirajte &amp;oznaku</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation>Uredi</translation>
+ <translation>&amp;Uredite</translation>
</message>
<message>
<source>Export Address List</source>
- <translation>Izvezi listu adresa</translation>
+ <translation>Izvezite listu adresa</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
@@ -132,12 +136,16 @@
<translation>Ponovite novu lozinku</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Prikažite lozinku</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
- <translation>Unesite novu lozinku za novčanik. &lt;br/&gt;Molimo Vas da koristite zaporku od &lt;b&gt;deset ili više slučajnih znakova&lt;/b&gt;, ili &lt;b&gt;osam ili više riječi.&lt;/b&gt;</translation>
+ <translation>Unesite novu lozinku za novčanik. &lt;br/&gt;Molimo vas da koristite zaporku od &lt;b&gt;deset ili više slučajnih znakova&lt;/b&gt;, ili &lt;b&gt;osam ili više riječi.&lt;/b&gt;</translation>
</message>
<message>
<source>Encrypt wallet</source>
- <translation>Šifriranje novčanika</translation>
+ <translation>Šifrirajte novčanik</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
@@ -145,7 +153,7 @@
</message>
<message>
<source>Unlock wallet</source>
- <translation>Otključaj novčanik</translation>
+ <translation>Otključajte novčanik</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
@@ -153,11 +161,11 @@
</message>
<message>
<source>Decrypt wallet</source>
- <translation>Dešifriranje novčanika.</translation>
+ <translation>Dešifrirajte novčanik</translation>
</message>
<message>
<source>Change passphrase</source>
- <translation>Promjena lozinke</translation>
+ <translation>Promijenite lozinku</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase to the wallet.</source>
@@ -165,7 +173,7 @@
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation>Potvrdi šifriranje novčanika</translation>
+ <translation>Potvrdite šifriranje novčanika</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
@@ -180,6 +188,10 @@
<translation>Novčanik šifriran</translation>
</message>
<message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 će se sada zatvoriti kako bi dovršio postupak šifriranja. Zapamtite da šifriranje vašeg novčanika ne može u potpunosti zaštititi vaše bitcoine od krađe preko zloćudnog softvera koji bi bio na vašem računalu.</translation>
+ </message>
+ <message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
<translation>VAŽNO: Sve prethodne pričuve vašeg novčanika trebale bi biti zamijenjene novo stvorenom, šifriranom datotekom novčanika. Zbog sigurnosnih razloga, prethodne pričuve nešifriranog novčanika će postati beskorisne čim počnete koristiti novi, šifrirani novčanik.</translation>
</message>
@@ -218,7 +230,15 @@
</context>
<context>
<name>BanTableModel</name>
- </context>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Mrežna maska</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Zabranjen do</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
@@ -227,7 +247,7 @@
</message>
<message>
<source>Synchronizing with network...</source>
- <translation>Usklađivanje s mrežom ...</translation>
+ <translation>Sinkronizira se s mrežom...</translation>
</message>
<message>
<source>&amp;Overview</source>
@@ -247,7 +267,7 @@
</message>
<message>
<source>Browse transaction history</source>
- <translation>Pretraži povijest transakcija</translation>
+ <translation>Pretražite povijest transakcija</translation>
</message>
<message>
<source>E&amp;xit</source>
@@ -255,35 +275,43 @@
</message>
<message>
<source>Quit application</source>
- <translation>Izlazak iz programa</translation>
+ <translation>Zatvorite aplikaciju</translation>
</message>
<message>
<source>&amp;About %1</source>
<translation>&amp;Više o %1</translation>
</message>
<message>
+ <source>Show information about %1</source>
+ <translation>Prikažite informacije o programu %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>Više o &amp;Qt</translation>
</message>
<message>
<source>Show information about Qt</source>
- <translation>Prikaži informacije o Qt</translation>
+ <translation>Prikažite informacije o Qt</translation>
</message>
<message>
<source>&amp;Options...</source>
<translation>Pos&amp;tavke...</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Promijenite postavke za %1</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
- <translation>Ši&amp;friraj novčanik...</translation>
+ <translation>Ši&amp;frirajte novčanik...</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>Spremi &amp;kopiju novčanika...</translation>
+ <translation>Spremite &amp;kopiju novčanika...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
- <translation>Promjena &amp;lozinke...</translation>
+ <translation>Promijenite &amp;lozinku...</translation>
</message>
<message>
<source>&amp;Sending addresses...</source>
@@ -295,15 +323,43 @@
</message>
<message>
<source>Open &amp;URI...</source>
- <translation>Otvori &amp;URI...</translation>
+ <translation>Otvorite &amp;URI...</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Novčanik:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>uobičajeni novčanik</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Kliknite da isključite mrežnu aktivnost.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Mrežna aktivnost isključena.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Kliknite da ponovo uključite mrežnu aktivnost.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Sinkroniziraju se zaglavlja (%1%)...</translation>
</message>
<message>
<source>Reindexing blocks on disk...</source>
<translation>Re-indeksiranje blokova na disku...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy je &lt;b&gt;uključen&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
- <translation>Slanje novca na bitcoin adresu</translation>
+ <translation>Pošaljite novac na Bitcoin adresu</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -319,7 +375,7 @@
</message>
<message>
<source>Open debugging and diagnostic console</source>
- <translation>Otvori konzolu za dijagnostiku</translation>
+ <translation>Otvorite konzolu za dijagnostiku</translation>
</message>
<message>
<source>&amp;Verify message...</source>
@@ -335,31 +391,31 @@
</message>
<message>
<source>&amp;Send</source>
- <translation>&amp;Pošalji</translation>
+ <translation>&amp;Pošaljite</translation>
</message>
<message>
<source>&amp;Receive</source>
- <translation>Pri&amp;mi</translation>
+ <translation>Pri&amp;mite</translation>
</message>
<message>
<source>&amp;Show / Hide</source>
- <translation>Po&amp;kaži / Sakrij</translation>
+ <translation>Po&amp;kažite / Sakrijte</translation>
</message>
<message>
<source>Show or hide the main Window</source>
- <translation>Prikaži ili sakrij glavni prozor</translation>
+ <translation>Prikažite ili sakrijte glavni prozor</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation>Šifriranje privatnih ključeva koji u novčaniku</translation>
+ <translation>Šifrirajte privatne ključeve u novčaniku</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Poruku potpišemo s bitcoin adresom, kako bi dokazali vlasništvo nad tom adresom</translation>
+ <translation>Poruku potpišemo s Bitcoin adresom, kako bi dokazali vlasništvo nad tom adresom</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Provjeravanje poruke, kao dokaz, da je potpisana navedenom bitcoin adresom</translation>
+ <translation>Provjerite poruku da je potpisana s navedenom Bitcoin adresom</translation>
</message>
<message>
<source>&amp;File</source>
@@ -379,19 +435,19 @@
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Zatraži uplatu (stvara QR kod i bitcoin: URI adresu)</translation>
+ <translation>Zatražite uplatu (stvara QR kod i bitcoin: URI adresu)</translation>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
- <translation>Prikaži popis korištenih adresa i oznaka za slanje novca</translation>
+ <translation>Prikažite popis korištenih adresa i oznaka za slanje novca</translation>
</message>
<message>
<source>Show the list of used receiving addresses and labels</source>
- <translation>Prikaži popis korištenih adresa i oznaka za primanje novca</translation>
+ <translation>Prikažite popis korištenih adresa i oznaka za primanje novca</translation>
</message>
<message>
<source>Open a bitcoin: URI or payment request</source>
- <translation>Otvori bitcoin: URI adresu ili zahtjev za uplatu</translation>
+ <translation>Otvorite bitcoin: URI adresu ili zahtjev za uplatu</translation>
</message>
<message>
<source>&amp;Command-line options</source>
@@ -403,17 +459,21 @@
</message>
<message>
<source>Indexing blocks on disk...</source>
- <translation>Indeksiram blokove na disku...</translation>
+ <translation>Indeksiraju se blokovi na disku...</translation>
</message>
<message>
<source>Processing blocks on disk...</source>
- <translation>Procesiram blokove na disku...</translation>
+ <translation>Procesiraju se blokovi na disku...</translation>
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation><numerusform>Obrađen %n blok povijesti transakcije.</numerusform><numerusform>Obrađeno %n bloka povijesti transakcije.</numerusform><numerusform>Obrađeno %n blokova povijesti transakcije.</numerusform></translation>
</message>
<message>
+ <source>%1 behind</source>
+ <translation>%1 iza</translation>
+ </message>
+ <message>
<source>Last received block was generated %1 ago.</source>
<translation>Zadnji primljeni blok je bio ustvaren prije %1.</translation>
</message>
@@ -438,10 +498,18 @@
<translation>Ažurno</translation>
</message>
<message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Prikažite pomoć programa %1 kako biste ispisali moguće opcije preko terminala</translation>
+ </message>
+ <message>
<source>%1 client</source>
<translation>%1 klijent</translation>
</message>
<message>
+ <source>Connecting to peers...</source>
+ <translation>Spaja se na klijente...</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Ažuriranje...</translation>
</message>
@@ -458,6 +526,11 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Novčanik: %1</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Vrsta: %1
@@ -484,6 +557,14 @@
<translation>Dolazna transakcija</translation>
</message>
<message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>Generiranje HD ključeva je &lt;b&gt;uključeno&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Generiranje HD ključeva je &lt;b&gt;isključeno&lt;/b&gt;</translation>
+ </message>
+ <message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>Novčanik je &lt;b&gt;šifriran&lt;/b&gt; i trenutno &lt;b&gt;otključan&lt;/b&gt;</translation>
</message>
@@ -491,7 +572,11 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Novčanik je &lt;b&gt;šifriran&lt;/b&gt; i trenutno &lt;b&gt;zaključan&lt;/b&gt;</translation>
</message>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Dogodila se kobna greška. Bitcoin ne može više sigurno nastaviti te će se zatvoriti.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -516,7 +601,11 @@
</message>
<message>
<source>Dust:</source>
- <translation>Prah:</translation>
+ <translation>Prašina:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Nakon naknade:</translation>
</message>
<message>
<source>Change:</source>
@@ -527,6 +616,14 @@
<translation>Izaberi sve/ništa</translation>
</message>
<message>
+ <source>Tree mode</source>
+ <translation>Prikažite kao stablo</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Prikažite kao listu</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Iznos</translation>
</message>
@@ -552,19 +649,55 @@
</message>
<message>
<source>Copy address</source>
- <translation>Kopiraj adresu</translation>
+ <translation>Kopirajte adresu</translation>
</message>
<message>
<source>Copy label</source>
- <translation>Kopiraj oznaku</translation>
+ <translation>Kopirajte oznaku</translation>
</message>
<message>
<source>Copy amount</source>
- <translation>Kopiraj iznos</translation>
+ <translation>Kopirajte iznos</translation>
</message>
<message>
<source>Copy transaction ID</source>
- <translation>Kopiraj ID transakcije</translation>
+ <translation>Kopirajte ID transakcije</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Zaključajte nepotrošen input</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Otključajte nepotrošen input</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Kopirajte iznos</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Kopirajte naknadu</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Kopirajte iznos nakon naknade</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Kopirajte količinu bajtova</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Kopirajte prašinu</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Kopirajte ostatak</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 zaključen)</translation>
</message>
<message>
<source>yes</source>
@@ -575,15 +708,31 @@
<translation>ne</translation>
</message>
<message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Oznaka postane crvene boje ako bilo koji primatelj dobije iznos manji od trenutnog praga "prašine" (sićušnog iznosa).</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Može varirati +/- %1 satoši(ja) po inputu.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(nema oznake)</translation>
</message>
- </context>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>ostatak od %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(ostatak)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
- <translation>Uredi adresu</translation>
+ <translation>Uredite adresu</translation>
</message>
<message>
<source>&amp;Label</source>
@@ -591,21 +740,17 @@
</message>
<message>
<source>The label associated with this address list entry</source>
- <translation>Oznaka bitcoin adrese</translation>
+ <translation>Oznaka ovog zapisa u adresaru</translation>
</message>
<message>
<source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Bitcoin adresa. Izmjene adrese su moguće samo za adrese za slanje.</translation>
+ <translation>Adresa ovog zapisa u adresaru. Može se mijenjati samo kod adresa za slanje.</translation>
</message>
<message>
<source>&amp;Address</source>
<translation>&amp;Adresa</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nova adresa za primanje</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nova adresa za slanje</translation>
</message>
@@ -619,15 +764,19 @@
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>Upisana adresa "%1" nije valjana bitcoin adresa.</translation>
+ <translation>Upisana adresa "%1" nije valjana Bitcoin adresa.</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adresa "%1" već postoji kao primateljska adresa s oznakom "%2" te se ne može dodati kao pošiljateljska adresa.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Upisana adresa "%1" je već u adresaru.</translation>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Unesena adresa "%1" postoji već u imeniku pod oznakom "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation>Ne mogu otključati novčanik.</translation>
+ <translation>Ne može se otključati novčanik.</translation>
</message>
<message>
<source>New key generation failed.</source>
@@ -638,13 +787,21 @@
<name>FreespaceChecker</name>
<message>
<source>A new data directory will be created.</source>
- <translation>Stvoren će biti novi direktorij za podatke.</translation>
+ <translation>Bit će stvorena nova podatkovna mapa.</translation>
</message>
<message>
<source>name</source>
<translation>ime</translation>
</message>
<message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Mapa već postoji. Dodajte %1 ako namjeravate stvoriti novu mapu ovdje.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>Put već postoji i nije mapa.</translation>
+ </message>
+ <message>
<source>Cannot create data directory here.</source>
<translation>Nije moguće stvoriti direktorij za podatke na tom mjestu.</translation>
</message>
@@ -660,36 +817,80 @@
<translation>(%1-bit)</translation>
</message>
<message>
+ <source>About %1</source>
+ <translation>O programu %1</translation>
+ </message>
+ <message>
<source>Command-line options</source>
<translation>Opcije programa u naredbenoj liniji</translation>
</message>
+</context>
+<context>
+ <name>Intro</name>
<message>
- <source>Usage:</source>
- <translation>Upotreba:</translation>
+ <source>Welcome</source>
+ <translation>Dobrodošli</translation>
</message>
<message>
- <source>command-line options</source>
- <translation>opcije programa u naredbenoj liniji</translation>
+ <source>Welcome to %1.</source>
+ <translation>Dobrodošli u %1.</translation>
</message>
<message>
- <source>Start minimized</source>
- <translation>Pokreni minimiziran</translation>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation>Kako je ovo prvi put da je ova aplikacija pokrenuta, možete izabrati gdje će %1 spremati svoje podatke.</translation>
</message>
- </context>
-<context>
- <name>Intro</name>
<message>
- <source>Welcome</source>
- <translation>Dobrodošli</translation>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>Kada kliknete OK, %1 počet će preuzimati i procesirati cijeli lanac blokova (%2GB) počevši s najranijim transakcijama u %3 kad je %4 prvi put pokrenut.</translation>
+ </message>
+ <message>
+ <source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
+ <translation>Početna sinkronizacija je vrlo zahtjevna i može otkriti hardverske probleme kod vašeg računala koji su prije prošli nezamijećeno. Svaki put kad pokrenete %1, nastavit će preuzimati odakle je stao.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>Ako odlučite ograničiti spremanje lanca blokova pomoću pruninga (obrezivanja), treba preuzeti i procesirati povijesne podatke. Bit će obrisani naknadno kako bi se smanjila količina zauzetog prostora na disku.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>Koristite uobičajenu podatkovnu mapu</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>Odaberite različitu podatkovnu mapu:</translation>
</message>
<message>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>Bit će spremljeno barem %1 GB podataka u ovoj mapi te će se povećati tijekom vremena.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>Otprilike %1 GB podataka bit će spremljeno u ovoj mapi.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>%1 preuzet će i pohraniti kopiju Bitcoinovog lanca blokova.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Novčanik bit će pohranjen u ovoj mapi.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>Greška: Zadana podatkovna mapa "%1" ne može biti stvorena.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Greška</translation>
</message>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>Dostupno %n GB slobodnog prostora</numerusform><numerusform>Dostupno %n GB slobodnog prostora</numerusform><numerusform>Dostupno %n GB slobodnog prostora</numerusform></translation>
+ </message>
</context>
<context>
<name>ModalOverlay</name>
@@ -698,10 +899,50 @@
<translation>Oblik</translation>
</message>
<message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation>Nedavne transakcije možda još nisu vidljive pa vam stanje novčanika može biti netočno. Ove informacije bit će točne nakon što vaš novčanik dovrši sinkronizaciju s Bitcoinovom mrežom, kako je opisano dolje.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation>Mreža neće prihvatiti pokušaje trošenja bitcoina koji su utjecani sa strane transakcija koje još nisu vidljive.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Broj preostalih blokova</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Nepoznato...</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation>Posljednje vrijeme bloka</translation>
</message>
- </context>
+ <message>
+ <source>Progress</source>
+ <translation>Napredak</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>Postotak povećanja napretka na sat</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>računa...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Preostalo vrijeme do završetka sinkronizacije</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Sakrijte</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1)...</source>
+ <translation>Nepoznato. Sinkroniziraju se zaglavlja (%1)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -736,6 +977,14 @@
<translation>&amp;Glavno</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Automatski pokrenite %1 nakon prijave u sustav.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Pokrenite %1 kod prijave u sustav</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation>Veličina predmemorije baze podataka</translation>
</message>
@@ -752,10 +1001,42 @@
<translation>IP adresa proxy servera (npr. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
</message>
<message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation>Prikazuje se ako je isporučeni uobičajeni SOCKS5 proxy korišten radi dohvaćanja klijenata preko ovog tipa mreže.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Koristite zaseban SOCKS&amp;5 proxy kako biste dohvatili klijente preko Tora:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Sakrijte ikonu sa sustavne trake.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Sakrijte ikonu</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Minimizirati aplikaciju umjesto zatvoriti, kada se zatvori prozor. Kada je ova opcija omogućena, aplikacija će biti zatvorena tek nakon odabira naredbe Izlaz u izborniku.</translation>
</message>
<message>
+ <source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
+ <translation>URL-ovi treće stranke (npr. preglednik blokova) koji se javljaju u kartici transakcija kao elementi kontekstnog izbornika. %s u URL-u zamijenjen je hashom transakcije. Višestruki URL-ovi su odvojeni vertikalnom crtom |.</translation>
+ </message>
+ <message>
+ <source>Active command-line options that override above options:</source>
+ <translation>Aktivne terminalne opcije koje poništavaju navedene opcije:</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Otvorite konfiguracijsku datoteku programa %1 s radne mape.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Otvorite konfiguracijsku datoteku</translation>
+ </message>
+ <message>
<source>Reset all client options to default.</source>
<translation>Nastavi sve postavke programa na početne vrijednosti.</translation>
</message>
@@ -768,10 +1049,42 @@
<translation>&amp;Mreža</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Isključuje napredne mogućnosti ali će svi blokovi ipak biti potpuno validirani. Vraćanje na prijašnje stanje zahtijeva ponovo preuzimanje cijelog lanca blokova. Realna količina zauzetog prostora na disku može biti ponešto veća.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Obrezujte pohranu &amp;blokova na</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Vraćanje na prijašnje stanje zahtijeva ponovo preuzimanje cijelog lanca blokova.</translation>
+ </message>
+ <message>
+ <source>(0 = auto, &lt;0 = leave that many cores free)</source>
+ <translation>(0 = automatski odredite, &lt;0 = ostavite slobodno upravo toliko jezgri)</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation>&amp;Novčanik</translation>
</message>
<message>
+ <source>Expert</source>
+ <translation>Stručne postavke</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Uključite postavke kontroliranja inputa</translation>
+ </message>
+ <message>
+ <source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
+ <translation>Ako isključite trošenje nepotvrđenog ostatka, ostatak transakcije ne može biti korišten dok ta transakcija ne dobije barem jednu potvrdu. Također utječe na to kako je vaše stanje računato.</translation>
+ </message>
+ <message>
<source>&amp;Spend unconfirmed change</source>
<translation>&amp;Trošenje nepotvrđenih vraćenih iznosa</translation>
</message>
@@ -784,6 +1097,22 @@
<translation>Mapiraj port koristeći &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Prihvatite veze izvana.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Dozvolite dolazeće veze</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>Spojite se na Bitcoin mrežu kroz SOCKS5 proxy.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;Spojite se kroz SOCKS5 proxy (uobičajeni proxy)</translation>
+ </message>
+ <message>
<source>Proxy &amp;IP:</source>
<translation>Proxy &amp;IP:</translation>
</message>
@@ -796,6 +1125,26 @@
<translation>Proxy vrata (npr. 9050)</translation>
</message>
<message>
+ <source>Used for reaching peers via:</source>
+ <translation>Korišten za dohvaćanje klijenata preko:</translation>
+ </message>
+ <message>
+ <source>IPv4</source>
+ <translation>IPv4-a</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6-a</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Tora</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>Spojite se na Bitcoin mrežu kroz zaseban SOCKS5 proxy za povezivanje na Tor.</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;Prozor</translation>
</message>
@@ -820,6 +1169,10 @@
<translation>Jezi&amp;k sučelja:</translation>
</message>
<message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation>Jezik korisničkog sučelja može se postaviti ovdje. Postavka će vrijediti nakon ponovnog pokretanja programa %1.</translation>
+ </message>
+ <message>
<source>&amp;Unit to show amounts in:</source>
<translation>&amp;Jedinica za prikaz iznosa:</translation>
</message>
@@ -828,6 +1181,14 @@
<translation>Izaberite željeni najmanji dio bitcoina koji će biti prikazan u sučelju i koji će se koristiti za plaćanje.</translation>
</message>
<message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>Ovisi želite li prikazati mogućnosti kontroliranja inputa ili ne.</translation>
+ </message>
+ <message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;URL-ovi treće stranke o transakciji</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;U redu</translation>
</message>
@@ -840,10 +1201,42 @@
<translation>standardne vrijednosti</translation>
</message>
<message>
+ <source>none</source>
+ <translation>ništa</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>Potvrdite resetiranje opcija</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Potrebno je ponovno pokretanje klijenta kako bi se promjene aktivirale.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>Zatvorit će se klijent. Želite li nastaviti?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Konfiguracijske postavke</translation>
+ </message>
+ <message>
+ <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
+ <translation>Ova konfiguracijska datoteka je korištena za specificiranje napredne korisničke opcije koje će poništiti postavke GUI-a. Također će bilo koje opcije navedene preko terminala poništiti ovu konfiguracijsku datoteku.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Greška</translation>
</message>
<message>
+ <source>The configuration file could not be opened.</source>
+ <translation>Konfiguracijska datoteka nije se mogla otvoriti.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Ova promjena zahtijeva da se klijent ponovo pokrene.</translation>
+ </message>
+ <message>
<source>The supplied proxy address is invalid.</source>
<translation>Priložena proxy adresa je nevažeća.</translation>
</message>
@@ -859,20 +1252,184 @@
<translation>Prikazani podatci mogu biti zastarjeli. Vaš novčanik se automatski sinkronizira s Bitcoin mrežom kada je veza uspostavljena, ali taj proces još nije završen.</translation>
</message>
<message>
+ <source>Watch-only:</source>
+ <translation>Isključivno promatrane adrese:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Dostupno:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>Trenutno stanje koje možete trošiti</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>Neriješeno:</translation>
+ </message>
+ <message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation>Ukupan iznos transakcija koje se još moraju potvrditi te se ne računa kao stanje koje se može trošiti</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation>Nezrelo:</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>Izrudareno stanje koje još nije dozrijevalo</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>Stanja</translation>
+ </message>
+ <message>
<source>Total:</source>
<translation>Ukupno:</translation>
</message>
- </context>
+ <message>
+ <source>Your current total balance</source>
+ <translation>Vaše trenutno svekupno stanje</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>Vaše trenutno stanje kod eksluzivno promatranih (watch-only) adresa</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Stanje koje se može trošiti:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Nedavne transakcije</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>Nepotvrđene transakcije isključivo promatranim adresama</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>Izrudareno stanje na isključivo promatranim adresama koje još nije dozrijevalo</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>Trenutno ukupno stanje na isključivo promatranim adresama</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
<message>
+ <source>Payment request error</source>
+ <translation>Greška kod zahtjeva za plaćanje</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Ne može se pokrenuti klijent: rukovatelj "kliknite da platite"</translation>
+ </message>
+ <message>
<source>URI handling</source>
<translation>URI upravljanje</translation>
</message>
- </context>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' nije ispravan URI. Koristite 'bitcoin:' umjesto toga.</translation>
+ </message>
+ <message>
+ <source>Payment request fetch URL is invalid: %1</source>
+ <translation>URL za dohvatu zahtjeva za plaćanje neispravan: %1</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Nevažeća adresa za plaćanje %1</translation>
+ </message>
+ <message>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation>Ne može se parsirati URI! Uzrok tomu može biti nevažeća Bitcoin adresa ili neispravni parametri kod URI-a.</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>Rukovanje datotekom zahtjeva za plaćanje</translation>
+ </message>
+ <message>
+ <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
+ <translation>Nije moguće iščitati datoteku zahtjeva za plaćanje! Uzrok tomu može biti nevažeća datoteka zahtjeva za plaćanje.</translation>
+ </message>
+ <message>
+ <source>Payment request rejected</source>
+ <translation>Zahtjev za plaćanje odbijen</translation>
+ </message>
+ <message>
+ <source>Payment request network doesn't match client network.</source>
+ <translation>Mreža zahtjeva za plaćanje ne poklapa se s mrežom klijenta.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Zahtjev za plaćanje istekao.</translation>
+ </message>
+ <message>
+ <source>Payment request is not initialized.</source>
+ <translation>Zahtjev za plaćanje nije inicijaliziran.</translation>
+ </message>
+ <message>
+ <source>Unverified payment requests to custom payment scripts are unsupported.</source>
+ <translation>Neprovjereni zahtjevi za plaćanje prilagođenim skriptima za plaćanje su nepodržani.</translation>
+ </message>
+ <message>
+ <source>Invalid payment request.</source>
+ <translation>Nevažeći zahtjev za plaćanje.</translation>
+ </message>
+ <message>
+ <source>Requested payment amount of %1 is too small (considered dust).</source>
+ <translation>Traženi iznos plaćanja %1 je premalen (smatra se "prašinom", sićušnim iznosom).</translation>
+ </message>
+ <message>
+ <source>Refund from %1</source>
+ <translation>Povrat iz %1</translation>
+ </message>
+ <message>
+ <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
+ <translation>Zahtjev za plaćanje %1 je prevelik (%2 bajt(ov)a, dozvoljeno %3 bajt(ov)a).</translation>
+ </message>
+ <message>
+ <source>Error communicating with %1: %2</source>
+ <translation>Greška kod komuniciranja s %1: %2</translation>
+ </message>
+ <message>
+ <source>Payment request cannot be parsed!</source>
+ <translation>Zahtjev za plaćanje ne može se parsirati!</translation>
+ </message>
+ <message>
+ <source>Bad response from server %1</source>
+ <translation>Neispravan odgovor sa strane servera %1</translation>
+ </message>
+ <message>
+ <source>Network request error</source>
+ <translation>Greška kod mrežnog zahtjeva</translation>
+ </message>
+ <message>
+ <source>Payment acknowledged</source>
+ <translation>Plaćanje priznato</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>User Agent</source>
+ <translation>Korisnički agent</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>Čvor/Servis</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>NodeId (ID čvora)</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>Ping</translation>
+ </message>
+ <message>
<source>Sent</source>
<translation>Poslano</translation>
</message>
@@ -888,13 +1445,85 @@
<translation>Iznos</translation>
</message>
<message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Unesite Bitcoin adresu (npr. %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 d</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 h</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 m</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 s</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>Ništa</translation>
+ </message>
+ <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
<message>
+ <source>%1 ms</source>
+ <translation>%1 ms</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation><numerusform>%n sekund</numerusform><numerusform>%n sekundi</numerusform><numerusform>%n sekundi</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation><numerusform>%n minut</numerusform><numerusform>%n minuta</numerusform><numerusform>%n minuta</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation><numerusform>%n sat</numerusform><numerusform>%n sata</numerusform><numerusform>%n sati</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation><numerusform>%n dan</numerusform><numerusform>%n dana</numerusform><numerusform>%n dana</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation><numerusform>%n tjedan</numerusform><numerusform>%n tjedna</numerusform><numerusform>%n tjedana</numerusform></translation>
+ </message>
+ <message>
<source>%1 and %2</source>
<translation>%1 i %2</translation>
</message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation><numerusform>%n godina</numerusform><numerusform>%n godine</numerusform><numerusform>%n godina</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 B</source>
+ <translation>%1 B</translation>
+ </message>
+ <message>
+ <source>%1 KB</source>
+ <translation>%1 KB</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 MB</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 GB</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation>%1 se još nije sigurno zatvorio.</translation>
+ </message>
<message>
<source>unknown</source>
<translation>nepoznato</translation>
@@ -902,7 +1531,23 @@
</context>
<context>
<name>QObject::QObject</name>
- </context>
+ <message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Greška kod parsiranja argumenata unesnih preko terminala: %1.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>Greška: Zadana podatkovna mapa "%1" ne postoji.</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Greška: Ne može se parsirati konfiguracijska datoteka: %1.</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>Greška: %1</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
<message>
@@ -913,7 +1558,11 @@
<source>Save QR Code</source>
<translation>Spremi QR kod</translation>
</message>
- </context>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>PNG slika (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -933,6 +1582,22 @@
<translation>Konzola za dijagnostiku</translation>
</message>
<message>
+ <source>General</source>
+ <translation>Općenito</translation>
+ </message>
+ <message>
+ <source>Using BerkeleyDB version</source>
+ <translation>Verzija BerkeleyDB-a</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>Datadir (podatkovna mapa)</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation>Vrijeme pokretanja</translation>
+ </message>
+ <message>
<source>Network</source>
<translation>Mreža</translation>
</message>
@@ -953,6 +1618,30 @@
<translation>Trenutni broj blokova</translation>
</message>
<message>
+ <source>Memory Pool</source>
+ <translation>Memorijski bazen</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>Trenutan broj transakcija</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>Korištena memorija</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation>Novčanik:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(ništa)</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Resetirajte</translation>
+ </message>
+ <message>
<source>Received</source>
<translation>Primljeno</translation>
</message>
@@ -961,6 +1650,22 @@
<translation>Poslano</translation>
</message>
<message>
+ <source>&amp;Peers</source>
+ <translation>&amp;Klijenti</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation>Zabranjeni klijenti</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>Odaberite klijent kako biste vidjeli detaljne informacije.</translation>
+ </message>
+ <message>
+ <source>Whitelisted</source>
+ <translation>Na bijeloj listi</translation>
+ </message>
+ <message>
<source>Direction</source>
<translation>Smjer</translation>
</message>
@@ -969,10 +1674,74 @@
<translation>Verzija</translation>
</message>
<message>
+ <source>Starting Block</source>
+ <translation>Početni blok</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation>Broj sinkroniziranih zaglavlja</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>Broj sinkronizranih blokova</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>Korisnički agent</translation>
+ </message>
+ <message>
+ <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation>Otvorite datoteku zapisa programa %1 iz trenutne podatkovne mape. Može potrajati nekoliko sekundi za velike datoteke zapisa.</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>Smanjite veličinu fonta</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>Povećajte veličinu fonta</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>Usluge</translation>
+ </message>
+ <message>
+ <source>Ban Score</source>
+ <translation>Broj zabrana</translation>
+ </message>
+ <message>
<source>Connection Time</source>
<translation>Trajanje veze</translation>
</message>
<message>
+ <source>Last Send</source>
+ <translation>Zadnja pošiljka</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>Zadnji primitak</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>Vrijeme pinga</translation>
+ </message>
+ <message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation>Trajanje trenutno izvanrednog pinga</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>Zakašnjenje pinga</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>Min ping</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation>Vremenski ofset</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation>Posljednje vrijeme bloka</translation>
</message>
@@ -993,10 +1762,114 @@
<translation>Ukupno:</translation>
</message>
<message>
+ <source>In:</source>
+ <translation>Dolazne:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Izlazne:</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation>Datoteka ispisa za debagiranje</translation>
+ </message>
+ <message>
<source>Clear console</source>
<translation>Očisti konzolu</translation>
</message>
<message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;sat</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;dan</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;tjedan</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;godinu</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Odspojite</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>Zabranite za</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;Ukinite zabranu</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>uobičajeni novčanik</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Dobrodošli u %1 RPC konzolu.</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>Koristite tipke gore i dolje za izbor već korištenih naredbi. %1 kako biste očistili ekran i povijest naredbi.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Utipkajte %1 za pregled dostupnih naredbi.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Za više informacija o korištenju ove konzole utipkajte %1.</translation>
+ </message>
+ <message>
+ <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
+ <translation>UPOZORENJE: Prevaranti su aktivni i govore korisnicima da utipkaju naredbe ovdje kako bi ispraznili sadržaje njihovih novčanika. Ne koristite ovu konzolu bez da u potpunosti razumijete posljedice naredbe.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Mrežna aktivnost isključena</translation>
+ </message>
+ <message>
+ <source>Executing command without any wallet</source>
+ <translation>Izvršava se naredba bez bilo kakvog novčanika</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Izvršava se naredba koristeći novčanik "%1"</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(ID čvora: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>preko %1</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>nikad</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>Dolazni</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>Izlazni</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation>Da</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation>Ne</translation>
+ </message>
+ <message>
<source>Unknown</source>
<translation>Nepoznato</translation>
</message>
@@ -1016,22 +1889,74 @@
<translation>&amp;Poruka:</translation>
</message>
<message>
+ <source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
+ <translation>Opcionalna poruka koja se može dodati kao privitak zahtjevu za plaćanje. Bit će prikazana kad je zahtjev otvoren. Napomena: Ova poruka neće biti poslana zajedno s uplatom preko Bitcoin mreže.</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation>Opcionalna oznaka koja će se povezati s novom primateljskom adresom.</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>Koristite ovaj formular kako biste zahtijevali uplate. Sva su polja &lt;b&gt;opcionalna&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation>Opcionalan iznos koji možete zahtijevati. Ostavite ovo prazno ili unesite nulu ako ne želite zahtijevati specifičan iznos.</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Obriši sva polja</translation>
</message>
<message>
+ <source>Clear</source>
+ <translation>Obrišite</translation>
+ </message>
+ <message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Izvorne SegWit adrese (tzv. Bech32 ili BIP-173) smanjuju vaše transakcijske naknade ubuduće i nude bolju zaštitu protiv tipfelera, ali stari novčanici ih ne podržavaju. Kada je ova opcija isključena, bit će umjesto toga stvorena adresa koja je kompatibilna sa starijim novčanicima.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generirajte izvornu SegWit (Bech32) adresu</translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation>Povijest zahtjeva za plaćanje</translation>
+ </message>
+ <message>
<source>&amp;Request payment</source>
<translation>&amp;Zatraži plaćanje</translation>
</message>
<message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation>Prikazuje izabran zahtjev (isto učini dvostruki klik na zapis)</translation>
+ </message>
+ <message>
<source>Show</source>
<translation>Pokaži</translation>
</message>
<message>
+ <source>Remove the selected entries from the list</source>
+ <translation>Uklonite odabrane zapise s popisa</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Uklonite</translation>
+ </message>
+ <message>
+ <source>Copy URI</source>
+ <translation>Kopirajte URI</translation>
+ </message>
+ <message>
<source>Copy label</source>
<translation>Kopiraj oznaku</translation>
</message>
<message>
+ <source>Copy message</source>
+ <translation>Kopirajte poruku</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>Kopiraj iznos</translation>
</message>
@@ -1055,6 +1980,14 @@
<translation>&amp;Spremi sliku...</translation>
</message>
<message>
+ <source>Request payment to %1</source>
+ <translation>&amp;Zatražite plaćanje na adresu %1</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>Informacije o uplati</translation>
+ </message>
+ <message>
<source>URI</source>
<translation>URI</translation>
</message>
@@ -1075,6 +2008,10 @@
<translation>Poruka</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Novčanik</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI je predug, probajte skratiti tekst za naslov / poruku.</translation>
</message>
@@ -1105,7 +2042,15 @@
<source>(no message)</source>
<translation>(bez poruke)</translation>
</message>
- </context>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(nikakav iznos zahtijevan)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Zatraženo</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -1113,6 +2058,18 @@
<translation>Slanje novca</translation>
</message>
<message>
+ <source>Coin Control Features</source>
+ <translation>Mogućnosti kontroliranja inputa</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>Inputi...</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>automatski izabrano</translation>
+ </message>
+ <message>
<source>Insufficient funds!</source>
<translation>Nedovoljna sredstva</translation>
</message>
@@ -1133,14 +2090,78 @@
<translation>Naknada:</translation>
</message>
<message>
+ <source>After Fee:</source>
+ <translation>Nakon naknade:</translation>
+ </message>
+ <message>
<source>Change:</source>
<translation>Vraćeno:</translation>
</message>
<message>
+ <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
+ <translation>Ako je ovo aktivirano, ali adresa u koju treba poslati ostatak je prazna ili nevažeća, onda će ostatak biti poslan u novo generiranu adresu.</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation>Zadana adresa u koju će ostatak biti poslan</translation>
+ </message>
+ <message>
<source>Transaction Fee:</source>
<translation>Naknada za transakciju:</translation>
</message>
<message>
+ <source>Choose...</source>
+ <translation>Birajte...</translation>
+ </message>
+ <message>
+ <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
+ <translation>Korištenje rezervnu naknadu može rezultirati slanjem transakcije kojoj može trebati nekoliko sati ili dana (ili pak nikad) da se potvrdi. Uzmite u obzir ručno biranje naknade ili pričekajte da se cijeli lanac validira.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Upozorenje: Procjena naknada trenutno nije moguća.</translation>
+ </message>
+ <message>
+ <source>collapse fee-settings</source>
+ <translation>Sažimajte opcije naknade</translation>
+ </message>
+ <message>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Zadajte prilagođeu naknadu po kB (1000 bajtova) virtualne veličine transakcije.
+
+Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po kB" za transakciju veličine 500 bajtova (polovica od 1 kB) rezultirala bi ultimativno naknadom od samo 50 satošija.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>po kilobajtu</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Sakrijte</translation>
+ </message>
+ <message>
+ <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
+ <translation>Plaćanje minimalnu naknadu je dovoljno ukoliko je volumen transakcija manja od prostora u blokovima. Budite svjesni da ovo može završiti tako da se transakcija nikad ne potvrdi ako je potražnja za Bitcoin transakcijama veća nego što mreža može procesirati.</translation>
+ </message>
+ <message>
+ <source>(read the tooltip)</source>
+ <translation>(pročitajte opis alata)</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>Preporučeno:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>Zadano:</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Pametna procjena naknada još nije inicijalizirana. Uobičajeno traje nekoliko blokova...)</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>Pošalji novce većem broju primatelja u jednoj transakciji</translation>
</message>
@@ -1157,6 +2178,18 @@
<translation>Prah:</translation>
</message>
<message>
+ <source>Confirmation time target:</source>
+ <translation>Ciljno vrijeme potvrde:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Uključite Replace-By-Fee</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Pomoću mogućnosti Replace-By-Fee (BIP-125) možete povećati naknadu transakcije nakon što je poslana. Bez ovoga može biti preporučena veća naknada kako bi nadoknadila povećani rizik zakašnjenja transakcije.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Obriši &amp;sve</translation>
</message>
@@ -1173,18 +2206,82 @@
<translation>&amp;Pošalji</translation>
</message>
<message>
+ <source>Copy quantity</source>
+ <translation>Kopiraj iznos</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>Kopiraj iznos</translation>
</message>
<message>
+ <source>Copy fee</source>
+ <translation>Kopirajte naknadu</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Kopirajte iznos nakon naknade</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Kopirajte količinu bajtova</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Kopirajte sićušne iznose ("prašinu")</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Kopirajte ostatak</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blokova)</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 na %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Jeste li sigurni da želite poslati transakciju?</translation>
+ </message>
+ <message>
<source>or</source>
<translation>ili</translation>
</message>
<message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Možete kasnije povećati naknadu (javlja Replace-By-Fee, BIP-125).</translation>
+ </message>
+ <message>
+ <source>from wallet %1</source>
+ <translation>iz novčanika %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Molim vas, pregledajte svoju transakciju.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Naknada za transakciju</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Ne javlja Replace-By-Fee, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Ukupni iznos</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Potvrdi slanje novca</translation>
</message>
<message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>Adresa primatelja je nevažeća. Provjerite ponovno, molim vas.</translation>
+ </message>
+ <message>
<source>The amount to pay must be larger than 0.</source>
<translation>Iznos mora biti veći od 0.</translation>
</message>
@@ -1197,6 +2294,50 @@
<translation>Iznos je veći od stanja novčanika kad se doda naknada za transakcije od %1.</translation>
</message>
<message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>Duplikatna adresa pronađena: adrese trebaju biti korištene samo jedanput.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Neuspješno stvorenje transakcije!</translation>
+ </message>
+ <message>
+ <source>The transaction was rejected with the following reason: %1</source>
+ <translation>Transakcija je bila odbijena zbog sljedećeg razloga: %1</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>Naknada veća od %1 smatra se apsurdno visokim naknadom.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Zahtjev za plaćanje istekao.</translation>
+ </message>
+ <message>
+ <source>Pay only the required fee of %1</source>
+ <translation>Platite samo potrebnu naknadu u iznosu od %1</translation>
+ </message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>Procijenjeno je da će početi potvrđivanje unutar %n bloka.</numerusform><numerusform>Procijenjeno je da će početi potvrđivanje unutar %n bloka.</numerusform><numerusform>Procijenjeno je da će početi potvrđivanje unutar %n blokova.</numerusform></translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Upozorenje: Nevažeća Bitcoin adresa</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Upozorenje: Nepoznata adresa u koju će ostatak biti poslan</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>Potvrdite zadanu adresu u koju će ostatak biti poslan</translation>
+ </message>
+ <message>
+ <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
+ <translation>Adresa koju ste izabrali kamo ćete poslati ostatak nije dio ovog novčanika. Bilo koji iznosi u vašem novčaniku mogu biti poslani na ovu adresu. Jeste li sigurni?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(nema oznake)</translation>
</message>
@@ -1216,6 +2357,18 @@
<translation>&amp;Oznaka:</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation>Odaberite prethodno korištenu adresu</translation>
+ </message>
+ <message>
+ <source>This is a normal payment.</source>
+ <translation>Ovo je normalna uplata.</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>Bitcoin adresa na koju ćete poslati uplatu</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1228,31 +2381,95 @@
<translation>Alt+P</translation>
</message>
<message>
+ <source>Remove this entry</source>
+ <translation>Obrišite ovaj zapis</translation>
+ </message>
+ <message>
+ <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
+ <translation>Naknada će biti oduzeta od poslanog iznosa. Primatelj će primiti manji iznos od onoga koji unesete u polje iznosa. Ako je odabrano više primatelja, onda će naknada biti podjednako raspodijeljena.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>Oduzmite naknadu od iznosa</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Koristite dostupno stanje</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Poruka:</translation>
</message>
<message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>Ovo je neautenticiran zahtjev za plaćanje.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>Ovo je autenticiran zahtjev za plaćanje.</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <translation>Unesite oznaku za ovu adresu kako bi ju dodali u vaš adresar</translation>
+ </message>
+ <message>
+ <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
+ <translation>Poruka koja je dodana uplati: URI koji će biti spremljen s transakcijom za referencu. Napomena: Ova poruka neće biti poslana preko Bitcoin mreže.</translation>
+ </message>
+ <message>
<source>Pay To:</source>
<translation>Primatelj plaćanja:</translation>
</message>
<message>
+ <source>Memo:</source>
+ <translation>Zapis:</translation>
+ </message>
+ <message>
<source>Enter a label for this address to add it to your address book</source>
<translation>Unesite oznaku za ovu adresu kako bi ju dodali u vaš adresar</translation>
</message>
</context>
<context>
<name>SendConfirmationDialog</name>
- </context>
+ <message>
+ <source>Yes</source>
+ <translation>Da</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
- </context>
+ <message>
+ <source>%1 is shutting down...</source>
+ <translation>Zatvara se %1...</translation>
+ </message>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation>Ne ugasite računalo dok ovaj prozor ne nestane.</translation>
+ </message>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>Potpisi - Potpisujte / Provjerite poruku</translation>
+ </message>
+ <message>
<source>&amp;Sign Message</source>
<translation>&amp;Potpišite poruku</translation>
</message>
<message>
+ <source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
+ <translation>Možete potpisati poruke/dogovore svojim adresama kako biste dokazali da možete pristupiti bitcoinima poslanim na te adrese. Budite oprezni da ne potpisujte ništa nejasno ili nasumično, jer napadi phishingom vas mogu prevariti da prepišite svoj identitet njima. Potpisujte samo detaljno objašnjene izjave s kojima se slažete.</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>Bitcoin adresa pomoću koje ćete potpisati poruku</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Odaberite prethodno korištenu adresu</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1273,10 +2490,22 @@
<translation>Potpis</translation>
</message>
<message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>Kopirajte trenutni potpis u međuspremnik</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation>Potpišite poruku kako biste dokazali da posjedujete ovu Bitcoin adresu</translation>
+ </message>
+ <message>
<source>Sign &amp;Message</source>
<translation>&amp;Potpišite poruku</translation>
</message>
<message>
+ <source>Reset all sign message fields</source>
+ <translation>Resetirajte sva polja formulara</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Obriši &amp;sve</translation>
</message>
@@ -1285,18 +2514,78 @@
<translation>&amp;Potvrdite poruku</translation>
</message>
<message>
+ <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
+ <translation>Unesite primateljevu adresu, poruku (provjerite da kopirate prekide crta, razmake, tabove, itd. točno) i potpis ispod da provjerite poruku. Pazite da ne pridodate veće značenje potpisu nego što je sadržano u samoj poruci kako biste izbjegli napad posrednika (MITM attack). Primijetite da ovo samo dokazuje da stranka koja potpisuje prima na adresu. Ne može dokažati da je neka stranka poslala transakciju!</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>Bitcoin adresa kojom je poruka potpisana</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>Provjerite poruku da budete sigurni da je potpisana zadanom Bitcoin adresom</translation>
+ </message>
+ <message>
<source>Verify &amp;Message</source>
<translation>&amp;Potvrdite poruku</translation>
</message>
<message>
+ <source>Reset all verify message fields</source>
+ <translation>Resetirajte sva polja provjeravanja poruke</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Kliknite "Potpišite poruku" da generirate potpis</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>Unesena adresa je neispravna.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Molim provjerite adresu i pokušajte ponovo.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>Unesena adresa ne odnosi se na ključ.</translation>
+ </message>
+ <message>
<source>Wallet unlock was cancelled.</source>
<translation>Otključavanje novčanika je otkazano.</translation>
</message>
<message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>Privatni ključ za unesenu adresu nije dostupan.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Potpisivanje poruke neuspješno.</translation>
+ </message>
+ <message>
<source>Message signed.</source>
<translation>Poruka je potpisana.</translation>
</message>
- </context>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>Potpis nije mogao biti dešifriran.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Molim provjerite potpis i pokušajte ponovo.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>Potpis se ne poklapa sa sažetkom poruke (message digest).</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Provjera poruke neuspješna.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Poruka provjerena.</translation>
+ </message>
+</context>
<context>
<name>SplashScreen</name>
<message>
@@ -1306,16 +2595,40 @@
</context>
<context>
<name>TrafficGraphWidget</name>
- </context>
+ <message>
+ <source>KB/s</source>
+ <translation>KB/s</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Otvoren za još %n blok</numerusform><numerusform>Otvoren za još %n bloka</numerusform><numerusform>Otvoren za još %n blokova</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Otvoren do %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1 nije dostupan</translation>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>subokljen s transakcijom broja potvrde %1</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, %1</source>
+ <translation>0/nepotvrđeno, %1</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>u memorijskom bazenu</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>nije u memorijskom bazenu</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>napušteno</translation>
</message>
<message>
<source>%1/unconfirmed</source>
@@ -1330,10 +2643,6 @@
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, još nije bio uspješno emitiran</translation>
- </message>
- <message>
<source>Date</source>
<translation>Datum</translation>
</message>
@@ -1362,6 +2671,10 @@
<translation>vlastita adresa</translation>
</message>
<message>
+ <source>watch-only</source>
+ <translation>isključivo promatrano</translation>
+ </message>
+ <message>
<source>label</source>
<translation>oznaka</translation>
</message>
@@ -1369,6 +2682,10 @@
<source>Credit</source>
<translation>Uplaćeno</translation>
</message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>dozrije za još %n blok</numerusform><numerusform>dozrije za još %n bloka</numerusform><numerusform>dozrije za još %n blokova</numerusform></translation>
+ </message>
<message>
<source>not accepted</source>
<translation>Nije prihvaćeno</translation>
@@ -1378,6 +2695,14 @@
<translation>Zaduženje</translation>
</message>
<message>
+ <source>Total debit</source>
+ <translation>Ukupni debit</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Ukupni kredit</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Naknada za transakciju</translation>
</message>
@@ -1398,6 +2723,30 @@
<translation>ID transakcije</translation>
</message>
<message>
+ <source>Transaction total size</source>
+ <translation>Ukupna veličina transakcije</translation>
+ </message>
+ <message>
+ <source>Transaction virtual size</source>
+ <translation>Virtualna veličina transakcije</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>Indeks outputa</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Trgovac</translation>
+ </message>
+ <message>
+ <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation>Generirani novčići moraju dozrijeti %1 blokova prije nego što mogu biti potrošeni. Kada ste generirali ovaj blok, bio je emitiran na mreži kako bi bio dodan lancu blokova. Ako ne uspije ući u lanac, stanje će mu promijeniti na "neprihvaćeno" i neće se moći trošiti. Ovo se može dogoditi povremeno ako drugi čvor generira blok u roku od nekoliko sekundi od vas.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Informacije za debugiranje</translation>
+ </message>
+ <message>
<source>Transaction</source>
<translation>Transakcija</translation>
</message>
@@ -1409,14 +2758,26 @@
<source>Amount</source>
<translation>Iznos</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>istina</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>laž</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
<source>This pane shows a detailed description of the transaction</source>
<translation>Ovaj prozor prikazuje detaljni opis transakcije</translation>
</message>
- </context>
+ <message>
+ <source>Details for %1</source>
+ <translation>Detalji za %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
@@ -1431,17 +2792,37 @@
<source>Label</source>
<translation>Oznaka</translation>
</message>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Otvoren za još %n blok</numerusform><numerusform>Otvoren za još %n bloka</numerusform><numerusform>Otvoren za još %n blokova</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Otvoren do %1</translation>
</message>
<message>
+ <source>Unconfirmed</source>
+ <translation>Nepotvrđeno</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>Napušteno</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>Potvrđuje se (%1 od %2 preporučenih potvrda)</translation>
+ </message>
+ <message>
<source>Confirmed (%1 confirmations)</source>
<translation>Potvrđen (%1 potvrda)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Ovaj blok nije bio primljen od strane bilo kojeg drugog čvora i vjerojatno neće biti prihvaćen!</translation>
+ <source>Conflicted</source>
+ <translation>Sukobljeno</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>Nezrelo (%1 potvrda/e, bit će dostupno nakon %2)</translation>
</message>
<message>
<source>Generated but not accepted</source>
@@ -1468,6 +2849,10 @@
<translation>Rudareno</translation>
</message>
<message>
+ <source>watch-only</source>
+ <translation>isključivo promatrano</translation>
+ </message>
+ <message>
<source>(n/a)</source>
<translation>(n/d)</translation>
</message>
@@ -1488,6 +2873,14 @@
<translation>Vrsta transakcije.</translation>
</message>
<message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>Ovisi je li isključivo promatrana adresa povezana s ovom transakcijom ili ne.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>Korisničko definirana namjera transakcije.</translation>
+ </message>
+ <message>
<source>Amount removed from or added to balance.</source>
<translation>Iznos odbijen od ili dodan k saldu.</translation>
</message>
@@ -1543,10 +2936,22 @@
<translation>Ostalo</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Unesite adresu, ID transakcije ili oznaku za pretragu</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Min iznos</translation>
</message>
<message>
+ <source>Abandon transaction</source>
+ <translation>Napustite transakciju</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>Povećajte transakcijsku naknadu</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>Kopiraj adresu</translation>
</message>
@@ -1563,6 +2968,14 @@
<translation>Kopiraj ID transakcije</translation>
</message>
<message>
+ <source>Copy raw transaction</source>
+ <translation>Kopirajte sirovu transakciju</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>Kopirajte potpune transakcijske detalje</translation>
+ </message>
+ <message>
<source>Edit label</source>
<translation>Izmjeni oznaku</translation>
</message>
@@ -1571,6 +2984,10 @@
<translation>Prikaži detalje transakcije</translation>
</message>
<message>
+ <source>Export Transaction History</source>
+ <translation>Izvozite povijest transakcija</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Datoteka podataka odvojenih zarezima (*.csv)</translation>
</message>
@@ -1579,6 +2996,10 @@
<translation>Potvrđeno</translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation>Isključivo promatrano</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Datum</translation>
</message>
@@ -1603,6 +3024,18 @@
<translation>Izvoz neuspješan</translation>
</message>
<message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>Nastala je greška pokušavajući snimiti povijest transakcija na %1.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Izvoz uspješan</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>Povijest transakcija je bila uspješno snimljena na %1.</translation>
+ </message>
+ <message>
<source>Range:</source>
<translation>Raspon:</translation>
</message>
@@ -1613,17 +3046,61 @@
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>Jedinica u kojoj ćete prikazati iznose. Kliknite da izabrate drugu jedinicu.</translation>
+ </message>
+</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>Nije pokrenut nikakav novčanik.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
<source>Send Coins</source>
<translation>Slanje novca</translation>
</message>
- </context>
+ <message>
+ <source>Fee bump error</source>
+ <translation>Greška kod povećanja naknade</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Povećavanje transakcijske naknade neuspješno</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>Želite li povećati naknadu?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>Trenutna naknada:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>Povećanje:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>Nova naknada:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>Potvrdite povećanje naknade</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>Transakcija ne može biti potpisana.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>Transakcija ne može biti izvršena.</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -1646,74 +3123,522 @@
<source>Backup Failed</source>
<translation>Arhiviranje nije uspjelo</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>Nastala je greška pokušavajući snimiti podatke novčanika na %1.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Sigurnosna kopija uspješna</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>Podaci novčanika su bili uspješno snimljeni na %1.</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>Odustanite</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Postavke:</translation>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation>Distribuirano pod MIT licencom softvera. Vidite pripadajuću datoteku %s ili %s.</translation>
</message>
<message>
- <source>Specify data directory</source>
- <translation>Odaberi direktorij za datoteke</translation>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation>Obrezivanje postavljeno ispod minimuma od %d MiB. Molim koristite veći broj.</translation>
</message>
<message>
- <source>Specify your own public address</source>
- <translation>Odaberi vlastitu javnu adresu</translation>
+ <source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
+ <translation>Obrezivanje: zadnja sinkronizacija novčanika ide dalje od obrezivanih podataka. Morate koristiti -reindex (ponovo preuzeti cijeli lanac blokova u slučaju obrezivanog čvora)</translation>
</message>
<message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Prihvati komande iz tekst moda i JSON-RPC</translation>
+ <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
+ <translation>Ponovno skeniranje nije moguće u obrezanim načinu (pruned mode). Morat ćete koristiti -reindex, što će ponovno preuzeti cijeli lanac blokova.</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Izvršavaj u pozadini kao uslužnik i prihvaćaj komande</translation>
+ <source>Error: A fatal internal error occurred, see debug.log for details</source>
+ <translation>Greška: Dogodila se kobna interna greška. Vidite debug.log za detalje</translation>
+ </message>
+ <message>
+ <source>Pruning blockstore...</source>
+ <translation>Obrezuje se blockstore...</translation>
+ </message>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>Ne može se pokrenuti HTTP server. Vidite debug.log za više detalja.</translation>
</message>
<message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Block creation options:</source>
- <translation>Opcije za kreiranje bloka:</translation>
+ <source>The %s developers</source>
+ <translation>Ekipa %s</translation>
+ </message>
+ <message>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>Program ne može pristupiti podatkovnoj mapi %s. %s je vjerojatno već pokrenut.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Ne može ponuditi specifične veze i dati addrman da traži izlazne veze istovremeno.</translation>
+ </message>
+ <message>
+ <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation>Greška kod iščitanja %s! Svi ključevi su ispravno učitani, ali transakcijski podaci ili zapisi u adresaru mogu biti nepotpuni ili netočni.</translation>
+ </message>
+ <message>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Grupirajte outpute po adresi, birajući sve ili ništa umjesto biranja po outputu. Privatnost je povećana jer je adresa korištena samo jedanput (osim ako netko šalje na tu adresu nakon trošenja iz nje), ali može rezultirati neznatno većim naknadama jer suboptimalno biranje novčića može nastati zbog dodanog ograničenja (uobičajeno: %u)</translation>
+ </message>
+ <message>
+ <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
+ <translation>Molimo provjerite jesu li datum i vrijeme na vašem računalu točni. Ako je vaš sat krivo namješten, %s neće raditi ispravno.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Molimo vas da doprinijete programu %s ako ga smatrate korisnim. Posjetite %s za više informacija.</translation>
+ </message>
+ <message>
+ <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
+ <translation>Baza blokova sadrži blok koji je naizgled iz budućnosti. Može to biti posljedica krivo namještenog datuma i vremena na vašem računalu. Obnovite bazu blokova samo ako ste sigurni da su točni datum i vrijeme na vašem računalu.</translation>
+ </message>
+ <message>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation>Ovo je eksperimentalna verzija za testiranje - koristite je na vlastitu odgovornost - ne koristite je za rudarenje ili trgovačke primjene</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>Ovo je transakcijska naknada koju možete odbaciti ako je ostatak manji od "prašine" (sićušnih iznosa) po ovoj stopi</translation>
+ </message>
+ <message>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>Ne mogu se ponovo odigrati blokovi. Morat ćete ponovo složiti bazu koristeći -reindex-chainstate.</translation>
+ </message>
+ <message>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Baza se ne može povratiti na stanje prije raskola. Morat ćete ponovno preuzeti lanac blokova</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Upozorenje: Čini se da se mreža ne slaže u potpunosti! Izgleda da su neki rudari suočeni s poteškoćama.</translation>
+ </message>
+ <message>
+ <source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
+ <translation>Upozorenje: Izgleda da se ne slažemo u potpunosti s našim klijentima! Možda ćete se vi ili ostali čvorovi morati ažurirati.</translation>
+ </message>
+ <message>
+ <source>%d of last 100 blocks have unexpected version</source>
+ <translation>%d od zadnjih 100 blokova ima neočekivanu verziju</translation>
+ </message>
+ <message>
+ <source>%s corrupt, salvage failed</source>
+ <translation>%s pokvaren, spašavanje neuspješno</translation>
+ </message>
+ <message>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation>-maxmempool mora biti barem %d MB</translation>
+ </message>
+ <message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>Ne može se razriješiti adresa -%s: '%s'</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>Indeks ostatka izvan dosega</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Copyright (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation>Pokvarena baza blokova otkrivena</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>Želite li sada obnoviti bazu blokova?</translation>
+ </message>
+ <message>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Greška kod stvaranja %s. S ovom verzijom ne možete stvoriti novčanike koji nisu HD.</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation>Greška kod inicijaliziranja baze blokova</translation>
+ </message>
+ <message>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation>Greška kod inicijaliziranja okoline baze novčanika %s!</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>Greška kod pokretanja programa %s!</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Greška kod učitavanja %s: Privatni ključevi mogu biti isključeni samo tijekom stvaranja</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Greška kod učitavanja %s: Novčanik pokvaren</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Greška kod učitavanja %s: Novčanik zahtijeva noviju verziju softvera %s.</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>Greška kod pokretanja baze blokova</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation>Greška kod otvaranja baze blokova</translation>
</message>
<message>
<source>Error: Disk space is low!</source>
<translation>Pogreška: Nema dovoljno prostora na disku!</translation>
</message>
<message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation>Neuspješno slušanje na svim portovima. Koristite -listen=0 ako to želite.</translation>
+ </message>
+ <message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Neuspješno ponovo skeniranje novčanika tijekom inicijalizacije</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>Uvozi se...</translation>
+ </message>
+ <message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>Neispravan ili nepostojeći blok geneze. Možda je kriva podatkovna mapa za mrežu?</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>Brzinska provjera inicijalizacije neuspješna. %s se zatvara.</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>Neispravan iznos za -%s=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>Neispravan iznos za -discardfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>Neispravan iznos za -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Zadana mapa blokova "%s" ne postoji.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Ažurira se txindex baza</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>Pokreće se popis P2P adresa...</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>Pokreće se popis zabrana...</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation>Nema dovoljno dostupnih datotečnih opisivača.</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>Obrezivanje (prune) ne može biti postavljeno na negativnu vrijednost.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>Način obreživanja (pruning) nekompatibilan je s parametrom -txindex.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>Odigraju se ponovno blokovi...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>Premotavaju se blokovi...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>Izvorni kod je dostupan na %s.</translation>
+ </message>
+ <message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>Neuspješno računanje ostatka i transakcijske naknade</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>Ne može se povezati na %s na ovom računalu. %s je vjerojatno već pokrenut.</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation>Ne mogu se generirati ključevi</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
+ <translation>Nepodržan argument -benchmark ignoriran. Koristite -debug=bench.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
+ <translation>Nepodržan argument -debugnet ignoriran. Koristite -debug=net.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -tor found, use -onion.</source>
+ <translation>Nepodržan argument -tor pronađen. Koristite -onion.</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Nepodržana kategorija zapisa %s=%s.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>Ažurira se UTXO baza</translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation>Komentar pod "Korisnički agent" (%s) sadrži nesigurne znakove.</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>Provjeravaju se blokovi...</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>Novčanik je trebao prepravak: ponovo pokrenite %s</translation>
+ </message>
+ <message>
+ <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
+ <translation>Greška: Neuspješno slušanje dolažećih veza (listen je izbacio grešku %s)</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
+ <translation>Neispravan iznos za -maxtxfee=&lt;amount&gt;: '%s' (mora biti barem minimalnu naknadu za proslijeđivanje od %s kako se ne bi zapela transakcija)</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation>Iznos transakcije je premalen za poslati nakon naknade</translation>
+ </message>
+ <message>
+ <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
+ <translation>Morat ćete ponovno složiti bazu koristeći -reindex kako biste se vratili na neobrezivan način (unpruned mode). Ovo će ponovno preuzeti cijeli lanac blokova.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
+ <translation>Greška kod učitavanja %s: Ne možete isključiti HD na već postojećem HD novčaniku</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation>Greška kod iščitanja baze. Zatvara se klijent.</translation>
+ </message>
+ <message>
+ <source>Error upgrading chainstate database</source>
+ <translation>Greška kod ažuriranja baze stanja lanca</translation>
+ </message>
+ <message>
<source>Information</source>
<translation>Informacija</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Šalji trace/debug informacije na konzolu umjesto u debug.log datoteku</translation>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Neispravna -onion adresa ili ime računala: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Neispravna -proxy adresa ili ime računala: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
+ <translation>Neispravan iznos za -paytxfee=&lt;amount&gt;: '%s' (mora biti barem %s)</translation>
+ </message>
+ <message>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation>Neispravna mrežna maska zadana u -whitelist: '%s'</translation>
+ </message>
+ <message>
+ <source>Need to specify a port with -whitebind: '%s'</source>
+ <translation>Treba zadati port pomoću -whitebind: '%s'</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation>Smanjuje se -maxconnections sa %d na %d zbog sustavnih ograničenja.</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation>Potpisivanje transakcije neuspješno</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Zadan -walletdir "%s" ne postoji</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Zadan -walletdir "%s" je relativan put</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Korisničko ime za JSON-RPC veze</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Zadan -walletdir "%s" nije mapa</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>Transakcijiski iznos je premalen da plati naknadu</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>Ovo je eksperimentalni softver.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>Transakcijski iznos premalen</translation>
+ </message>
+ <message>
+ <source>Transaction too large for fee policy</source>
+ <translation>Transakcija prevelika za politiku naknada</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>Transakcija prevelika</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation>Ne može se povezati na %s na ovom računalu. (povezivanje je vratilo grešku %s)</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>Ne mogu se generirati početni ključevi</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>Provjerava(ju) se novčanik/(ci)...</translation>
+ </message>
+ <message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Novčanik %s nalazi se izvan mape novčanika %s</translation>
</message>
<message>
<source>Warning</source>
<translation>Upozorenje</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Lozinka za JSON-RPC veze</translation>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <translation>Upozorenje: nepoznata nova pravila aktivirana (versionbit %i)</translation>
+ </message>
+ <message>
+ <source>Zapping all transactions from wallet...</source>
+ <translation>Brišu se sve transakcije iz novčanika...</translation>
+ </message>
+ <message>
+ <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
+ <translation>-maxtxfee je postavljen preveliko. Naknade ove veličine će biti plaćene na individualnoj transakciji.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
+ <translation>Greška kod učitavanja %s: Ne možete uključiti HD na već postojećem novčaniku koji nije HD</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>Ovo je transakcijska naknada koju ćete možda platiti kada su nedostupne procjene naknada.</translation>
+ </message>
+ <message>
+ <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
+ <translation>Ovaj proizvod sadrži softver razvijen sa strane OpenSSL Projecta za upotrebu u OpenSSL Toolkitu %s, kriptografski softver koji je napisao Eric Young te UPnP softver koji je napisao Thomas Bernard.</translation>
+ </message>
+ <message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation>Ukupna duljina stringa verzije mreže (%i) prelazi maksimalnu duljinu (%i). Smanjite broj ili veličinu komentara o korisničkom agentu (uacomments).</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
+ <translation>Nepodržan argument -socks pronađen. Postavljanje verziju SOCKS-a nije više moguće. Samo su SOCKS5 proxyji podržani.</translation>
</message>
<message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Izvršite naredbu kada se najbolji blok promjeni (%s u cmd je zamjenjen sa block hash)</translation>
+ <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
+ <translation>Nepodržan argument -whitelistalwaysrelay ignoriran. Koristite -whitelistelay i/ili -whitelistforcerelay.</translation>
</message>
<message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Dozvoli DNS upite za -addnode, -seednode i -connect</translation>
+ <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
+ <translation>Upozorenje: Zbiva se rudarenje blokova nepoznatih verzija! Moguće je da su nepoznata pravila na snazi</translation>
+ </message>
+ <message>
+ <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
+ <translation>Upozorenje: Datoteka novčanika je pokvarena, ali su podaci spašeni! Original %s snimljen je kao %s u %s; ako su transakcije ili stanje neispravni, onda biste trebali restorirati sa sigurnosne kopije (backupa).</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation>%s je postavljen preveliko!</translation>
+ </message>
+ <message>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>Greška kod učitavanja novčanika %s. Duplikat imena novčanika zadan.</translation>
+ </message>
+ <message>
+ <source>Keypool ran out, please call keypoolrefill first</source>
+ <translation>Ispraznio se bazen ključeva. Molim pozovite keypoolrefill najprije</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>Pokreću se mrežne niti...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>Ovaj novčanik će izbjegavati plaćanje manje od minimalne naknade prijenosa.</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>Ovo je minimalna transakcijska naknada koju plaćate za svaku transakciju.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>Ovo je transakcijska naknada koju ćete platiti ako pošaljete transakciju.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>Iznosi transakcije ne smiju biti negativni</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>Transakcija ima prevelik lanac memorijskog bazena</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>Transakcija mora imati barem jednog primatelja</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation>Nepoznata mreža zadana kod -onlynet: '%s'</translation>
</message>
<message>
<source>Insufficient funds</source>
<translation>Nedovoljna sredstva</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Ne može se generirati ključ adrese na koju će se poslati ostatak. Privatni ključevi su isključeni kod ovog novčanika.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Ne može se ažurirati novčanik koji nije HD bez ažuriranja radi podrške za bazen ključeva prije raskola. Molim koristite -upgradewallet=169900 ili -upgradewallet bez zadane verzije.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Neuspješno procjenjivanje naknada. Fallbackfee je isključena. Pričekajte nekoliko blokova ili uključite -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Nije moguće pisati u podatkovnu mapu '%s'; provjerite dozvole.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Učitavanje indeksa blokova...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts
index 05cc28402a..3a3990c265 100644
--- a/src/qt/locale/bitcoin_hu.ts
+++ b/src/qt/locale/bitcoin_hu.ts
@@ -30,6 +30,10 @@
<translation>Kiválasztott cím törlése a listából</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Írja be a keresendő címet vagy címkét</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Jelenlegi nézet exportálása fájlba</translation>
</message>
@@ -128,6 +132,10 @@
<translation>Új jelszó újra</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Jelszó megjelenítése</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Gépelje be az új kulcsmondatot a pénztárcához.&lt;br/&gt;
Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű karaktert &lt;/b&gt;, vagy &lt;b&gt; nyolc vagy több szót &lt;/b&gt;.</translation>
@@ -327,6 +335,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Kattintson a hálózati tevékenység újbóli engedélyezéséhez.</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Fejlécek Szinkronizálása (%1%)...</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>Lemezen lévő blokkok újraindexelése...</translation>
</message>
@@ -719,10 +731,6 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>&amp;Cím</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Új fogadó cím</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Új küldő cím</translation>
</message>
@@ -739,10 +747,6 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>A megadott "%1" cím nem egy érvényes Bitcoin-cím.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>A megadott "%1" cím már szerepel a címjegyzékben.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Tárca feloldása sikertelen</translation>
</message>
@@ -788,42 +792,6 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<source>Command-line options</source>
<translation>Parancssoros opciók</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Használat:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>parancssoros opciók</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Kezelőfelület beállításai:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Adatkönyvtár kiválasztása induláskor (alapértelmezett: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Nyelvbeállítás, például "de_DE" (alapértelmezett: rendszer nyelve)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Indítás lekicsinyítve</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>SLL gyökér-igazolások megadása fizetési kérelmekhez (alapértelmezett: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Indítóképernyő mutatása induláskor (alapértelmezett: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>A grafikus felület összes megváltoztatott beállításának a visszaállítása</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1005,6 +973,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Megmutatja, hogy az alapértelmezett SOCKS5 proxy van-e használatban, hogy elérje a párokat ennél a hálózati típusnál.</translation>
</message>
<message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Ikon elrejtése a tálcáról.</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Az alkalmazásból való kilépés helyett az eszköztárba kicsinyíti az alkalmazást az ablak bezárásakor. Ez esetben az alkalmazás csak a Kilépés menüponttal zárható be.</translation>
</message>
@@ -1069,6 +1041,14 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>&amp;UPnP port-feltérképezés</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Külső csatlakozások elfogadása.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Bejövő kapcsolatok engedélyezése.</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Csatlakozás a Bitcoin hálózatához SOCKS5 proxyn keresztül</translation>
</message>
@@ -1149,6 +1129,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Mutassa a pénzküldés beállításait vagy ne.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;Harmadik féltől származó tranzakció URL-ek</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1746,6 +1730,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Használja a fel és le nyilakat az előzményekben való navigáláshoz, és %1 -et a képernyő törlésére.</translation>
</message>
<message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Több információért használja a konzolban a %1 parancsot.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>FIGYELEM: Csalók megpróbálnak felhasználókat rávenni, hogy parancsokat írjanak be ide, és ellopják a tárca tartalmát. Ne használja ezt a konzolt anélkül, hogy teljesen megértené egy parancs kiadásának a következményeit.</translation>
</message>
@@ -1825,6 +1813,14 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Törlés</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Segwit címek (Bech32 vagy BIP-173) csökkentik a tranzakciók díját és jobb védelmet biztosítanak gépelési hibával szemben, de a régi pénztárcák nem támogatják. Ha nincs aktiválva, egy régi pénztárcával is kompatibilis cím lesz létrehozva.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Segwit cím (Bech32) létrehozása</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>A kért kifizetések története</translation>
</message>
@@ -1912,6 +1908,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Üzenet</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Tárca</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>A keletkezett URI túl hosszú, próbálja meg csökkenteni a cimke / üzenet szövegének méretét.</translation>
</message>
@@ -2034,6 +2034,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Elrejtés</translation>
</message>
<message>
+ <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
+ <translation>Alacsony díj is megfelelő, ha nincs több tranzakció mint amennyi hely a blokkokban. Figyelem! Ha a hálózat túlterhelt, lehetséges, hogy a tranzakció nem lesz megerősítve.</translation>
+ </message>
+ <message>
<source>(read the tooltip)</source>
<translation>(olvasd el a gyorstippet)</translation>
</message>
@@ -2062,6 +2066,14 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Por-határ:</translation>
</message>
<message>
+ <source>Confirmation time target:</source>
+ <translation>Várható megerősítési idő:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Replace-By-Fee bekapcsolása</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Mindent &amp;töröl</translation>
</message>
@@ -2110,16 +2122,16 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Biztosan el akarja küldeni?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>hozzáadva, mint tranzakciós díj</translation>
+ <source>or</source>
+ <translation>vagy</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Teljes Összeg %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Később növelheti a tranzakció díját (lásd Replace-By-Fee, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>vagy</translation>
+ <source>Transaction fee</source>
+ <translation>Tranzakciós díj</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2233,10 +2245,22 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>&amp;Vonja le a díjat az összegből</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>Elérhető egyenleg használata</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Üzenet:</translation>
</message>
<message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>Ez egy nem hitelesített fizetési kérelem.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>Ez egy hitelesített fizetési kérelem.</translation>
+ </message>
+ <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation>Adjon egy címkét ehhez a címhez, hogy bekerüljön a használt címek közé</translation>
</message>
@@ -2407,10 +2431,6 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>%1 -ig megnyitva</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/megerősítetlen, %1</translation>
</message>
@@ -2439,10 +2459,6 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Állapot</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, még nem sikerült közvetíteni</translation>
- </message>
- <message>
<source>Date</source>
<translation>Dátum</translation>
</message>
@@ -2573,10 +2589,6 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>%1 -ig megnyitva</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Megerősítetlen</translation>
</message>
@@ -2601,10 +2613,6 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Éretlen (%1 megerősítés, %2 után lesz elérhető)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Ezt a blokkot egyetlen másik csomópont sem kapta meg, így valószínűleg nem lesz elfogadva!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generálva, de nincs elfogadva</translation>
</message>
@@ -2833,6 +2841,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Jelenlegi díj:</translation>
</message>
<message>
+ <source>Increase:</source>
+ <translation>Növekedés:</translation>
+ </message>
+ <message>
<source>New fee:</source>
<translation>Új díj:</translation>
</message>
@@ -2840,7 +2852,11 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<source>Can't sign transaction.</source>
<translation>Tranzakció aláírása sikertelen.</translation>
</message>
- </context>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>A tranzakciót nem lehet elküldeni</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -2871,33 +2887,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<source>The wallet data was successfully saved to %1.</source>
<translation>A tárca adatai sikeresen elmentve %1.</translation>
</message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opciók
-</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Adatkönyvtár
-</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Kapcsolódás egy csomóponthoz a peerek címeinek megszerzése miatt, majd szétkapcsolás</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Adja meg az Ön saját nyilvános címét</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Parancssoros és JSON-RPC parancsok elfogadása
-</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>MIT szoftver licenc alapján terjesztve, tekintse meg a hozzátartozó fájlt %s or %s</translation>
</message>
@@ -2906,9 +2899,8 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Hiba: Fatális belső hiba történt, nézze meg a debug.log -ot a részletekért</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Háttérben futtatás daemonként és parancsok elfogadása
-</translation>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>HTTP szerver indítása sikertelen. A részleteket lásd: debug log.</translation>
</message>
<message>
<source>Bitcoin Core</source>
@@ -2919,20 +2911,20 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>A %s fejlesztők</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Parancs, amit akkor hajt végre, amikor egy tárca-tranzakció megváltozik (%s a parancsban lecserélődik a blokk TxID-re)</translation>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation>Ez egy kiadás előtt álló, teszt verzió - csak saját felelősségre - ne használja bányászatra vagy kereskedéshez.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>UPnP használata porttovábbításra (alapértelmezett: 1, amikor kiszolgál és nem használt a -proxy)</translation>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Figyelem: A hálózat úgy tűnik nem teljesen egyezik! Néhány bányász problémákat tapasztalhat.</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; lehet:</translation>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation>-maxmempool legalább %d MB kell legyen.</translation>
</message>
<message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Kívülről érkező kapcsolatok elfogadása (alapértelmezett: 1, ha nem használt a -proxy vagy a -connect)</translation>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Szerzői jog (C) fenntartva %i-%i</translation>
</message>
<message>
<source>Corrupted block database detected</source>
@@ -2951,6 +2943,18 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>A tárca-adatbázis inicializálása nem sikerült: %s!</translation>
</message>
<message>
+ <source>Error loading %s</source>
+ <translation>Hiba a(z) %s betöltése közben</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Hiba a(z) %s betöltése közben: A tárca hibás.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Hiba a(z) %s betöltése közben: A tárcához %s újabb verziója szükséges.</translation>
+ </message>
+ <message>
<source>Error loading block database</source>
<translation>Hiba a blokk adatbázis betöltése közben.</translation>
</message>
@@ -2967,6 +2971,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Egyik hálózati porton sem sikerül hallgatni. Használja a -listen=0 kapcsolót, ha ezt szeretné.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>A tárca átvizsgálása közben hiba történt.</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importálás</translation>
</message>
@@ -2975,6 +2983,10 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Helytelen vagy nemlétező genézis blokk. Helytelen hálózati adatkönyvtár?</translation>
</message>
<message>
+ <source>Loading P2P addresses...</source>
+ <translation>P2P címek betöltése...</translation>
+ </message>
+ <message>
<source>Loading banlist...</source>
<translation>Tiltólista betöltése...</translation>
</message>
@@ -2983,44 +2995,44 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Nincs elég fájlleíró. </translation>
</message>
<message>
- <source>Transaction fee and change calculation failed</source>
- <translation>A tranzakciós díj és a visszajáró kiszámítása nem sikerült</translation>
+ <source>Replaying blocks...</source>
+ <translation>Blokkok újrajátszása...</translation>
</message>
<message>
- <source>Verifying blocks...</source>
- <translation>Blokkok ellenőrzése...</translation>
+ <source>Rewinding blocks...</source>
+ <translation>Blokkok visszapörgetése...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Tárca beállítások:</translation>
+ <source>The source code is available from %s.</source>
+ <translation>A forráskód elérhető: %s.</translation>
</message>
<message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Saját IP-cím felfedezése (alapértelmezett: 1, amikor kiszolgál és nem használt a -externalip)</translation>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>A tranzakciós díj és a visszajáró kiszámítása nem sikerült</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>A fehérlistán szereplő felek nem lesznek automatikusan kitiltva és a tranzakcióik is mindig továbbítva lesznek, akkor is ha már a megerősítésre váró listán (mempool) vannak. Hasznos például összekötő csomópontokon (gateway).</translation>
+ <source>Upgrading UTXO database</source>
+ <translation>Blokk adatbázis frissítése</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(alapértelmezett: %u)</translation>
+ <source>Verifying blocks...</source>
+ <translation>Blokkok ellenőrzése...</translation>
</message>
<message>
- <source>Error reading from database, shutting down.</source>
- <translation>Hiba az adatbázis olvasásakor, leállítás</translation>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>A Tárca újraírása szükséges: Indítsa újra a %s-t.</translation>
</message>
<message>
- <source>Information</source>
- <translation>Információ</translation>
+ <source>Error reading from database, shutting down.</source>
+ <translation>Hiba az adatbázis olvasásakor, leállítás</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>RPC szerver opciók:</translation>
+ <source>Error upgrading chainstate database</source>
+ <translation>Hiba a blokk adatbázis betöltése közben</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>trace/debug információ küldése a konzolra a debog.log fájl helyett</translation>
+ <source>Information</source>
+ <translation>Információ</translation>
</message>
<message>
<source>Signing transaction failed</source>
@@ -3039,32 +3051,14 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>Túl nagy tranzakció</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Felhasználói név JSON-RPC csatlakozásokhoz
-</translation>
+ <source>Verifying wallet(s)...</source>
+ <translation>Tárcák ellenőrzése...</translation>
</message>
<message>
<source>Warning</source>
<translation>Figyelem</translation>
</message>
<message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Az adatbázist újra kell építeni -reindex használatával, hogy a -tindex-et módosítsd.</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Jelszó JSON-RPC csatlakozásokhoz
-</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Parancs, amit akkor hajt végre, amikor a legjobb blokk megváltozik (%s a cmd-ban lecserélődik a blokk hash-re)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>DNS-kikeresés engedélyezése az addnode-nál és a connect-nél</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Figyelem: Ismeretlen blokkokat bányásznak! Lehetséges, hogy ismeretlen szabályok érvényesek.</translation>
</message>
@@ -3073,50 +3067,6 @@ Kérem a kulcsmondatban használjon &lt;b&gt; tíz vagy több véletlenszerű ka
<translation>%s étéke nagyon magas!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(alapértelmezett: %s)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Hiba a tárca betöltése közben %s. Érvénytelen karakterek a -tárca fájlnevében.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Hány blokkot ellenőrizzen induláskor (alapértelmezett: %u, 0 = mindet)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>IP-címek megjelenítése a naplóban (alapértelmezett: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Kapcsolatonkénti maximum fogadó buffer, &lt;n&gt;*1000 byte (alapértelmezett: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Kapcsolatonkénti maximum küldő buffer, &lt;n&gt;*1000 byte (alapértelmezett: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Kulcshalmaz méretének a beállítása &lt;n&gt;(alapértelmezett: %u) </translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Konfigurációs fájl megadása (alapértelmezett: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Csatlakozás időtúllépése milliszekundumban (minimum: 1, alapértelmezett: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Pid-fájl megadása (alapértelmezett: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Tranzakciók küldésekor a jóváhagyatlan visszajáró elköltése (alapértelmezés: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Hálózati szálak indítása...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_id.ts b/src/qt/locale/bitcoin_id.ts
new file mode 100644
index 0000000000..1a4c7236d1
--- /dev/null
+++ b/src/qt/locale/bitcoin_id.ts
@@ -0,0 +1,969 @@
+<TS language="id" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>Klik kanan untuk mengubah alamat atau label</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>Buat sebuah alamat baru</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;Baru</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Salin alamat yang dipilih ke dalam clipboard sistem</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Salin</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>&amp;Tutup</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>Hapus alamat yang dipilih dari daftar</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Masukkan alamat atau label untuk mencari</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Ekspor data dalam tab saat ini ke file</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;Export</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;Hapus</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Pilih alamat untuk mengirim koin kepada</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Pilih alamat untuk menerima koin</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>P&amp;ilih</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Alamat mengirim</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Alamat menerima</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Ini adalah alamat Bitcoin anda untuk mengirim pembayaran. Selalu periksa jumlah dan alamat penerima sebelum mengirim koin</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Ini adalah alamat Bitcoin anda untuk menerima pembayaran. Disarankan untuk menggunakan alamat penerimaan baru untuk setiap transaksi</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Salin Alamat</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Copy &amp;Label</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Edit</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Export Daftar Alamat</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>File dipisahkan dengan Comma (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Exporting Gagal</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Terjadi kesalahan saat menyimpan daftar alamat %1. Silahkan coba kembali.</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Alamat</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(tanpa label)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation>Dialog passphrase</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>Masukan passphrase</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>Passphrase baru</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>Ulangi passphrase baru</translation>
+ </message>
+ <message>
+ <source>Show password</source>
+ <translation>Tampilkan kata sandi</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Masukkan passphrase baru ke dompet.&lt;br/&gt;Harap gunakan passphrase dari &lt;b&gt;sepuluh atau lebih karakter acak&lt;/b&gt;, or &lt;b&gt;delapan atau lebih kata&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Enkripsi wallet</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Tindakan ini memerlukan passphrase untuk membuka wallet anda</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Buka wallet</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Tindakan ini memerlukan passphrase untuk mendekripsi wallet anda</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Dekripsi wallet</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Ganti passphrase</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Masukan passphrase lama dan passphrase baru ke wallet</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Konfirmasi proses enkripsi wallet</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Peringatan: Jika anda mengenkripsi wallet anda dan lupa/hilang passphrase anda, anda akan ‭&lt;b&gt; KEHILANGAN SEMUA BITCOIN ANDA &lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Apa anda yakin ingin mengenkripsi wallet anda?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Wallet terenkripsi</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 akan ditutup sekarang untuk menyelesaikan proses enkripsi. Ingat bahwa mengenkripsi dompet Anda tidak dapat sepenuhnya melindungi bitcoin Anda dari pencurian oleh malware yang menginfeksi komputer Anda.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>PENTING: Semua cadangan sebelumnya yang Anda buat dari file dompet Anda harus diganti dengan file dompet terenkripsi yang baru dibuat. Untuk alasan keamanan, cadangan sebelumnya dari file dompet yang tidak terenkripsi akan menjadi tidak berguna segera setelah Anda mulai menggunakan dompet terenkripsi yang baru.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Enkripsi wallet gagal</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Enkripsi wallet gagal karena kesalahan internal. Wallet anda belum terenkripsi</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Passphrase yang dimasukan tidak cocok.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Gagal membuka wallet</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Passphrase yang dimasukan untuk dekripsi wallet salah</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Gagal mendekripsi wallet</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Passphrase wallet berhasil diganti</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Peringatan: Caps Lock key menyala!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Netmask</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Dibanned hingga</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>&amp;Verifikasi pesan...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>Sedang sinkronisasi dengan jaringan</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;Overview</translation>
+ </message>
+ <message>
+ <source>Node</source>
+ <translation>Node</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>Tampilkan gambaran umum dompet</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;Transaksi</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>Telusuri history transaksi</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>&amp;Keluar</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Tutup aplikasi</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;Tentang %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Tunjukan informasi tentang %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>Tentang &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Tampilkan informasi tentang Qt</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;Pilihan...</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>Ubah pilihan konfigurasi untuk %1</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;Enkripsi wallet...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>&amp;Backup wallet</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>&amp;Ganti Passphrase...</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses...</source>
+ <translation>&amp;Mengirim alamat</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses...</source>
+ <translation>&amp;Menerima alamat...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Buka &amp;URI...</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Dompet:</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Klik untuk menonaktifkan aktifitas network</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Aktifitas network tidak aktif</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Klik untuk mengaktifkan kembali network</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>Kirim koin ke alamat Bitcoin</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>Backup wallet ke lokasi lain</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Ganti passphrase yang digunakan untuk enkripsi wallet</translation>
+ </message>
+ <message>
+ <source>&amp;Debug window</source>
+ <translation>&amp;Debug window</translation>
+ </message>
+ <message>
+ <source>Open debugging and diagnostic console</source>
+ <translation>Buka debugging dan diagnostic console</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Verifikasi pesan...</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Wallet</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;Kirim</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Terima</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Tampilkan/ Sembunyikan</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Tampilkan atau sembunyikan tampilan utama</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Enkripsi private keys wallet anda</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Tambahkan pesan di alamat Bitcoin untuk membuktikan bahwa anda pemiliknya</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Verifikasi pesan untuk memastikan bahwa telah ditanda tangani dengan alamat Bitcoin tertentu</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;File</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;Pengaturan</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;Bantuan</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Toolbar Tabs</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Tampilkan daftar alamat kirim yg telah digunakan dan label</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Peringatan</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Informasi</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>Terkini</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 client</translation>
+ </message>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Menghubungkan ke peers...</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>Catching up...</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Tanggal: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Jumlah: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Tipe: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Label: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Alamat: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Transaksi terkirim</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Transaksi datang</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>Pembuatan kunci HD &lt;b&gt;diaktifkan&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Pembuatan kunci HD &lt;b&gt;dinonaktifkan&lt;/b&gt;</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation>Pemilihan koin</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Jumlah:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bytes:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Jumlah:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Biaya:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Dust:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Setelah biaya:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Ganti:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>(tidak)pilih semua</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Mode pohon</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Mode list</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Jumlah</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>Diterima dengan label</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Diterima dengan alamat</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Tanggal</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>Konfirmasi</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Telah dikonfirmasi</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Salin alamat</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Salin label</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Salin jumla</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Salin ID transaksi</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Kunci yang tidak digunakan</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Buka kunci yang tidak digunakan</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Salin jumlah</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Salin biaya</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Salin setelah biaya</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>salin bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Salin dust</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Salin perubahan</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 terkunci)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>Ya</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>Tidak</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(tanpa label)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(ganti)</translation>
+ </message>
+</context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation>Ubah Alamat</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;Label</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>Alamat pengirim baru</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Ubah alamat penerima</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Ubah alamat pengieim</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Tidak bisa membuka wallet</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Pembuatan kunci baru gagal.</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>name</source>
+ <translation>nama</translation>
+ </message>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation>versi</translation>
+ </message>
+ <message>
+ <source>(%1-bit)</source>
+ <translation>(%1-bit)</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>Tentang %1</translation>
+ </message>
+ </context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Jumlah</translation>
+ </message>
+ </context>
+<context>
+ <name>QObject::QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>Copy label</source>
+ <translation>Salin label</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Salin jumla</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Address</source>
+ <translation>Alamat</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Jumlah</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Wallet</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Tanggal</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(tanpa label)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Quantity:</source>
+ <translation>Jumlah:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bytes:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Jumlah:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Biaya:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Setelah biaya:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Ganti:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Dust:</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Salin jumlah</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Salin jumla</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Salin setelah biaya</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>salin bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Salin dust</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Salin perubahan</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(tanpa label)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ </context>
+<context>
+ <name>SendConfirmationDialog</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ </context>
+<context>
+ <name>SplashScreen</name>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation>Tanggal</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Jumlah</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Tanggal</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(tanpa label)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Copy address</source>
+ <translation>Salin alamat</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Salin label</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Salin jumla</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Salin ID transaksi</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>File dipisahkan dengan Comma (*.csv)</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Telah dikonfirmasi</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Tanggal</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Label</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Alamat</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Exporting gagal</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;Export</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Ekspor data dalam tab saat ini ke file</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Information</source>
+ <translation>Informasi</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Peringatan</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+</context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts
index 0918b58285..a487936fd2 100644
--- a/src/qt/locale/bitcoin_id_ID.ts
+++ b/src/qt/locale/bitcoin_id_ID.ts
@@ -30,6 +30,10 @@
<translation>Hapus alamat yang sementara dipilih dari daftar</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Masukkan alamat atau label untuk mencari</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Ekspor data dalam tab sekarang ke sebuah berkas</translation>
</message>
@@ -63,11 +67,11 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Ini adalah alamat- alamat Bitcoin Anda untuk mengirimkan pembayaran. Selalu periksa jumlah dan alamat penerima sebelum mengirimkan koin.</translation>
+ <translation>Berikut ialah alamat-alamat Bitcoin Anda yang digunakan untuk mengirimkan pembayaran. Selalu periksa jumlah dan alamat penerima sebelum mengirimkan koin.</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Ini adalah alamat- alamat Bitcoin Anda untuk menerima pembayaran. Dianjurkan untuk menggunakan alamat penerima yang baru setiap melakukan transaksi.</translation>
+ <translation>Berikut ialah alamat-alamat Bitcoin Anda yang digunakan untuk menerima pembayaran. Dianjurkan untuk menggunakan alamat penerimaan baru untuk setiap transaksi.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -87,13 +91,17 @@
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>File yang berformat(*.csv)</translation>
+ <translation>Berkas CSV (*.csv)</translation>
</message>
<message>
<source>Exporting Failed</source>
- <translation>Mengekspor Gagal</translation>
+ <translation>Gagal Mengekspor</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Terjadi kesalahan saat mencoba menyimpan daftar alamat ke %1. Silakan coba lagi.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
<message>
@@ -113,19 +121,23 @@
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
- <translation>Dialog Kata kunci</translation>
+ <translation>Dialog Kata Sandi</translation>
</message>
<message>
<source>Enter passphrase</source>
- <translation>Masukkan kata kunci</translation>
+ <translation>Masukkan kata sandi</translation>
</message>
<message>
<source>New passphrase</source>
- <translation>Kata kunci baru</translation>
+ <translation>Kata sandi baru</translation>
</message>
<message>
<source>Repeat new passphrase</source>
- <translation>Ulangi kata kunci baru</translation>
+ <translation>Ulangi kata sandi baru</translation>
+ </message>
+ <message>
+ <source>Show password</source>
+ <translation>Tampilkan kata sandi</translation>
</message>
<message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
@@ -165,7 +177,7 @@
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>Peringatan: Jika Anda enkripsi dompet Anda dan lupa kata sandi anda, Anda akan &lt;b&gt;KEHILANGAN SEMUA BITCOIN ANDA&lt;/b&gt;!</translation>
+ <translation>Peringatan: Jika Anda mengenkripsi dompet Anda dan lupa kata sandi Anda, Anda akan &lt;b&gt;KEHILANGAN SEMUA BITCOIN ANDA&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -314,6 +326,14 @@
<translation>Buka &amp;URI</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Wallet:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>wallet default</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Klik untuk menonaktifkan aktivitas jaringan.</translation>
</message>
@@ -334,6 +354,10 @@
<translation>Mengindex ulang blok di dalam disk...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy di &lt;b&gt;aktifkan&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Kirim koin ke alamat Bitcoin</translation>
</message>
@@ -502,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Wallet: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Tipe: %1
@@ -679,10 +709,22 @@
<translation>Tidak</translation>
</message>
<message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Dapat bervariasi +/- %1 satoshi per input.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tidak ada label)</translation>
</message>
- </context>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>kembalian dari %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(kembalian)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -706,10 +748,6 @@
<translation>&amp;Alamat</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Alamat penerima baru</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Alamat pengirim baru</translation>
</message>
@@ -726,8 +764,12 @@
<translation>Alamat yang dimasukkan "%1" bukanlah alamat Bitcoin yang valid.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Alamat yang dimasukkan "%1" sudah ada di dalam buku alamat.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Alamat "%1" sudah ada sebagai alamat penerimaan dengan label "%2" sehingga tidak bisa ditambah sebagai alamat pengiriman.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Alamat "%1" yang dimasukkan sudah ada di dalam buku alamat dengan label "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -779,42 +821,6 @@
<source>Command-line options</source>
<translation>Pilihan Command-line</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Penggunaan:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>pilihan command-line</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Pilihan UI:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Pilih direktori data saat memulai (default: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Pilih bahasa, contoh "id_ID" (default: system locale)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Start minimized</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Pilih sertifikat root SSL untuk permintaan pembayaran {default: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Tampilkan layar kilat saat memulai (default: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Hapus semua pengaturan pada GUI.</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -831,6 +837,18 @@
<translation>Karena ini adalah pertama kalinya program dijalankan, Anda dapat memilih lokasi %1 akan menyimpan data.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>Ketika Anda mengklik OK, %1 akan mulai mengunduh dan memproses %4 block chain penuh (%2GB), dimulai dari transaksi-transaksi awal di %3 saat %4 diluncurkan pertama kali.</translation>
+ </message>
+ <message>
+ <source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
+ <translation>Sinkronisasi awal sangat berat dan mungkin akan menunjukkan permasalahan pada perangkat keras komputer Anda yang sebelumnya tidak tampak. Setiap kali Anda menjalankan %1, aplikasi ini akan melanjutkan pengunduhan dari posisi terakhir.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>Apabila Anda memilih untuk membatasi penyimpanan block chain (pruning), data historis tetap akan diunduh dan diproses. Namun, data akan dihapus setelahnya untuk menjaga pemakaian disk agar tetap sedikit.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>Gunakan direktori data default.</translation>
</message>
@@ -843,6 +861,22 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>Setidaknya %1 GB data akan disimpan di direktori ini dan akan berkembang seiring berjalannya waktu.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>%1 GB data akan disimpan di direktori ini.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>%1 akan mengunduh dan menyimpan salinan Bitcoin block chain.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Dompet juga akan disimpan di direktori ini.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" cannot be created.</source>
<translation>Kesalahan: Direktori data "%1" tidak dapat dibuat.</translation>
</message>
@@ -866,10 +900,50 @@
<translation>Formulir</translation>
</message>
<message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation>Transaksi-transaksi terkini mungkin belum terlihat dan oleh karenanya, saldo dompet Anda mungkin tidak tepat. Informasi ini akan akurat ketika dompet Anda tersinkronisasi dengan jaringan Bitcoin, seperti rincian berikut.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation>Usaha untuk menggunakan bitcoin yang dipengaruhi oleh transaksi yang belum terlihat tidak akan diterima oleh jaringan.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Jumlah blok tersisa</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Tidak diketahui...</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation>Waktu blok terakhir</translation>
</message>
- </context>
+ <message>
+ <source>Progress</source>
+ <translation>Perkembangan</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>Peningkatan perkembangan per jam</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>menghitung...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Estimasi waktu tersisa sampai tersinkronisasi</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Sembunyikan</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1)...</source>
+ <translation>Tidak diketahui. Menyinkronisasikan Headers (%1)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -888,7 +962,11 @@
<source>Select payment request file</source>
<translation>Pilih data permintaan pembayaran</translation>
</message>
- </context>
+ <message>
+ <source>Select payment request file to open</source>
+ <translation>Pilih data permintaan pembayaran yang akan dibuka</translation>
+ </message>
+</context>
<context>
<name>OptionsDialog</name>
<message>
@@ -900,6 +978,14 @@
<translation>&amp;Utama</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Mulai %1 secara otomatis setelah masuk ke dalam sistem.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>Mulai %1 ketika masuk ke &amp;sistem</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation>Ukuran cache &amp;database</translation>
</message>
@@ -916,6 +1002,22 @@
<translation>Alamat IP proxy (cth. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
</message>
<message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation>Perlihatkan apabila proxy SOCKS5 default digunakan untuk berhungan dengan orang lain lewat tipe jaringan ini.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Menggunakan proxy SOCKS5 tersendiri untuk berhubungan dengan orang lain melalui layanan Tor:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Sembunyikan ikon dari system tray.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Sembunyikan ikon tray</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Minimalisasi aplikasi ketika jendela ditutup. Ketika pilihan ini dipilih, aplikasi akan menutup seluruhnya jika anda memilih Keluar di menu yang tersedia.</translation>
</message>
@@ -928,6 +1030,14 @@
<translation>Pilihan command-line yang aktif menimpa diatas opsi: </translation>
</message>
<message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Buka file konfigurasi %1 dari direktori kerja.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Buka Berkas Konfigurasi</translation>
+ </message>
+ <message>
<source>Reset all client options to default.</source>
<translation>Kembalikan semua pengaturan ke awal.</translation>
</message>
@@ -940,6 +1050,18 @@
<translation>&amp;Jaringan</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Menonaktifkan beberapa fitur canggih akan tetapi semua block akan tetap divalidasi seutuhnya. Mengembalikan pengaturan ini memerlukan untuk mengunduh seluruh blockchain. Penggunaan disk mungkin akan lebih tinggi.</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Mengembalikan pengaturan ini membutuhkan pengunduhan seluruh blockchain lagi. </translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt;0 = leave that many cores free)</translation>
</message>
@@ -972,10 +1094,22 @@
<translation>Petakan port dengan &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Terima koneksi-koneksi dari luar.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Terima koneksi-koneksi masuk</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Hubungkan ke jaringan Bitcoin melalui SOCKS5 proxy.</translation>
</message>
<message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;Hubungkan melalui proxy SOCKS5 (proxy default):</translation>
+ </message>
+ <message>
<source>Proxy &amp;IP:</source>
<translation>IP Proxy:</translation>
</message>
@@ -988,6 +1122,10 @@
<translation>Port proxy (cth. 9050)</translation>
</message>
<message>
+ <source>Used for reaching peers via:</source>
+ <translation>Digunakan untuk berhubungan dengan peers melalui:</translation>
+ </message>
+ <message>
<source>IPv4</source>
<translation>IPv4</translation>
</message>
@@ -1000,6 +1138,10 @@
<translation>Tor</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>Koneksi ke jaringan bitcoin melalui proxy SOCKS5 yang berbeda untuk layanan Tor tersembunyi.</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;Jendela</translation>
</message>
@@ -1024,6 +1166,10 @@
<translation>&amp;Bahasa Antarmuka Pengguna:</translation>
</message>
<message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation>Bahasa tampilan dapat diatur di sini. Pengaturan ini akan berpengaruh setelah memulai ulang %1.</translation>
+ </message>
+ <message>
<source>&amp;Unit to show amounts in:</source>
<translation>&amp;Unit untuk menunjukkan nilai:</translation>
</message>
@@ -1036,6 +1182,10 @@
<translation>Ingin menunjukkan cara pengaturan koin atau tidak.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;URL transaksi pihak ketiga</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;YA</translation>
</message>
@@ -1064,10 +1214,22 @@
<translation>Klien akan dimatikan, apakah anda hendak melanjutkan?</translation>
</message>
<message>
+ <source>Configuration options</source>
+ <translation>Konfigurasi pengaturan</translation>
+ </message>
+ <message>
+ <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
+ <translation>File konfigurasi digunakan untuk menspesifikkan pilihan khusus pengguna yang akan menimpa pengaturan GUI. Sebagai tambahan, pengaturan command-line apapun akan menimpa file konfigurasi itu.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Terjadi sebuah kesalahan</translation>
</message>
<message>
+ <source>The configuration file could not be opened.</source>
+ <translation>Berkas konfigurasi tidak dapat dibuka.</translation>
+ </message>
+ <message>
<source>This change would require a client restart.</source>
<translation>Perubahan ini akan memerlukan restart klien</translation>
</message>
@@ -1087,6 +1249,10 @@
<translation>Informasi terlampir mungkin sudah kedaluwarsa. Dompet Anda secara otomatis mensinkronisasi dengan jaringan Bitcoin ketika sebuah hubungan terbentuk, namun proses ini belum selesai.</translation>
</message>
<message>
+ <source>Watch-only:</source>
+ <translation>Hanya lihat:</translation>
+ </message>
+ <message>
<source>Available:</source>
<translation>Tersedia:</translation>
</message>
@@ -1122,9 +1288,77 @@
<source>Your current total balance</source>
<translation>Jumlah saldo Anda sekarang</translation>
</message>
- </context>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>Saldomu di alamat hanya lihat</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Bisa digunakan:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Transaksi-transaksi terkini</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>Transaksi yang belum terkonfirmasi ke alamat hanya lihat</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>Saldo hasil mining di alamat hanya lihat yang belum bisa digunakan</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>Jumlah saldo di alamat hanya lihat</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Terjadi kesalahan pada permintaan pembayaran</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Tidak bisa memulai bitcoin: handler click-to-pay</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>Pengelolaan URI</translation>
+ </message>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' bukanlah alamat URI yang valid. Silakan gunakan 'bitcoin:'.</translation>
+ </message>
+ <message>
+ <source>Payment request fetch URL is invalid: %1</source>
+ <translation>URL permintaan pembayaran tidak valid: %1</translation>
+ </message>
+ <message>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation>URI tidak bisa dimengerti! Hal ini bisa disebabkan karena alamat Bitcoin yang tidak sah atau parameter URI yang tidak tepat.</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>Pengelolaan file permintaan pembayaran</translation>
+ </message>
+ <message>
+ <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
+ <translation>File permintaan pembayaran tidak bisa dibaca! Hal ini bisa disebabkan karena file permintaan pembayaran tidak valid.</translation>
+ </message>
+ <message>
+ <source>Payment request rejected</source>
+ <translation>Permintaan pembayaran ditolak</translation>
+ </message>
+ <message>
+ <source>Payment request network doesn't match client network.</source>
+ <translation>Jaringan permintaan pembayaran tidak sesuai dengan jaringan klien.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Permintaan pembayaran telah kadaluarsa.</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1307,6 +1541,10 @@
<translation>1 &amp;tahun</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>wallet default</translation>
+ </message>
+ <message>
<source>Yes</source>
<translation>Ya</translation>
</message>
@@ -1416,6 +1654,10 @@
<source>Label</source>
<translation>Label</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Dompet</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1487,6 +1729,10 @@
<translation>Biaya Transaksi:</translation>
</message>
<message>
+ <source>Hide</source>
+ <translation>Sembunyikan</translation>
+ </message>
+ <message>
<source>Recommended:</source>
<translation>Disarankan</translation>
</message>
@@ -1551,6 +1797,14 @@
<translation>Salin Perubahan</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Biaya Transaksi</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Permintaan pembayaran telah kadaluarsa.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tidak ada label)</translation>
</message>
@@ -1776,58 +2030,14 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Pilihan:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Tentukan direktori data</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Hubungkan ke node untuk menerima alamat peer, dan putuskan</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Tentukan alamat publik Anda sendiri</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Menerima perintah baris perintah dan JSON-RPC</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Berjalan dibelakang sebagai daemin dan menerima perintah</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Jalankan perintah ketika perubahan transaksi dompet (%s di cmd digantikan oleh TxID)</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Terima hubungan dari luar (standar: 1 kalau -proxy atau -connect tidak dipilih)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Pilihan pembuatan blok:</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Pilih koneksi:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>Menemukan database blok yang rusak </translation>
</message>
<message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Jangan memuat dompet dan menonaktifkan panggilan dompet RPC</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Apakah Anda ingin coba membangun kembali database blok sekarang?</translation>
</message>
@@ -1864,38 +2074,14 @@
<translation>Deskripsi berkas tidak tersedia dengan cukup.</translation>
</message>
<message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Tentukan arsip dompet (dalam direktori data)</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>Blok-blok sedang diverifikasi...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opsi dompet:</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Hubungkan melalui proxy SOCKS5</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informasi</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>Opsi server RPC:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Kirim info jejak/debug ke konsol bukan berkas debug.log</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Mengecilkan berkas debug.log saat klien berjalan (Standar: 1 jika tidak -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Tandatangani transaksi tergagal</translation>
</message>
@@ -1908,10 +2094,6 @@
<translation>Transaksi terlalu besar</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nama pengguna untuk hubungan JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Peringatan</translation>
</message>
@@ -1920,18 +2102,6 @@
<translation>Setiap transaksi dalam dompet sedang di-'Zap'...</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Kata sandi untuk hubungan JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Menjalankan perintah ketika perubahan blok terbaik (%s dalam cmd digantikan oleh hash blok)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Izinkan peninjauan DNS untuk -addnote, -seednode dan -connect</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>Jaringan tidak diketahui yang ditentukan dalam -onlynet: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_is.ts b/src/qt/locale/bitcoin_is.ts
new file mode 100644
index 0000000000..6a4e26ac22
--- /dev/null
+++ b/src/qt/locale/bitcoin_is.ts
@@ -0,0 +1,997 @@
+<TS language="is" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>Smelltu á hægri músatakka til að breyta færslugildi eða merkingu</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>Búa til nýtt færslugildi</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;Nýtt</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Afrita valið færslugildi í klemmuspjald</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Afrita</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>&amp;Loka</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>Eyða völdu færslugildi úr listanum</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Flytja gögn í flipanum í skrá</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;Flytja út</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;Eyða</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Veldu færslugildi sem greiða skal til</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Veldu færslugildi sem á að taka við mynt</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>&amp;Veldu</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Færslugildi sem senda frá sér</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Færslugildi sem þiggja til sín</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Þetta eru Bitcoin færslugildin sem senda greiðslur. Skoðið ævinlega vel upphæðina og færslugildin sem þiggja greiðslur áður en mynt er send.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Þetta eru Bitcoin færslugildin sem þiggja greiðslur. Mælt er með að nota aldrei sama færslugildið til að þiggja fleiri en eina greiðslu.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Afrita færslugildi</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Afrita og &amp;Merkja</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Breyta</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Flytja út færslulista</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Gildi aðskilin með kommu (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Útflutningur tókst ekki</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Ekki tókst að vista færslugildalistann á %1. Reyndu aftur.</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Merking</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Færslugildi</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(engin merking)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation>Lykilsetning</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>Skráðu lykilsetningu</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>Ný lykilsetning</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>Endurtaktu nýja lykilsetningu</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Skráðu nýju lykilsetninguna í veskið. &lt;br/&gt;Vinsamlegast notaðu lykilsetningu með &lt;b&gt;tíu eða fleiri slembibókstöfum&lt;/b&gt;, eða &lt;b&gt;átta eða fleiri orðum&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Dulkóða veski</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Þessi aðgerð þarf að fá lykilsetninguna þína til að opna veskið.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Opna veskið</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Þessi aðgerð þarf lykilsetninguna þína til að dulráða veskið.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Dulráða veskið</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Breyta lykilsetningu</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Skráðu gömlu lykilsetninguna og þá nýju í veskið.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Staðfesta dulkóðun veskis</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Viðvörun: Ef þú dulkóðar veskið og týnir lykilsetningunn þá munt þú &lt;b&gt;TAPA ALLRI ÞINNI BITCOIN MYNT&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Ertu viss um að þú viljir dulkóða veskið þitt?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Veski dulkóðað</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 lokast núna til að dulkóðun klárist. Mundu að dulkóðun veskis kemur ekki að fullu í veg fyrir að mynt verði stolið úr tölvunni þinni með aðstoð smitforrita. </translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>MIKILVÆGT: Nýja dulkóðaða veskisskráin þarf að koma í staðinn fyrir öll fyrri afrit sem þú hefur gert af upprunalegu veskisskránni. Af öryggisástæðum munu öll fyrri afrit af ódulkóðaða veskinu verða óvirk um leið og þú byrjar að nota nýja, dulkóðaða veskið.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Dulkóðun veskis mistókst</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Dulkóðun veskis mistóks vegna innri villu. Veskið þitt var ekki dulkóðað.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Lykilsetningarnar eru ekki þær sömu.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Ekki tókst að opna veskið</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Lykilsetningin sem notuð var til að dulráða veskið var ekki rétt.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Ekki tókst að dulráða veski</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Það tókst að breyta lykilsetningu veskis.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Viðvörun: Kveikt er á HÁSTÖFUM!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Netgríma</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Bannað til</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>Undirrita &amp;skilaboð</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>Samstilli við netið...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;Yfirlit</translation>
+ </message>
+ <message>
+ <source>Node</source>
+ <translation>Hnútur</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>Sýna almennt yfirlit af veski</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;Færslur</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>Skoða færslusögu</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>&amp;Hætta</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Hætta í forriti</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;Um %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Sýna upplýsingar um %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>Um &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Sýna upplýsingar um Qt</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;Valkostir...</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>Breyta samstillingum fyrir %1</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;Dulkóða veski...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>&amp;Öryggisafrit á veski...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>&amp;Breyta lykilsetningu</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses...</source>
+ <translation>&amp;Sendi færslugildi...</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses...</source>
+ <translation>&amp;Tek við færslugildum...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Opna &amp;URL...</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Smelltu til að loka fyrir netumferð.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Slökkt á netumferð.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Smelltu til að hefja aftur netumferð.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Samstilli hausa (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Endurraða blokkum á drifi...</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>Senda mynt í Bitcoin færslugildi</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>Öryggisafrita veski á annan stað</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Breyta lykilsetningunni sem gildir um dulkóðun veskis</translation>
+ </message>
+ <message>
+ <source>&amp;Debug window</source>
+ <translation>&amp;Kembunargluggi</translation>
+ </message>
+ <message>
+ <source>Open debugging and diagnostic console</source>
+ <translation>Opna kembunar- og greiningarstjórnborð</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Yfirfara skilaboð...</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Veski</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;Senda</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Taka við</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Sýna / Fela</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Sýna eða fela megin glugga</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Dulkóða einkalyklana sem tilheyra veskinu þínu</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Kvitta undir skilaboð með Bitcoin færslugildunum þínum til að sanna að þú eigir þau</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Yfirfara skilaboð til að tryggja að kvittað hafi verið fyrir þau með tilteknum Bitcoin færslugildum</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;Skrá</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;Stillingar</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;Hjálp</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Tólaborð flipa</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Óska eftir greiðslum (býr til QR kóða og bitcoin: URI)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Sýna lista yfir færslugildi sem notuð hafa verið til sendingar og merkingar þeirra</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Sýna færslugildi sem notuð hafa verið til að taka við mynt og merkingar þeirra</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI or payment request</source>
+ <translation>Opna bitcoin: URI eða greiðslubeiðni</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Raða blokkum á drifi</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Vinn úr blokkum á drifi...</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 á eftir</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Síðasta viðtekna blokk var búin til fyrir %1 síðan.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Færslur á eftir þessari munu ekki sjást.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Villa</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Viðvörun</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Upplýsingar</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>Uppfært</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Sýna %1 hjálparskilaboðin til að fá lista yfir valkosti Bitcoin aðgerðir í skipanalínu</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 biðlarar</translation>
+ </message>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Tengist jafningjum...</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>Færist nær...</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Dagsetning: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Upphæð: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Tegund: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Merki: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Færslugildi: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Send færsla</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Móttökufærsla</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>HD lyklagerð er &lt;b&gt;virkjuð&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>HD lyklagerð er &lt;b&gt;óvirk&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation>Veskið er &lt;b&gt;dulkóðað&lt;/b&gt; og núna &lt;b&gt;ólæst&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation>Veskið er &lt;b&gt;dulkóðað&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Alvarleg villa átti sér stað. Bitcoin getur ekki haldið áfram með öruggum hætti og stoppar hér.</translation>
+ </message>
+</context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation>Myntval</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Magn:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bæti:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Upphæð:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Gjald:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Ryk:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Eftirgjald:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Skiptimynt:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>(af)velja allt</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Hrísluhamur</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Listahamur</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Upphæð</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>Móttekið með merkingu</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Móttekið með færslugildi</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Afrita færslugildi</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Afrita merki</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Þetta merki verður rautt ef einhver viðtakandi tekur við upphæð sem er lægri en núgildandi þröskuldur.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(ekkert merki)</translation>
+ </message>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation>Breyta færslugildi</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;Merki</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation>Merking tengd þessu færslugildi</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>Færslugildið sem tengt er þessari færslu. Þessu má einungis breyta þegar sent er.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>Nýtt móttökufærslugildi</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>Nýtt sendingarfærslugildi</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Breyta móttökufærslugildi</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Breyta sendingarfærslugildi</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Færslugildið sem slegið var inn "%1" er ekki leyfilegt Bitcoin færslugildi.</translation>
+ </message>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Villa</translation>
+ </message>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Fjöldi blokka sem eftir eru</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Tími síðustu blokkar</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>IP tala staðgengils (t.d. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ </message>
+ <message>
+ <source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
+ <translation>URL frá þriðja aðila (t.d. blokkarskoðari) sem birtast í færsluflipanum sem samhengisatriði. %s í URL-inu skipt út fyrir færslutvíkross. Mörg URL eru aðskilin með lóðréttu striki |.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Villa</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>Uppgefið færslugildi staðgengils er ógilt.</translation>
+ </message>
+</context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>Námuunnin innistæða sem hefur enn ekki komið fram</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>Innistæða færslugilda sem eru einungis til skoðunar</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>Óstaðfestar færslur til færslugilda sem eru einungis til skoðunar</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>Námuunnin innistæða á færslugildum sem eru einungis til skoðunar og hafa ekki komið fram</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>Innistæða á færslugildum sem eru einungis til skoðunar</translation>
+ </message>
+</context>
+<context>
+ <name>PaymentServer</name>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Ógilt færslugildi til greiðslu %1</translation>
+ </message>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Upphæð</translation>
+ </message>
+ </context>
+<context>
+ <name>QObject::QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>Block chain</source>
+ <translation>Blokkarkeðja</translation>
+ </message>
+ <message>
+ <source>Current number of blocks</source>
+ <translation>Núverandi fjöldi blokka</translation>
+ </message>
+ <message>
+ <source>Starting Block</source>
+ <translation>Upphafsblokk</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>Samhæfðar blokkir</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Tími síðustu blokkar</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Merki:</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation>Valfrjálst merki sem tengist nýju móttökufærslutölunni.</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Afrita merki</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Address</source>
+ <translation>Vistfang</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Upphæð</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Merki</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Veski</translation>
+ </message>
+ <message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>URI varð of langt, reyndu að minnka texta í merki / skilaboðum.</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Merki</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(ekkert merki)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Quantity:</source>
+ <translation>Magn:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bæti:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Upphæð:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Gjald:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Eftirgjald:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Skiptimynt:</translation>
+ </message>
+ <message>
+ <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
+ <translation>Það er í lagi að greiða einungis lágmarksupphæðina svo framarlega sem færslurúmtakið er minna en plássið í blokkunum. En gætið þess að þegar það er meiri eftirspurn eftir bitcoin færslum en netið getur unnið úr þá gæti svo farið að færslurnar verða aldrei samþykktar.</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Smart gjald er ekki gangsett ennþá. Þetta tekur venjulega nokkrar blokkir...)</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Ryk:</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(ekkert merki)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Merki:</translation>
+ </message>
+ </context>
+<context>
+ <name>SendConfirmationDialog</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ </context>
+<context>
+ <name>SplashScreen</name>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation>Fullgerð mynt verður að nýta %1 blokkir. Þegar þú bjóst til þessa blokk, þá var jafnóðum tilkynnt á netinu að hún eigi að bætast við blokkakeðjuna. Ef hún kemst ekki í keðjuna þá mun staða hennar breytast í "ósamþykkt" og ekki verður hægt að nota hana. Þetta gerist annað slagið ef annar hnútpunktur klárar blokk nokkrum sekúndum á undan þinni.</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Upphæð</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Merki</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Námuunnið</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(ekkert merki)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Mined</source>
+ <translation>Námuunnið</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Afrita færslugildi</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Afrita merki</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Gildi aðskilin með kommu (*.csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Merki</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Vistfang</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Útflutningur tókst ekki</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;Flytja út</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Flytja gögn í flipanum í skrá</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation>Villa við lestur %s! Allir lyklar fóru inn á réttan hátt, en færslugögn eða færslugildi gætu verið röng eða horfin.</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Viðvörun: Netið er ekki í fullu samræmi! Einhver námuvinnsla virðist í ólagi.</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Upplýsingar</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Viðvörun</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
+ <translation>Viðvörun: Óþekkt blokkarútgáfa í námavinnslu! Það er mögulegt að óþekktum reglum sé fylgt</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Villa</translation>
+ </message>
+</context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts
index eabd3d8ae9..7513e3e30e 100644
--- a/src/qt/locale/bitcoin_it.ts
+++ b/src/qt/locale/bitcoin_it.ts
@@ -30,6 +30,10 @@
<translation>Rimuovi dalla lista l'indirizzo attualmente selezionato</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Inserisci un indirizzo o un'etichetta da cercare</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Esporta su file i dati contenuti nella tabella corrente</translation>
</message>
@@ -322,6 +326,14 @@
<translation>Apri &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Portafoglio:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Portafoglio predefinito:</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Clicca per disattivare la rete.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Re-indicizzazione blocchi su disco...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Il Proxy è &lt;b&gt;enabled&lt;/b&gt;:%1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Invia fondi ad un indirizzo Bitcoin</translation>
</message>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Portafoglio: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Tipo: %1
@@ -730,10 +752,6 @@
<translation>&amp;Indirizzo</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nuovo indirizzo di ricezione</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nuovo indirizzo d'invio</translation>
</message>
@@ -750,10 +768,6 @@
<translation>L'indirizzo inserito "%1" non è un indirizzo bitcoin valido.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>L'indirizzo inserito "%1" è già in rubrica.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Impossibile sbloccare il portamonete.</translation>
</message>
@@ -803,42 +817,6 @@
<source>Command-line options</source>
<translation>Opzioni della riga di comando</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Utilizzo:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opzioni della riga di comando</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opzioni interfaccia:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Seleziona la directory dei dati all'avvio (default: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Imposta la lingua, ad esempio "it_IT" (default: locale di sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Avvia ridotto a icona</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Imposta un certificato SSL root per le richieste di pagamento (default: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Mostra schermata iniziale all'avvio (default: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Reimposta tutti i campi dell'interfaccia grafica</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1024,6 +1002,18 @@
<translation>Mostra se il proxy SOCK5 di default che p stato fornito è usato per raggiungere i contatti attraverso questo tipo di rete.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Usa una SOCKS&amp;5 proxy differente per raggiungere peers usando servizi Tor hidden</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Nascondi l'icona nella barra delle applicazioni.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Nascondi l'icona della barra delle applicazioni</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Riduci ad icona invece di uscire dall'applicazione quando la finestra viene chiusa. Attivando questa opzione l'applicazione terminerà solo dopo aver selezionato Esci dal menu File.</translation>
</message>
@@ -1057,6 +1047,22 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Rete</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Disattiva alcune funzionalità avanzate, ma tutti i blocchi saranno ancora completamente validati. Per ripristinare questa impostazione è necessario rieseguire il download dell'intera blockchain. L'utilizzo effettivo del disco potrebbe essere leggermente superiore.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Eliminare e bloccare l'archiviazione su</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Per ripristinare questa impostazione è necessario rieseguire il download dell'intera blockchain.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = automatico, &lt;0 = lascia questo numero di core liberi)</translation>
</message>
@@ -1089,6 +1095,14 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Mappa le porte tramite &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Accetta connessione esterne.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Accetta connessioni in entrata</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Connessione alla rete Bitcoin attraverso un proxy SOCKS5.</translation>
</message>
@@ -1169,6 +1183,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Specifica se le funzionalita di coin control saranno visualizzate.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;URLs per transazioni terzi </translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1311,6 +1329,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Gestione URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin: //' non è un URI valido. Usa invece "bitcoin:".</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>URL di recupero della Richiesta di pagamento non valido: %1</translation>
</message>
@@ -1512,10 +1534,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Errore: La cartella dati "%1" specificata non esiste.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Errore: impossibile interpretare il file di configurazione: %1. Usare esclusivamente la sintassi chiave=valore.</translation>
- </message>
- <message>
<source>Error: %1</source>
<translation>Errore: %1</translation>
</message>
@@ -1606,6 +1624,14 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Utilizzo memoria</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Portafoglio:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(nessuno)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Ripristina</translation>
</message>
@@ -1774,6 +1800,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>&amp;Elimina Ban</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>Portafoglio predefinito:</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Benvenuto nella console RPC di %1.</translation>
</message>
@@ -1782,6 +1812,14 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Usa le flecce su e giú per navigare nella storia, e %1 per pulire lo schermo</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Digita %1 per una descrizione di comandi disponibili</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Per maggiori informazioni su come usare questa console digita %1</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>ATTENZIONE: I truffatori sono stati attivi in quest'area, cercando di convincere gli utenti a digitare linee di comando e rubando i contenuti dei loro portafogli. Non usare questa console senza la piena consapevolezza delle ramificazioni di un comando.</translation>
</message>
@@ -1790,6 +1828,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Attività di rete disabilitata</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Esecuzione del comando senza alcun portafoglio</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(id nodo: %1)</translation>
</message>
@@ -1861,6 +1903,14 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Cancella</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Gli indirizzi nativi segwit (noti anche come Bech32 o BIP-173) riducono le spese di transazione e offrono una migliore protezione dagli errori di battitura, ma i vecchi portafogli non li supportano. Se deselezionata, verrà creato un indirizzo compatibile con i portafogli meno recenti.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Genera indirizzo nativo segwit (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Cronologia pagamenti richiesti</translation>
</message>
@@ -1948,6 +1998,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Messaggio</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Portafoglio</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation> L'URI risultante è troppo lungo, prova a ridurre il testo nell'etichetta / messaggio.</translation>
</message>
@@ -2062,12 +2116,16 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>minimizza le impostazioni di commissione</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>per kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Specifica una tariffa personalizzata per kB (1.000 byte) della dimensione virtuale della transazione
+
+Nota: poiché la commissione è calcolata su base per byte, una commissione di "100 satoshi per kB" per una dimensione di transazione di 500 byte (metà di 1 kB) alla fine produrrà una commissione di soli 50 satoshi.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Se la commissione personalizzata è impostata su 1000 satoshi e la transazione è di soli 250 byte, allora "per kilobyte" paga solo 250 satoshi di commissione, mentre "somma almeno" paga 1000 satoshi. Per transazioni più grandi di un kilobyte, entrambe le opzioni pagano al kilobyte.</translation>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2114,6 +2172,14 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Obiettivo del tempo di conferma:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Attiva Replace-By-Fee</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Con Replace-By-Fee (BIP-125) si puo' aumentare la commissione sulla transazione dopo averla inviata. Senza questa, una commissione piu' alta e' consigliabile per compensare l'aumento del rischio dovuto al ritardo della transazione.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Cancella &amp;tutto</translation>
</message>
@@ -2170,16 +2236,28 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation> Sei sicuro di voler inviare?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation> Includi il costo della transazione</translation>
+ <source>or</source>
+ <translation>o</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Importo Totale %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Si puo' aumentare la commissione successivamente (segnalando Replace-By-Fee, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>o</translation>
+ <source>Please, review your transaction.</source>
+ <translation>Per favore, rivedi la tua transazione.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Commissione transazione</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Senza segnalare Replace-By-Fee, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Importo totale</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2519,10 +2597,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>in conflitto con una transazione con %1 conferme</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/non confermati, %1</translation>
</message>
@@ -2551,14 +2625,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Stato</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, non è ancora stata trasmessa con successo</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, trasmessa attraverso %n nodi</numerusform><numerusform>, trasmessa attraverso %n nodi</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2643,6 +2709,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Dimensione totale della transazione</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Dimensione virtuale della transazione</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Indice di output</translation>
</message>
@@ -2709,10 +2779,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation><numerusform>Aperto per altri %n blocchi</numerusform><numerusform>Aperto per altri %n blocchi</numerusform></translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Non confermata</translation>
</message>
@@ -2737,10 +2803,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Immaturo (%1 conferme, sarà disponibile fra %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Questo blocco non è stato ricevuto da alcun altro nodo e probabilmente non sarà accettato!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generati, ma non accettati</translation>
</message>
@@ -3051,38 +3113,18 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<source>The wallet data was successfully saved to %1.</source>
<translation>Il portamonete è stato correttamente salvato in %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Annulla</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opzioni:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Specifica la cartella dati</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Connessione ad un nodo e successiva disconnessione per recuperare gli indirizzi dei peer</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Specifica il tuo indirizzo pubblico</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accetta comandi da riga di comando e JSON-RPC</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distribuito sotto la licenza software del MIT, si veda il file %s o %s incluso</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Se &lt;category&gt; non è specificato oppure se &lt;category&gt; = 1, mostra tutte le informazioni di debug.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>La modalità prune è configurata al di sotto del minimo di %d MB. Si prega di utilizzare un valore più elevato.</translation>
</message>
@@ -3099,18 +3141,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Errore: si è presentato un errore interno fatale, consulta il file debug.log per maggiori dettagli</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Commissione (in %s/kB) da aggiungere alle transazioni inviate (default: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning del blockstore...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Esegui in background come demone ed accetta i comandi</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Impossibile avviare il server HTTP. Dettagli nel log di debug.</translation>
</message>
@@ -3123,52 +3157,20 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Sviluppatori di %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Un importo (in %s/kB) che sarà utilizzato quando la stima delle commissioni non ha abbastanza dati (default: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Accetta le transazioni trasmesse ricevute da peers in whitelist anche se non si stanno trasmettendo transazioni (default: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Associa all'indirizzo indicato e resta permanentemente in ascolto su di esso. Usa la notazione [host]:porta per l'IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Non è possibile ottenere i dati sulla cartella %s. Probabilmente %s è già in esecuzione.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Elimina tutte le transazioni dal portamonete e recupera solo quelle che fanno parte della blockchain attraverso il comando -rescan all'avvio.</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Non e' possibile fornire connessioni specifiche e contemporaneamente usare addrman per trovare connessioni uscenti. </translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Errore lettura %s! Tutte le chiavi sono state lette correttamente, ma i dati delle transazioni o della rubrica potrebbero essere mancanti o non corretti.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Esclude l'informazione di debug per una categoria. Può essere usata in congiunzione con -debug=1 per generare i log di debug per tutte le categorie eccetto una o più categorie specificate.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Esegue un comando quando lo stato di una transazione del portamonete cambia (%s in cmd è sostituito da TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Transazioni extra da mantenere in memoria per ricostruzioni compatte del blocco (predefinito: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Se questo blocco è nella catena, assume che esso e i suoi predecessori siano validi e potenzialmente salta la verifica dei loro script (0 per verificarli tutti, predefinito: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Regolazione della massima differenza media di tempo dei peer consentita. L'impostazione dell'orario locale può essere impostata in avanti o indietro di questa quantità. (default %u secondi)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Totale massimo di commissioni (in %s) da usare in una transazione singola o di gruppo del wallet; valori troppo bassi possono abortire grandi transazioni (default: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Raggruppa gli output per indirizzo, selezionando tutti o nessuno, invece di selezionarli in base all'output. La privacy è migliorata in quanto un indirizzo viene usato una sola volta (a meno che qualcuno vi invii denaro dopo che avevate già speso da quell'indirizzo), ma può comportare commissioni leggermente più alte visto che le limitazioni aggiunte possono condurre a una selezione subottimale degli input da spendere (default: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3179,22 +3181,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Per favore contribuite se ritenete %s utile. Visitate %s per maggiori informazioni riguardo il software.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Ottiene gli indirizzi dei peer attraverso interrogazioni DNS, in caso di scarsa disponibilità (predefinito: 1 a meno che -connect non sia specificato)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Riduce i requisiti di spazio di archiviazione abilitando la cancellazione dei vecchi blocchi ("pruning" o potatura). Questo consente di richiedere alla pruneblockchain RPC di cancellare specifici blocchi e abilita il pruning automatico dei vecchi blocchi se viene fornita una dimensione specifica in MiB. Questa modalità è incompatibile con -txindex e -rescan. Attenzione: Per ripristinare questa impostazione è necessario riscaricare l'intera blockchain. (predefinito: 0 = disabilita il pruning dei blocchi, 1 = permetti il pruning manuale tramite RPC, &gt;%u = pota automaticamente i file di blocco per stare sotto una dimensione specifica in MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Imposta la tariffa di commissione più bassa (in %s/kB) per transazioni da includere nella creazione del blocco. (predefinito: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Imposta il numero di thread per la verifica degli script (da %u a %d, 0 = automatico, &lt;0 = lascia questo numero di core liberi, predefinito: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Il database dei blocchi contiene un blocco che sembra provenire dal futuro. Questo può essere dovuto alla data e ora del tuo computer impostate in modo scorretto. Ricostruisci il database dei blocchi se sei certo che la data e l'ora sul tuo computer siano corrette</translation>
</message>
@@ -3215,18 +3201,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Impossibile riportare il database ad un livello pre-fork. Dovrai riscaricare tutta la blockchain</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Utilizza UPnP per mappare la porta in ascolto (default: 1 quando in ascolto e -proxy non è specificato)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Username e hash password per connessioni JSON-RPC. Il campo &lt;userpw&gt; utilizza il formato: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Uno script python standard è incluso in share/rpcuser. Il cliente quindi si connette normalmente utilizzando la coppia di argomenti rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt;. Questa opzione può essere specificata più volte</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Il portafoglio non creerà transazioni che violino i limiti della mempool chain (predefinito: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Attenzione: La rete non sembra essere pienamente d'accordo! Alcuni minatori sembrano riscontrare problemi.</translation>
</message>
@@ -3235,10 +3209,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Attenzione: Sembra che non vi sia pieno consenso con i nostri peer! Un aggiornamento da parte tua o degli altri nodi potrebbe essere necessario.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Imposta se salvare la mempool allo spegnimento e caricarla alla riaccensione (predefinito: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d degli ultimi 100 blocchi hanno una versione inaspettata</translation>
</message>
@@ -3251,42 +3221,14 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>-maxmempool deve essere almeno %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>Valori possibili per &lt;category&gt;:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accetta connessioni dall'esterno (predefinito: 1 se -proxy o -connect non sono utilizzati)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Aggiungi commento alla stringa dell'applicazione utente</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Prova a recuperare le chiavi private da un portafoglio corrotto all'avvio</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opzioni creazione blocco:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Impossobile risolvere l'indirizzo -%s: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Opzioni di selezione della catena:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Cambio indice fuori paramentro</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Opzioni di connessione:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3295,36 +3237,12 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Rilevato database blocchi corrotto</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opzioni di Debug/Test:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Disabilita il portamonete e le relative chiamate RPC</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Vuoi ricostruire ora il database dei blocchi?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Abilita pubblicazione hash blocco in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Abilità pubblicazione hash transazione in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Abilita pubblicazione blocchi raw in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Abilita pubblicazione transazione raw in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Abilita la sostituzione della transazione nel pool della memoria (default: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Errore durante la creazione %s: non e' possibile creare portafogli non-HD con questa versione.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3363,6 +3281,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Nessuna porta disponibile per l'ascolto. Usa -listen=0 se vuoi procedere comunque.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Impossibile ripetere la scansione del portafoglio durante l'inizializzazione</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importazione...</translation>
</message>
@@ -3387,8 +3309,12 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Importo non valido per -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Mantieni la memory pool delle transazioni al di sotto di &lt;n&gt; megabytes (default: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>La cartella specificata "%s" non esiste.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Aggiornamento del database txindex</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3399,26 +3325,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Caricamento bloccati...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Posizione del cookie di aiutorizzazione (default: data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Non ci sono abbastanza descrittori di file disponibili.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Connessione ai soli nodi appartenenti alla rete &lt;net&gt; (ipv4, ipv6 o Tor)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Mostra questo messaggio di aiuto ed esci</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Mostra la versione ed esci</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>La modalità prune non può essere configurata con un valore negativo.</translation>
</message>
@@ -3427,14 +3337,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>La modalità prune è incompatibile con l'opzione -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Ricostruisci lo stato della catena e l'indice dei blocchi partendo dai file blk*.dat presenti sul disco</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Ricrea l'indice della catena dei blocchi partendo da quelli già indicizzati</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Ripetizione dei blocchi...</translation>
</message>
@@ -3443,14 +3345,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Verifica blocchi...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Imposta la dimensione della cache del database in megabyte (%d a %d, predefinito: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Specifica il file del portamonete (all'interno della cartella dati)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Il codice sorgente è disponibile in %s</translation>
</message>
@@ -3463,6 +3357,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Impossibile collegarsi a %s su questo computer. Probabilmente %s è già in esecuzione.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Impossibile generare le chiavi</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Ignorata opzione -benchmark non supportata, utilizzare -debug=bench.</translation>
</message>
@@ -3483,14 +3381,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Aggiornamento del database UTXO</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Usa UPnP per mappare la porta di ascolto (predefinito: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Utilizza la catena di prova</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Il commento del User Agent (%s) contiene caratteri non sicuri.</translation>
</message>
@@ -3499,90 +3389,26 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Verifica blocchi...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opzioni di Debug/Test del portafoglio:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Il portamonete necessita di essere riscritto: riavviare %s per completare</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opzioni portamonete:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permette connessioni JSON-RPC dall'origine specificata. I valori validi per &lt;ip&gt; sono un singolo IP (ad es. 1.2.3.4), una network/netmask (ad es. 1.2.3.4/255.255.255.0) oppure una network/CIDR (ad es. 1.2.3.4/24). Questa opzione può essere specificata più volte.</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Resta in ascolto sull'indirizzo indicato ed inserisce in whitelist i peer che vi si collegano. Usa la notazione [host]:porta per l'IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Crea nuovi file con i permessi di default del sistema, invece che con umask 077 (ha effetto solo con funzionalità di portamonete disabilitate)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Scopre i propri indirizzi IP (predefinito: 1 se in ascolto ed -externalip o -proxy non sono specificati)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Errore: attesa per connessioni in arrivo fallita (errore riportato %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Esegue un comando in caso di ricezione di un allarme pertinente o se si rileva un fork molto lungo (%s in cmd è sostituito dal messaggio)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Le commissioni (in %s/kB) inferiori a questo valore sono considerate pari a zero per trasmissione, mining e creazione della transazione (default: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Nel caso in cui paytxfee non sia impostato, include una commissione tale da ottenere un avvio delle conferme entro una media di n blocchi (predefinito: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Importo non valido per -maxtxfee=&lt;amount&gt;: '%s' (deve essere almeno pari alla commissione 'minrelay fee' di %s per prevenire transazioni bloccate)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Dimensione massima dei dati in transazioni di trasporto dati che saranno trasmesse ed incluse nei blocchi (predefinito: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Randomizza le credenziali per ogni connessione proxy. Permette la Tor stream isolation (predefinito: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>L'importo della transazione risulta troppo basso per l'invio una volta dedotte le commissioni.</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>I peer inclusi in whitelist non possono subire ban per DoS e le loro transazioni saranno sempre trasmesse, anche nel caso in cui si trovino già nel mempool. Ciò è utile ad es. per i gateway</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Per ritornare alla modalità unpruned sarà necessario ricostruire il database utilizzando l'opzione -reindex. L'intera blockchain sarà riscaricata.</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(default: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Accetta richieste REST pubbliche (predefinito: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Crea automaticamente il servizio Tor (default: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Connessione attraverso un proxy SOCKS5</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Errore caricamento %s: Non puoi disabilitare HD in un portafoglio HD già esistente</translation>
</message>
@@ -3595,10 +3421,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Errore durante l'aggiornamento del database chainstate</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importa blocchi da un file blk000??.dat esterno all'avvio</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informazioni</translation>
</message>
@@ -3619,44 +3441,28 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Netmask non valida specificata in -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Mantiene in memoria al massimo &lt;n&gt; transazioni non collegabili (predefinito: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>È necessario specificare una porta con -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opzioni trasmissione nodo:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opzioni server RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Riduzione -maxconnections da %d a %d a causa di limitazioni di sistema.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Ripete la scansione della block chain per individuare le transazioni che mancano dal wallet all'avvio</translation>
+ <source>Signing transaction failed</source>
+ <translation>Firma transazione fallita</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Invia le informazioni di trace/debug alla console invece che al file debug.log</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>-walletdir "%s" specificata non esiste</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Mostra tutte le opzioni di debug (utilizzo: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>-walletdir "%s" specificata e' un path relativo</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Riduce il file debug.log all'avvio del client (predefinito: 1 se -debug non è impostato)</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Firma transazione fallita</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>-walletdir "%s" specificata non e' una directory</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3667,14 +3473,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Questo è un software sperimentale.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Password porta controllo Tor (default: empty)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Porta di controllo Tor da usare se in ascolto su onion (default: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Importo transazione troppo piccolo</translation>
</message>
@@ -3691,18 +3489,18 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Impossibile associarsi a %s su questo computer (l'associazione ha restituito l'errore %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Aggiorna il wallet all'ultimo formato all'avvio</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nome utente per connessioni JSON-RPC</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Impossibile generare chiave iniziale</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Verifica portafoglio/i...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Il portafoglio %s e' situato fuori dalla directory del portafoglio %s </translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Attenzione</translation>
</message>
@@ -3711,98 +3509,18 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Attenzione: nuove regole non conosciute attivate (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Imposta se operare in modalità solo blocchi (default: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>È necessario ricostruire il database usando -reindex per cambiare -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Eliminazione dal portamonete di tutte le transazioni...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Opzioni di notifica ZeroMQ</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Password per connessioni JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Esegue un comando quando il miglior blocco cambia (%s nel cmd è sostituito dall'hash del blocco)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Consente interrogazioni DNS per -addnode, -seednode e -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = mantiene metadati tx, ad es. proprietario account ed informazioni di richiesta di pagamento, 2 = scarta metadati tx)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee è impostato molto alto! Commissioni così alte possono venir pagate anche su una singola transazione.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Resta in attesa di connessioni JSON-RPC sull'indirizzo indicato. Questa opzione viene ignorata a meno che anche -rpcallowip non sia trasmesso. Port è opzionale e prevale su -rpcport. Usa la notazione [host]:porta per IPv6. Questa opzione può essere specificata più volte (predefinito: 127.0.0.1 e ::1 ovvero localhost, o se -rpcallowip è stato specificato, 0.0.0.0 e :: ovvero tutti gli indirizzi)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Non mantenere le transazioni nella mempool più a lungo di &lt;n&gt; ore (default: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Byte equivalenti per ottimizzazione segnale dedicati a ritrasmissione ed estrazione (default: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Errore caricamento %s: Non puoi abilitare HD in un portafoglio non-HD già esistente</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Errore caricamento portafoglio %s. Il parametro -wallet deve solo specificare un nome file (non un percorso).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Le commissioni (in %s/kB) inferiori a questo valore sono considerate pari a zero per la creazione della transazione (default: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Forza la trasmissione della transazione da peer in whitelist anche se violano le regole di trasmissione locali (predefinito: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Determina quanto sarà approfondita la verifica da parte di -checkblocks (0-4, predefinito: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Mantiene l'indice completo delle transazioni usato dalla chiamata rpc getrawtransaction (predefinito: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Numero di secondi di sospensione prima della riconnessione per i peer che mostrano un comportamento anomalo (predefinito: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Emette informazioni di debug (predefinito: %u, fornire &lt;category&gt; è opzionale)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Imposta che la serializzazione degli hex di transazioni o blocchi grezzi sia riportata in maniere non-verbose, non-segwit(0) o segwit(1) (predefinito: %d)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Supporta filtraggio di blocchi e transazioni con filtri bloom (default: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>La tariffa di commissione (in %s/kB) che indica la tua tolleranza a scartare il cambio aggiungendolo alla commissione (predefinito: %s).</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Questo è il costo di transazione che potresti pagare quando le stime della tariffa non sono disponibili.</translation>
</message>
@@ -3815,10 +3533,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>La lunghezza totale della stringa di network version (%i) eccede la lunghezza massima (%i). Ridurre il numero o la dimensione di uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Cerca di mantenere il traffico in uscita al di sotto della soglia scelta (in MiB ogni 24h), 0 = nessun limite (default: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Argomento -socks non supportato. Non è più possibile impostare la versione SOCKS, solamente i proxy SOCKS5 sono supportati.</translation>
</message>
@@ -3827,10 +3541,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Argomento non supportato -whitelistalwaysrelay è stato ignorato, utilizzare -whitelistrelay e/o -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Usa un proxy SOCKS5 a parte per raggiungere i peer attraverso gli hidden services di Tor (predefinito: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Attenzione: si stanno minando versioni sconocsiute di blocchi! E' possibile che siano attive regole sconosciute</translation>
</message>
@@ -3839,110 +3549,18 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Attenzione: file del Portafoglio corrotto, dati recuperati! %s originale salvato come %s in %s; se il saldo o le transazioni non sono corrette effettua un ripristino da un backup.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>I peer in whitelist che si connettono dal dato indirizzo IP (es. 1.2.3.4) o dalla rete annotata CIDR (es. 1.2.3.0/24). Può essere specificato più volte.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s ha un'impostazione molto alta!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(predefinito: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Interroga sempre i DNS per ottenere gli indirizzi dei peer (predefinito: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Errore caricamento portafoglio %s. Il nome file -wallet deve essere un file regolare.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Errore caricamento portafoglio %s. Il nome file -wallet specificato è duplicato.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Errore caricamento portafoglio %s. Caratteri invalidi nel nome file -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Numero di blocchi da controllare all'avvio (predefinito: %u, 0 = tutti)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Include gli indirizzi IP nell'output del debug (predefinito: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Keypool esaurito, prima invocare keypoolrefill</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Resta in attesa di connessioni JSON-RPC su &lt;port&gt; (predefinito: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Resta in attesa di connessioni su &lt;port&gt; (predefinito: %u o testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Mantiene al massimo &lt;n&gt; connessioni verso i peer (predefinito: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Configura il portamonete per la trasmissione di transazioni</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Buffer di ricezione massimo per connessione, &lt;n&gt;*1000 byte (predefinito: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Buffer di invio massimo per connessione, &lt;n&gt;*1000 byte (predefinito: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Antepone un timestamp all'output del debug (predefinito: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Trasmette ed include nei blocchi transazioni di trasporto dati (predefinito: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Trasmette transazioni non-P2SH multisig (predefinito: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Imposta la dimensione del pool di chiavi a &lt;n&gt; (predefinito: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Imposta la dimensione massima del blocco BIP141 (default: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Imposta il numero di thread destinati a rispondere alle chiamate RPC (predefinito %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Specifica il file di configurazione (predefinito: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Specifica il timeout di connessione in millisecondi (minimo:1, predefinito: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Specifica il file pid (predefinito: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Abilita la spesa di resto non confermato quando si inviano transazioni (predefinito: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Inizializzazione dei thread di rete...</translation>
</message>
@@ -3959,10 +3577,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Questo è il costo di transazione che pagherai se invii una transazione.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Soglia di disconnessione per i peer che si comportano in maniera anomala (predefinito: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Gli importi di transazione non devono essere negativi</translation>
</message>
@@ -3983,6 +3597,18 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Fondi insufficienti</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Impossibile generare una chiave di indirizzo di modifica. Le chiavi private sono disabilitate per questo portafoglio.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Impossibile aggiornare un portafoglio diviso non HD senza aggiornamento per supportare il keypool pre-split. Si prega di utilizzare -upgradewallet = 169900 o -upgradewallet senza specificare la versione.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Stima della commissione non riuscita. Fallbackfee è disabilitato. Attendi qualche blocco o abilita -fallbackfee.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Caricamento dell'indice dei blocchi...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_it_IT.ts b/src/qt/locale/bitcoin_it_IT.ts
index 4f74d0f437..d97d888f23 100644
--- a/src/qt/locale/bitcoin_it_IT.ts
+++ b/src/qt/locale/bitcoin_it_IT.ts
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>copia l'indirizzo selezionato correntemente nella clipboard di sistema</translation>
+ <translation>Copia l'indirizzo selezionato nella clipboard di sistema</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -30,6 +30,10 @@
<translation>Cancella l'indirizzo attualmente selezionato dalla lista.</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Inserire indirizzo o etichetta da cercare</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Esportare i dati nella scheda corrente in un file</translation>
</message>
@@ -228,7 +232,7 @@
</message>
<message>
<source>Banned Until</source>
- <translation>bannato fino </translation>
+ <translation>Bannato fino </translation>
</message>
</context>
<context>
@@ -318,6 +322,14 @@
<translation>Apri &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Portafoglio</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Portafoglio predefinito</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Clicca per disabilitare attività di rete.</translation>
</message>
@@ -674,10 +686,6 @@
<translation>&amp;Indirizzo</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nuovo indirizzo di ricezione</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nuovo indirizzo di invio</translation>
</message>
@@ -694,10 +702,6 @@
<translation>L'indirizzo inserito "%1" non è un indirizzo Bitcoin valido.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>L'indirizzo inserito "%1" è già nella rubrica.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Non posso sbloccare il portafoglio.</translation>
</message>
@@ -743,19 +747,7 @@
<source>Command-line options</source>
<translation>Opzioni linea di comando</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Utilizzo:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opzioni linea di comando</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opzioni UI</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -767,6 +759,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Il wallet verra' inoltre memorizzato su questa cartella.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Errore</translation>
</message>
@@ -774,6 +770,14 @@
<context>
<name>ModalOverlay</name>
<message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation>Le transazioni recenti potrebbero non essere ancora visibili, e quindi il saldo del wallet potrebbe essere incorretto. Questa informazione verra' corretta non appena il tuo wallet ha finito di sincronizzarsi con la rete bitcoin, come specificato di seguito.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation>Tentare di spendere bitcoin che sono affetti da transazioni non ancora mostrate, non verra' accettato dal network.</translation>
+ </message>
+ <message>
<source>Number of blocks left</source>
<translation>Numero di blocchi rimanente</translation>
</message>
@@ -788,18 +792,50 @@
<translation>Opzioni</translation>
</message>
<message>
+ <source>Configuration options</source>
+ <translation>Opzioni di configurazione</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Errore</translation>
</message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Questa modifica richiede un riavvio del client</translation>
+ </message>
</context>
<context>
<name>OverviewPage</name>
+ <message>
+ <source>Available:</source>
+ <translation>Disponibile:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>Saldo disponibile</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Transazioni recenti</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Payment request rejected</source>
+ <translation>Richiesta di pagamento rifiutata</translation>
+ </message>
+ <message>
+ <source>Refund from %1</source>
+ <translation>Rimborso da %1</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
+ <message>
+ <source>Sent</source>
+ <translation>Inviato</translation>
+ </message>
</context>
<context>
<name>QObject</name>
@@ -816,6 +852,14 @@
</context>
<context>
<name>RPCConsole</name>
+ <message>
+ <source>Sent</source>
+ <translation>Inviato</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Portafoglio predefinito</translation>
+ </message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
@@ -842,6 +886,10 @@
<source>Label</source>
<translation>Etichetta</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Portafoglio</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts
index 2e8791d7ab..2ee78dbb29 100644
--- a/src/qt/locale/bitcoin_ja.ts
+++ b/src/qt/locale/bitcoin_ja.ts
@@ -3,11 +3,11 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>アドレスまたはラベルを編集するにはダブルクリック</translation>
+ <translation>右クリックでアドレスまたはラベルを編集</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>新規アドレスの作成</translation>
+ <translation>新しいアドレスを作成</translation>
</message>
<message>
<source>&amp;New</source>
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>現在選択されているアドレスをシステムのクリップボードにコピーする</translation>
+ <translation>現在選択されているアドレスをシステムのクリップボードにコピー</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -27,11 +27,15 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>選択されたアドレスを一覧から削除する</translation>
+ <translation>選択されたアドレスを一覧から削除</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>検索したいアドレスまたはラベルを入力</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>ファイルに現在のタブのデータをエクスポート</translation>
+ <translation>このタブのデータをファイルにエクスポート</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -43,11 +47,11 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>先のアドレスを選択</translation>
+ <translation>コインを送りたいアドレスを選択</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>支払いを受け取るアドレスを指定する</translation>
+ <translation>コインを受け取りたいアドレスを選択</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -55,19 +59,19 @@
</message>
<message>
<source>Sending addresses</source>
- <translation>送金用</translation>
+ <translation>送金先アドレス</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation>受け取りアドレス</translation>
+ <translation>受取用アドレス</translation>
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>これらは支払いを送信するためのあなたの Bitcoin アドレスです。コインを送信する前に、常に額と受信アドレスを確認してください。</translation>
+ <translation>これらは、あなたが知っている支払い送り先の Bitcoin アドレスです。コインを送る前に、必ず金額と送金先アドレスを確認してください。</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>これらは支払いを受け取るためのビットコインアドレスです。トランザクションごとに新しい受け取り用アドレスを作成することが推奨されます。</translation>
+ <translation>これらは支払いを受け取るための、あなたの Bitcoin アドレスです。トランザクションごとに新しい受け取り用アドレスを作成することが推奨されます。</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -145,7 +149,7 @@
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>この操作はウォレットをアンロックするためにパスフレーズが必要です。</translation>
+ <translation>この操作を続行するには、ウォレットをアンロックするためのパスフレーズが必要です。</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -153,7 +157,7 @@
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>この操作はウォレットの暗号化解除のためにパスフレーズが必要です。</translation>
+ <translation>この操作を続行するには、ウォレットの暗号化を解除するためのパスフレーズが必要です。</translation>
</message>
<message>
<source>Decrypt wallet</source>
@@ -173,7 +177,7 @@
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation>警告: もしもあなたのウォレットを暗号化してパスフレーズを失ってしまったなら、&lt;b&gt;あなたの Bitcoin はすべて失われます&lt;/b&gt;!</translation>
+ <translation>警告: もしもあなたのウォレットを暗号化してパスフレーズを忘れてしまったら、&lt;b&gt;あなたの Bitcoin はすべて失われます&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -185,11 +189,11 @@
</message>
<message>
<source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>暗号化処理を完了させるため %1 をいますぐ終了します。ウォレットの暗号化では、コンピュータに感染したマルウェアなどによるビットコインの盗難から完全に守ることはできないことにご注意ください。</translation>
+ <translation>暗号化処理を完了させるため %1 をいますぐ終了します。ウォレットを暗号化しても、コンピュータに感染したマルウェアなどによる Bitcoin の盗難を完全に防ぐことはできないことにご注意ください。</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation>重要: 過去のウォレット ファイルのバックアップは、暗号化された新しいウォレット ファイルに取り替える必要があります。セキュリティ上の理由により、暗号化された新しいウォレットを使い始めると、暗号化されていないウォレット ファイルのバックアップはすぐに使えなくなります。</translation>
+ <translation>重要: 今までに作成されたウォレット ファイルのバックアップは、暗号化された新しいウォレット ファイルに置き換える必要があります。セキュリティ上の理由により、暗号化された新しいウォレットを使い始めると、暗号化されていないウォレット ファイルのバックアップはすぐに使えなくなります。</translation>
</message>
<message>
<source>Wallet encryption failed</source>
@@ -221,7 +225,7 @@
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
- <translation>警告: Caps Lock キーがオンになっています!</translation>
+ <translation>警告: Caps Lock キーがオンになっています!</translation>
</message>
</context>
<context>
@@ -243,7 +247,7 @@
</message>
<message>
<source>Synchronizing with network...</source>
- <translation>ネットワークに同期中……</translation>
+ <translation>ネットワークと同期しています……</translation>
</message>
<message>
<source>&amp;Overview</source>
@@ -322,6 +326,14 @@
<translation>URI を開く (&amp;U)...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>ウォレット:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>デフォルトウォレット</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>クリックするとネットワーク活動を無効化します。</translation>
</message>
@@ -335,11 +347,15 @@
</message>
<message>
<source>Syncing Headers (%1%)...</source>
- <translation>未知。ヘッダを同期しています (%1%)...</translation>
+ <translation>ヘッダーを同期しています (%1%)...</translation>
</message>
<message>
<source>Reindexing blocks on disk...</source>
- <translation>ディスク上のブロックのインデックスを再作成中...</translation>
+ <translation>ディスク上のブロックのインデックスを再作成しています...</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>プロキシは &lt;b&gt;有効&lt;/b&gt;です: %1</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
@@ -379,7 +395,7 @@
</message>
<message>
<source>&amp;Receive</source>
- <translation>入金 (&amp;R)</translation>
+ <translation>受取 (&amp;R)</translation>
</message>
<message>
<source>&amp;Show / Hide</source>
@@ -395,11 +411,11 @@
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>あなたが所有していることを証明するために、あなたの Bitcoin アドレスでメッセージに署名してください</translation>
+ <translation>Bitcoin アドレスをあなたが所有していることを証明するために、そのアドレスでメッセージに署名してください</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>指定された Bitcoin アドレスで署名されたことを確認するためにメッセージを検証します</translation>
+ <translation>指定された Bitcoin アドレスで署名されたことを確認するために、メッセージを検証してください</translation>
</message>
<message>
<source>&amp;File</source>
@@ -419,15 +435,15 @@
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>支払いを要求する (QRコードとbitcoin:ではじまるURIを生成する)</translation>
+ <translation>支払いをリクエストする (QRコードとbitcoin:ではじまるURIを生成する)</translation>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
- <translation>使用済みの送金用アドレスとラベルの一覧を表示する</translation>
+ <translation>使用したことのある送金用アドレスとラベルの一覧を表示する</translation>
</message>
<message>
<source>Show the list of used receiving addresses and labels</source>
- <translation>支払いを受け取るアドレスとラベルのリストを表示する</translation>
+ <translation>使用したことのある受け取り用アドレスとラベルの一覧を表示する</translation>
</message>
<message>
<source>Open a bitcoin: URI or payment request</source>
@@ -439,7 +455,7 @@
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n の Bitcoin ネットワークへのアクティブな接続</numerusform></translation>
+ <translation><numerusform>Bitcoin ネットワークへのアクティブな接続は %n 個</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
@@ -463,7 +479,7 @@
</message>
<message>
<source>Transactions after this will not yet be visible.</source>
- <translation>この後の取引はまだ表示されません。</translation>
+ <translation>この後の取引はまだ表示されていません。</translation>
</message>
<message>
<source>Error</source>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>ウォレット: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>タイプ: %1
@@ -553,7 +575,7 @@
</message>
<message>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>致命的なエラーが発生しました。Bitcoin は安全に継続することができず終了するでしょう。</translation>
+ <translation>致命的なエラーが発生しました。Bitcoin を安全に動作し続けることができないため終了します。</translation>
</message>
</context>
<context>
@@ -688,7 +710,7 @@
</message>
<message>
<source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>少なくともひとつの受取額が現在のダスト閾値を下回る場合にはこのラベルは赤くなります。</translation>
+ <translation>少なくともひとつの受取額が現在のダスト閾値を下回る場合に、このラベルは赤くなります。</translation>
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
@@ -730,28 +752,28 @@
<translation>アドレス帳 (&amp;A)</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>新しい受信アドレス</translation>
- </message>
- <message>
<source>New sending address</source>
- <translation>新しい送信アドレス</translation>
+ <translation>新しい送金用アドレス</translation>
</message>
<message>
<source>Edit receiving address</source>
- <translation>入金アドレスを編集</translation>
+ <translation>受け取り用アドレスを編集</translation>
</message>
<message>
<source>Edit sending address</source>
- <translation>送信アドレスを編集</translation>
+ <translation>送金用アドレスを編集</translation>
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
<translation>入力されたアドレス "%1" は無効な Bitcoin アドレスです。</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>入力されたアドレス "%1" は既にアドレス帳にあります。</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>アドレス "%1" は、既に受け取り用アドレスにラベル "%2" として存在するので、送金用アドレスとしては追加できません。</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>入力されたアドレス"%1"は、既にアドレス帳にラベル "%2" として存在します。</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -774,7 +796,7 @@
</message>
<message>
<source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>ディレクトリがもうあります。 新しいのディレクトリを作るつもりなら%1を書いてください。</translation>
+ <translation>ディレクトリが既に存在します。 新しいディレクトリを作成したい場合は %1 を追加してください。</translation>
</message>
<message>
<source>Path already exists, and is not a directory.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>コマンドライン オプション</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>使用法:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>コマンドライン オプション</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>UIオプション:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>起動時にデータ ディレクトリを選ぶ (初期値: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>言語設定 例: "de_DE" (初期値: システムの言語)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>最小化された状態で起動する</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>支払いリクエスト用にSSLルート証明書を設定する (デフォルト:-system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>起動時にスプラッシュ画面を表示する (初期値: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>GUI で行われた設定の変更を全てリセット</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -860,19 +846,19 @@
</message>
<message>
<source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
- <translation>この初期同期には多大なリソースを消費し、あなたのコンピュータにこれまで見つからなかったハードウェア上の問題を露呈させるかもしれません。%1 を実行する度に、中断された時点からダウンロードを継続します。</translation>
+ <translation>この初期同期には多大なリソースを消費し、あなたのコンピュータでこれまで見つからなかったハードウェア上の問題が発生する場合があります。%1 を実行する度に、中断された時点からダウンロードを再開します。</translation>
</message>
<message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation>ブロックチェーンの保存容量に制限を設けることを選択した場合 (剪定) にも、過去のデータのダウンロードおよび処理が必要になります。しかしこれらのデータはディスク使用量を低く抑えるためにその後削除されるでしょう</translation>
+ <translation>ブロックチェーンの保存容量に制限を設けることを選択した場合 (剪定) にも、過去のデータのダウンロードおよび処理が必要になります。しかし、これらのデータはディスク使用量を低く抑えるために、後で削除されます。</translation>
</message>
<message>
<source>Use the default data directory</source>
- <translation>初期値のデータ ディレクトリを使用</translation>
+ <translation>既定のデータ ディレクトリを使用</translation>
</message>
<message>
<source>Use a custom data directory:</source>
- <translation>任意のデータ ディレクトリを使用:</translation>
+ <translation>カスタムのデータ ディレクトリを使用:</translation>
</message>
<message>
<source>Bitcoin</source>
@@ -919,11 +905,11 @@
</message>
<message>
<source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation>確認できない最近のトランザクションがあるかもしれません。これによりウォレットの残高は不正確なものである可能性があります。この情報はウォレットが一度ビットコインネットワークへの同期が完了すると正確なものとなります。詳細は下記を参照してください。</translation>
+ <translation>最近のトランザクションがまだ表示されていない可能性があります。そのため、ウォレットの残高が正しく表示されていないかもしれません。この情報は、ウォレットが Bitcoin ネットワークへの同期が完了すると正確なものとなります。詳細は下記を参照してください。</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation>まだ表示されていないトランザクションが影響するビットコインを使用しようとすると、ネットワークから認証がなされないでしょう。</translation>
+ <translation>まだ表示されていないトランザクションが影響する Bitcoin を使用しようとすると、ネットワークから認証を受けられません。</translation>
</message>
<message>
<source>Number of blocks left</source>
@@ -1024,6 +1010,10 @@
<translation>このネットワークタイプ経由で、与えられたデフォルトのSOCKS5プロキシを使用してピアに到達した場合に表示する。</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Tor秘匿サービス経由でピアに接続するために専用のSOCKS5プロキシを利用する:</translation>
+ </message>
+ <message>
<source>Hide the icon from the system tray.</source>
<translation>システムトレイのアイコンを隠す</translation>
</message>
@@ -1064,6 +1054,22 @@
<translation>ネットワーク (&amp;N)</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>いくつかの高度な機能は無効になりますが、すべてのブロックは完全に検証されます。この設定を元に戻すには、ブロック チェーン全体を再ダウンロードする必要があります。実際のディスク使用量は多少多くなる可能性があります。</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>剪定 / ブロックの保存容量</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>この設定を元に戻すには、ブロック チェーン全体を再ダウンロードする必要があります。</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = 自動、0以上 = 指定した数のコアをフリーにする)</translation>
</message>
@@ -1330,6 +1336,10 @@
<translation>URI の操作</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' は正しいURIではありません。 'bitcoin:'を利用してください。</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>支払い要求の取得先URLが無効です: %1</translation>
</message>
@@ -1426,11 +1436,11 @@
</message>
<message>
<source>Sent</source>
- <translation>送金</translation>
+ <translation>送信</translation>
</message>
<message>
<source>Received</source>
- <translation>受取</translation>
+ <translation>受信</translation>
</message>
</context>
<context>
@@ -1527,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>エラー: コマンドライン引数のパース: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>エラー: 指定のデータ ディレクトリ "%1" は存在しません。</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>エラー: 設定ファイルをパースできません: %1。key=value という記法のみを利用してください。</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>エラー: 設定ファイルが読み込めません: %1</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1625,16 +1639,24 @@
<translation>メモリ使用量</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>ウォレット:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(なし)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>リセット (&amp;R)</translation>
</message>
<message>
<source>Received</source>
- <translation>受取</translation>
+ <translation>受信</translation>
</message>
<message>
<source>Sent</source>
- <translation>送金</translation>
+ <translation>送信</translation>
</message>
<message>
<source>&amp;Peers</source>
@@ -1793,6 +1815,10 @@
<translation>Banを解除する (&amp;U)</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>デフォルトウォレット</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>%1 のRPCコンソールへようこそ。</translation>
</message>
@@ -1817,6 +1843,14 @@
<translation>ネットワーク活動は無効化されました</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>ウォレットを含めずにコマンドを実行する</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>"%1"のウォレットを使ってコマンドを実行する</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(ノードID: %1)</translation>
</message>
@@ -1888,6 +1922,14 @@
<translation>クリア</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Segwitアドレス(Bech32もしくはBIP-173アドレス)を利用すると手数料が安くなり、また誤入力防止機能も強化されますが、Segwitアドレスをサポートしない古いウォレットとの互換性は失われます。チェックを外すと、古いウォレットとの互換性を保った古いアドレスが代わりに生成されます。</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Segwitアドレス(Bech32アドレス)を生成する</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>支払リクエスト履歴</translation>
</message>
@@ -1896,10 +1938,6 @@
<translation>支払をリクエストする (&amp;R)</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Bech32形式のアドレスを生成</translation>
- </message>
- <message>
<source>Show the selected request (does the same as double clicking an entry)</source>
<translation>選択されたリクエストを表示する(項目をダブルクリックすることでも表示できます)</translation>
</message>
@@ -1979,6 +2017,10 @@
<translation>メッセージ</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>ウォレット</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI が長くなり過ぎます。ラベルやメッセージのテキストを短くしてください。</translation>
</message>
@@ -2093,12 +2135,16 @@
<translation>手数料設定を折りたたむ</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>1キロバイトあたり手数料</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>トランザクションの仮想サイズの kB (1,000 バイト) あたりのカスタム手数料を指定します。
+
+注: 手数料はバイト単位で計算されるので、500 バイト (1 kBの半分) のトランザクションサイズに対する "kB あたり 100 satoshi" の手数料は、最終的にわずか 50 satoshiとなります。</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>カスタム手数料が1000satoshiに設定されている場合、トランザクションサイズが250バイトとすると、「1キロバイトあたり手数料」では250satoshiの手数料のみを支払いますが、「最小手数料」では1000satoshiを支払います。1キロバイトを超えるトランザクションの場合には、どちらの方法を選択したとしても1キロバイトあたりで支払われます。</translation>
+ <source>per kilobyte</source>
+ <translation>1キロバイトあたり手数料</translation>
</message>
<message>
<source>Hide</source>
@@ -2149,6 +2195,10 @@
<translation>Replace-By-Fee を有効</translation>
</message>
<message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>手数料の上乗せ(Replace-By-Fee: BIP-125を参照)によってトランザクションを送信した後でも手数料を上乗せすることができます。この機能を利用しない場合、予め手数料を多めに見積もっておかないと送金が遅れる可能性があります。</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>すべてクリア (&amp;A)</translation>
</message>
@@ -2205,16 +2255,32 @@
<translation>送ってよろしいですか?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>取引手数料として追加された</translation>
+ <source>or</source>
+ <translation>または</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>合計: %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>手数料は後から上乗せすることができます(Replace-By-Feeのシグナル: BIP-125を参照)。</translation>
</message>
<message>
- <source>or</source>
- <translation>または</translation>
+ <source>from wallet %1</source>
+ <translation>ウォレット %1 から</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>トランザクションを見直してください。</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>取引手数料</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>BIP-125による手数料上乗せ機能を利用していません。</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>合計</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2336,6 +2402,10 @@
<translation>送金額から手数料を差し引く (&amp;U)</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>利用可能な残額を使用</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>メッセージ:</translation>
</message>
@@ -2398,7 +2468,7 @@
</message>
<message>
<source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
- <translation>あなたの所有しているアドレスによりメッセージや合意書に署名をすることで、それらアドレスに対して送られたビットコインを受け取ることができることを証明できます。フィッシング攻撃により不正にあなたの識別情報を署名させられてしまうことを防ぐために、不明確なものやランダムなものに対して署名しないよう注意してください。合意することが可能な、よく詳細の記された文言にのみ署名するようにしてください。</translation>
+ <translation>あなたの所有しているアドレスによりメッセージや合意書に署名をすることで、それらアドレスに対して送られたビットコインを受け取ることができることを証明できます。フィッシング攻撃により不正にあなたの識別情報を署名させられてしまうことを防ぐために、不明確なものやランダムなものに対して署名しないよう注意してください。あなたが同意した、よく詳細の記された文言にのみ署名するようにしてください。</translation>
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
@@ -2554,10 +2624,6 @@
<translation>%1 検証のトランザクションと衝突</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/オフライン</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/未検証, %1</translation>
</message>
@@ -2586,14 +2652,6 @@
<translation>ステータス</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>まだブロードキャストが成功していません</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>%n ノードにブロードキャスト</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>日付</translation>
</message>
@@ -2678,6 +2736,10 @@
<translation>トランザクションの全体サイズ</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>トランザクションの仮想サイズ</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>出力インデックス</translation>
</message>
@@ -2748,10 +2810,6 @@
<translation>ユニット %1 を開く</translation>
</message>
<message>
- <source>Offline</source>
- <translation>オフライン</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>未検証</translation>
</message>
@@ -2776,10 +2834,6 @@
<translation>未成熟(%1検証。%2検証完了後に使用可能となります)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>このブロックは他のどのノードによっても受け取られないで、多分受け入れられないでしょう!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>生成されましたが承認されませんでした</translation>
</message>
@@ -2891,6 +2945,10 @@
<translation>その他</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>検索するアドレス、トランザクションID、またはラベルを入力してください</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>最小の額</translation>
</message>
@@ -3086,38 +3144,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>ウォレット データは正常に%1に保存されました。</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>キャンセル</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>オプション:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>データ ディレクトリの指定</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>ピア アドレスを取得するためにノードに接続し、そして切断します</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>あなた自身のパブリックなアドレスを指定</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>コマンドラインと JSON-RPC コマンドを許可</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>MITソフトウェアライセンスのもとで配布されています。付属のファイル %s または %s を参照してください</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>&lt;category&gt; が与えられなかった場合や &lt;category&gt; = 1 の場合には、すべてのデバッグ情報が出力されます。</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>剪定が最小値の %d MiB以下に設定されています。もっと大きな値を使用してください。</translation>
</message>
@@ -3134,18 +3172,10 @@
<translation>エラー:致命的な内部エラーが発生しました。詳細はdebug.logを参照してください</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>送信するトランザクションに付加する手数料 (%s/kB単位) (初期値: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>ブロックデータを剪定しています……</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>デーモンとしてバックグランドで実行しコマンドを許可</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>HTTPサーバを開始できませんでした。詳細はデバッグログをご確認ください。</translation>
</message>
@@ -3158,52 +3188,20 @@
<translation>%s の開発者</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>十分なデータが蓄積されていない場合に手数料推定機能が利用する手数料レート (%s/kB) (デフォルト: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>トランザクションの中継を行っていない場合でも、ホワイトリストのピアから受け取った中継トランザクションは受け取るようにする (デフォルト: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>指定のアドレスへバインドし、その上で常にリッスンします。IPv6 は [ホスト名]:ポート番号 と表記します</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>データ ディレクトリ %s のロックを取得することができません。おそらく %s は実行中です。</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>ウォレットの全トランザクションを削除し、これらを-rescanオプションを用いることで起動時にブロックチェインのデータのみからリカバリします。</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>特定の接続が利用できず、またaddrmanは外向き接続を見つけられませんでした。</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>%s の読み込みエラー! すべてのキーは正しく読み取れますが、取引データやアドレス帳のエントリが失われたか、正しくない可能性があります。</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>カテゴリに対してデバッグ情報を除外する。-debug=1 とともに用いることで、一つ以上の指定されたカテゴリを除くすべてのカテゴリのデバッグログを出力できる。</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>ウォレットの取引を変更する際にコマンドを実行 (cmd の %s は TxID に置換される)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>コンパクトブロック再構成のために追加のトランザクションをメモリ内に保管しておく (デフォルト: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>このブロックがブロックチェーン内に含まれていた場合には、このブロックおよびそれ以前のすべてのブロックを有効であるとみなし、スクリプトの検証を省略する (0ならすべてを検証、デフォルト: %s、テストネット: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>時間オフセット調整値のピア中央値に対する最大の許容値。ローカル時間の見込み値は、接続するピアにより前方ないし後方へ影響されます。(初期値: %u 秒)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>ひとつのウォレットトランザクションまたは生トランザクションで使用する合計手数料の最大値 (%s 単位)。低すぎる値を指定すると巨大なトランザクションの作成ができなくなります (規定値: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>出力ごとではなく、アドレス単位に出力をまとめて選択します。(後からまたそのアドレスに支払われない限り)アドレスが一度しか使用されないためプライバシーが向上します。ただし追加の制限により最適ではないコイン選択が発生した場合に、わずかに高い手数料となる可能性があります。(初期値: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3214,22 +3212,6 @@
<translation>%s が有用だと感じられた方はぜひプロジェクトへの貢献をお願いします。ソフトウェアのより詳細な情報については %s をご覧ください。</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>保有するピアアドレスが少ない場合、DNS ルックアップによりピアアドレスを問い合わせる (-connect を使っていない場合の初期値: 1)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>古いブロックの剪定 (削除) を有効にすることでストレージの必要量を削減する。これにより pruneblockchain RPC を呼び出すことで指定されたブロックを削除することができます。またターゲットサイズが MiB 単位で指定された場合には古いブロックの自動剪定が有効となります。このモードは -txindex および -rescan オプションと互換性がありません。警告: この設定を最有効化するにはすべてのブロックチェーンの再ダウンロードが必要となります。(デフォルト: 0 = ブロックの剪定を無効化する, 1 = RPC 経由での手動剪定を許可する, &gt;%u = MiB 単位で指定されたターゲットサイズを常に下回るようにブロックファイルを自動的に剪定する)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>ブロック生成時に取り込まれるトランザクションの最低手数料率 (%s/kB 単位)。(デフォルト: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>スクリプト検証スレッドを設定 (%uから%dの間, 0 = 自動, &lt;0 = たくさんのコアを自由にしておく, 初期値: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>ブロックのデータベースに未来の時刻のブロックが含まれています。これはおそらくお使いのコンピュータに設定されている日時が間違っていることを示しています。お使いのコンピュータの日時が本当に正しい場合にのみ、ブロックのデータベースの再構築を行ってください。</translation>
</message>
@@ -3250,18 +3232,6 @@
<translation>データベースをフォーク前の状態に巻き戻せませんでした。ブロックチェーンを再ダウンロードする必要があります</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>リッスン ポートの割当に UPnP を使用 (初期値: リッスン中および-proxy が指定されていない場合は1)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>JSON-RPC 接続時のユーザ名とハッシュ化されたパスワード。&lt;userpw&gt; フィールドのフォーマットは &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;。標準的な Python スクリプトが share/rpcuser 内に含まれています。クライアントは通常の場合には rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; を利用して接続を行います。このオプションは複数回指定できます。</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>ウォレットがmempoolチェーン制限数を超えてトランザクションを作らないようにする (初期値: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>警告: ネットワークは完全に合意が取れていないようです。幾人かのマイナーに何らかの障害が発生しているようです。</translation>
</message>
@@ -3270,10 +3240,6 @@
<translation>警告: ピアと完全に合意が取れていないようです!このノードまたは他のノードのアップグレードが必要なようです。</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>シャットダウン時に mempool を保存し、再起動時にロードするかどうか (初期値: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>直近の100ブロックの内%dが予期しないバージョンを含んでいます</translation>
</message>
@@ -3286,42 +3252,14 @@
<translation>-maxmempoolは最低でも %d MB必要です</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt;は以下の値を指定できます:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>外部からの接続を許可 (初期値: -proxy または -connect を使用していない場合は1)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>ユーザエージェント文字列にコメントを</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>起動時に壊れたウォレットから秘密鍵を復旧することを試す</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>ブロック作成オプション:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>-%s アドレス '%s' を解決できません</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>チェイン選択オプション:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>おつりのインデックスが範囲外です</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>接続オプション:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3331,36 +3269,12 @@
</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>デバッグ/テスト用オプション:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>ウォレットは読み込まず、ウォレットRPCコールを無効化する</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>ブロック データベースを今すぐ再構築しますか?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>&lt;address&gt;に対し、ハッシュブロックの公開を有効にする</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>&lt;address&gt; に対し、ハッシュトランザクションの公開を有効にする</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>&lt;address&gt; に対し、生ブロックの公開を有効にする</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>&lt;address&gt; に対し、生トランザクションの公開を有効にする</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>メモリプール内のトランザクションの置換を有効化する (デフォルト: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>%sの作成に失敗しました。このバージョンではHDウォレット以外を作成することはできません。</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3375,6 +3289,10 @@
<translation>%s 読み込みエラー</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>%s の読み込みエラー: 秘密鍵の無効化はウォレットの生成時のみ可能です。</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>%s 読み込みエラー: ウォレットが壊れました</translation>
</message>
@@ -3399,6 +3317,10 @@
<translation>ポートのリッスンに失敗しました。必要であれば -listen=0 を使用してください。</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>初期化の途中でウォレットの再スキャンに失敗しました</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>インポートしています……</translation>
</message>
@@ -3423,8 +3345,12 @@
<translation>不正な額 -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>トランザクションのメモリ・プールの総量を &lt;n&gt; メガバイト以下に維持する (初期値: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>指定のブロックディレクトリ"%s"は存在しません。</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>txindex データベースを更新しています</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3435,26 +3361,10 @@
<translation>banリストを読み込んでいます...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>認証クッキーの場所 (デフォルト: )</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>使用可能なファイルディスクリプタが不足しています。</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>&lt;net&gt; (ipv4, ipv6 または onion) ネットワーク内のノードだけに接続する</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>このヘルプメッセージを表示し終了する</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>バージョンを表示し終了</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>剪定値は負の値に設定できません。</translation>
</message>
@@ -3463,14 +3373,6 @@
<translation>剪定モードは-txindexと互換性がありません。</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>チェイン状態およびブロックインデックスをディスク上の blk*.dat ファイルから再構築する</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>既にインデックスされたブロックからチェイン状態を再構築する</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>ブロックをリプレイしています...</translation>
</message>
@@ -3479,14 +3381,6 @@
<translation>ブロックを巻き戻しています...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>データベースのキャッシュサイズをメガバイトで設定 (%dから%d。初期値: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>ウォレットのファイルを指定 (データ・ディレクトリの中に)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>ソースコードは %s より入手可能です。</translation>
</message>
@@ -3499,6 +3393,10 @@
<translation>このコンピュータの %s にバインドすることができません。おそらく %s は既に実行されています。</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>鍵を生成できません</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>サポートされていない引数 -benchmark は無視されました。-debug=bench を使用してください。</translation>
</message>
@@ -3519,14 +3417,6 @@
<translation>UTXOデータベースを更新しています</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>リッスンポートの割当に UPnP を使用 (初期値: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>テストチェインを利用する</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>ユーザエージェントのコメント (%s) には安全でない文字が含まれています。</translation>
</message>
@@ -3535,90 +3425,26 @@
<translation>ブロックの検証中...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>ウォレットのデバッグ・テスト用オプション:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>ウォレットが書き直される必要がありました: 完了するために %s を再起動します</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>ウォレットオプション:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>指定したアクセス元からのJSON-RPC接続を許可する。有効な&lt;ip&gt;は、単一のIP (例 1.2.3.4)、ネットワーク/ネットマスク (1.2.3.4/255.255.255.0)、またはネットワーク/CIDR (1.2.3.4/24)です。このオプションは複数回指定できます。</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>指定されたアドレスおよび、そこに接続を行ってきたホワイトリストのピアに対してバインドを行います。IPv6の場合には [host]:port 表記を使用してください</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>umask 077 ではなく、システムのデフォルトパーミッションで新規ファイルを作成する (ウォレット機能が無効化されていた場合にのみ有効)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>自分のIPアドレスを解決する (規定値: リッスンをしており、-externalipまたは-proxyオプションが指定されていない場合は1)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>エラー: 内向きの接続をリッスンするのに失敗しました (エラー %s が返却されました)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>関連のアラートをもらってもすごく長いのフォークを見てもコマンドを実行 (コマンドの中にあるの%sはメッセージから置き換えさせる)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>トランザクションの中継、採掘および作成の際には、この値未満の手数料 (%s/kB単位) はゼロであるとみなす (デフォルト: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>paytxfee が設定されていなかった場合、平均して n ブロック以内にトランザクションが検証され始めるのに十分な手数料を含める (初期値: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>-maxtxfee=&lt;amount&gt; の数量の指定が不正です: '%s' (トランザクションが詰まってしまうのを防ぐため、少なくとも %s の最小中継手数料を指定しなければいけません)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>中継および採掘を行う際の、データ運送トランザクションの中のデータの最大サイズ (初期値: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>認証情報をプロキシー接続ごとにランダム化する。これによりTorストリーム分離をすることができます (規定値: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>手数料差引後のトランザクションの金額が小さすぎるため、送金できません。</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>ホワイトリストのピアはDoSによるアクセス禁止処理が無効化され、トランザクションは例えmempool内に既に存在していたとしても常にリレーされます。これは例えばゲートウェイに対して有用です</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>非剪定モードに戻るためには-reindexオプションを使用してデータベースを再構築する必要があります。これによりブロックチェイン全体の再ダウンロードが行われます。</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(規定値: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>公開 REST リクエストを許可する (初期値: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Tor秘匿サービスを自動的に作成する (初期値: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>SOCKS5 プロキシ経由で接続する</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>%s の読み込みエラー: HDウォレットが既に存在するため、HDウォレットを無効化できません</translation>
</message>
@@ -3631,10 +3457,6 @@
<translation>チェインステートデータベースの更新エラー</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>起動時に外部の blk000??.dat ファイルからブロックをインポート</translation>
- </message>
- <message>
<source>Information</source>
<translation>情報</translation>
</message>
@@ -3655,42 +3477,14 @@
<translation>-whitelist に対する無効なネットマスクです: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>最大で &lt;n&gt; 個の孤立したトランザクションをメモリの中に保持する (初期値: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>-whitebind を用いてポートを指定する必要があります: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>ノード中継オプション:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPCサーバのオプション:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>システム上の制約から、-maxconnections を %d から %d に削減しました。</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>起動時に失ったウォレットの取引のブロック チェーンを再スキャン</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>トレース/デバッグ情報を debug.log ファイルの代わりにコンソールへ送る</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>すべてのデバッグオプションを表示する (使い方: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>クライアント起動時に debug.log ファイルを縮小 (初期値: -debug オプションを指定しない場合は1)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>取引の署名に失敗しました</translation>
</message>
@@ -3703,14 +3497,6 @@
<translation>これは実験的なソフトウェアです。</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor管理ポートのパスワード (初期値: 空文字)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Onion のリッスンが有効になっている場合に使用するTor管理ポート (初期値: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>取引の額が小さ過ぎます</translation>
</message>
@@ -3727,18 +3513,18 @@
<translation>このコンピュータの %s にバインドすることができません (バインドが返したエラーは %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>起動時にウォレットを最新のフォーマットにアップグレード</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC 接続のユーザー名</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>初期化キーを生成できません</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>ウォレットの確認中...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>ウォレット「%s」がウォレットフォルダ「%s」の外に存在します</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>警告</translation>
</message>
@@ -3747,106 +3533,18 @@
<translation>警告: 未知の新しいルールが有効化されました (バージョンビット %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>ブロック限定モードにおいて動作を行うかどうか (初期値: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>-txindex を変更するには -reindex を使用してデータベースを再構築する必要があります</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>ウォレットからすべてのトランザクションを消去しています...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ通知オプション:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC 接続のパスワード</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>最良のブロックに変更する際にコマンドを実行 (cmd の %s はブロック ハッシュに置換される)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>-addnode, -seednode と -connect で DNS ルックアップを許可する</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = トランザクションのメタデータ、例えばアカウントの所有者や支払リクエストの内容を保持する, 2 = トランザクションのメタデータを破棄する)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee が非常に高く設定されています!ひとつのトランザクションでこの量の手数料が支払われてしまうことがあります。</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>指定されたアドレスに対して JSON-RPC 接続をリッスンしするようバインドします。このオプションは -rpcallowip も指定されている場合以外には無視されます。ポートはオプションであり -rpcport をオーバーライドします。IPv6の場合には [host]:port 表記を使用してください。このオプションは複数回指定することが可能です (初期値: 127.0.0.1 および ::1、すなわち localhost または -rpcallowip が指定されている場合には 0.0.0.0 および ::、すなわちすべてのアドレス)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>mempool内でトランザクションを &lt;n&gt; 時間以上保持しない (初期値: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>中継や採掘を行う際のトランザクション内の、sigopあたりバイト数の相当量 (初期値: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>%s の読み込みエラー: 非HDウォレットが既に存在するため、HDウォレットを有効化できません</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>ウォレット %s の読み込みエラー。-wallet パラメータはファイル名だけを指定してください (パス名ではありません)。</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>トランザクション作成の際、この値未満の手数料 (%s/kB単位) はゼロであるとみなす (デフォルト: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>ホワイトリストのピアから受け取ったトランザクションに関しては、たとえローカルの中継ポリシーに違反しているとしても中継を行うようにする (デフォルト: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>-checkblocks のブロックの検証レベル (0-4, 初期値: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>getrawtransaction rpc 呼び出し時に用いる、完全なトランザクションインデックスを保持する (初期値: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>不正なピアを再接続するまでの秒数 (初期値: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>デバッグ情報を出力する (初期値: %u, &lt;category&gt; の指定は任意です)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>非冗長モードで返却する生トランザクションやブロックの16進数表現のシリアライゼーションフォーマットを非 segwit (0) または segwit (1) のものに設定する (デフォルト: %d)</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>ウォレットを保持するディレクトリの指定 (初期値: &lt;datadir&gt;/wallets 存在する場合、その他の場合 &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>デバッグログファイルの位置の指定: 絶対パスまたはデータディレクトリからの相対パス (初期値: %s)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Bloomフィルタによる、ブロックおよびトランザクションのフィルタリングを有効化する (初期値: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>おつりを捨てて手数料 (初期値: %s) に追加する場合に許容される手数料レート (%s/kB 単位)。注記: このレートで出力がダストだった場合には出力は捨てられますが、最も長いターゲットの手数料見積額で制限される、ダスト中継手数料および上記の放棄手数料までは常に捨てられます。</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>これは手数料の推定機能が利用できない場合に支払うトランザクション手数料です。</translation>
</message>
@@ -3859,10 +3557,6 @@
<translation>ネットワークバージョン文字 (%i) の長さが最大の長さ (%i) を超えています。UAコメントの数や長さを削減してください。</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>送信転送量を与えられた目標値以下に維持するようにする (24時間あたり何MiBかで指定)。0 の場合は無制限 (初期値: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>サポートされていない引数 -socks が見つかりました。SOCKSバージョンの設定はできないようになりました。SOCKS5プロキシのみがサポートされています。</translation>
</message>
@@ -3871,10 +3565,6 @@
<translation>サポートされていない引数 -whitelistalwaysrelay は無視されました。-whitelistrelay または -whitelistforcerelay を利用してください</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Tor 秘匿サービスを通し、別々の SOCKS5 プロキシを用いることでピアに到達する (初期値: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>警告: 未知のバージョンのブロックが採掘されました。未知のルールが導入された可能性があります</translation>
</message>
@@ -3883,110 +3573,18 @@
<translation>警告: ウォレットファイルが破損していましたのでデータを復旧しました!元の %s は %s として %s に保存されました; 残高やトランザクションが正しくない場合にはバックアップから復元してください。</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>ホワイトリストとして登録するピアノ、接続元の IP アドレス (例: 1.2.3.4) または CIDR 表現のネットワーク (例: 1.2.3.0/24)。複数回指定することもできる</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s の設定値は高すぎます</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(デフォルト: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>DNS ルックアップを通してピアアドレスを常に問い合わせる (初期値: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>ウォレット %s の読み込みエラー。-wallet のファイル名は通常のファイルでなければいけません。</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>ウォレット %s の読み込みエラー。重複する -wallet ファイル名が指定されました。</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>ウォレット %s の読み込みエラー。-walletファイル名内に無効な文字が含まれています。</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>起動時に点検するブロック数 (初期値: %u, 0=すべて)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>デバッグ出力にIPアドレスを含める (初期値: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>鍵プールが枯渇しました。まずはじめに keypoolrefill を呼び出してください</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>&lt;port&gt; で JSON-RPC 接続をリッスン (初期値: %u、testnet は %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>接続のリッスンを &lt;port&gt; で行う (初期値: %u、testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>ピアの接続数を最大でも &lt;n&gt; 個に維持する (初期値: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>ウォレットのトランザクションをブロードキャストする</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>接続毎の最大受信バッファ &lt;n&gt;*1000 バイト (初期値: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>接続毎の最大送信バッファ &lt;n&gt;*1000 バイト (初期値: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>デバッグ出力にタイムスタンプを付ける (初期値: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>データ運送トランザクションのリレーおよび採掘を行う (初期値: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>P2SHでないマルチシグトランザクションをリレーする (初期値: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>key pool のサイズを &lt;n&gt; (初期値: %u) にセット</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>BIP141ブロック重みの最大値を設定 (初期値: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>RPC サービスのスレッド数を設定 (初期値: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>設定ファイルの指定 (初期値: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>接続のタイムアウトをミリセコンドで指定 (最小値: 1, 初期値: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>pid ファイルの指定 (初期値: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>トランザクション送信時に未検証のおつりを使用する (デフォルト: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>ネットワークのスレッドを起動しています...</translation>
</message>
@@ -4003,10 +3601,6 @@
<translation>これは取引を送信する場合に支払う取引手数料です。</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>不正なピアを切断するためのしきい値 (初期値: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>取引の額は負であってはいけません</translation>
</message>
@@ -4027,6 +3621,26 @@
<translation>残高不足</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>おつりアドレスの鍵を生成することができません。このウォレットでは秘密鍵が無効です。</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>事前分割キープールをサポートするようにアップグレードせずに、非HD分割ウォレットをアップグレードすることはできません。 -upgradewallet=169900 または、バージョンを指定しない -upgradewallet を使用してください。</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>手数料の見積りに失敗しました。代替手数料は無効です。数ブロック待つか、-fallbackfee を有効にしてください。</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>警告: 秘密鍵が無効なウォレット {%s} で秘密鍵を検出しました。</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>データディレクトリ '%s' に書き込むことができません。アクセス権を確認してください。</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>ブロック インデックスを読み込んでいます...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts
index 971ceeb3c0..57053ac62d 100644
--- a/src/qt/locale/bitcoin_ka.ts
+++ b/src/qt/locale/bitcoin_ka.ts
@@ -30,6 +30,10 @@
<translation>მონიშნული მისამართის წაშლა სიიდან</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>შეიყვანეთ საძებნი მისამართი ან ნიშნული</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>ამ ბარათიდან მონაცემების ექსპორტი ფაილში</translation>
</message>
@@ -132,6 +136,10 @@
<translation>გაიმეორეთ ახალი ფრაზა-პაროლი</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>პაროლის ჩვენება</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>აკრიფეთ ახალი პასფრაზა საფულისათვის.&lt;br/&gt; გამოიყენეთ &lt;b&gt;ათი ან მეტი შემთხვევითი სიმბოლოსაგან &lt;/b&gt;, ან &lt;b&gt;რვა ან მეტი სიტყვისაგან&lt;/b&gt; შემდგარი პასფრაზა.</translation>
</message>
@@ -180,10 +188,26 @@
<translation>საფულე დაშიფრულია</translation>
</message>
<message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 ახლა დაიხურება დაშიფრვის პროცესის დასასრულებლად. გახსოვდეთ, რომ თქვენი საფული დაშიფრვა სრულად არ იცავს თქვენს ბიტკოინებს მოპარვისგან მავნე პროგრამების მიერ თქვენი კომპიუტერის ინფიცირების საშუალებით.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>მნიშვნელოვანი: ნებისმიერი საფულის წინა სარეზერვო კოპია, რომელიც თქვენ შექმენით, უნდა იყოს ჩანაცვლებული ახლად გენერირებული, დაშიფრული საფულის ფაილით. უსაფრთხოების მიზნებისთვის, დაუშიფრავი საფულის ფაილის წინა სარეზევო კოპიები გახდება გამოუყენებული იმ წამსვე, როდესაც დაიწყებთ ახალი, დაშიფრული საფულის გამოყენებას.</translation>
+ </message>
+ <message>
<source>Wallet encryption failed</source>
<translation>საფულის დაშიფვრა წარუმატებით დამთვრდა</translation>
</message>
<message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>საფულის დაშიფრვა ვერ მოხდა შიდა შეცდომის გამო. თქვენი საფულე არ არის დაშიფრული.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>მოწოდებული ფრაზა-პაროლები არ ემთხვევა ერთმანეთს.</translation>
+ </message>
+ <message>
<source>Wallet unlock failed</source>
<translation>საფულის გახსნა წარუმატებლად შესრულდა</translation>
</message>
@@ -194,6 +218,10 @@
</context>
<context>
<name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/ქსელის მასკა</translation>
+ </message>
</context>
<context>
<name>BitcoinGUI</name>
@@ -282,6 +310,22 @@
<translation>&amp;URI-ის გახსნა...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>საფულე:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>ნაგულისხმევი საფულე</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>დააწკაპეთ ქსელური აქტივობის გასათიშად.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>ქსელური აქტივობა გათიშულია.</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>დისკზე ბლოკების რეინდექსაცია...</translation>
</message>
@@ -434,6 +478,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>საფულე: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>ტიპი: %1
@@ -623,19 +673,7 @@
<source>Command-line options</source>
<translation>კომანდების ზოლის ოპციები</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>გამოყენება:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>კომანდების ზოლის ოპციები</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>მომხმარებლის ინტერფეისის ოპციები:</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -1048,6 +1086,10 @@
<source>Clear console</source>
<translation>კონსოლის გასუფთავება</translation>
</message>
+ <message>
+ <source>default wallet</source>
+ <translation>ნაგულისხმევი საფულე</translation>
+ </message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
@@ -1146,6 +1188,10 @@
<source>Label</source>
<translation>ნიშნული</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>საფულე</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1257,6 +1303,10 @@
<translation>რაოდენობის კოპირება</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>ტრანსაქციის საფასური - საკომისიო</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(ნიშნული არ არის)</translation>
</message>
@@ -1482,62 +1532,14 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>ოპციები:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>მიუთითეთ მონაცემთა კატალოგი</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>მიერთება კვანძთან, პირების მისამართების მიღება და გათიშვა</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>მიუთითეთ თქვენი საჯარო მისამართი</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>საკომანდო სტრიქონისა და JSON-RPC-კომამდების ნებართვა</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>რეზიდენტულად გაშვება და კომანდების მიღება</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>მოცემულ მისამართზე მიჯაჭვა მუდმივად მასზე მიყურადებით. გამოიყენეთ [host]:port ფორმა IPv6-სათვის</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>კომანდის შესრულება საფულის ტრანსაქციის ცვლილებისას (%s კომანდაში ჩანაცვლდება TxID-ით)</translation>
- </message>
- <message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; შეიძლება იყოს:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>გარედან შეერთებების დაშვება (ნაგულისხმევი: 1 თუ არ გამოიყენება -proxy ან -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>ბლოკის შექმნის ოპციები:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>შენიშნულია ბლოკთა ბაზის დაზიანება</translation>
</message>
<message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>არ ჩაიტვირთოს საფულე და აიკრძალოს საფულისადმი RPC-მიმართვები</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>გავუშვათ ბლოკთა ბაზის ხელახლა აგება ეხლა?</translation>
</message>
@@ -1574,34 +1576,14 @@
<translation>არ არის საკმარისი ფაილ-დესკრიპტორები.</translation>
</message>
<message>
- <source>Specify wallet file (within data directory)</source>
- <translation>მიუთითეთ საფულის ფაილი (კატალოგში)</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>ბლოკების ვერიფიკაცია...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>სფულის ოპციები:</translation>
- </message>
- <message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>ბრძანების შესრულება შესაბამისი უწყების მიღებისას ან როცა შეინიშნება საგრძნობი გახლეჩა (cmd-ში %s შეიცვლება მესიჯით)</translation>
- </message>
- <message>
<source>Information</source>
<translation>ინფორმაცია</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>ტრასირების/დახვეწის ინფოს გაგზავნა კონსოლზე debug.log ფაილის ნაცვლად</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>debug.log ფაილის შეკუმშვა გაშვებისას (ნაგულისხმევია: 1 როცა არ აყენია -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>ტრანსაქციების ხელმოწერა ვერ მოხერხდა</translation>
</message>
@@ -1614,34 +1596,14 @@
<translation>ტრანსაქცია ძალიან დიდია</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>მომხმარებლის სახელი JSON-RPC-შეერთებისათვის</translation>
- </message>
- <message>
<source>Warning</source>
<translation>გაფრთხილება</translation>
</message>
<message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>საჭიროა ბაზის ხელახალი აგება, გამოიყენეთ -reindex რათა შეცვალოთ -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>ტრანსაქციების ჩახსნა საფულიდან...</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>პაროლი JSON-RPC-შეერთებისათვის</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>კომანდის შესრულება უკეთესი ბლოკის გამოჩენისას (%s კომანდაში ჩანაცვლდება ბლოკის ჰეშით)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>DNS-ძებნის დაშვება -addnode, -seednode და -connect-სათვის</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>-onlynet-ში მითითებულია უცნობი ქსელი: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_kk_KZ.ts b/src/qt/locale/bitcoin_kk_KZ.ts
index e9cbf5f99c..95df921686 100644
--- a/src/qt/locale/bitcoin_kk_KZ.ts
+++ b/src/qt/locale/bitcoin_kk_KZ.ts
@@ -236,6 +236,10 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
+ <message>
+ <source>Wallet</source>
+ <translation>Әмиян</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_ko.ts b/src/qt/locale/bitcoin_ko.ts
new file mode 100644
index 0000000000..aa05383a83
--- /dev/null
+++ b/src/qt/locale/bitcoin_ko.ts
@@ -0,0 +1,471 @@
+<TS language="ko" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>마우스 오른쪽 클릭을 해서 라벨이나 주소를 편집할 수 있습니다</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>새로운 주소 발급받기</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;발급받기</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>선택된 주소 클립보드에 붙여넣기</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;복사</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>&amp;닫기</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>선택한 주소 리스트에서 삭제</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>검색할 주소나 라벨을 입력하세요</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>현재 탭의 데이터를 파일로 내보냅니다</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;내보내기</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;삭제하기</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>코인을 보낼 주소를 선택하세요</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>코인을 받을 주소를 선택하세요</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>&amp;선택하기</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>보낼 주소</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>받을 주소</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>이것은 비트코인 전송을 위한 주소입니다. 코인을 보내기 전에 항상 받는 주소와 수량을 확인하세요</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>이것은 비트코인 수신을 위한 주소입니다. 코인을 받을 때 마다 항상 다른 주소를 사용 하시는 것을 권장합니다.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;주소 복사</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>&amp;라벨 복사</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;편집</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>주소 목록 내보내기</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>내보내기 실패</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>주소 목록을 %1 로 저장하는 작업이 실패했습니다. 다시 시도해 주세요.</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ </context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>암호문 입력</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>새 암호문</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>새 암호문 다시 입력</translation>
+ </message>
+ <message>
+ <source>Show password</source>
+ <translation>비밀번호 보이기</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>새 암호문을 지갑에 입력합니다. &lt;br/&gt;이러한 형식의 암호문을 사용해 주십시요.&lt;b&gt;10개 이상의 임의 문자&lt;/b&gt; 또는 &lt;b&gt;8개 이상의 단어&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>지갑 암호화</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>이 작업을 수행하려면 지갑을 잠금 해제 할 암호문이 필요합니다.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>지갑 잠금 해제</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>이 작업을 수행하려면 지갑을 복호화할 암호문이 필요합니다.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>지갑 복호화</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>암호문 변경</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>예전 암호문과 변경할 암호문을 입력하십시요.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>지갑 암호화 확인</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>경고: 지갑이 암호화된 상태로 당신의 암호문을 잃어버리셨다면, 당신은 &lt;b&gt;모든 비트코인을 잃게됩니다&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>진짜로 지갑을 암호화 할까요?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>지갑 암호화</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 이(가) 암호화 작업을 위해 종료됩니다. 이 암호화 작업이 바이러스로부터 비트코인을 완전히 지키지 못한다는 점을 기억하십시요.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>중요: 예전에 만들었던 모든 백업 파일은 새로 만들어진 암호화된 지갑 파일으로 교체됩니다. 보안을 위해서 예전에 만들었던 암호화 되지 않은 백업 파일은 당신이 새로 암호화된 지갑을 사용하고 사용할 수 없게 됩니다. </translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>지갑 암호화 실패</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>내부 오류로 인해 지갑 암호화가 실패했습니다. 지갑이 암호화 되지 않았습니다.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>입력한 암호문이 일치하지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>지갑 잠금 해제 실패</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>지갑 복호화를 위한 암호문이 일치하지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>지갑 복호화 실패</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>지갑 암호문이 성공적으로 변경되었습니다.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>주의: Caps Lock이 켜져있습니다!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Netmask</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>특정 시점까지 차단</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>&amp;메시지에 서명하기...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>네트워크와 동기화중...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;개요</translation>
+ </message>
+ <message>
+ <source>Node</source>
+ <translation>노드</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>지갑의 일반적인 개요 표시</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;거래</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>거래 기록 보기</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>&amp;나가기</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>애플리케이션 종료</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;%1에 대해</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>%1에 대한 정보 표시</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>&amp;Qt에 대해</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Qt에 대한 정보 표시</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>&amp;설정...</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>%1에 대한 구성 수정</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;지갑 암호화...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>&amp;지갑 백업...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>&amp;암호문 변경...</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses...</source>
+ <translation>&amp;보낼 주소...</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses...</source>
+ <translation>&amp;받을 주소...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>&amp;URL 열기</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>지갑:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>기본 지갑</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>클릭해서 네트워크 활동 중지</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>네트워크 활동 중지</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>클릭해서 네트워크 활동 활성화</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>헤더 동기화 (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>디스크에서 블럭 불러오는 중</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>비트코인 주소로 코인 보내기</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>이 지갑을 다른 곳으로 백업</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>지갑 암호화에 사용될 암호문 바꾸기</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ </context>
+<context>
+ <name>QObject::QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>default wallet</source>
+ <translation>기본 지갑</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ </context>
+<context>
+ <name>SendCoinsEntry</name>
+ </context>
+<context>
+ <name>SendConfirmationDialog</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ </context>
+<context>
+ <name>SplashScreen</name>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>내보내기 실패</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;내보내기</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>현재 탭의 데이터를 파일로 내보냅니다</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>송금액은 마이너스가 될 수 없습니다</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts
index b0e1bbdf15..76ac713e05 100644
--- a/src/qt/locale/bitcoin_ko_KR.ts
+++ b/src/qt/locale/bitcoin_ko_KR.ts
@@ -30,6 +30,10 @@
<translation>현재 목록에 선택한 주소 삭제</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>검색하기 위한 주소 또는 표 입력</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>현재 탭에 있는 데이터를 파일로 내보내기</translation>
</message>
@@ -59,7 +63,7 @@
</message>
<message>
<source>Receiving addresses</source>
- <translation>받은 주소들</translation>
+ <translation>받는 주소들</translation>
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
@@ -322,6 +326,14 @@
<translation>&amp;URI 열기...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>지갑:&lt;br&gt;</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>&lt;br&gt;기본 지갑</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>네트워크 활동을 중지하려면 클릭.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>디스크에서 블록 다시 색인중...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>프록시가 &lt;b&gt;활성화&lt;/b&gt; 되었습니다: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>비트코인 주소로 코인 전송</translation>
</message>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>지갑: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>종류: %1
@@ -730,10 +752,6 @@
<translation>주소(&amp;A)</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>새 받는 주소</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>새 보내는 주소</translation>
</message>
@@ -750,8 +768,12 @@
<translation>입력한 "%1" 주소는 올바른 비트코인 주소가 아닙니다.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>입력된 주소는"%1" 이미 주소록에 있습니다.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>주소 "%1"은 이미 "%2"로 받는 주소로 존재하여 보내는 주소로 저장할 수 없습니다.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>입력된 주소 "%1"은 "%2"로 이미 주소록에 있습니다.</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>명령줄 옵션</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>사용법:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>명령줄 옵션</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>UI 옵션:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>실행시 데이터 폴더 선택하기 (기본값: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>"ko_KR"와 같이 언어를 설정하십시오 (기본값: 시스템 로캘)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>최소화된 상태에서 시작</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>지불 요청을 위한 SSL 루트 인증서 설정 (기본값: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>실행시 시작화면 보기 (기본값: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>GUI를 통해 수정된 모든 설정을 초기화</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1068,6 +1054,22 @@
<translation>네트워크(&amp;N)</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>일부분의 고급 기능을 취소 하지만 모든 블록들은 검증될 것입니다. 이 설정을 되돌리려면 처음부터 블록체인을 다시 다운로드 받아야 합니다. 실제 디스크 사용량은 더 많을수도 있습니다.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>블록 데이터 축소와 저장할 곳</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>이 설정을 되돌리려면 처음주터 블록체인을 다시 다운로드 받아야 합니다.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = 자동, &lt;0 = 지정된 코어 개수만큼 사용 안함)</translation>
</message>
@@ -1334,6 +1336,10 @@
<translation>URI 핸들링</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://"은 잘못된 URI입니다. 'bitcoin:'을 사용하십시오.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>지불 요청의 URL이 올바르지 않습니다: %1</translation>
</message>
@@ -1531,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>%1 명령 파싱 실패 </translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>에러: 지정한 데이터 폴더 "%1"은 존재하지 않습니다.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>에러: 설정파일을 파싱할수 없습니다: %1. key=value syntax만 사용가능합니다.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>에러: 구성 파일 %1을 파싱할 수 없습니다</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1629,6 +1639,14 @@
<translation>메모리 사용량</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>지갑:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(없음)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>리셋(&amp;R)</translation>
</message>
@@ -1797,6 +1815,10 @@
<translation>노드 추방 취소(&amp;U)</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>&lt;br&gt;기본 지갑</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>%1 RPC 콘솔에 오신걸 환영합니다</translation>
</message>
@@ -1821,6 +1843,14 @@
<translation>네트워크 활동이 정지됨.</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>지갑 없이 명령 실행</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>"%1" 지갑을 사용하여 명령 실행</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(노드 ID: %1)</translation>
</message>
@@ -1892,20 +1922,20 @@
<translation>지우기</translation>
</message>
<message>
- <source>Requested payments history</source>
- <translation>지출기록 확인</translation>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Bech32 주소 (BIP-173)는 더 적은 수수료와 오입금으로부터 방지해 줍니다. Bech32가 비활성화 되어있으면 P2SH 기반의 세그윗 주소가 대신 생성됩니다.</translation>
</message>
<message>
- <source>&amp;Request payment</source>
- <translation>지불 요청(&amp;R)</translation>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Bech32 세그윗 주소 생성</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Bech32 주소 (BIP-173)는 더 적은 수수료와 오입금으로부터 방지해 줍니다. Bech32가 비활성화 되어있으면 P2SH 기반의 세그윗 주소가 대신 생성됩니다.</translation>
+ <source>Requested payments history</source>
+ <translation>지출기록 확인</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Bech32 주소 생성</translation>
+ <source>&amp;Request payment</source>
+ <translation>지불 요청(&amp;R)</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1987,6 +2017,10 @@
<translation>메시지</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>지갑</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI 결과가 너무 길음, 라벨/메세지의 글을 줄이도록 하세요.</translation>
</message>
@@ -2101,12 +2135,16 @@
<translation>수수료 설정 접기</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>킬로바이트 당</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>거래 가상 크기의 kB (1,000 바이트)당 수수료을 지정하십시오.
+
+참고 : 수수료는 바이트 단위로 계산되므로 거래 크기가 500 바이트 (1kB의 절반)일때에 수수료가 "100 satoshis / kB"이면 궁극적으로 50사토시의 수수료만 발생합니다.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>사용자 정의 수수료가 1000사토시로 지정된 경우 거래의 크기가 250바이트 일 경우 1킬로바이트당 250사토시만 지불되지만 "최소 수수료"에선 1000사토시가 지불됩니다. 1킬로바이트가 넘는 거래인 경우 어떠한 경우에든 1킬로바이트 기준으로 지불됩니다.</translation>
+ <source>per kilobyte</source>
+ <translation>킬로바이트 당</translation>
</message>
<message>
<source>Hide</source>
@@ -2218,14 +2256,6 @@
<translation>정말로 보내시겠습니까?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>거래 수수료로 추가됨</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>총 액수 %1</translation>
- </message>
- <message>
<source>or</source>
<translation>또는</translation>
</message>
@@ -2234,10 +2264,26 @@
<translation>추후에 거래 수수료를 올릴 수 있습니다 (Replace-By-Fee, BIP-125 지원)</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>%1 지갑에서</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>거래를 재검토 하십시오</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>거래 수수료</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>Replace-By-Fee, BIP-125 지원 안함</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>총액&lt;br&gt;</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>코인 전송을 확인</translation>
</message>
@@ -2579,10 +2625,6 @@
<translation>%1 승인이 있는 거래와 충돌 함</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/오프라인</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/미승인, %1</translation>
</message>
@@ -2611,14 +2653,6 @@
<translation>상태</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>. 아직 성공적으로 통보하지 않음</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, %n개 노드를 통해 전파</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>날짜</translation>
</message>
@@ -2703,6 +2737,10 @@
<translation>거래 총 크기</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>가상 거래 사이즈</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>출력 인덱스</translation>
</message>
@@ -2773,10 +2811,6 @@
<translation>%1 까지 열림</translation>
</message>
<message>
- <source>Offline</source>
- <translation>오프라인</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>미확인</translation>
</message>
@@ -2801,10 +2835,6 @@
<translation>충분히 숙성되지 않은 상태 (%1 승인, %2 후에 사용 가능합니다)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>이 블록은 다른 노드로부터 받지 않아 허용되지 않을 것임!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>생성되었으나 거절됨</translation>
</message>
@@ -3078,7 +3108,7 @@
</message>
<message>
<source>Could not commit transaction</source>
- <translation>트랜잭션을 커밋 할 수 없습니다.</translation>
+ <translation>거래를 커밋 할 수 없습니다.</translation>
</message>
</context>
<context>
@@ -3115,38 +3145,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>지갑 정보가 %1에 성공적으로 저장되었습니다.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>취소</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>옵션:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>데이터 폴더 지정</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>피어 주소를 받기 위해 노드에 연결하고, 받은 후에 연결을 끊습니다</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>공인 주소를 지정하십시오</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>명령줄과 JSON-RPC 명령 수락</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>MIT 소프트웨어 라이센스에 따라 배포 됨, 첨부 파일 %s 또는 %s을 참조하십시오.</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>&lt;category&gt;가 제공되지 않거나 &lt;category&gt; = 1 인 경우, 모든 디버깅 정보를 출력</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>블록 축소가 최소치의 %d MiB 밑으로 설정되어 있습니다. 더 높은 값을 사용해 보세요.</translation>
</message>
@@ -3163,18 +3173,10 @@
<translation>에러: 치명적인 내부 오류가 발생했습니다, 자세한 내용은 debug.log 를 확인해주세요.</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>송금 거래시 추가되는 수수료 (%s/kB) (기본값: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>블록 데이터를 축소 중입니다..</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>데몬으로 백그라운드에서 실행하고 명령을 허용</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>HTTP 서버를 시작할 수 없습니다. 자세한 사항은 디버그 로그를 확인 하세요.</translation>
</message>
@@ -3187,50 +3189,18 @@
<translation>%s 개발자</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>충분한 데이터가 축적되지 않은 상태에서의 수수료 추정 기능이 사용하는 수수료 비율(%s/kB) (기본값: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>거래의 중계를 하지 않더라도 화이트 리스트에 포함된 피어에서 받은 트랜잭션은 중계하기 (기본값: %d)</translation>
- </message>
- <message>
- <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source>
- <translation>노드를 추가하여 연결을 지속합니다 ('addnode' RPC 명령어 도움말을 참고하세요)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>선택된 주소로 고정하며 항상 리슨(Listen)합니다. IPv6 프로토콜인 경우 [host]:port 방식의 명령어 표기법을 사용합니다.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>%s 데이터 디렉토리에 락을 걸 수 없었습니다. %s가 이미 실행 중인 것으로 보입니다.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>시작시 모든 지갑 거래를 삭제하고 -rescan을 통하여 블록체인만 복구합니다.</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>특정 연결을 제공 할 수없고 addrman이 나가는 연결을 찾을 수 없습니다.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>%s 불러오기 오류: 주소 키는 모두 정확하게 로드되었으나 거래 데이터와 주소록 필드에서 누락이나 오류가 존재할 수 있습니다.</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>지갑 거래가 바뀌면 명령을 실행합니다.(%s 안의 명령어가 TxID로 바뀝니다)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>압축 블록 재구성을 위해 메모리에 보관해야하는 추가 거래 (기본값: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>이 블록이 체인에 있으면 해당 블록과 그 조상이 유효하며 잠재적으로 스크립트 확인을 건너 뜁니다 (0은 모두 확인, 기본값: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>허용 된 최대 중간 피어 시간 오프셋 조정. 시간에 대한 지역적 전망치는 전방 또는 후방의 피어에 의해 영향을 받을 수 있습니다. (기본값: %u 초)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>컴퓨터의 날짜와 시간이 올바른지 확인하십시오! 시간이 잘못되면 %s은 제대로 동작하지 않습니다.</translation>
</message>
@@ -3239,14 +3209,6 @@
<translation>%s가 유용하다고 생각한다면 프로젝트에 공헌해주세요. 이 소프트웨어에 대한 보다 자세한 정보는 %s를 방문해주십시오.</translation>
</message>
<message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>블록 생성시 거래가 포함되도록 최저 수수료율을 설정하십시오 (%s/kB 단위). (기본값: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>스크립트 인증 스레드의 갯수 설정 (%u-%d, 0 = 자동, &lt;0 = 지정된 코어 개수만큼 사용 안함, 기본값: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>블록 데이터베이스에 미래의 블록이 포함되어 있습니다. 이것은 사용자의 컴퓨터의 날짜와 시간이 올바르게 설정되어 있지 않을때 나타날 수 있습니다. 만약 사용자의 컴퓨터의 날짜와 시간이 올바르다고 확신할 때에만 블록 데이터 베이스의 재구성을 하십시오</translation>
</message>
@@ -3255,6 +3217,10 @@
<translation>출시 전의 테스트 빌드 입니다. - 스스로의 책임하에 사용하십시오 - 채굴이나 상업적 용도로 프로그램으로 사용하지 마십시오</translation>
</message>
<message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>이것은 수수료 견적을 이용할 수 없을 때 지불 할 수 있는 거래 수수료입니다.</translation>
+ </message>
+ <message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
<translation>블록을 재생할 수 없습니다. -reindex-chainstate를 사용하여 데이터베이스를 다시 빌드 해야 합니다.</translation>
</message>
@@ -3263,18 +3229,6 @@
<translation>데이터베이스를 포크 전 상태로 돌리지 못했습니다. 블록체인을 다시 다운로드 해주십시오.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: 열려있거나 -proxy 옵션을 사용하지 않을 시 1)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>클라이언트JSON-RPC 연결시 사용자 이름과 해시화된 암호문. &lt;userpw&gt; 필드는 &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt; 포멧으로 구성되어 있습니다. 전형적 파이썬 스크립트에선 share/rpcuser가 포함되어 있습니다. 그런 다음 클라이언트는 rpcuser=&lt;USERNAME&gt;/ rpcpassword=&lt;PASSWORD&gt; 쌍의 인수를 사용하여 정상적으로 연결합니다. 이 옵션은 여러번 지정할 수 있습니다.</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>지갑은 mempool chain limit (기본값: %u) 을 위반하는 거래를 생성하지 않습니다.</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다. </translation>
</message>
@@ -3283,10 +3237,6 @@
<translation>경고: 현재 비트코인 버전이 다른 네트워크 참여자들과 동일하지 않은 것 같습니다. 당신 또는 다른 참여자들이 동일한 비트코인 버전으로 업그레이드 할 필요가 있습니다.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>종료시 mempool 저장과 재시작시 로드 여부 (기본 : %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>지난 100개의 블록 중 %d개에 예상치 못한 버전이 있습니다.</translation>
</message>
@@ -3299,42 +3249,14 @@
<translation>-maxmempool은 최소한 %d MB가 필요합니다</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; 지정 가능:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>외부 접속을 승인합니다</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>사용자 에이전트 문자열에 코멘트 첨부</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>시작시 망가진 wallet.dat에서 개인키 복원을 시도합니다</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>블록 생성 옵션:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>%s 주소를 확인할 수 없습니다: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>체인 선택 옵션:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>범위 밖의 인덱스 변경</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>연결 설정 : </translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3343,38 +3265,10 @@
<translation>손상된 블록 데이터베이스가 감지되었습니다</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>디버그 및 테스트 설정</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>지갑 불러오기를 하지마시오 또한 지갑 RPC 연결을 차단하십시오</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>블록 데이터베이스를 다시 생성하시겠습니까?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>&lt;address&gt;에 대한 해시 블록 공개 활성화</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>&lt;address&gt;에 대한 해시 거래 공개 활성화</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>&lt;address&gt;에 대한 원시 블록 공개 활성화</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>&lt;address&gt;에 대한 원시 거래 공개 활성화</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>메모리 풀(pool) 내의 거래 치환(replacement) 활성화 (기본값: %u)</translation>
- </message>
- <message>
<source>Error initializing block database</source>
<translation>블록 데이터베이스를 초기화하는데 오류</translation>
</message>
@@ -3387,6 +3281,10 @@
<translation>%s 불러오기 오류</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>%s 로딩 실패: 개인키는 생성할때만 불능하게 만들 수 있습니다</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>%s 불러오기 오류: 지갑 오류</translation>
</message>
@@ -3411,6 +3309,10 @@
<translation>어떤 포트도 반응하지 않습니다. 사용자 반응=0 만약 원한다면</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>지갑 스캔 오류</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>들여오기 중...</translation>
</message>
@@ -3435,8 +3337,12 @@
<translation>유효하지 않은 금액 -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>거래 메모리 풀의 용량을 &lt;n&gt;메가바이트 아래로 유지하기 (기본값: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>디렉토리 "%s"에 지정한 블록들이 존재하지 않습니다.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>txindex 데이터베이스 업테이트중</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3447,26 +3353,10 @@
<translation>추방리스트를 불러오는 중...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>인증 쿠키의 위치 (기본값: data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>사용 가능한 파일 디스크립터-File Descriptor-가 부족합니다. </translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>오직 &lt;net&gt; 네트워크로 로만 접속 (IPv4, IPv6 혹은 onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>도움말 메시지 출력 후 종료</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>버전 출력후 종료</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>블록 축소는 음수로 설정할 수 없습니다.</translation>
</message>
@@ -3475,14 +3365,6 @@
<translation>블록 축소 모드는 -txindex와 호환되지 않습니다.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>현재의 blk*.dat 파일들로부터 블록체인 색인을 재구성합니다.</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>현재 색인 된 블록들로부터 블록체인을 재구성합니다.</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>블록 재생중...</translation>
</message>
@@ -3491,14 +3373,6 @@
<translation>블록 되감는중...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>데이터베이스 케시 크기를 메가바이트로 설정(%d 부터 %d, 기본값: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>데이터 폴더 안에 지갑 파일을 선택하세요.</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>소스코드는 %s 에서 확인하실 수 있습니다.</translation>
</message>
@@ -3511,6 +3385,10 @@
<translation>이 컴퓨터의 %s에 바인딩 할 수 없습니다. 아마도 %s이 실행중인 것 같습니다.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>키값 생성 불가</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>지원하지 않는 인수 -benchmark 은 무시됩니다, -debug=bench 형태로 사용하세요.</translation>
</message>
@@ -3531,14 +3409,6 @@
<translation>UTXO 데이터베이스 업그레이드</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>테스트 체인 사용</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>사용자 정의 코멘트 (%s)에 안전하지 못한 글자가 포함되어 있습니다.</translation>
</message>
@@ -3547,90 +3417,26 @@
<translation>블록 검증중...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>지갑 디버깅/테스트 옵션:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>지갑을 새로 써야 합니다: 완성하기 위하여 %s을 다시 시작하십시오.</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>지갑 옵션:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>특정 소스에서의 JSON-RPC 연결 허가. 유효한 &lt;ip&gt; 같은 하나의 IP주소 (예 1.2.3.4), 네트워크/넷마스크 (예 1.2.3.4/255.255.255.0) 혹은 네트워크/CIDR (예 1.2.3.4/24). 이 옵션은 복수로 설정 할 수 있습니다.</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>선택된 주소로 고정하여 화이트리스트에 포함된 피어에 접속합니다. IPv6 프로토콜인 경우 [host]:port 방식의 명령어 표기법을 사용합니다.</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>umask 077 대신 시스템 기본 퍼미션으로 새 파일을 만듭니다 (지갑 기능이 비활성화 상태에서만 유효합니다)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>자신의 주소를 탐색 (기본값: 열려있거나 -externalip 나 -proxy 옵션이 없으면 1)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>오류: 들어오는 연결을 리슨(Listen)하는데 실패했습니다 (오류 리턴 %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>이 사항과 관련있는 경고가 발생하거나 아주 긴 포크가 발생했을 때 명령어를 실행해 주세요. (cmd 명령어 목록에서 %s는 메시지로 대체됩니다) </translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>해당 금액(%s/kB) 보다 적은 수수료는 중계, 채굴, 거래 생성에서 수수료 면제로 간주됩니다 (기본값: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>paytxfee가 설정되어 있지 않다면 평균 n 블록안에 승인이 이루어지도록 충분한 수수료가 포함됩니다 (기본값: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>유효하지 않은 금액 -maxtxfee=&lt;amount&gt;: '%s' (거래가 막히는 상황을 방지하게 위해 적어도 %s 의 중계 수수료를 지정해야 합니다)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>중계 및 채굴을 할 때 데이터 운송 거래에서 데이터의 최대 크기 (기본값: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>인증정보를 프록시 연결마다 무작위로 합니다. 이는 Tor 스트림을 격리시킬 수 있습니다 (기본값: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>거래액이 수수료를 지불하기엔 너무 작습니다</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>화이트리스트에 포함된 피어는 이미 메모리풀에 포함되어 있어도 DoS 추방이 되지 않으며 그들의 거래가 항상 중계됩니다, 이는 예를 들면 게이트웨이에서 유용합니다.</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>축소 모드를 해제하고 데이터베이스를 재구성 하기 위해 -reindex를 사용해야 합니다. 이 명령은 모든 블록체인을 다시 다운로드 할 것 입니다.</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(기본값: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>공개 REST 요청을 허가 (기본값: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Tor서비스를 자동적으로 생성 (기본값: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>SOCK5 프록시를 통해 연결</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>%s 불러오기 오류: 이미 HD 지갑이 존재하는 상태에서 HD 지갑을 비활성화 할 수 없습니다</translation>
</message>
@@ -3643,10 +3449,6 @@
<translation>체인 상태 데이터베이스 업그레이드 중 오류가 발생했습니다.</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>외부 blk000??.dat 파일에서 블록을 가져오기</translation>
- </message>
- <message>
<source>Information</source>
<translation>정보</translation>
</message>
@@ -3667,44 +3469,28 @@
<translation>유효하지 않은 넷마스크가 -whitelist: '%s" 를 통해 지정됨</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>최대 &lt;n&gt;개의 연결할 수 없는 거래를 메모리에 저장 (기본값: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>-whitebind를 이용하여 포트를 지정해야 합니다: '%s"</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Node 중계 옵션:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC 서버 설정</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>시스템 한계로 인하여 -maxconnections를 %d 에서 %d로 줄였습니다.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>시작시 누락된 지갑 거래에 대해 블록 체인을 다시 검색 합니다</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>추적오류 정보를 degug.log 자료로 보내는 대신 콘솔로 보내기</translation>
+ <source>Signing transaction failed</source>
+ <translation>거래를 서명하는것을 실패하였습니다.</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>모든 디버그 설정 보기(설정: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>애러: 지정한 지갑 폴더 "%s"은 존재하지 않습니다.</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>클라이언트 시작시 debug.log 파일 비우기(기본값: 디버그 안할때 1)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>애러: 지정한 지갑 폴더 "%s"은 상대 경로입니다.</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>거래를 서명하는것을 실패하였습니다.</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>애러: 지정한 지갑 폴더 "%s"은 디렉토리가 아닙니다.</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3715,14 +3501,6 @@
<translation>이 소프트웨어는 시험적입니다.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor 관리 포트 암호 (기본값: 공란)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>onion 열림이 활성화시 Tor 관리 포트 사용 (기본값: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>거래액이 너무 적습니다</translation>
</message>
@@ -3739,14 +3517,6 @@
<translation>초기 키값 생성 불가</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>시작시 지갑 포멧을 최신으로 업그레이드 합니다</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC 연결에 사용할 사용자 이름</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>지갑(들) 검증중...</translation>
</message>
@@ -3763,106 +3533,18 @@
<translation>경고: 알려지지 않은 새로운 규칙이 활성화되었습니다. (버전비트 %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>블록 전용 모드로 동작할지 여부 (기본값: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>-txindex를 바꾸기 위해서는 -reindex를 사용해서 데이터베이스를 재구성해야 합니다. </translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>지갑의 모든거래내역 건너뛰기...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ 알림 옵션:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC 연결에 사용할 암호</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>최고의 블록이 변하면 명령을 실행 (cmd 에 있는 %s 는 블록 해시에 의해 대체되어 짐)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>-addnode, -seednode, -connect 옵션에 대해 DNS 탐색 허용</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = 거래의 메타 데이터를 유지함 예. 계좌정보 와 지불 요구 정보, 2 = 거래 메타 데이터 파기)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee값이 너무 큽니다! 하나의 거래에 너무 큰 수수료가 지불 됩니다.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>주어진 주소에 바인드하여 JSON-RPC 연결을 기다립니다. 이 옵션은 -rpcallowip도 전달되지 않으면 무시됩니다. 포트는 옵션이며 -rpcport를 대체합니다. IPv6의 경우 [host]:port 표기법을 사용하십시오. 이 옵션은 여러 번 지정 할 수 있습니다 (기본값 : 127.0.0.1 및 ::1 즉, localhost 또는 -rpcallowip이 지정되면 0.0.0.0 및 모든 주소).</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>메모리 풀에 있는 거래 기록을 &lt;n&gt;시간 후 부터는 유지하지 않기 (기본값: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>릴레이 및 마이닝 거래의 sigop 당 동등한 바이트 (기본값: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>%s 불러오기 오류: 비-HD 지갑이 존재하는 상태에서 HD 지갑을 활성화 할 수 없습니다</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>지갑 %s 로딩 에러, -wallet 매개변수는 파일 이름만 지정 해야 합니다 (경로가 아님).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>해당 금액(%s/kB) 보다 적은 수수료는 수수료 면제로 간주됩니다.(기본값: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>피어들이 로컬 중계 정책을 위반하더라도 화이트 리스트에 포함된 피어인경우 강제로 중계하기 (기본값: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>-checkblocks을 통한 블록 점검 (0-4, 기본값: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>getrawtransaction를 RPC CALL를 통해 완전한 거래 인덱스 유지 (기본값: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>이상행동을 하는 네트워크 참여자들을 다시 연결시키는데 걸리는 시간 (기본값: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>디버그 정보 출력 (기본값: %u, &lt;category&gt; 제공은 선택입니다)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight</source>
- <translation>최대 BIP141 블록 무게: 설정값 *4. 현재 미 지원 옵션입니다. -blockmaxweight 를 대신 쓰세요.</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>non-segwit(0) 또는 segwit(1) (기본값: %d) 가 아닌 자세한 정보 표시 모드로 반환 된 원시 거래 또는 블록 hex의 직렬화를 설정합니다.</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>지갑 파일을 저장하기 위한 폴더를 설정하세요 (기본값: &lt;datadir&gt;/wallets 또는 &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>디버그 로그 파일의 저장 위치를 지정하세요: 이것은 별도의 위치나 블록체인 저장위치와 동일할 수 있습니다 (기본값: %s)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>블룸필터를 통해 블록과 거래 필터링 지원 (기본값: %u)</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>이것은 수수료 견적을 이용할 수 없을 때 지불 할 수 있는 거래 수수료입니다.</translation>
</message>
@@ -3875,10 +3557,6 @@
<translation>네트워크 버전 문자 (%i)의 길이가 최대길이 (%i)를 초과합니다. UA코멘트의 갯수나 길이를 줄이세요.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>아웃바운드 트래픽을 설정된 목표치 이하로 유지하기 (24시간당 MiB기준), 0 = 무제한 (기본값: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>지원하지 않는 인수 -socks를 찾았습니다. 설정된 SOCKS의 버전은 더이상 사용할 수 없으며, SOCK5 프록시만을 지원합니다.</translation>
</message>
@@ -3887,10 +3565,6 @@
<translation>지원하지 않는 인수 -whitelistalwaysrelay 는 무시됩니다, -whitelistrelay 나 -whitelistforcerelay 를 사용해 주세요.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Tor 서비스를 이용하여 피어에게 연결하기 위해 분리된 SOCKS5 프록시를 사용 (기본값: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>경고: 알려지지 않은 버전의 블록이 채굴되었습니다. 알려지지 않은 규칙이 적용되었을 가능성이 있습니다.</translation>
</message>
@@ -3899,110 +3573,18 @@
<translation>경고 : 지갑파일이 손상되어 데이터가 복구되었습니다. 원래의 %s 파일은 %s 후에 %s 이름으로 저장됩니다. 잔액과 거래 내역이 정확하지 않다면 백업 파일로 부터 복원해야 합니다. </translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>설정된 IP주소 (보기 1.2.3.4) 혹은 CIDR로 작성된 네트워크 (보기 1.2.3.0/24)로 화이트리스트에 포함된 피어에 접속합니다. 이 설정은 복수로 지정 할 수 있습니다.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s가 매우 높게 설정되었습니다!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(기본값: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>DNS lookup을 통해 항상 피어주소에 대한 쿼리 보내기 (기본값: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>지갑 %s 로딩 에러, -wallet 파일 이름은 일반 파일이어야합니다.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>지갑 %s 로딩 에러, 중복된 -wallet 파일이름을 입력했습니다.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>지갑 %s 로딩 에러, -wallet 파일이름에 잘못된 문자가 있습니다.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>시작시 점검할 블록 갯수 (기본값: %u, 0 = 모두)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>디버그 출력에 IP주소 포함하기 (기본값: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Keypool이 종료되었습니다. 먼저 keypoolrefill을 호출하십시오.</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>JSON-RPC 연결을 &lt;port&gt;포트로 받기 (기본값: %u 혹은 테스트넷: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>&lt;port&gt;포트로 연결 받기 (기본값: %u 혹은 테스트넷: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>피어 연결수를 &lt;n&gt;개로 유지 (기본값: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>지갑 브로드캐스트 거래를 만들기</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>접속별 최대 수신 버퍼. &lt;n&gt; × 1000바이트 (기본값: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>접속별 최대 전송 버퍼. &lt;n&gt; × 1000바이트 (기본값: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>디버그 출력에 타임 스탬프 포함하기 (기본값: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>데이터 운송 거래를 중계 및 채굴 (기본값: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>비 P2SH 다중서명을 중계 (기본값: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>키 풀 사이즈를 &lt;n&gt; 로 설정 (기본값: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>최대 BIP141 블록 무게 설정 (기본값: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>원격 프로시져 호출 서비스를 위한 쓰레드 개수를 설정 (기본값 : %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>설정파일 지정 (기본값: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>밀리초 단위로 연결 제한시간을 설정 (최소값: 1, 기본값: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>pid 파일 지정 (기본값: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>거래를 보낼 때 검증되지 않은 잔돈 쓰기 (기본값: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>네트워크 스레드 시작중...</translation>
</message>
@@ -4019,10 +3601,6 @@
<translation>이것은 거래를 보낼 경우 지불 할 거래 수수료입니다.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>비정상적인 피어의 연결을 차단시키기 위한 임계값 (기본값: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>거래액은 반드시 정수여야합니다.</translation>
</message>
@@ -4043,6 +3621,26 @@
<translation>자금이 부족합니다!</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>거스름돈 주소 생성불가. 이 지갑에서는 개인키가 비활성화 되어 있습니다.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>HD split을 하지 않은 지갑은 pre split keypool로 업그레이드 하지 않은 이상 업그레이드가 불가능합니다. -upgradewallet=169900 이나 -upgradewallet (버전을 정하지 않고) 명령을 사용하십시오.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>수수료 견적 실패. Fallbackfee 비활성화 상태. 몇 블록을 기다리거나 -fallbackfee를 활성화 시키십시오.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>주의: {%s}지갑에서 비활성화된 개인키 발견</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>"%s" 데이터 폴더에 쓰기 불가능. 권한을 확인하십시오.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>블록 인덱스를 불러오는 중...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ku_IQ.ts b/src/qt/locale/bitcoin_ku_IQ.ts
index 0d94e8271f..8041f5bcc1 100644
--- a/src/qt/locale/bitcoin_ku_IQ.ts
+++ b/src/qt/locale/bitcoin_ku_IQ.ts
@@ -376,10 +376,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>هەڵبژاردنەکان:</translation>
- </message>
- <message>
<source>Information</source>
<translation>زانیاری</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ky.ts b/src/qt/locale/bitcoin_ky.ts
index 83cb76b453..c49160609d 100644
--- a/src/qt/locale/bitcoin_ky.ts
+++ b/src/qt/locale/bitcoin_ky.ts
@@ -224,6 +224,10 @@
<source>Message</source>
<translation>Билдирүү</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Капчык</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -292,10 +296,6 @@
<context>
<name>TransactionDesc</name>
<message>
- <source>%1/offline</source>
- <translation>%1/тармакта эмес</translation>
- </message>
- <message>
<source>Date</source>
<translation>Дата</translation>
</message>
diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts
index 6715eaab2e..c0ff1030f1 100644
--- a/src/qt/locale/bitcoin_la.ts
+++ b/src/qt/locale/bitcoin_la.ts
@@ -14,6 +14,10 @@
<translation>Dele active selectam inscriptionem ex enumeratione</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Insere inscriptionem vel titulum ut quaeras</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exporta data in hac tabella in plicam</translation>
</message>
@@ -289,15 +293,7 @@
<source>Command-line options</source>
<translation>Optiones mandati initiantis</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Usus:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Optiones mandati intiantis</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -552,6 +548,10 @@
<source>Copy &amp;Address</source>
<translation>&amp;Copia Inscriptionem</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Cassidile</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -598,6 +598,10 @@
<source>S&amp;end</source>
<translation>&amp;Mitte</translation>
</message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transactionis merces</translation>
+ </message>
</context>
<context>
<name>SendCoinsEntry</name>
@@ -748,50 +752,10 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Optiones:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Specifica indicem datorum</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Conecta ad nodum acceptare inscriptiones parium, et disconecte</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Specifica tuam propriam publicam inscriptionem</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accipe terminalis et JSON-RPC mandata.</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Operare infere sicut daemon et mandata accipe</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Nucleus</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Conglutina ad inscriptionem datam et semper in eam ausculta. Utere [moderatrum]:porta notationem pro IPv6</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Facere mandatum quotiescumque cassidilis transactio mutet (%s in mandato sbstituitur ab TxID)</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accipe conexiones externas (praedefinitum: 1 nisi -proxy neque -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Optiones creandi frustorum:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>Corruptum databasum frustorum invenitur</translation>
</message>
@@ -836,14 +800,6 @@
<translation>Informatio</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Mitte informationem vestigii/debug ad terminale potius quam plicam debug.log</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Diminue plicam debug.log ad initium clientis (praedefinitum: 1 nisi -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Signandum transactionis abortum est</translation>
</message>
@@ -856,26 +812,10 @@
<translation>Transactio nimis magna</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nomen utentis pro conexionibus JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Monitio</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Tessera pro conexionibus JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Pelle mandatum quando optissimum frustum mutat (%s in mandato substituitur ab hash frusti)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permitte quaerenda DNS pro -addnode, -seednode, et -connect</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>Ignotum rete specificatum in -onlynet: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts
index 73c37d2daf..26d89de8e9 100644
--- a/src/qt/locale/bitcoin_lt.ts
+++ b/src/qt/locale/bitcoin_lt.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Spustelėkite dešinįjį klavišą norint keisti adresą arba etiketę</translation>
+ <translation>Spustelėkite dešinįjį klaviša norint keisti adresą arba etiketę</translation>
</message>
<message>
<source>Create a new address</source>
@@ -30,6 +30,10 @@
<translation>Ištrinti pasirinktą adresą iš sąrašo</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Įveskite adresą ar žymę į paiešką</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Eksportuoti informaciją iš dabartinės lentelės į failą</translation>
</message>
@@ -41,14 +45,78 @@
<source>&amp;Delete</source>
<translation>&amp;Trinti</translation>
</message>
- </context>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Pasirinkite adresą, kuriam siūsite monetas</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Pasirinkite adresą su kuriuo gauti monetas</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>P&amp;asirinkti</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Išsiuntimo adresai</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Gavimo adresai</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Tai yra jūsų Bitcoin adresai išeinantiems mokėjimams. Visada pasitikrinkite sumą ir gavėjo adresą prieš siunčiant lėšas. </translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Tai yra Jūsų Bitcoin adresai įeinantiems mokėjimams. Kiekvienam mokėjimui rekomenduojama naudoti naują adresą. </translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Kopijuoti adresą</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Kopijuoti &amp;Žymę</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Keisti</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Eksportuoti adresų sąrašą</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Kableliais atskirtų duomenų failas (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Eksportavimas nepavyko</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Bandant išsaugoti adresų sąrašą - įvyko klaida keliant į %1. Prašome bandyti dar kartą.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
<message>
+ <source>Label</source>
+ <translation>Žymė</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>Adresas</translation>
</message>
- </context>
+ <message>
+ <source>(no label)</source>
+ <translation>(nėra žymės)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
@@ -67,7 +135,95 @@
<source>Repeat new passphrase</source>
<translation>Pakartokite naują slaptafrazę</translation>
</message>
- </context>
+ <message>
+ <source>Show password</source>
+ <translation>Rodyti slaptažodį</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Įveskite naują piniginės slaptafrazę.&lt;br/&gt;Prašome naudoti slaptafrazę iš &lt;b&gt; 10 ar daugiau atsitiktinių simbolių&lt;/b&gt; arba &lt;b&gt;aštuonių ar daugiau žodžių&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Užšifruoti piniginę</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Ši operacija reikalauja jūsų piniginės slaptafrazės jai atrakinti.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Atrakinti piniginę</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Ši operacija reikalauja jūsų piniginės slaptafrazės jai iššifruoti.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Iššifruoti piniginę</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Pakeisti slaptafrazę</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Įveskite seną ir naują piniginės slaptafrazes.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Patvirtinkite piniginės užšifravimą</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Dėmesio: jei užšifruosite savo piniginę ir pamesite slaptafrazę, jūs&lt;b&gt;PRARASITE VISUS SAVO BITCOINUS&lt;/b&gt;! </translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Ar tikrai norite šifruoti savo piniginę?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Piniginė užšifruota</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>SVARBU: Betkokios ankstesnės jūsų piniginės atsarginės kopijos turėtų būti pakeistos naujai sugeneruotu, užšifruotu piniginės failu. Dėl saugumo sumetimų, anstesnės neužšifruotos piniginės kopijos failas taps nenaudingu nuo momento, kai nauja ir užšifruota piniginė bus pradėta naudoti. </translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Nepavyko užšifruoti piniginę</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Dėl vidinės klaidos nepavyko užšifruoti piniginę.Piniginė neužšifruota.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Įvestos slaptafrazės nesutampa.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Nepavyko atrakinti piniginę</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Neteisingai įvestas slaptažodis piniginės iššifravimui.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Nepavyko iššifruoti piniginės</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Piniginės slaptažodis sėkmingai pakeistas.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Įspėjimas: įjungtas Caps Lock klavišas!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
<message>
@@ -134,6 +290,10 @@
<translation>&amp;Parinktys...</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Keisti %1 konfigūracijos galimybes</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Užšifruoti piniginę...</translation>
</message>
@@ -158,6 +318,30 @@
<translation>Atidaryti &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Piniginė</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>numatyta piniginė</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Spauskite norėdami išjungti tinklo veiklą.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Tinklo veikla išjungta.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Spauskite norėdami įjungti tinklo veiklą.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Sinchronizuojamos Antraštės (%1%)...</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>Blokai iš naujo indeksuojami...</translation>
</message>
@@ -214,6 +398,14 @@
<translation>Užšifruoti privačius raktus, kurie priklauso jūsų piniginei</translation>
</message>
<message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Pasirašydami žinutes su savo Bitcoin adresais įrodysite jog esate jų savininkas </translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Patikrinkite žinutę, jog įsitikintumėte, kad ją pasirašė nurodytas Bitcoin adresas</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Failas</translation>
</message>
@@ -234,6 +426,18 @@
<translation>Komandinės eilutės parametrai</translation>
</message>
<message>
+ <source>Processing blocks on disk...</source>
+ <translation>Blokai apdirbami diske...</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Paskutinis gautas blokas buvo sukurtas prieš %1.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Sekančios operacijos dar nebus matomos. </translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Klaida</translation>
</message>
@@ -250,6 +454,10 @@
<translation>Atnaujinta</translation>
</message>
<message>
+ <source>%1 client</source>
+ <translation>%1 klientas</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Vejamasi...</translation>
</message>
@@ -260,6 +468,36 @@
</translation>
</message>
<message>
+ <source>Amount: %1
+</source>
+ <translation>Suma: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>Piniginė: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Spausti: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Antraštė: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Adresas: %1
+</translation>
+ </message>
+ <message>
<source>Sent transaction</source>
<translation>Sandoris nusiųstas</translation>
</message>
@@ -334,6 +572,50 @@
<source>Confirmed</source>
<translation>Patvirtintas</translation>
</message>
+ <message>
+ <source>Copy address</source>
+ <translation>Kopijuoti adresą</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopijuoti žymę</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopijuoti sumą</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Sandorio ID</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Kopijuoti mokestį</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Kopijuoti po mokesčio</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Kopijuoti baitus</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Kopijuoti keisti</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>taip</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>ne</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nėra žymės)</translation>
+ </message>
</context>
<context>
<name>EditAddressDialog</name>
@@ -367,15 +649,7 @@
<source>Command-line options</source>
<translation>Komandinės eilutės parametrai</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Naudojimas:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>komandinės eilutės parametrai</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -387,6 +661,10 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Piniginė taip pat bus saugojama šiame direktyve.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Klaida</translation>
</message>
@@ -701,6 +979,10 @@
<translation>Išvalyti konsolę</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>numatyta piniginė</translation>
+ </message>
+ <message>
<source>never</source>
<translation>Niekada</translation>
</message>
@@ -731,7 +1013,15 @@
<source>Clear</source>
<translation>Išvalyti</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopijuoti žymę</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopijuoti sumą</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -746,9 +1036,25 @@
<source>Address</source>
<translation>Adresas</translation>
</message>
+ <message>
+ <source>Label</source>
+ <translation>Žymė</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Piniginė</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Žymė</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nėra žymės)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -812,7 +1118,35 @@
<source>S&amp;end</source>
<translation>&amp;Siųsti</translation>
</message>
- </context>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopijuoti sumą</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Kopijuoti mokestį</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Kopijuoti po mokesčio</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Kopijuoti baitus</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Kopijuoti keisti</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Sandorio mokestis</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nėra žymės)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
<message>
@@ -927,13 +1261,49 @@
</context>
<context>
<name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Žymė</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(nėra žymės)</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
<message>
+ <source>Copy address</source>
+ <translation>Kopijuoti adresą</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopijuoti žymę</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopijuoti sumą</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Sandorio ID</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Kableliais atskirtų duomenų failas (*.csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Žymė</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>Adresas</translation>
</message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Eksportavimas nepavyko</translation>
+ </message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
@@ -950,26 +1320,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Parinktys:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Nustatyti duomenų aplanką</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Nurodykite savo nuosavą viešą adresą</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Priimti komandinę eilutę ir JSON-RPC komandas</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Dirbti fone kaip šešėlyje ir priimti komandas</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin branduolys</translation>
</message>
@@ -986,26 +1336,10 @@
<translation>Informacija</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Siųsti atsekimo/derinimo info į konsolę vietoj debug.log failo</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Vartotojo vardas JSON-RPC jungimuisi</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Įspėjimas</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Slaptažodis JSON-RPC sujungimams</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Leisti DNS paiešką sujungimui ir mazgo pridėjimui</translation>
- </message>
- <message>
<source>Insufficient funds</source>
<translation>Nepakanka lėšų</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts
index f4aef3a5a8..fc74e787ed 100644
--- a/src/qt/locale/bitcoin_lv_LV.ts
+++ b/src/qt/locale/bitcoin_lv_LV.ts
@@ -26,6 +26,10 @@
<translation>Izdzēst iezīmētās adreses no saraksta</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Ierakstiet meklējamo nosaukumu vai adresi</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Datus no tekošā ieliktņa eksportēt uz failu</translation>
</message>
@@ -50,6 +54,10 @@
<translation>&amp;Kopēt adresi</translation>
</message>
<message>
+ <source>Copy &amp;Label</source>
+ <translation>Kopēt &amp;Marķējumu</translation>
+ </message>
+ <message>
<source>&amp;Edit</source>
<translation>&amp;Rediģēt</translation>
</message>
@@ -96,6 +104,10 @@
<translation>Jaunā parole vēlreiz</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Rādīt paroli</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Šifrēt maciņu</translation>
</message>
@@ -441,15 +453,7 @@
<source>Command-line options</source>
<translation>Komandrindas iespējas</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Lietojums:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>komandrindas izvēles</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -900,6 +904,10 @@
<source>Label</source>
<translation>Nosaukums</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Maciņš</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -995,6 +1003,10 @@
<translation>&amp;Sūtīt</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Transakcijas maksa</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(bez nosaukuma)</translation>
</message>
@@ -1192,50 +1204,10 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Iespējas:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Norādiet datu direktoriju</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Pievienoties mezglam, lai iegūtu citu mezglu adreses, un atvienoties</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Norādiet savu publisko adresi</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Pieņemt komandrindas un JSON-RPC komandas</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Darbināt fonā kā servisu un pieņemt komandas</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; var būt:</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Bloka izveidošanas iestatījumi:</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Savienojuma iestatījumi:</translation>
- </message>
- <message>
- <source>Debugging/Testing options:</source>
- <translation>Atkļūdošanas/Testēšanas iestatījumi:</translation>
- </message>
- <message>
<source>Error loading block database</source>
<translation>Kļūda ielādējot bloku datubāzi</translation>
</message>
@@ -1252,22 +1224,10 @@
<translation>Pārbauda blokus...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Maciņa iespējas:</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informācija</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>RPC servera iestatījumi:</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Debug/trace informāciju izvadīt konsolē, nevis debug.log failā</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Transakcijas parakstīšana neizdevās</translation>
</message>
@@ -1280,26 +1240,10 @@
<translation>Transakcija ir pārāk liela</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC savienojumu lietotājvārds</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Brīdinājums</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC savienojumu parole</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Izpildīt komandu, kad labāk atbilstošais bloks izmainās (%s cmd aizvieto ar bloka hešu)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Atļaut DNS uzmeklēšanu priekš -addnode, -seednode un -connect</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>-onlynet komandā norādīts nepazīstams tīkls: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_mk_MK.ts b/src/qt/locale/bitcoin_mk_MK.ts
index 4db72972e0..8bbf985d30 100644
--- a/src/qt/locale/bitcoin_mk_MK.ts
+++ b/src/qt/locale/bitcoin_mk_MK.ts
@@ -498,6 +498,10 @@
<source>&amp;Save Image...</source>
<translation>&amp;Сними Слика...</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Паричник</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -586,10 +590,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Опции:</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Биткоин Core</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ml.ts b/src/qt/locale/bitcoin_ml.ts
new file mode 100644
index 0000000000..fdd3bd74bd
--- /dev/null
+++ b/src/qt/locale/bitcoin_ml.ts
@@ -0,0 +1,336 @@
+<TS language="ml" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>വിലാസം അല്ലെങ്കിൽ ലേബൽ എഡിറ്റുചെയ്യാൻ വലത് ക്ലിക്കുചെയ്യുക</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>ഒരു പുതിയ വിലാസം സൃഷ്ടിക്കുക</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;പുതിയത്</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>നിലവിൽ തിരഞ്ഞെടുത്ത വിലാസം സിസ്റ്റം ക്ലിപ്പ്ബോർഡിലേക്ക് പകർത്തുക</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp; പകർത്തുക
+</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>അ&amp;ടയ്ക്കുക</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>പട്ടികയിൽ നിന്ന് നിലവിൽ തിരഞ്ഞെടുത്ത വിലാസം ഇല്ലാതാക്കുക</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>നിലവിലെ ടാബിൽ ഒരു ഫയലിൽ ഡാറ്റ എക്സ്പോർട്ട് ചെയ്യുക</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp; കയറ്റുമതി ചെയ്യുക</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;ഇല്ലാതാക്കുക</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>നാണയങ്ങൾ അയയ്ക്കാനുള്ള വിലാസം തിരഞ്ഞെടുക്കുക</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>നാണയങ്ങൾ സ്വീകരിക്കാൻ വിലാസം തിരഞ്ഞെടുക്കുക</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>തി&amp;രഞ്ഞെടുക്കുക</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>വിലാസങ്ങൾ അയയ്ക്കുന്നു</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>സ്വീകരിക്കുന്ന വിലാസങ്ങൾ</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>പേയ്മെന്റുകൾ അയയ്ക്കുന്നതിനുള്ള നിങ്ങളുടെ ബിറ്റ്കോയിൻ വിലാസങ്ങളാണ് ഇവ. നാണയങ്ങൾ അയയ്ക്കുന്നതിനുമുമ്പ് എല്ലായ്പ്പോഴും തുകയും സ്വീകരിക്കുന്ന വിലാസവും പരിശോധിക്കുക.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>പേയ്മെന്റ് സ്വീകരിക്കുന്നതിന് നിങ്ങളുടെ ബിറ്റ്കോയിൻ വിലാസങ്ങളാണ് ഇവ. ഓരോ ഇടപാടിനും പുതിയ സ്വീകരിക്കുന്ന വിലാസം ഉപയോഗിക്കുന്നതാണ് ഉചിതം.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;വിലാസം പകർത്തുക</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>പകർത്തുക &amp;ലേബൽ</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;ചിട്ടപ്പെടുത്തുക</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>കയറ്റുമതി വിലാസ ലിസ്റ്റ്</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>കോമയാൽ വേർതിരിച്ച ഫയൽ (* .csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>കയറ്റുമതി പരാജയപ്പെട്ടു</translation>
+ </message>
+ </context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>ലേബൽ</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>വിലാസം</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(ലേബൽ ഇല്ല)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation>രഹസ്യപദപ്രയോഗ സംഭാഷണം</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>രഹസ്യപദപ്രയോഗം നൽകുക</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>പുതിയ രഹസ്യപദപ്രയോഗം</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>പുതിയ രഹസ്യപദപ്രയോഗം ആവർത്തിക്കുക</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>വാലറ്റിൽ പുതിയ രഹസ്യപദപ്രയോഗം നൽകുക. &lt;br/&gt; &lt;b&gt; പത്തോ അതിലധികമോ റാൻഡം പ്രതീകങ്ങൾ &lt;/ b&gt; അല്ലെങ്കിൽ &lt;b&gt; എട്ട് അല്ലെങ്കിൽ അതിൽ കൂടുതൽ വാക്കുകൾ &lt;/ b&gt; ഒരു രഹസ്യപദപ്രയോഗം ഉപയോഗിക്കുക.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>വാലറ്റ് എൻക്രിപ്റ്റ് ചെയ്യുക</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>നിങ്ങളുടെ വാലറ്റ് അൺലോക്കുചെയ്യാൻ ഈ പ്രവർത്തനത്തിന് നിങ്ങളുടെ വാലറ്റ് രഹസ്യപദപ്രയോഗം ആവശ്യമാണ്.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>വാലറ്റ് അൺലോക്ക് ചെയ്യുക</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>ഈ പ്രവർത്തനത്തിന് വാലറ്റ് ഡീക്രിപ്റ്റ് ചെയ്യുന്നതിന് നിങ്ങളുടെ വാലറ്റ് പാസ്ഫ്രെയ്സ് ആവശ്യമാണ്.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>വാലറ്റ് ഡീക്രിപ്റ്റ് ചെയ്യുക</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>പാസ്ഫ്രെയ്സ് മാറ്റുക</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>പഴയ രഹസ്യപദപ്രയോഗം പുതിയ രഹസ്യപദപ്രയോഗം വാലറ്റിൽ നൽകുക.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>വാലറ്റ് എൻക്രിപ്ഷൻ സ്ഥിരീകരിക്കുക</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>മുന്നറിയിപ്പ്: നിങ്ങളുടെ വാലറ്റ് എൻക്രിപ്റ്റ് ചെയ്ത് പാസ്ഫ്രെയ്സ് നഷ്ടപ്പെടുകയാണെങ്കിൽ, നിങ്ങളുടെ എല്ലാ ബിറ്റ്കൊയിനുകളും നഷ്ടപ്പെടും!</translation>
+ </message>
+ </context>
+<context>
+ <name>BanTableModel</name>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>(no label)</source>
+ <translation>(ലേബൽ ഇല്ല)</translation>
+ </message>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ </context>
+<context>
+ <name>QObject::QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Address</source>
+ <translation>വിലാസം</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>ലേബൽ</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>ലേബൽ</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(ലേബൽ ഇല്ല)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>(no label)</source>
+ <translation>(ലേബൽ ഇല്ല)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ </context>
+<context>
+ <name>SendConfirmationDialog</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ </context>
+<context>
+ <name>SplashScreen</name>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>ലേബൽ</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(ലേബൽ ഇല്ല)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>കോമയാൽ വേർതിരിച്ച ഫയൽ (* .csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>ലേബൽ</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>വിലാസം</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>കയറ്റുമതി പരാജയപ്പെട്ടു</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp; കയറ്റുമതി ചെയ്യുക</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>നിലവിലെ ടാബിൽ ഒരു ഫയലിൽ ഡാറ്റ എക്സ്പോർട്ട് ചെയ്യുക</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts
index 478dfb4d37..b5224bce2b 100644
--- a/src/qt/locale/bitcoin_mn.ts
+++ b/src/qt/locale/bitcoin_mn.ts
@@ -26,6 +26,10 @@
<translation>Одоо сонгогдсон байгаа хаягуудыг жагсаалтаас устгах</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Хайлт хийхийн тулд хаяг эсвэл шошгыг оруул</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Сонгогдсон таб дээрхи дата-г экспортлох</translation>
</message>
@@ -225,10 +229,6 @@
<source>version</source>
<translation>хувилбар</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Хэрэглээ:</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -408,6 +408,10 @@
<source>Copy &amp;Address</source>
<translation>Хаягийг &amp;Хуулбарлах</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Түрүйвч</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -560,14 +564,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Сонголтууд:</translation>
- </message>
- <message>
- <source>Wallet options:</source>
- <translation>Түрүйвчийн сонголтууд:</translation>
- </message>
- <message>
<source>Information</source>
<translation>Мэдээллэл</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts
index 4798ab724a..075c44c75f 100644
--- a/src/qt/locale/bitcoin_ms_MY.ts
+++ b/src/qt/locale/bitcoin_ms_MY.ts
@@ -30,6 +30,11 @@
<translation>Padam alamat semasa yang dipilih dari senaraiyang dipilih dari senarai</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Masukkan alamat atau label untuk carian
+</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>
Alihkan fail data ke dalam tab semasa</translation>
@@ -133,6 +138,11 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Ulangi frasa laluan baru</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Tunjukkan kata laluan
+</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Memasukkan frasa laluan baru kepada dompet.&lt;br/&gt;Sila mengunakkan frasa laluan yang&lt;b&gt;mengandungi 10 atau lebih aksara rawak&lt;/b&gt;,ataupun&lt;b&gt;lapan atau lebih perkataan.&lt;/b&gt;</translation>
</message>
@@ -319,6 +329,15 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Buka &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>dompet</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>dompet lalai
+</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Tekan untuk lumpuhkan rangkaian</translation>
</message>
@@ -410,6 +429,21 @@ Alihkan fail data ke dalam tab semasa</translation>
<source>&amp;Help</source>
<translation>tolong</translation>
</message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Bar alat tab
+</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Request payments (generates QR codes and bitcoin: URIs)
+</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Tunjukkan senarai alamat dan label yang digunakan
+</translation>
+ </message>
</context>
<context>
<name>CoinControlDialog</name>
@@ -471,6 +505,11 @@ Alihkan fail data ke dalam tab semasa</translation>
</context>
<context>
<name>RPCConsole</name>
+ <message>
+ <source>default wallet</source>
+ <translation>dompet lalai
+</translation>
+ </message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
@@ -489,6 +528,10 @@ Alihkan fail data ke dalam tab semasa</translation>
<source>Label</source>
<translation>Label</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>dompet</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts
index c791e1a877..89c8e4174b 100644
--- a/src/qt/locale/bitcoin_nb.ts
+++ b/src/qt/locale/bitcoin_nb.ts
@@ -30,6 +30,10 @@
<translation>Slett den valgte adressen fra listen.</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Skriv inn adresse eller merkelapp for å søke</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Eksporter data fra nåværende fane til fil</translation>
</message>
@@ -730,10 +734,6 @@
<translation>&amp;Adresse</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Ny mottaksadresse</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Ny utsendingsadresse</translation>
</message>
@@ -750,10 +750,6 @@
<translation>Den angitte adressen "%1" er ikke en gyldig Bitcoin-adresse.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Den angitte adressen "%1" er allerede i adresseboken.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Kunne ikke låse opp lommebok.</translation>
</message>
@@ -803,42 +799,6 @@
<source>Command-line options</source>
<translation>Kommandolinjevalg</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Bruk:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>kommandolinjevalg</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Grensesnittvalg:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Velg datakatalog for oppstart (default: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Sett språk, for eksempel "nb_NO" (default: system-«locale»)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Begynn minimert</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Sett SSL-rootsertifikat for betalingshenvendelser (default: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Vis velkomstbilde ved oppstart (default: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Nullstill alle innstillinger endret i det grafiske brukergrensesnittet</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1028,6 +988,14 @@
<translation>Bruk egen SOCKS&amp;5-proxy for å nå noder via Tor hidden services:</translation>
</message>
<message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Skjul ikonet fra systemkurven.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Skjul systemkurvsikon</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Minimer i stedet for å avslutte applikasjonen når vinduet lukkes. Når dette er valgt, vil applikasjonen avsluttes kun etter at Avslutte er valgt i menyen.</translation>
</message>
@@ -1092,6 +1060,14 @@
<translation>Sett opp port ved hjelp av &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Tillat tilkoblinger fra utsiden</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Tillatt innkommend&amp;e tilkoblinger</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Koble til Bitcoin-nettverket gjennom en SOCKS5 proxy.</translation>
</message>
@@ -1172,6 +1148,10 @@
<translation>Skal myntkontroll funksjoner vises eller ikke.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>Tredjepart transaksjon URLer</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1515,10 +1495,6 @@
<translation>Feil: Den spesifiserte datamappen "%1" finnes ikke.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Feil: Kan ikke lese oppsettsfil: %1. Bruk kun syntaksen nøkkel=verdi.</translation>
- </message>
- <message>
<source>Error: %1</source>
<translation>Feil: %1</translation>
</message>
@@ -1785,6 +1761,14 @@
<translation>Bruk ↑ og ↓ til å navigere historikk, og %1 for å tømme skjermen.</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Skriv %1 for en oversikt over tilgjengelige kommandoer.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>For mer informasjon om hvordan konsollet brukes skriv %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>Advarsel: Svindlere har vært på ferde, i oppfordringen om å skrive kommandoer her, for å stjele lommebokinnhold. Ikke bruk konsollen uten at du forstår alle ringvirkningene av en kommando.</translation>
</message>
@@ -1951,6 +1935,10 @@
<translation>Melding</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Lommebok</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Resulterende URI er for lang, prøv å redusere teksten for merkelapp / melding.</translation>
</message>
@@ -2069,10 +2057,6 @@
<translation>per kilobyte</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Hvis den egendefinerte avgiften er satt til 1000 satoshis og transaksjonen bare er 250 bytes, da vil "per kilobyte" bare betale 250 satoshis i gebyr, mens "minstebeløp" betaler 1000 satoshis. For transaksjoner større enn en kilobyte vil begge betale for antall kilobyte.</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Skjul</translation>
</message>
@@ -2117,6 +2101,14 @@
<translation>Bekreftelsestidsmål:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Aktiver Replace-By-Fee</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Med Replace-By-Fee (BIP-125) kan du øke transaksjonens gebyr etter at den er sendt. Uten dette aktivert anbefales et høyere gebyr for å kompensere for risikoen for at transaksjonen blir forsinket. </translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Fjern &amp;Alt</translation>
</message>
@@ -2173,16 +2165,20 @@
<translation>Er du sikker på at du vil sende?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>lagt til som transaksjonsgebyr</translation>
+ <source>or</source>
+ <translation>eller</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Totalt beløp %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Du kan øke gebyret senere (signaliserer Replace-By-Fee, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>eller</translation>
+ <source>Transaction fee</source>
+ <translation>Transaksjonsgebyr</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Signaliserer ikke Replace-By-Fee, BIP-125</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2526,10 +2522,6 @@
<translation>gikk ikke overens med en transaksjon med %1 bekreftelser</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/frakoblet</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/ubekreftet, %1</translation>
</message>
@@ -2558,14 +2550,6 @@
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, har ikke blitt kringkastet enda</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, kringkast gjennom %n node</numerusform><numerusform>, kringkast gjennom %n noder</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Dato</translation>
</message>
@@ -2720,10 +2704,6 @@
<translation>Åpen til %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Frakoblet</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Ubekreftet</translation>
</message>
@@ -2748,10 +2728,6 @@
<translation>Umoden (%1 bekreftelser, vil være tilgjengelig etter %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Denne blokken har ikke blitt mottatt av noen andre noder og vil sannsynligvis ikke bli akseptert!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generert, men ikke akseptert</translation>
</message>
@@ -3062,38 +3038,14 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Lommebokdata lagret til %1.</translation>
</message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Innstillinger:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Angi mappe for datafiler</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Koble til node for å hente adresser til andre noder, koble så fra igjen</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Angi din egen offentlige adresse</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Ta imot kommandolinje- og JSON-RPC-kommandoer</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Lisensiert MIT. Se tilhørende fil %s eller %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Hvis &lt;category&gt; ikke er oppgitt eller hvis &lt;category&gt; = 1, ta ut all informasjon for feilsøking.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Beskjæringsmodus er konfigurert under minimum på %d MiB. Vennligst bruk et høyere nummer.</translation>
</message>
@@ -3110,18 +3062,10 @@
<translation>Feil: En fatal intern feil oppstod, se debug.log for detaljer</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Gebyr (i %s/kB) for å legge til i transaksjoner du sender (standardverdi: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Beskjærer blokklageret...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Kjør i bakgrunnen som daemon og ta imot kommandoer</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Kunne ikke starte HTTP-tjener. Se feilrettingslogg for detaljer.</translation>
</message>
@@ -3134,54 +3078,18 @@
<translation>%s-utviklerne</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>En gebyrsats (i %s(kB) som bil bli brukt når gebyrvurdering har utilstrekkelig data (forvalg: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Godta stafettransaksjoner mottatt fra hvitlistede likemenn, selv når transaksjoner ikke stafettsendes (forvalg: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Bind til angitt adresse. Bruk [vertsmaskin]:port notasjon for IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Kan ikke låse datamappen %s. %s kjører antagelig allerede.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Slett alle transaksjoner i lommeboken og gjenopprett kun de delene av blokkjeden gjennom -rescan ved oppstart</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Kan ikke angi spesifikke tilkoblinger og ha addrman til å finne utgående tilkoblinger samtidig. </translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Feil under lesing av %s! Alle nøkler har blitt lest rett, men transaksjonsdata eller adressebokoppføringer kan mangle eller være uriktige.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Ekskluder feilrettingsinformasjon for en kategori. Kan brukes i sammenheng med -debug=1 til utdatafeilrettingslogger for alle kategorier, unntatt én eller flere angitte kategorier.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Kjør kommando når en lommeboktransaksjon endres (%s i kommando er erstattet med TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Ekstra transaksjoner å beholde i minne for rekonstruksjoner av kompakte blokker (forvalg: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Hvis denne blokken er i kjeden, anta at den og dens opphav er gyldig, og alternativt hopp over deres skriptbekreftelse (0 for å bekrefte alle, forvalg: %s, testnett: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Maksimalt tillatt justering av mediantid av likemenn. Lokalt tidsperspektiv kan påvirkes av likemenn fremover og bakover med denne mengden. (forvalg: %u sekunder)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Maksimalt totalgebyr (i %s) å bruke i én lommebokstransaksjon eller råtransaksjon; en for lav verdi kan avbryte store transaksjoner (forvalg: %s)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>Sjekk at din datamaskins dato og klokke er stilt rett! Hvis klokka er feil, vil ikke %s fungere ordentlig.</translation>
</message>
@@ -3190,22 +3098,6 @@
<translation>Bidra hvis du finner %s nyttig. Besøk %s for mer informasjon om programvaren.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Spørring om likemannsadresser via DNS-oppslag, hvis adressemengden er lav (forvalg: 1 om ikke -connect brukes)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Reduser lagringskrav ved å skru på beskjæring (sletting) av gamle blokker. Dette tillater pruneblockchain RPC å bli påkalt for sletting av spesifikke blokker, og skrur på automatisk beskjæring av gamle blokker hvis målstørrelsen i MiB oppgis. Dette moduset er inkompatibelt med -txindex og -rescan. Advarsel: Tilbakestilling av dette krever ny nedlasting av hele blokkjeden. (forvalg: 0 = skru av beskjæring av blokker, 1 = tillat manuell beskjæring via RPC, &gt;%u = automatisk beskjæring av blokkfiler for å ikke overstige angitt målstørrelse, i MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Sett laveste gebyrtakst (i %s/kB) for transaksjoner som skal inkluderes i blokkopprettelse. (forvalg: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Angi antall tråder for skriptverifisering (%u til %d, 0 = auto, &lt;0 = la det antallet kjerner være ledig, standard: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Blokkdatabasen inneholder en blokk som ser ut til å være fra fremtiden. Dette kan være fordi dato og tid på din datamaskin er satt feil. Gjenopprett kun blokkdatabasen når du er sikker på at dato og tid er satt riktig.</translation>
</message>
@@ -3226,18 +3118,6 @@
<translation>Kan ikke spole tilbake databasen til en tilstand før forgreiningen. Du må laste ned blokkjeden igjen</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Bruk UPnP for lytteport (standardverdi: 1 ved lytting og uten -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Brukernavn og sjekksummert JSON-RPC-tilkoblinger. Dette feltet &lt;userpw&gt; kommer i formatet: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Et kanonisk Python-skript er inkludert i share/rpcuser. Klienten kobler så til bed bruk av rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; argumentpar. Dette valget kan angis flere ganger</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Lommeboka vil ikke opprette transaksjoner som forgriper seg på grenser for hukommelsespuljekjeder (forvalg: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Advarsel: Nettverket ser ikke ut til å være i overenstemmelse! Noen utvinnere ser ut til å ha problemer.</translation>
</message>
@@ -3246,10 +3126,6 @@
<translation>Advarsel: Vi ser ikke ut til å være i full overenstemmelse med våre likemenn! Du kan trenge å oppgradere, eller andre noder kan trenge å oppgradere.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Hvorvidt hukommelsespuljen skal lagres ved avstengning og lastes inn ved omstart (forvalg: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d av minst 100 blokker har uventet versjon</translation>
</message>
@@ -3262,42 +3138,14 @@
<translation>-maxmempool må være minst %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; kan være:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Ta imot tilkoblinger fra utsiden (standardverdi: 1 hvis uten -proxy eller -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Legg til kommentarer i brukeragent-strengen</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Forsøk å gjenopprette private nøkler fra ei skadet lommebok ved oppstart</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Valg for opprettelse av blokker:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Kunne ikke slå opp -%s-adresse: "%s"</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Kjedeutvelgelsesinnstillinger:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Kjedeindeks utenfor rekkevidde</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Innstillinger for tilkobling:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Kopirett © %i-%i</translation>
</message>
@@ -3306,36 +3154,12 @@
<translation>Oppdaget korrupt blokkdatabase</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Valg for feilsøking/testing:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Ikke last inn lommeboken og deaktiver RPC-kall</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Ønsker du å gjenopprette blokkdatabasen nå?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Slå på publish hash block i &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Slå på publish hash transaction i &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Slå på publisering av råblokk i &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Slå på publisering av råtransaksjon i &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Aktiver transaksjonserstatning i hukommelsespuljen (forvalg: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Feil under oppretting av %s: Du kan ikke lage en lommebok uten HD med denne versjonen.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3374,6 +3198,10 @@
<translation>Kunne ikke lytte på noen port. Bruk -listen=0 hvis det er dette du vil.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Klarte ikke gå igjennom lommeboken under oppstart</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importerer...</translation>
</message>
@@ -3398,10 +3226,6 @@
<translation>Ugyldig beløp for -fallbackfee=&lt;amount&gt;: "%s"</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Hold transaksjonspuljen under &lt;n&gt; megabyte (forvalg: %u)</translation>
- </message>
- <message>
<source>Loading P2P addresses...</source>
<translation>Laster maskin-til-maskin -adresser…</translation>
</message>
@@ -3410,26 +3234,10 @@
<translation>Laster inn bannlysningsliste…</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Plassering for autentiseringskake (forvalg: datamappe)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>For få fildeskriptorer tilgjengelig.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Bare koble til noder i nettverket &lt;net&gt; (IPv4, IPv6 eller onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Skriv ut denne hjelpemeldingen og avslutt</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Skriv ut denne versjonen og avslutt</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Beskjæringsmodus kan ikke konfigureres med en negativ verdi.</translation>
</message>
@@ -3438,14 +3246,6 @@
<translation>Beskjæringsmodus er ikke kompatibel med -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Bygg opp igjen kjedetilstand og blokkindeks fra blk*.dat-filer på disk</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Bygg opp igjen kjedetilstand fra blokker som er indeksert nå</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Spiller av blokker igjen…</translation>
</message>
@@ -3454,14 +3254,6 @@
<translation>Spoler tilbake blokker…</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Sett databasen sin størrelse på hurtigbufferen i megabytes (%d til %d, standardverdi: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Angi lommebokfil (inne i datamappe)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Kildekoden er tilgjengelig fra %s.</translation>
</message>
@@ -3494,14 +3286,6 @@
<translation>Oppgraderer UTXO-database</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Bruk UPnP for å sette opp lytteport (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Bruk testkjede</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>User Agent kommentar (%s) inneholder utrygge tegn.</translation>
</message>
@@ -3510,90 +3294,26 @@
<translation>Verifiserer blokker...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Lommebok-feilretting/-testinnstillinger</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Lommeboka må skrives om: Start %s på nytt for å fullføre</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Valg for lommebok:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Tillat JSON-RPC-tilkoblinger fra angitt kilde. Gyldig for &lt;ip&gt; er en enkelt IP (f. eks. 1.2.3.4), et nettverk/nettmaske (f. eks. 1.2.3.4/255.255.255.0) eller et nettverk/CIDR (f. eks. 1.2.3.4/24). Dette alternativet kan angis flere ganger</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Bind til gitt adresse og hvitlist peers som kobler seg til den. Bruk [host]:port notasjon for IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Opprett nye filer med standardtillatelser i systemet, i stedet for umask 077 (kun virksom med lommebokfunksjonalitet slått av)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Oppdag egne IP-adresser (standardverdi: 1 ved lytting og ingen -externalip eller -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Feil: Lytting etter innkommende tilkoblinger feilet (lytting returnerte feil %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Utfør kommando når et relevant varsel er mottatt eller vi ser en veldig lang gaffel (%s i kommando er erstattet med melding)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Gebyrer (i %s/kB) mindre enn dette anses som null gebyr for videresending, graving og laging av transaksjoner (standardverdi: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Hvis paytxfee ikke er angitt, inkluderer da nok i gebyr til at transaksjoner gjennomsnittligt bekreftes innen n blokker (standardverdi: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Ugyldig beløp for -maxtxfee=&lt;amount&gt;: '%s' (må være minst minimum relé gebyr på %s for å hindre fastlåste transaksjoner)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maksimal størrelse på data i databærende transaksjoner vi videresender og ufører graving på (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Bruk tilfeldig identitet for hver proxytilkobling. Dette muliggjør TOR stream isolasjon (standardverdi: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Transaksjonsbeløpet er for lite til å sendes etter at gebyret er fratrukket</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Hvitlistede noder kan ikke DoS-blokkeres, og deres transaksjoner videresendes alltid, selv om de allerede er i hukommelsespuljen. Nyttig f.eks. for en portner.</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Du må gjenoppbygge databasen ved hjelp av -reindex for å gå tilbake til ubeskåret modus. Dette vil laste ned hele blokkjeden på nytt.</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(standardverdi: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Godta offentlige REST forespørsler (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Automatisk opprette Tor skjult tjeneste (standardverdi: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Koble til via SOCKS5-proxy</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Feil ved innlasting av %s: Du kan ikke skru av HD på ei HD-lommebok som allerede finnes</translation>
</message>
@@ -3606,10 +3326,6 @@
<translation>Feil ved oppgradering av kjedetilstandsdatabase</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importerer blokker fra ekstern fil blk000??.dat ved oppstart</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informasjon</translation>
</message>
@@ -3630,44 +3346,28 @@
<translation>Ugyldig nettmaske spesifisert i -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Hold på det meste &lt;n&gt; transaksjoner som ikke kobles i minnet (standardverdi: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Må oppgi en port med -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Node alternativer for videresending:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Innstillinger for RPC-tjener:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduserer -maxconnections fra %d til %d, pga. systembegrensninger.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Se gjennom blokkjeden etter manglende lommeboktransaksjoner ved oppstart</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Send spor-/feilsøkingsinformasjon til konsollen istedenfor filen debug.log</translation>
+ <source>Signing transaction failed</source>
+ <translation>Signering av transaksjon feilet</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Vis alle feilsøkingsvalg (bruk: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Oppgitt -walletdir "%s" eksisterer ikke</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Krymp filen debug.log når klienten starter (standardverdi: 1 hvis uten -debug)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Oppgitt -walletdir "%s" er en relativ sti</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>Signering av transaksjon feilet</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Oppgitt -walletdir "%s" er ikke en katalog</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3678,14 +3378,6 @@
<translation>Dette er eksperimentell programvare.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Passord for Tor-kontrollport (standardverdi: tom)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Tor-kontrollport å bruke hvis onion-lytting er aktivert (standardverdi: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Transaksjonen er for liten</translation>
</message>
@@ -3702,18 +3394,18 @@
<translation>Kan ikke binde til %s på denne datamaskinen (binding returnerte feilen %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Oppgrader lommebok til nyeste format ved oppstart</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Brukernavn for JSON-RPC forbindelser</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Klarte ikke lage første nøkkel</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Lommebokbekreftelse pågår…</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Lommebok %s befinner seg utenfor lommebokkatalog %s</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Advarsel</translation>
</message>
@@ -3722,98 +3414,18 @@
<translation>Advarsel: Ukjente nye regler aktivert (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Hvorvidt å operere i modus med kun blokker (standardverdi: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Du må bygge opp igjen databasen ved bruk av -reindex for å endre -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Zapper alle transaksjoner fra lommeboken...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Valg for ZeroMQ-meldinger:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Passord for JSON-RPC forbindelser</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Utfør kommando når beste blokk endrer seg (%s i kommandoen erstattes med blokkens hash)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Tillat oppslag i DNS for -addnode, -seednode og -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = behold metadata for transaksjon som f. eks. kontoeier og informasjon om betalingsanmodning, 2 = dropp metadata for transaksjon)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee er satt veldig høyt! Så stort gebyr kan bli betalt ved en enkelt transaksjon.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Bind til angitt adresse for lytting til JSON-RPC-tilkoblinger. Dette valget ses bort fra om ikke -rcpallowip også sendes. Port er valgfritt og overstyrer -rpcport. Bruk notasjon i formatet [host]:port for IPv6. Dette valget kan angis flere ganger (forvalg: 127.0.0.1 og ::1 ,altså, lokalvert, eller hvis -rpcallowip har blitt angitt, 0.0.0.0 og :: ,altså, alle adresser)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Ikke hold transaksjoner i minnet lenger enn &lt;n&gt; timer (standard: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Overenstemmende byte per sigop i transaksjoner for stafett og utvinning (forvalg: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Feil ved innlasting av %s: Du kan ikke skru på HD på ei ikke-HD-lommebok som allerede finnes</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Feil under innlasting av lommeboka %s. -wallet parameter må kun angi et filnavn (ikke en sti).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Gebyrer (i %s/Kb) mindre enn dette anses som null gebyr for laging av transaksjoner (standardverdi: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Tving igjennom stafettransaksjoner av hvitlistede likemenn, selv når de ikke overholder lokal stafettpraksis (forvalg: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Hvor grundig blokkverifiseringen til -checkblocks er (0-4, standardverdi: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Oppretthold en full transaksjonsindeks, brukt av getrawtransaction RPC-kall (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Antall sekunder noder med dårlig oppførsel hindres fra å koble til på nytt (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Ta ut feilsøkingsinformasjon (standardverdi: %u, bruk av &lt;category&gt; er valgfritt)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Setter serialisering av råtransaksjon eller heksadesimal verdi for blokk returnert i ikke-ordrikt modus, non-segwit(0) eller segwit(1) (forvalg: %d)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Støtte filtrering av blokker og transaksjoner med bloomfiltre (standardverdi: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Gebyrtakst (i %s(kB) som indikerer din toleranse for å avslå veksel ved å legge det til gebyret (forvalg: %s). Merk: Otdata avslås hvis det er støv på dette nivået, men det vil alltid bli avslått opptil hva støv-nivået er for stafettoppsettet, og gebyravslag uver det begrenses av gebyroverslaget for det lengste målet</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Dette er transaksjonsgebyret du kan betale når gebyranslag ikke er tilgjengelige.</translation>
</message>
@@ -3826,10 +3438,6 @@
<translation>Total lengde av nettverks-versionstreng (%i) er over maks lengde (%i). Reduser tallet eller størrelsen av uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Prøv å holde utgående trafikk under angitt mål (i MB per 24t), 0 = ingen grense (standard: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Argumentet -socks er ikke støttet. Det er ikke lenger mulig å sette SOCKS-versjon; bare SOCKS5-proxyer er støttet.</translation>
</message>
@@ -3838,10 +3446,6 @@
<translation>Argumentet -whitelistalwaysrelay støttes ikke, og blir ignorert, bruk -whitelistrelay og/eller -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Bruk separate SOCKS5 proxyer for å nå noder via Tor skjulte tjenester (standardverdi: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Advarsel: Ukjente blokkversjoner blir utvunnet! Det er mulig ukjente regler er i spill</translation>
</message>
@@ -3850,110 +3454,18 @@
<translation>Advarsel: Lommeboksfil skadet, data berget! Original %s lagret som %s i %s; hvis din saldo eller transaksjoner er uriktige, bør du gjenopprette fra sikkerhetskopi.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Hvitlist brukere som kobler til fra en gitt IP-adresse (e.g. 1.2.3.4) eller nettverk med CIDR-notasjon (f.eks. 1.2.3.0/24). Kan angis mange ganger.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s er satt veldig høyt!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(standardverdi: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Alltid søk etter nodeadresser via DNS-oppslag (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Feil under innlasting av lommeboka %s. -lommebokfilnavn må være ei vanlig fil.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Feil ved innlasting av lommeboka %s. Duplisert -wallet -filnavn angitt.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Feil ved innlasting av lommeboka %s. Ugyldige tegn i -wallet filename.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Hvor mange blokker skal sjekkes ved oppstart (standardverdi: %u, 0 = alle)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Inkludere IP-adresser i feilsøkingslogg (standardverdi: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Nøkkelpuljen gikk tom, kall keypoolrefill først</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Lytt etter JSON-RPC tilkoblinger på &lt;port&gt; (standardverdi: %u eller testnett: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Lytt etter tilkoblinger på &lt;port&gt; (standardverdi: %u eller testnett: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Hold maks &lt;n&gt; koblinger åpne til andre noder (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Få lommeboken til å kringkaste transaksjoner</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maks mottaksbuffer per forbindelse, &lt;n&gt;*1000 bytes (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maks sendebuffer per forbindelse, &lt;n&gt;*1000 bytes (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Sett inn tidsstempel i front av feilsøkingsdata (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Videresend og ufør graving av databærende transaksjoner (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Videresend ikke-P2SH multisig (standardverdi: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Angi størrelse på nøkkel-lager til &lt;n&gt; (forvalg: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Sett maksimal BIP141-blokkvekt (forvalg: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Sett antall tråder til betjening av RPC-kall (standardverdi: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Angi konfigurasjonsfil (standardverdi: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Angi tidsavbrudd for forbindelse i millisekunder (minimum: 1, standardverdi: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Angi pid-fil (standardverdi: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Bruk ubekreftet veksel ved sending av transaksjoner (standardverdi: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Starter nettverkstråder…</translation>
</message>
@@ -3970,10 +3482,6 @@
<translation>Dette er transaksjonsgebyret du betaler som forsender av transaksjon.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Grenseverdi for å koble fra noder med dårlig oppførsel (standardverdi: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Transaksjonsbeløpet kan ikke være negativt</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ne.ts b/src/qt/locale/bitcoin_ne.ts
index 903a834f8c..4da7d64cee 100644
--- a/src/qt/locale/bitcoin_ne.ts
+++ b/src/qt/locale/bitcoin_ne.ts
@@ -436,10 +436,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>वालेटको सबै कारोबार मेटाउनुहोस् र -स्टार्टअपको पुनः स्क्यान मार्फत ब्लकचेनका ती भागहरूलाई मात्र पुनः प्राप्त गर्नुहोस्</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>ब्लक डाटाबेसमा भविष्यबाट आए जस्तो देखिने एउटा ब्लक हुन्छ । तपाईंको कम्प्युटरको मिति र समय गलत तरिकाले सेट गरिएकाले यस्तो हुन सक्छ । तपाईं आफ्नो कम्प्युटरको मिति र समय सही छ भनेर पक्का हुनुहुन्छ भने मात्र ब्लक डाटाबेस पुनर्निर्माण गर्नुहोस् ।</translation>
</message>
@@ -448,10 +444,6 @@
<translation>प्रि-फर्क अवस्थामा डाटाबेस रिवाइन्ड गर्न सकिएन । तपाईंले फेरि ब्लकचेन डाउनलोड गर्नु पर्ने हुन्छ</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>UPnP प्रयोग गरेर सुन्ने पोर्टलाई म्याप गर्नुहोस् (सुन्दा र -प्रोक्सी नहुँदा डिफल्ट: 1)</translation>
- </message>
- <message>
<source>%s corrupt, salvage failed</source>
<translation>%s मा क्षति, बचाव विफल भयो</translation>
</message>
@@ -460,22 +452,6 @@
<translation>-maxmempool कम्तिमा %d MB को हुनुपर्छ ।</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&amp;lt;वर्ग&amp;gt; निम्न आकारको हुनसक्छ:</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>प्रयोगकर्ता एजेन्ट स्ट्रिङमा टिप्पणी जोड्नुहोस्</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>स्टार्टअपमा क्षति पूगेको वालेटबाट निजी की प्राप्त गर्न प्रयास गर्नुहोस्</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>ब्लक सिर्जनाको बिकल्प:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>-%s ठेगाना: &amp;apos;%s&amp;apos; निश्चय गर्न सकिँदैन</translation>
</message>
@@ -484,10 +460,6 @@
<translation>सूचकांक परिवर्तन सीमा भन्दा बाहर</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>कनेक्सनको विकल्प:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>सर्वाधिकार (C) %i-%i</translation>
</message>
@@ -496,14 +468,6 @@
<translation>क्षति पुगेको ब्लक डाटाबेस फेला पर</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>डिबगिङ/परीक्षणका विकल्पहरू:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>वालेट लोड नगर्नुहोस् र वालेट RPC कलहरू अक्षम गर्नुहोस्</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>तपाईं अहिले ब्लक डेटाबेस पुनर्निर्माण गर्न चाहनुहुन्छ ?</translation>
</message>
@@ -524,78 +488,26 @@
<translation>असमर्थित तर्क -टोर फेला पर्यो, -ओनियन प्रयोग गर्नुहोस् । </translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>UPnP प्रयोग गरेर सुन्ने पोर्ट म्याप गर्नुहोस् (डिफल्ट: %u) </translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>ब्लक प्रमाणित गरिँदै...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>वालेट डिबगिङ/परीक्षणका विकल्पहरू:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>वालेट फेरि लेख्नु आवश्यक छ: पूरा गर्न %s लाई पुन: सुरु गर्नुहोस्</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>वालेटका विकल्पहरू:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>निर्दिष्ट गरिएको स्रोतबाट आएको JSON-RPC कनेक्सनलाई अनुमति दिनुहोस् । एकल IP (e.g. 1.2.3.4), नेटवर्क/नेटमास्क (उदाहरण 1.2.3.4/255.255.255.0) वा नेटवर्क/CIDR (उदाहरण 1.2.3.4/24) &amp;lt;ip&amp;gt; का लागि मान्य छन् । यो विकल्पलाई धेरै पटक निर्दिष्ट गर्न सकिन्छ</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>दिइएको ठेगानामा बाँध्नुहोस् र यसमा कनेक्ट गर्ने सहकर्मीलाई श्वेतसूचीमा राख्नुहोस् । IPv6 लागि [होस्ट]:पोर्ट संकेतन प्रयोग गर्नुहोस्</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>umask 077 को सट्टामा प्रणालीको डिफल्ट अनुमतिको साथमा नयाँ फाइलहरू सिर्जना गर्नुहोस् । (असक्षम गरिएको वालेट कार्यक्षमतामा मात्र प्रभावकारी हुने)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>आफ्नै IP ठेगाना पत्ता लगाउनुहोस् (सुन्दा र -बाहिरीआइपी वा -प्रोक्सी नहुँदा डिफल्ट: 1 )</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>त्रुटि: आगमन कनेक्सनमा सुन्ने कार्य असफल भयो (सुन्ने कार्यले त्रुटि %s फर्कायो)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>सान्दर्भिक चेतावनी प्राप्त गर्दा आदेश कार्यान्वयन गर्नुहोस् नभए धेरै लामो फोर्क देखा पर्न सक्छ । (cmd को %s लाई सन्देशले प्रतिस्थापन गर्छ)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>रिले, खनन वा कारोबारको सिर्जनाको लागि यो भन्दा कम शुल्क (%s/kB मा) लाई शून्य शुल्कको रूपमा लिइन्छ । (डिफल्ट: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>paytxfee सेट गरिएको छैन भने, औसतमा n ब्लक भित्र कारोबार पुष्टिकरण सुरु होस् भन्नका लागि पर्याप्त शुल्क समावेश गर्नुहोस् (डिफल्ट: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>maxtxfee=&amp;lt;रकम&amp;gt;: का लागि अमान्य रकम &amp;apos;%s&amp;apos; (कारोबारलाई अड्कन नदिन अनिवार्य रूपमा कम्तिमा %s को न्यूनतम रिले शुल्क हुनु पर्छ)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>हामीले रिले र खनन गर्ने डाटा वाहक कारोबारको डाटाको अधिकतम आकार (डिफल्ट: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>हरेक प्रोक्सी कनेक्सनका लागि क्रेडिन्सियल अनियमित बनाउनुहोस् । यसले टोर स्ट्रिमको अलगावलाई सक्षम पार्छ (डिफल्ट: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>कारोबार रकम शुल्क कटौती गरेपछि पठाउँदा धेरै नै सानो हुन्छ</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>श्वेतसूचीका सहकर्मी पहिलैबाट मेमपूल, उपयोगीमा भए पनि उनीहरूलाई DoS banned गर्न सकिँदैन र उनीहरूको कारोबार सधैं रिले हुन्छ, उदाहरण, गेटवेको लाग</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>तपाईंले काटछाँट नगरेको मोडमा जान पुनः सूचकांक प्रयोग गरेर डाटाबेस पुनर्निर्माण गर्नु पर्ने हुन्छ । यसले सम्पूर्ण ब्लकचेनलाई फेरि डाउनलोड गर्नेछ</translation>
</message>
diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts
index 685b1583b8..152d89f878 100644
--- a/src/qt/locale/bitcoin_nl.ts
+++ b/src/qt/locale/bitcoin_nl.ts
@@ -30,6 +30,10 @@
<translation>Verwijder het geselecteerde adres van de lijst</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Vul adres of label in om te zoeken</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exporteer de data in de huidige tab naar een bestand</translation>
</message>
@@ -71,11 +75,11 @@
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>&amp;Kopiëer Adres</translation>
+ <translation>&amp;Kopiëer adres</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>Kopieer &amp;Label</translation>
+ <translation>Kopieer &amp;label</translation>
</message>
<message>
<source>&amp;Edit</source>
@@ -299,11 +303,11 @@
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Versleutel Portemonnee...</translation>
+ <translation>&amp;Versleutel portemonnee...</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>&amp;Backup Portemonnee...</translation>
+ <translation>&amp;Backup portemonnee...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
@@ -322,6 +326,14 @@
<translation>Open &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Portemonnee:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>standaard portemonnee</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Klik om de netwerkactiviteit te stoppen.</translation>
</message>
@@ -335,13 +347,17 @@
</message>
<message>
<source>Syncing Headers (%1%)...</source>
- <translation>Kopteksten synchroniseren (%1%)...</translation>
+ <translation>Blokhoofden synchroniseren (%1%)...</translation>
</message>
<message>
<source>Reindexing blocks on disk...</source>
<translation>Bezig met herindexeren van blokken op harde schijf...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy is &lt;b&gt;ingeschakeld&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Verstuur munten naar een Bitcoinadres</translation>
</message>
@@ -383,7 +399,7 @@
</message>
<message>
<source>&amp;Show / Hide</source>
- <translation>&amp;Toon / Verberg</translation>
+ <translation>&amp;Toon / verberg</translation>
</message>
<message>
<source>Show or hide the main Window</source>
@@ -491,7 +507,7 @@
</message>
<message>
<source>Connecting to peers...</source>
- <translation>Gelijke worden verbonden...</translation>
+ <translation>Verbinden met peers...</translation>
</message>
<message>
<source>Catching up...</source>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Portemonnee: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Type: %1
@@ -576,7 +598,7 @@
</message>
<message>
<source>Fee:</source>
- <translation>Transactiekosten:</translation>
+ <translation>Vergoeding:</translation>
</message>
<message>
<source>Dust:</source>
@@ -711,7 +733,7 @@
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
- <translation>Bewerk Adres</translation>
+ <translation>Bewerk adres</translation>
</message>
<message>
<source>&amp;Label</source>
@@ -730,10 +752,6 @@
<translation>&amp;Adres</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nieuw ontvangstadres</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nieuw verzendadres</translation>
</message>
@@ -750,8 +768,12 @@
<translation>Het opgegeven adres "%1" is een ongeldig Bitcoinadres.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Het opgegeven adres "%1" bestaat al in uw adresboek.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adres "%1" bestaat al als ontvang adres met label "%2" en kan dus niet toegevoegd worden als verzend adres.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Het opgegeven adres "%1" bestaat al in uw adresboek onder label "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>Opdrachtregelopties</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Gebruik:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opdrachtregelopties</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>UI-opties:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Kies gegevensmap bij opstarten (standaard: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Stel taal in, bijvoorbeeld "nl_NL" (standaard: systeemlocale)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Geminimaliseerd starten</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Zet SSL-rootcertificaat voor betalingsverzoeken (standaard: -systeem-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Toon opstartscherm bij opstarten (standaard: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Reset alle wijzigingen aan instellingen gedaan in de GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -864,7 +850,7 @@
</message>
<message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation>Als u gekozen heeft om de block chain opslag te beperken (pruning), dan moet de historische data nog steeds gedownload en verwerkt worden, maar zal verwijderd worden naderhand om schijf gebruik zo laag mogelijk te houden.</translation>
+ <translation>Als u gekozen heeft om de blokketenopslag te beperken (pruning), dan moet de historische data nog steeds gedownload en verwerkt worden, maar zal verwijderd worden naderhand om schijf gebruik zo laag mogelijk te houden.</translation>
</message>
<message>
<source>Use the default data directory</source>
@@ -919,7 +905,7 @@
</message>
<message>
<source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation>Recente transacties zijn mogelijk nog niet zichtbaar. De balans van de geldbeugel is daarom mogelijk niet correct. Deze informatie is correct van zodra de synchronisatie met het Bitcoin-netwerk werd voltooid, zoals onderaan beschreven.</translation>
+ <translation>Recente transacties zijn mogelijk nog niet zichtbaar. De balans van de portemonnee is daarom mogelijk niet correct. Deze informatie is correct van zodra de synchronisatie met het Bitcoin-netwerk werd voltooid, zoals onderaan beschreven.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
@@ -959,7 +945,7 @@
</message>
<message>
<source>Unknown. Syncing Headers (%1)...</source>
- <translation>Onbekend. Kopteksten synchroniseren (%1%)...</translation>
+ <translation>Onbekend. Blokhoofden synchroniseren (%1%)...</translation>
</message>
</context>
<context>
@@ -1024,6 +1010,10 @@
<translation>Toont aan of de aangeleverde standaard SOCKS5 proxy gebruikt word om peers te bereiken via dit netwerktype.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Gebruik aparte SOCKS&amp;5-proxy om peers te bereiken via verborgen Tor-diensten:</translation>
+ </message>
+ <message>
<source>Hide the icon from the system tray.</source>
<translation>Verberg het icoon van de systeembalk.</translation>
</message>
@@ -1037,7 +1027,7 @@
</message>
<message>
<source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
- <translation>URL's van derden (bijvoorbeeld block explorer) die in de transacties tab verschijnen als contextmenuelementen. %s in de URL is vervangen door transactiehash. Verscheidene URL's zijn gescheiden door een verticale streep |. </translation>
+ <translation>URL's van derden (bijvoorbeeld blokexplorer) die in de transacties tab verschijnen als contextmenuelementen. %s in de URL is vervangen door transactiehash. Verscheidene URL's zijn gescheiden door een verticale streep |. </translation>
</message>
<message>
<source>Active command-line options that override above options:</source>
@@ -1057,13 +1047,29 @@
</message>
<message>
<source>&amp;Reset Options</source>
- <translation>&amp;Reset Opties</translation>
+ <translation>&amp;Reset opties</translation>
</message>
<message>
<source>&amp;Network</source>
<translation>&amp;Netwerk</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Geavanceerde functionaliteit wordt uitgeschakeld maar alle blokken worden nog steed volledig gevalideerd. Om deze instelling weer ongedaan te maken, moet de volledige blockchain opnieuw gedownload worden. Schijfgebruik kan iets toenemen.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Prune &amp; block opslag op</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Deze instelling terugzetten vereist het opnieuw downloaden van de gehele blockchain.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt;0 = laat dit aantal kernen vrij)</translation>
</message>
@@ -1077,7 +1083,7 @@
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation>Coin &amp;Control activeren</translation>
+ <translation>Coin &amp;control activeren</translation>
</message>
<message>
<source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
@@ -1165,7 +1171,7 @@
</message>
<message>
<source>User Interface &amp;language:</source>
- <translation>Taal &amp;Gebruikersinterface:</translation>
+ <translation>Taal &amp;gebruikersinterface:</translation>
</message>
<message>
<source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
@@ -1189,7 +1195,7 @@
</message>
<message>
<source>&amp;OK</source>
- <translation>&amp;OK</translation>
+ <translation>&amp;Oké</translation>
</message>
<message>
<source>&amp;Cancel</source>
@@ -1221,7 +1227,7 @@
</message>
<message>
<source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
- <translation>Het bevestigingsbestand wordt gebruikt om geavanceerde gebruikersopties te specificeren welke de GUI instellingen overschrijd. Daarnaast, zullen alle command-line opties dit configuratiebestand overschrijven.</translation>
+ <translation>Het configuratiebestand wordt gebruikt om geavanceerde gebruikersopties te specificeren welke de GUI instellingen overschrijd. Daarnaast, zullen alle command-line opties dit configuratiebestand overschrijven.</translation>
</message>
<message>
<source>Error</source>
@@ -1330,6 +1336,10 @@
<translation>URI-behandeling</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' is niet een geldige URI. Gebruik 'bitcoin:' in plaats daarvan.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>URL om betalingsverzoek te verkrijgen is ongeldig: %1</translation>
</message>
@@ -1527,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Fout bij het parsen van command line arguments: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Fout: Opgegeven gegevensmap "%1" bestaat niet.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Fout: Kan configuratiebestand niet verwerken: %1. Gebruik enkel de key=value syntax.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Fout: Kan niet het configuratie bestand parsen: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1625,6 +1639,14 @@
<translation>Geheugengebruik</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Portemonnee:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(geen)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Reset</translation>
</message>
@@ -1790,7 +1812,11 @@
</message>
<message>
<source>&amp;Unban</source>
- <translation>&amp;Maak ban voor Node ongedaan</translation>
+ <translation>&amp;Maak ban voor node ongedaan</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>standaard portemonnee</translation>
</message>
<message>
<source>Welcome to the %1 RPC console.</source>
@@ -1801,6 +1827,14 @@
<translation>Gebruik pijltjes omhoog en omlaag om door de geschiedenis te navigeren en %1 om het scherm te wissen.</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Typ %1 voor een overzicht van de beschikbare commando's.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Typ %1 voor meer informatie over het gebruik van deze console.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>WAARSCHUWING: Er zijn Scammers actief geweest, die gebruikers vragen om hier commando's te typen, waardoor de inhoud van hun portemonnee werd gestolen. Gebruik deze console niet zonder de gevolgen van een commando volledig te begrijpen.</translation>
</message>
@@ -1809,6 +1843,14 @@
<translation>Netwerkactiviteit uitgeschakeld</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Uitvoeren van commando zonder gebruik van een portemonnee</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Uitvoeren van commando met portemonnee "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(node id: %1)</translation>
</message>
@@ -1880,6 +1922,14 @@
<translation>Wissen</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Native segwit-adressen (Bech32 of BIP-173) reduceren later je transactiekosten en bieden een betere bescherming tegen typefouten, maar oude portemonnees ondersteunen deze niet. Een adres dat is compatibel met oudere portemonnees zal worden gecreëerd indien dit niet is aangevinkt.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Genereer native segwit-adres (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Geschiedenis van de betalingsverzoeken</translation>
</message>
@@ -1888,10 +1938,6 @@
<translation>&amp;Betalingsverzoek</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Genereer Bech32-adres</translation>
- </message>
- <message>
<source>Show the selected request (does the same as double clicking an entry)</source>
<translation>Toon het geselecteerde verzoek (doet hetzelfde als dubbelklikken)</translation>
</message>
@@ -1971,6 +2017,10 @@
<translation>Bericht</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Portemonnee</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Resulterende URI te lang, probeer de tekst korter te maken voor het label/bericht.</translation>
</message>
@@ -2046,7 +2096,7 @@
</message>
<message>
<source>Fee:</source>
- <translation>Kosten:</translation>
+ <translation>Vergoeding:</translation>
</message>
<message>
<source>After Fee:</source>
@@ -2066,7 +2116,7 @@
</message>
<message>
<source>Transaction Fee:</source>
- <translation>Transactiekosten:</translation>
+ <translation>Transactievergoeding:</translation>
</message>
<message>
<source>Choose...</source>
@@ -2074,23 +2124,27 @@
</message>
<message>
<source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
- <translation>Gebruik van de terugvalkosten kan resulteren in het verzenden van een transactie die meerdere uren of dagen (of nooit) zal duren om bevestigd te worden. Overweeg om handmatig de kosten in te geven of wacht totdat je de volledige keten hebt gevalideerd.</translation>
+ <translation>Gebruik van de terugvalkosten kan resulteren in het verzenden van een transactie die meerdere uren of dagen (of nooit) zal duren om bevestigd te worden. Overweeg om handmatig de vergoeding in te geven of wacht totdat je de volledige keten hebt gevalideerd.</translation>
</message>
<message>
<source>Warning: Fee estimation is currently not possible.</source>
- <translation>Waarschuwing: Schatting van de kosten is momenteel niet mogelijk.</translation>
+ <translation>Waarschuwing: Schatting van de vergoeding is momenteel niet mogelijk.</translation>
</message>
<message>
<source>collapse fee-settings</source>
- <translation>verberg kosteninstellingen</translation>
+ <translation>verberg vergoeding-instellingen</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>per kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Specificeer handmatig een vergoeding per kB (1,000 bytes) voor de virtuele grootte van de transactie.
+
+Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "100 satoshis per kB" voor een transactie ten grootte van 500 bytes (de helft van 1 kB) uiteindelijk een vergoeding van maar liefst 50 satoshis betekenen.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Als de aangepaste toeslag is ingesteld op 1000 satoshis en de transactie is maar 250 bytes, dan wordt bij "per kilobyte" 250 satoshis aan toeslag berekend, terwijl er bij "totaal tenminste" 1000 satoshis worden berekend. Voor transacties die groter zijn dan een kilobyte, wordt in beide gevallen per kilobyte de toeslag berekend.</translation>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2122,7 +2176,7 @@
</message>
<message>
<source>Add &amp;Recipient</source>
- <translation>Voeg &amp;Ontvanger Toe</translation>
+ <translation>Voeg &amp;ontvanger toe</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -2137,8 +2191,16 @@
<translation>Bevestigingstijddoel:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Activeer Replace-By-Fee</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Met Replace-By-Fee (BIP-125) kun je de vergoeding voor een transactie verhogen na dat deze verstuurd is. Zonder dit kan een hogere vergoeding aangeraden worden om te compenseren voor de hogere kans op transactie vertragingen.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
- <translation>Verwijder &amp;Alles</translation>
+ <translation>Verwijder &amp;alles</translation>
</message>
<message>
<source>Balance:</source>
@@ -2193,16 +2255,32 @@
<translation>Weet u zeker dat u wilt verzenden?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>toegevoegd als transactiekosten</translation>
+ <source>or</source>
+ <translation>of</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Totaalbedrag %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Je kunt de vergoeding later verhogen (signaleert Replace-By-Fee, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>of</translation>
+ <source>from wallet %1</source>
+ <translation>van portemonnee %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Controleer uw transactie aub.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transactiekosten</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Signaleert geen Replace-By-Fee, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Totaalbedrag</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2222,7 +2300,7 @@
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>Het totaal overschrijdt uw huidige saldo wanneer de %1 transactiekosten worden meegerekend.</translation>
+ <translation>Het totaal overschrijdt uw huidige saldo wanneer de %1 transactie vergoeding wordt meegerekend.</translation>
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
@@ -2246,7 +2324,7 @@
</message>
<message>
<source>Pay only the required fee of %1</source>
- <translation>Betaal alleen de verplichte transactiekosten van %1</translation>
+ <translation>Betaal alleen de verplichte transactie vergoeding van %1</translation>
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
@@ -2281,7 +2359,7 @@
</message>
<message>
<source>Pay &amp;To:</source>
- <translation>Betaal &amp;Aan:</translation>
+ <translation>Betaal &amp;aan:</translation>
</message>
<message>
<source>&amp;Label:</source>
@@ -2324,6 +2402,10 @@
<translation>Trek de transactiekosten a&amp;f van het bedrag.</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>Gebruik beschikbaar saldo</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Bericht:</translation>
</message>
@@ -2382,7 +2464,7 @@
</message>
<message>
<source>&amp;Sign Message</source>
- <translation>&amp;Onderteken Bericht</translation>
+ <translation>&amp;Onderteken bericht</translation>
</message>
<message>
<source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
@@ -2426,7 +2508,7 @@
</message>
<message>
<source>Sign &amp;Message</source>
- <translation>Onderteken &amp;Bericht</translation>
+ <translation>Onderteken &amp;bericht</translation>
</message>
<message>
<source>Reset all sign message fields</source>
@@ -2434,11 +2516,11 @@
</message>
<message>
<source>Clear &amp;All</source>
- <translation>Verwijder &amp;Alles</translation>
+ <translation>Verwijder &amp;alles</translation>
</message>
<message>
<source>&amp;Verify Message</source>
- <translation>&amp;Verifiëer Bericht</translation>
+ <translation>&amp;Verifiëer bericht</translation>
</message>
<message>
<source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
@@ -2454,7 +2536,7 @@
</message>
<message>
<source>Verify &amp;Message</source>
- <translation>Verifiëer &amp;Bericht</translation>
+ <translation>Verifiëer &amp;bericht</translation>
</message>
<message>
<source>Reset all verify message fields</source>
@@ -2542,10 +2624,6 @@
<translation>geconflicteerd met een transactie met %1 confirmaties</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/onbevestigd, %1</translation>
</message>
@@ -2574,10 +2652,6 @@
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, is nog niet met succes uitgezonden</translation>
- </message>
- <message>
<source>Date</source>
<translation>Datum</translation>
</message>
@@ -2662,6 +2736,10 @@
<translation>Transactie totale grootte</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Transactie virtuele grootte</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Output index</translation>
</message>
@@ -2671,7 +2749,7 @@
</message>
<message>
<source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation>Gegenereerde munten moeten %1 blokken rijpen voordat ze kunnen worden besteed. Toen dit blok gegenereerd werd, werd het uitgezonden naar het netwerk om aan de blokketen toegevoegd te worden. Als het niet lukt om in de keten toegevoegd te worden, zal de status te veranderen naar "niet geaccepteerd" en zal het niet besteedbaar zijn. Dit kan soms gebeuren als een ander knooppunt een blok genereert binnen een paar seconden na die van u.</translation>
+ <translation>Gegenereerde munten moeten %1 blokken rijpen voordat ze kunnen worden besteed. Toen dit blok gegenereerd werd, werd het uitgezonden naar het netwerk om aan de blokketen toegevoegd te worden. Als het niet lukt om in de keten toegevoegd te worden, zal de status te veranderen naar "niet geaccepteerd" en zal het niet besteedbaar zijn. Dit kan soms gebeuren als een ander node een blok genereert binnen een paar seconden na die van u.</translation>
</message>
<message>
<source>Debug information</source>
@@ -2732,10 +2810,6 @@
<translation>Open tot %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Onbevestigd</translation>
</message>
@@ -2760,10 +2834,6 @@
<translation>Niet beschikbaar (%1 bevestigingen, zal beschikbaar zijn na %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Dit blok is niet ontvangen bij andere nodes en zal waarschijnlijk niet worden geaccepteerd!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Gegenereerd maar niet geaccepteerd</translation>
</message>
@@ -3005,19 +3075,19 @@
</message>
<message>
<source>Fee bump error</source>
- <translation>Kosten stoot fout</translation>
+ <translation>Vergoedingsverhoging fout</translation>
</message>
<message>
<source>Increasing transaction fee failed</source>
- <translation>Verhogen transactiekosten is mislukt</translation>
+ <translation>Verhogen transactie vergoeding is mislukt</translation>
</message>
<message>
<source>Do you want to increase the fee?</source>
- <translation>Wil je de kosten verhogen?</translation>
+ <translation>Wil je de vergoeding verhogen?</translation>
</message>
<message>
<source>Current fee:</source>
- <translation>Huidige kosten:</translation>
+ <translation>Huidige vergoeding:</translation>
</message>
<message>
<source>Increase:</source>
@@ -3025,11 +3095,11 @@
</message>
<message>
<source>New fee:</source>
- <translation>Nieuwe kosten:</translation>
+ <translation>Nieuwe vergoeding:</translation>
</message>
<message>
<source>Confirm fee bump</source>
- <translation>Bevestig kostenaanpassing</translation>
+ <translation>Bevestig vergoedingsaanpassing</translation>
</message>
<message>
<source>Can't sign transaction.</source>
@@ -3074,64 +3144,36 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>De portemonneedata is succesvol opgeslagen in %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Annuleren</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opties:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Stel gegevensmap in</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Verbind naar een node om adressen van anderen op te halen, en verbreek vervolgens de verbinding</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Specificeer uw eigen publieke adres</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aanvaard opdrachtregel- en JSON-RPC-opdrachten</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Uitgegeven onder de MIT software licentie, zie het bijgevoegde bestand %s of %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Als er geen &lt;categorie&gt; is opgegeven of als de &lt;categorie&gt; 1 is, laat dan alle debugginginformatie zien.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Prune is ingesteld op minder dan het minimum van %d MiB. Gebruik a.u.b. een hoger aantal.</translation>
</message>
<message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
- <translation>Prune: laatste wallet synchronisatie gaat verder terug dan de middels -prune beperkte data. U moet -reindex gebruiken (downloadt opnieuw de gehele blockchain voor een pruned node)</translation>
+ <translation>Prune: laatste wallet synchronisatie gaat verder terug dan de middels -prune beperkte data. U moet -reindex gebruiken (downloadt opnieuw de gehele blokketen voor een pruned node)</translation>
</message>
<message>
<source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Herscannen is niet mogelijk i.c.m. -prune. U moet -reindex gebruiken dat de hele blockchain opnieuw zal downloaden.</translation>
+ <translation>Herscannen is niet mogelijk i.c.m. -prune. U moet -reindex gebruiken dat de hele blokketen opnieuw zal downloaden.</translation>
</message>
<message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>Fout: er is een fout opgetreden, zie debug.log voor details</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Transactiekosten (in %s/kB) toevoegen aan transacties die u doet (standaard: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
- <translation>Block opslag prunen...</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Draai in de achtergrond als daemon en aanvaard opdrachten</translation>
+ <translation>Blokopslag prunen...</translation>
</message>
<message>
<source>Unable to start HTTP server. See debug log for details.</source>
@@ -3146,52 +3188,20 @@
<translation>De %s ontwikkelaars</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Een transactietarief (in %s/kB) dat gebruikt wordt als de transactiekosten schatting niet genoeg data heeft. (normaal: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Accepteer doorgestuurde transacties ontvangen van goedgekeurde peers, ook wanneer je zelf geen transacties doorstuurt (standaard: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Bind aan opgegeven adres en luister er altijd op. Gebruik [host]:port notatie voor IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Kan geen lock verkrijgen op gegevensmap %s. %s draait waarschijnlijk al.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Verwijder alle transacties van de portemonnee en herstel alleen de delen van de blokketen door -rescan tijdens het opstarten</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Kan niet specifieke verbindingen voorzien en tegelijk addrman uitgaande verbindingen laten vinden.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Waarschuwing: Fout bij het lezen van %s! Alle sleutels zijn in goede orde uitgelezen, maar transactiedata of adresboeklemma's zouden kunnen ontbreken of fouten bevatten.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Sluit debugging informatie uit van een categorie. Dit kan samen gebruikt worden met -debug=1 om uitvoer debug logboeken te creëren voor alle categorieën, behalve één of meerdere categorieën.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Voer opdracht uit zodra een portemonneetransactie verandert (%s in cmd wordt vervangen door TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Extra transacties wordt bijgehouden voor compacte blokreconstructie (standaard: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Als dit blok in de keten staat, gaat het ervan uit dat dit blok en zijn voorouders geldig zijn en mogelijk hun script verificatie overslaan (0 om alles te verifiëren, standaard:%s, testnet:%s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Maximum toegestane peer tijd compensatie. Lokaal perspectief van tijd mag worden beinvloed door peers die met deze hoeveelheid voor of achter lopen. (standaard: %u seconden)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Maximum totale transactiekosten (in %s) om te gebruiken in een enkele portemoneetransactie; als dit te laag is ingesteld kunnen grote transacties worden verhinderd (standaard: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Groepeer outputs per adres, alles of niets selecterend, in plaats van per output. Privacy wordt verbeterd omdat een adres slechts één keer wordt gebruikt (tenzij iemand ernaar stuurt na ermee te betalen), maar kan resulteren in iets hogere fees, als gevolg van suboptimale coin selectie ten gevolge van de toegevoegde beperking (standaard: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3202,22 +3212,6 @@
<translation>Gelieve bij te dragen als je %s nuttig vindt. Bezoek %s voor meer informatie over de software.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Query voor peer adressen via DNS-lookup, als er weinig adressen zijn (standaard: 1 tenzij -connect gebruikt word)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Beperk benodigde opslag door het prunen (verwijderen) van oude blocks in te schakelen. Dit maakt het mogelijk om het pruneblockchain RPC commando aan te roepen om specifieke blocks te verwijderen, en maakt het automatische prunen van oude blocks mogelijk wanneer een doelgrootte in MiB is ingesteld. Deze modus is niet compatible met -txindex en -rescan. Waarschuwing: ongedaan maken van deze instellingen vereist het opnieuw downloaden van gehele de blockchain. (standaard:0 = uitschakelen prunen, 1 = handmatig prunen via RPC toestaan, &gt;%u = automatisch blockchain bestanden prunen om beneden de gespecificeerde doelgrootte in MiB te blijven)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Specificeer het laagste tarief (in %s/kB) voor transacties die bij het maken van een blok moeten worden in rekening worden gebracht (standaard: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Kies het aantal scriptverificatie processen (%u tot %d, 0 = auto, &lt;0 = laat dit aantal kernen vrij, standaard: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>De blokdatabase bevat een blok dat lijkt uit de toekomst te komen. Dit kan gebeuren omdat de datum en tijd van uw computer niet goed staat. Herbouw de blokdatabase pas nadat u de datum en tijd van uw computer correct heeft ingesteld.</translation>
</message>
@@ -3227,7 +3221,7 @@
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>Dit zijn de transactiekost die u mag afleggen als het wisselgeld kleiner is dan het stof op dit niveau</translation>
+ <translation>Dit is de transactievergoeding die u mag afleggen als het wisselgeld kleiner is dan stof op dit niveau</translation>
</message>
<message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
@@ -3238,18 +3232,6 @@
<translation>Niet mogelijk om de databank terug te draaien naar een staat voor de vork. Je zal je blokketen opnieuw moeten downloaden</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Gebruik UPnP om de luisterende poort te mappen (standaard: 1 als er geluisterd worden en geen -proxy is meegegeven)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Gebruikersnaam en gehasht wachtwoord voor JSON-RPC-verbindingen. De velden &lt;userpw&gt; is in het formaat: &lt;GEBRUIKERSNAAM&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Een kanoniek Pythonscript is inbegrepen in de share/rpcuser. De klant connecteert dan normaal via de rpcuser=&lt;GEBRUIKERSNAAM&gt;/rpcpassword=&lt;PASWOORD&gt; argumenten. Deze optie kan meerdere keren worden meegegeven</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Portemonnee creëert geen transacties die mempool-ketenlimieten schenden (standaard: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Waarschuwing: Het lijkt erop dat het netwerk geen consensus kan vinden! Sommige delvers lijken problemen te ondervinden.</translation>
</message>
@@ -3258,10 +3240,6 @@
<translation>Waarschuwing: Het lijkt erop dat we geen consensus kunnen vinden met onze peers! Mogelijk dient u te upgraden, of andere nodes moeten wellicht upgraden.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Of de mempool opgeslagen moet worden bij afsluiten en ingeladen moet worden tijdens herstarten (standaard: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d van de laatste 100 blokken hebben een onverwachte versie</translation>
</message>
@@ -3271,45 +3249,17 @@
</message>
<message>
<source>-maxmempool must be at least %d MB</source>
- <translation>-maxmempool moet tenminste %d MB zijn</translation>
- </message>
- <message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;categorie&gt; kan zijn:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accepteer verbindingen van buitenaf (standaard: 1 als geen -proxy of -connect is opgegeven)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Voeg commentaar toe aan de user agent string</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Probeer privésleutels te herstellen van een corrupte wallet bij opstarten</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Blokcreatie-opties:</translation>
+ <translation>-maxmempool moet minstens %d MB zijn</translation>
</message>
<message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Kan -%s adres niet herleiden: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Keten selectie opties:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Wijzigingsindex buiten bereik</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Verbindingsopties:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Auteursrecht (C) %i-%i</translation>
</message>
@@ -3318,36 +3268,12 @@
<translation>Corrupte blokkendatabase gedetecteerd</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Foutopsporing/Testopties:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Laad de wallet niet en schakel wallet RPC oproepen uit</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Wilt u de blokkendatabase nu herbouwen?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Sta toe om hashblok te publiceren in &lt;adres&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Stat toe om hashtransactie te publiceren in &lt;adres&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Sta toe rauw blok te publiceren in &lt;adres&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Sta toe ruwe transacties te publiceren in &lt;adres&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Transactie vervanging inschakelen in het geheugen (standaard: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Fout bij het maken van %s: Je kunt geen niet-HD portemonnees maken met deze versie.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3362,6 +3288,10 @@
<translation>Fout bij het laden van %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Fout bij het laden van %s: Geheime sleutels kunnen alleen worden uitgeschakeld tijdens het aanmaken</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Fout bij het laden van %s: Portomonnee corrupt</translation>
</message>
@@ -3386,6 +3316,10 @@
<translation>Mislukt om op welke poort dan ook te luisteren. Gebruik -listen=0 as u dit wilt.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Portemonnee herscannen tijdens initialisatie mislukt</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importeren...</translation>
</message>
@@ -3410,8 +3344,12 @@
<translation>Ongeldig bedrag voor -fallbackfee=&lt;bedrag&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>De transactiegeheugenpool moet onder de &lt;n&gt; megabytes blijven (standaard: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Opgegeven blocks map "%s" bestaat niet.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Upgraden txindex database</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3422,26 +3360,10 @@
<translation>Verbanningslijst aan het laden...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Locatie van de auth cookie (standaard: data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Niet genoeg file descriptors beschikbaar.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Verbind alleen met nodes in netwerk &lt;net&gt; (ipv4, ipv6 of onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Print dit helpbericht en sluit af</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Laat versie zien en sluit af</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Prune kan niet worden geconfigureerd met een negatieve waarde.</translation>
</message>
@@ -3450,14 +3372,6 @@
<translation>Prune-modus is niet compatible met -txindex</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Herbouw ketenstaat en block index met behulp van de blk*.dat bestanden op de hardeschijf</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Herbouw ketenstaat vanuit de huidige geindexeerde blokken</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Blokken opnieuw aan het afspelen...</translation>
</message>
@@ -3466,14 +3380,6 @@
<translation>Blokken aan het terugdraaien...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Zet database cache grootte in megabytes (%d tot %d, standaard: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Specificeer het portemonnee bestand (vanuit de gegevensmap)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>De broncode is beschikbaar van %s.</translation>
</message>
@@ -3486,6 +3392,10 @@
<translation>Niet in staat om %s te verbinden op deze computer. %s draait waarschijnlijk al.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Niet mogelijk sleutels te genereren</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Niet-ondersteund argument -benchmark genegeerd, gebruik -debug=bench.</translation>
</message>
@@ -3506,14 +3416,6 @@
<translation>Upgraden UTXO-database</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Gebruik UPnP om de luisterende poort te mappen (standaard: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Gebruik de test keten</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>User Agentcommentaar (%s) bevat onveilige karakters.</translation>
</message>
@@ -3522,88 +3424,24 @@
<translation>Blokken aan het controleren...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Portomonee debugging/testing opties:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Portemonnee moest herschreven worden: Herstart %s om te voltooien</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Portemonnee instellingen:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Sta JSON-RPC verbindingen toe vanuit een gespecificeerde bron. Geldig voor &lt;ip&gt; zijn een enkel IP (bijv. 1.2.3.4), een netwerk/netmask (bijv. 1.2.3.4/255.255.255.0) of een netwerk/CIDR (bijv. 1.2.3.4/24). Deze optie kan meerdere keren gespecificeerd worden.</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Bind aan opgegeven adres en keur peers die ermee verbinden goed. Gebruik [host]:poort notatie voor IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Creër nieuwe bestanden met standaard systeem bestandsrechten in plaats van umask 077 (alleen effectief met uitgeschakelde portemonnee functionaliteit)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Ontdek eigen IP-adressen (standaard: 1 voor luisteren en geen -externalip of -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Fout: luisteren naar binnenkomende verbindingen mislukt (luisteren gaf foutmelding %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Voer opdracht uit zodra een waarschuwing is ontvangen of wanneer we een erg lange fork detecteren (%s in opdracht wordt vervangen door bericht)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Transactiekosten (in %s/kB) kleiner dan dit worden beschouw dat geen transactiekosten in rekening worden gebracht voor doorgeven, mijnen en transactiecreatie (standaard: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Als paytxfee niet is ingesteld, voeg voldoende transactiekosten toe zodat transacties starten met bevestigingen binnen in n blokken (standaard: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
- <translation>ongeldig bedrag voor -maxtxfee=&lt;bedrag&gt;: '%s' (moet ten minste de minimale doorgeeftransactiekosten van %s het voorkomen geplakt transacties voorkomen)</translation>
- </message>
- <message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maximale grootte va n de gegevens in gegevensdragertransacties die we doorgeven en mijnen (standaard: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Gebruik willekeurige inloggegevens voor elke proxyverbinding. Dit maakt streamislatie voor Tor mogelijk (standaard: %u)</translation>
+ <translation>ongeldig bedrag voor -maxtxfee=&lt;bedrag&gt;: '%s' (moet ten minste de minimale doorgeefvergoeding van %s zijn om vastgelopen transacties te voorkomen)</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>Het transactiebedrag is te klein om te versturen nadat de transactiekosten in mindering zijn gebracht</translation>
- </message>
- <message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Goedgekeurde peers kunnen niet ge-DoS-banned worden en hun transacties worden altijd doorgegeven, zelfs als ze reeds in de mempool aanwezig zijn, nuttig voor bijv. een gateway</translation>
+ <translation>Het transactiebedrag is te klein om te versturen nadat de transactievergoeding in mindering is gebracht</translation>
</message>
<message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
- <translation>U moet de database herbouwen met -reindex om terug te gaan naar de niet-prune modus. Dit zal de gehele blockchain opnieuw downloaden.</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(standaard: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Accepteer publieke REST-verzoeken (standaard: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Creëer automatisch verborgen dienst van Tor (standaard:%d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Verbind door SOCKS5 proxy</translation>
+ <translation>U moet de database herbouwen met -reindex om terug te gaan naar de niet-prune modus. Dit zal de gehele blokketen opnieuw downloaden.</translation>
</message>
<message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
@@ -3618,10 +3456,6 @@
<translation>Fout bij het upgraden van de ketenstaat database</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importeer blokken van externe blk000??.dat-bestand bij opstarten</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informatie</translation>
</message>
@@ -3642,44 +3476,28 @@
<translation>Ongeldig netmask gespecificeerd in -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Houd maximaal &lt;n&gt; onverbonden transacties in geheugen (standaard: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Verplicht een poort met -whitebind op te geven: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Nodedoorgeefopties:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC server opties:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Verminder -maxconnections van %d naar %d, vanwege systeembeperkingen.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Herscan de blokketen voor missende portemonneetransacties bij opstarten</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Verzend trace/debug-info naar de console in plaats van het debug.log-bestand</translation>
+ <source>Signing transaction failed</source>
+ <translation>Ondertekenen van transactie mislukt</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Toon alle foutopsporingsopties (gebruik: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Opgegeven -walletdir "%s" bestaat niet</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Verklein debug.log-bestand bij het opstarten van de client (standaard: 1 als geen -debug)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Opgegeven -walletdir "%s" is een relatief pad</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>Ondertekenen van transactie mislukt</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Opgegeven -walletdir "%s" is geen map</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3690,14 +3508,6 @@
<translation>Dit is experimentele software.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor bepaalt poortwachtwoord (standaard: empty)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Tor bepaalt welke poort te gebruiken als luisteren naar onion wordt gebruikt (standaard: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Transactiebedrag te klein</translation>
</message>
@@ -3718,14 +3528,6 @@
<translation>Niet mogelijk initiële sleutels te genereren</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Upgrade portemonee naar laatste formaat bij opstarten</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Gebruikersnaam voor JSON-RPC-verbindingen</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>Portomenee(n) aan het verifiëren...</translation>
</message>
@@ -3742,96 +3544,20 @@
<translation>Waarschuwing: onbekende nieuwe regels geactiveerd (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Om in alleen een blokmodus te opereren (standaard: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>De database moet opnieuw opgebouwd worden met behulp van -reindex om -txindex te veranderen</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Bezig met het zappen van alle transacties van de portemonnee...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ notificatieopties:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Wachtwoord voor JSON-RPC-verbindingen</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Voer opdracht uit zodra het beste blok verandert (%s in cmd wordt vervangen door blokhash)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Sta DNS-naslag toe voor -addnode, -seednode en -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = behoudt tx meta data bijv. account eigenaar en betalingsverzoek informatie, 2. sla tx meta data niet op)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation>-maxtxfee staat zeer hoog! Transactiekosten van de grootte kunnen worden gebruikt in een enkele transactie.</translation>
- </message>
- <message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Bind aan gegeven adres om te luisteren voorJSON-RPC verbindingen. Deze optie zal genegeerd worden tenzij -rpcallowip ook aangegeven word. Port is optioneel en overschrijft -rpcport. Gebruik [host]:poort notatie voor IPv6. Deze optie van meerdere keren gebruikt worden (standaard: 127.0.0.1 en ::1 i.e., localhost, of als -rpcallowip gespecificeerd is, 0.0.0.0 en :: i.e., alle adressen)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Bewaar transactie niet langer dan &lt;n&gt; uren in de geheugenpool (standaard: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Equivalent byter per sigop in transactions voor doorsturen en mijnen (standaard: %u)</translation>
+ <translation>-maxtxfee staat zeer hoog! Transactiekosten van deze grootte kunnen worden gebruikt in een enkele transactie.</translation>
</message>
<message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Fout bij het laden van %s: Je kan HD niet activeren voor een reeds bestaande niet-HD-portemonnee</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Fout laden portemonnee %s. -wallet parameter mag alleen een bestandsnaam zijn (geen pad).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Transactiekosten (in %s/kB) kleiner dan dit worden beschouwd dat geen transactiekosten in rekening worden gebracht voor transactiecreatie (standaard: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Forceer het doorsturen van transacties van goedgekeurde peers, zelfs wanneer deze niet voldoen aan de lokale doorstuurregels (standaard: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Hoe grondig de blokverificatie van -checkblocks is (0-4, standaard: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Onderhoud een volledige transactieindex, gebruikt door de getrawtransaction rpc call (standaard: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Aantal seconden dat zich misdragende peers niet opnieuw kunnen verbinden (standaard: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Output extra debugginginformatie (standaard: %u, het leveren van &lt;categorie&gt; is optioneel)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Ondersteun filtering van blokken en transacties met bloomfilters (standaard: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Het kosten tarief (in %s/kB) dat de toelating van afdanken van wisselgeld aangeeft door het toevoegen aan de kosten (standaard: %s). Notitie: Een output zal afgedankt worden als het dust is in dit tarief, maar we zullen altijd afdanken tot aan de stof doorstuur kosten en een afdank tarief boven wat is gelimiteerd door de kosten inschatting voor het langste doel</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>Dit is de transactiekost die je mogelijk betaald indien geschatte tarief niet beschikbaar is</translation>
+ <translation>Dit is de transactievergoeding die je mogelijk betaalt indien geschatte tarief niet beschikbaar is</translation>
</message>
<message>
<source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
@@ -3842,10 +3568,6 @@
<translation>Totale lengte van netwerkversiestring (%i) overschrijdt maximale lengte (%i). Verminder het aantal of grootte van uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Pogingen om uitgaand verkeer onder een bepaald doel te houden (in MiB per 24u), 0 = geen limiet (standaard: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Niet-ondersteund argument -socks gevonden. Instellen van SOCKS-versie is niet meer mogelijk, alleen SOCKS5-proxies worden ondersteund.</translation>
</message>
@@ -3854,140 +3576,40 @@
<translation>Niet ondersteund argument -whitelistalwaysrelay genegeerd, gebruik -whitelistrelay en/of -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Gebruik een aparte SOCKS5 proxy om verborgen diensten van Tor te bereiken (standaard: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Waarschuwing: Onbekende blok versies worden gemined! Er zijn mogelijk onbekende regels in werking getreden</translation>
</message>
<message>
<source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Waarschuwing: portomonee bestand is corrupt, data is veiliggesteld! Originele %s is opgeslagen als %s in %s; als uw balans of transacties incorrect zijn dient u een backup terug te zetten.</translation>
- </message>
- <message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Goedgekeurde peers die verbinden vanaf een bepaald IP adres (vb. 1.2.3.4) of CIDR genoteerd netwerk (vb. 1.2.3.0/24). Kan meerdere keren worden gespecificeerd.</translation>
+ <translation>Waarschuwing: portemonnee bestand is corrupt, data is veiliggesteld! Originele %s is opgeslagen als %s in %s; als uw balans of transacties incorrect zijn dient u een backup terug te zetten.</translation>
</message>
<message>
<source>%s is set very high!</source>
<translation>%s is zeer hoog ingesteld!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(standaard: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Vind anderen door middel van een DNS-naslag (standaard: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Fout bij laden van portemonnee %s. -wallet bestandsnaam met een regulier bestand zijn.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Fout bij laden van portemonnee %s. Duplicaat -wallet bestandsnaam opgegeven.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Fout bij laden van portemonnee %s. Ongeldige tekens in -wallet bestandsnaam.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Aantal te checken blokken bij het opstarten (standaard: %u, 0 = allemaal)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>IP-adressen toevoegen in de debuguitvoer (standaard: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Keypool op geraakt, roep alsjeblieft eerst keypoolrefill functie aan</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Luister naar JSON-RPC-verbindingen op &lt;poort&gt; (standaard: %u of testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Luister naar verbindingen op &lt;poort&gt; (standaard: %u of testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Onderhoud maximaal &lt;n&gt; verbindingen naar peers (standaard: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Laat de portemonnee transacties uitsturen</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximum per-connectie ontvangstbuffer, &lt;n&gt;*1000 bytes (standaard: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximum per-connectie verstuurbuffer, &lt;n&gt;*1000 bytes (standaard: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Prepend debug output met tijdstempel (standaard: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Geef gegevensdragertransacties door en mijn ze ook (standaard: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Geef non-P2SH multisig door (standaard: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Stel sleutelpoelgrootte in op &lt;n&gt; (standaard: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Zet het BIP141 maximum gewicht van een blok (standaard: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Stel het aantal threads in om RPC-aanvragen mee te bedienen (standaard: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Specificeer configuratiebestand (standaard: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Specificeer de time-out tijd in milliseconden (minimum: 1, standaard: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Specificeer pid-bestand (standaard: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Besteed onbevestigd wisselgeld bij het doen van transacties (standaard: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Netwerkthread starten...</translation>
</message>
<message>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>De portemonnee vermijdt minder te betalen dan het minimale relay vergoeding.</translation>
+ <translation>De portemonnee vermijdt minder te betalen dan de minimale doorgeef vergoeding.</translation>
</message>
<message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Dit is het minimum transactietarief dat je betaald op elke transactie.</translation>
+ <translation>Dit is de minimum transactievergoeding dat je betaalt op elke transactie.</translation>
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Dit is het transactietarief dat je betaald wanneer je een transactie verstuurt.</translation>
- </message>
- <message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Drempel om verbinding te verbreken naar zich misdragende peers (standaard: %u)</translation>
+ <translation>Dit is de transactievergoeding dat je betaalt wanneer je een transactie verstuurt.</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
@@ -4010,6 +3632,26 @@
<translation>Ontoereikend saldo</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Kan geen sleutel genereren voor een wisselgeldadres. Geheime sleutels zijn uitgeschakeld voor deze portemonnee.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Het is niet mogelijk een non HD split portemonnee te upgraden zonder pre split keypool te ondersteunen. Gebruik -upgradewallet=169900 of -upgradewallet zonder een specifiek versie nummer.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Het inschatten van de vergoeding is gefaald. Fallbackfee is uitgeschakeld. Wacht een aantal blocks of schakel -fallbackfee in.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Waarschuwing: Geheime sleutels gedetecteerd in portemonnee {%s} met uitgeschakelde geheime sleutels</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Mag niet schrijven naar gegevensmap '%s'; controleer bestandsrechten.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Blokindex aan het laden...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts
index b1edaff68d..16c48dad93 100644
--- a/src/qt/locale/bitcoin_pam.ts
+++ b/src/qt/locale/bitcoin_pam.ts
@@ -30,6 +30,10 @@
<translation>Ilako ya ing kasalungsungan makapiling address keng listahan</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Magpalub kang address o label para pantunan</translation>
+ </message>
+ <message>
<source>&amp;Delete</source>
<translation>&amp;Ilako</translation>
</message>
@@ -273,15 +277,7 @@
<source>Command-line options</source>
<translation>Pipamilian command-line</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Pamanggamit:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>pipamilian command-line</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -536,6 +532,10 @@
<source>Copy &amp;Address</source>
<translation>&amp;Kopyan ing address</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Wallet</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -582,6 +582,10 @@
<source>S&amp;end</source>
<translation>Ipadala</translation>
</message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Bayad king Transaksion</translation>
+ </message>
</context>
<context>
<name>SendCoinsEntry</name>
@@ -732,42 +736,10 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Pipamilian:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Pilinan ing data directory</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Kumunekta king note ban ayakua mula reng peer address, at mako king panga konekta</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Sabyan me ing kekang pampublikong address</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Tumanggap command line at JSON-RPC commands</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Gumana king gulut bilang daemon at tumanggap commands</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Kapilubluban ning Bitcoin</translation>
</message>
<message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Tumanggap koneksion menibat king kilwal (default: 1 if no -proxy or -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Pipamilian king pamag-gawang block:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>Mekapansin lang me-corrupt a block database</translation>
</message>
@@ -796,34 +768,14 @@
<translation>&amp;Impormasion</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Magpadalang trace/debug info okeng console kesa keng debug.log file</translation>
- </message>
- <message>
<source>Transaction too large</source>
<translation>Maragul yang masiadu ing transaksion</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Username para king JSON-RPC koneksion</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Kapabaluan</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Password para king JSON-RPC koneksion</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>I-execute ing command istung mialilan ya ing best block (%s in cmd is replaced by block hash)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Payagan ing pamaglawe DNS para king -addnode, -seednode and -connect</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>E kilalang network ing mepili king -onlynet: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts
index 90de9167c8..03474f4df5 100644
--- a/src/qt/locale/bitcoin_pl.ts
+++ b/src/qt/locale/bitcoin_pl.ts
@@ -30,6 +30,10 @@
<translation>Usuń zaznaczony adres z listy</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Wprowadź adres albo etykietę aby wyszukać</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Eksportuj dane z aktywnej karty do pliku</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Powtórz nowe hasło</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Pokaż hasło</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Wprowadź nowe hasło do portfela.&lt;br/&gt;Proszę używać hasła złożonego z &lt;b&gt;10 lub więcej losowych znaków&lt;/b&gt; albo &lt;b&gt;8 lub więcej słów.&lt;/b&gt;</translation>
</message>
@@ -318,6 +326,14 @@
<translation>Otwórz URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Portfel:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>domyślny portfel</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Kliknij aby wyłączyć aktywność sieciową.</translation>
</message>
@@ -338,6 +354,10 @@
<translation>Ponowne indeksowanie bloków na dysku...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy jest &lt;b&gt;włączone&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Wyślij monety na adres bitcoinowy</translation>
</message>
@@ -506,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Portfel: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Typ: %1
@@ -726,10 +752,6 @@
<translation>&amp;Adres</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nowy adres odbiorczy</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nowy adres wysyłania</translation>
</message>
@@ -746,8 +768,12 @@
<translation>Wprowadzony adres "%1" nie jest prawidłowym adresem Bitcoin.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Wprowadzony adres "%1" znajduje się już w książce adresowej.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adres "%1" już istnieje jako adres odbiorczy z etykietą "%2" i dlatego nie można go dodać jako adresu nadawcy.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Wprowadzony adres "%1" już istnieje w książce adresowej z opisem "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -799,42 +825,6 @@
<source>Command-line options</source>
<translation>Opcje konsoli</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Użycie:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opcje konsoli</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opcje interfejsu</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Katalog danych używany podczas uruchamiania programu (domyślny: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Wybierz język, na przykład «de_DE» (domyślnie: język systemowy)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Uruchom zminimalizowany</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Ustaw certyfikaty główne SSL dla żądań płatności (domyślnie: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Wyświetl okno powitalne podczas uruchamiania (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Zresetuj wszystkie ustawienia zmienione w GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1020,6 +1010,18 @@
<translation>Pakazuje czy dostarczone domyślne SOCKS5 proxy jest użyte do połączenia z węzłami przez sieć tego typu.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Użyj oddzielnego proxy SOCKS&amp;5 aby osiągnąć węzły w ukrytych usługach Tor:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Ukryj ikonę z zasobnika systemowego.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Ukryj ikonę z zasobnika</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Minimalizuje zamiast zakończyć działanie programu przy zamykaniu okna. Kiedy ta opcja jest włączona, program zakończy działanie po wybieraniu Zamknij w menu.</translation>
</message>
@@ -1052,6 +1054,22 @@
<translation>&amp;Sieć</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Wyłącza niektóre zaawansowane funkcje, ale wszystkie bloki nadal będą w pełni sprawdzane. Przywrócenie tego ustawienia wymaga ponownego pobrania całego łańcucha bloków. Rzeczywiste wykorzystanie dysku może być nieco wyższe.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Przytnij magazyn &amp;bloków do</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Cofnięcie tego ustawienia wymaga ponownego załadowania całego łańcucha bloków.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = automatycznie, &lt;0 = zostaw tyle wolnych rdzeni)</translation>
</message>
@@ -1084,6 +1102,14 @@
<translation>Mapuj port używając &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Akceptuj połączenia z zewnątrz.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Zezwól na &amp;połączenia przychodzące</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Połącz się z siecią Bitcoin poprzez proxy SOCKS5.</translation>
</message>
@@ -1164,6 +1190,10 @@
<translation>Wybierz pokazywanie lub nie funkcji kontroli monet.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;Zewnętrzny URL podglądu transakcji</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1306,6 +1336,10 @@
<translation>Obsługa URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' nie jest poprawnym URI. Użyj 'bitcoin:'.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>URL pobrania żądania zapłaty jest nieprawidłowy: %1</translation>
</message>
@@ -1503,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Błąd podczas analizowania argumentów wiersza poleceń: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Błąd: Określony folder danych "%1" nie istnieje.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Błąd: Nie można przetworzyć pliku konfiguracyjnego: %1. Używaj tylko składni klucz=wartość.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Błąd: nie można przeanalizować pliku konfiguracyjnego: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1601,6 +1639,14 @@
<translation>Zużycie pamięci</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Portfel:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(brak)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Reset</translation>
</message>
@@ -1769,6 +1815,10 @@
<translation>&amp;Odblokuj</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>domyślny portfel</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Witaj w konsoli %1 RPC.</translation>
</message>
@@ -1777,6 +1827,14 @@
<translation>Użyj strzałek do przewijania historii i %1 aby wyczyścić ekran</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Wpisz %1 aby uzyskać listę dostępnych komend.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Aby uzyskać więcej informacji jak używać tej konsoli wpisz %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>UWAGA: Oszuści nakłaniają do wpisywania tutaj różnych poleceń aby ukraść portfel. Nie używaj tej konsoli bez pełnego zrozumienia wpisywanych poleceń.</translation>
</message>
@@ -1785,6 +1843,14 @@
<translation>Aktywność sieciowa wyłączona</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Wykonuję komendę bez portfela</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Wykonuję komendę używając portfela "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(id węzła: %1)</translation>
</message>
@@ -1856,6 +1922,14 @@
<translation>Wyczyść</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Natywne adresy segwit (aka Bech32 lub BIP-173) zmniejszają później twoje opłaty transakcyjne i dają lepsze zabezpieczenie przed literówkami, ale stare portfele ich nie obsługują. Jeżeli odznaczone, stworzony zostanie adres kompatybilny ze starszymi portfelami.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Wygeneruj natywny adres segwit (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Żądanie historii płatności</translation>
</message>
@@ -1943,6 +2017,10 @@
<translation>Wiadomość</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Portfel</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Wynikowy URI jest zbyt długi, spróbuj zmniejszyć tekst etykiety / wiadomości</translation>
</message>
@@ -2045,6 +2123,11 @@
<translation>Wybierz...</translation>
</message>
<message>
+ <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
+ <translation>206/5000
+Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która potwierdzi się w kilka godzin lub dni (lub nigdy). Rozważ wybranie opłaty ręcznie lub poczekaj, aż sprawdzisz poprawność całego łańcucha.</translation>
+ </message>
+ <message>
<source>Warning: Fee estimation is currently not possible.</source>
<translation>Uwaga: Oszacowanie opłaty za transakcje jest aktualnie niemożliwe.</translation>
</message>
@@ -2053,12 +2136,16 @@
<translation>zwiń opcje opłaty</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>za kilobajt</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Określ niestandardową opłatę za kB (1000 bajtów) wirtualnego rozmiaru transakcji.
+
+Uwaga: Ponieważ opłata jest naliczana za każdy bajt, opłata "100 satoshi za kB" w przypadku transakcji o wielkości 500 bajtów (połowa 1 kB) ostatecznie da opłatę w wysokości tylko 50 satoshi.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Jeżeli własna opłata zostanie ustawiona na 1000 satoshi, a transakcja będzie miała tylko 250 bajtów, to "za kilobajt" płaci tylko 250 satoshi, podczas gdy, "razem przynajmniej" płaci 1000 satoshi. Przy transakcjach większych niż kilobajt, w obu przypadkach płaci za każdy kilobajt.</translation>
+ <source>per kilobyte</source>
+ <translation>za kilobajt</translation>
</message>
<message>
<source>Hide</source>
@@ -2105,6 +2192,14 @@
<translation>Docelowy czas potwierdzenia:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Włącz RBF (podmiana transakcji przez podniesienie opłaty)</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Dzięki podmień-przez-opłatę (RBF, BIP-125) możesz podnieść opłatę transakcyjną już wysłanej transakcji. Bez tego, może być rekomendowana większa opłata aby zmniejszyć ryzyko opóźnienia zatwierdzenia transakcji.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Wyczyść &amp;wszystko</translation>
</message>
@@ -2161,16 +2256,32 @@
<translation>Czy na pewno chcesz wysłać?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>dodano jako opłata transakcyjna</translation>
+ <source>or</source>
+ <translation>lub</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Łączna kwota %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Możesz później zwiększyć opłatę (sygnalizuje podmień-przez-opłatę (RBF), BIP 125).</translation>
</message>
<message>
- <source>or</source>
- <translation>lub</translation>
+ <source>from wallet %1</source>
+ <translation>z portfela %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Proszę, zweryfikuj swoją transakcję.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Opłata transakcyjna</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Nie sygnalizuje podmień-przez-opłatę (RBF), BIP-125</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Łączna wartość</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2216,6 +2327,10 @@
<source>Pay only the required fee of %1</source>
<translation>Zapłać tylko wymaganą opłatę w wysokości %1</translation>
</message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>Przybliżony czas rozpoczęcia zatwierdzenia: %n blok.</numerusform><numerusform>Przybliżony czas rozpoczęcia zatwierdzenia: %n bloki.</numerusform><numerusform>Przybliżony czas rozpoczęcia zatwierdzenia: %n bloków.</numerusform><numerusform>Przybliżony czas rozpoczęcia zatwierdzenia: %n bloków.</numerusform></translation>
+ </message>
<message>
<source>Warning: Invalid Bitcoin address</source>
<translation>Ostrzeżenie: nieprawidłowy adres Bitcoin</translation>
@@ -2229,6 +2344,10 @@
<translation>Potwierdź zmianę adresu własnego</translation>
</message>
<message>
+ <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
+ <translation>Wybrany adres reszty nie jest częścią tego portfela. Dowolne lub wszystkie środki w twoim portfelu mogą być wysyłane na ten adres. Jesteś pewny?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(brak etykiety)</translation>
</message>
@@ -2284,6 +2403,10 @@
<translation>Odejmij od wysokości opłaty</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>Użyj dostępnego salda</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Wiadomość:</translation>
</message>
@@ -2503,10 +2626,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>sprzeczny z transakcją posiadającą %1 potwierdzeń</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/niezatwierdzone, %1</translation>
</message>
@@ -2535,14 +2654,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, nie został jeszcze pomyślnie rozesłany</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, przekazywany przez %n węzeł</numerusform><numerusform>, przekazywany przez %n węzły</numerusform><numerusform>, przekazywany przez %n węzłów</numerusform><numerusform>, przekazywany przez %n węzłów</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2582,6 +2693,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<source>Credit</source>
<translation>Uznanie</translation>
</message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>dojrzeje po %n kolejnym bloku</numerusform><numerusform>dojrzeje po %n kolejnych blokach</numerusform><numerusform>dojrzeje po %n kolejnych blokach</numerusform><numerusform>dojrzeje po %n kolejnych blokach</numerusform></translation>
+ </message>
<message>
<source>not accepted</source>
<translation>niezaakceptowane</translation>
@@ -2591,6 +2706,14 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Debet</translation>
</message>
<message>
+ <source>Total debit</source>
+ <translation>Łączne obciążenie</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Łączne uznanie</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Opłata transakcyjna</translation>
</message>
@@ -2615,6 +2738,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Rozmiar transakcji</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Wirtualny rozmiar transakcji</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Indeks wyjściowy</translation>
</message>
@@ -2623,6 +2750,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Kupiec</translation>
</message>
<message>
+ <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation>Wygenerowane monety muszą dojrzeć przez %1 bloków zanim będzie można je wydać. Gdy wygenerowałeś blok, został on rozgłoszony w sieci w celu dodania do łańcucha bloków. Jeżeli nie uda mu się wejść do łańcucha jego status zostanie zmieniony na "nie zaakceptowano" i nie będzie można go wydać. To czasem zdarza się gdy inny węzeł wygeneruje blok w kilka sekund od twojego.</translation>
+ </message>
+ <message>
<source>Debug information</source>
<translation>Informacje debugowania</translation>
</message>
@@ -2681,10 +2812,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Otwórz do %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Niepotwierdzone</translation>
</message>
@@ -2709,10 +2836,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Niedojrzała (%1 potwierdzeń, będzie dostępna po %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Ten blok nie został odebrany przez jakikolwiek inny węzeł i prawdopodobnie nie zostanie zaakceptowany!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Wygenerowane ale nie zaakceptowane</translation>
</message>
@@ -2760,7 +2883,19 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<source>Type of transaction.</source>
<translation>Rodzaj transakcji.</translation>
</message>
- </context>
+ <message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>Czy adres tylko-obserwowany jest lub nie użyty w tej transakcji.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>Zdefiniowana przez użytkownika intencja/cel transakcji.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Kwota odjęta z lub dodana do konta.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
@@ -2812,6 +2947,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Inne</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Wprowadź adres, identyfikator transakcji lub etykietę żeby wyszukać</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Minimalna kwota</translation>
</message>
@@ -2868,6 +3007,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Potwierdzony</translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation>Tylko-obserwowany</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2957,6 +3100,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Nowa opłata:</translation>
</message>
<message>
+ <source>Confirm fee bump</source>
+ <translation>Potwierdź zwiększenie opłaty</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Nie można podpisać transakcji.</translation>
</message>
@@ -2999,38 +3146,18 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<source>The wallet data was successfully saved to %1.</source>
<translation>Dane portfela zostały poprawnie zapisane w %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Anuluj</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opcje:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Wskaż folder danych</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Podłącz się do węzła aby otrzymać adresy peerów i rozłącz</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Podaj swój publiczny adres</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Akceptuj linię poleceń oraz polecenia JSON-RPC</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Rozprowadzane na licencji MIT, zobacz dołączony plik %s lub %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Jeżeli &lt;category&gt; nie zostanie określona lub &lt;category&gt; = 1, wyświetl wszystkie informacje debugowania.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Przycinanie skonfigurowano poniżej minimalnych %d MiB. Proszę użyć wyższej liczby.</translation>
</message>
@@ -3047,18 +3174,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Błąd: Wystąpił fatalny błąd wewnętrzny, sprawdź szczegóły w debug.log</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Prowizja (w %s/kB) dodawana do wysyłanych transakcji (domyślnie: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Przycinanie zapisu bloków...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Uruchom w tle jako daemon i przyjmuj polecenia</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Uruchomienie serwera HTTP nie powiodło się. Zobacz dziennik debugowania, aby uzyskać więcej szczegółów.</translation>
</message>
@@ -3071,94 +3190,74 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Deweloperzy %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Stawka prowizji (w %s/kB), która będzie użyta, gdy oszacowane dane o prowizjach nie będą wystarczające (domyślnie: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Skojarz z podanym adresem i nasłuchuj na nim. Użyj formatu [host]:port dla IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Nie można uzyskać blokady na katalogu z danymi %s. %s najprawdopodobniej jest już uruchomiony.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Usuwa wszystkie transakcje w portfelu i tylko odtwarza te części z łańcucha bloków poprzez -rescan przy starcie</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Nie można podać określonych połączeń i jednocześnie mieć addrman szukającego połączeń wychodzących.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Błąd odczytu %s! Wszystkie klucze zostały odczytane poprawnie, ale może brakować danych transakcji lub wpisów w książce adresowej, lub mogą one być nieprawidłowe.</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Wykonaj polecenie, kiedy transakcja portfela ulegnie zmianie (%s w poleceniu zostanie zastąpione przez TxID)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>Proszę sprawdzić czy data i czas na Twoim komputerze są poprawne! Jeżeli ustawienia zegara będą złe, %s nie będzie działał prawidłowo.</translation>
</message>
<message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Ustaw liczbę wątków skryptu weryfikacyjnego (%u do %d, 0 = auto, &lt;0 = zostaw tyle rdzeni wolnych, domyślnie: %d)</translation>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Wspomóż proszę, jeśli uznasz %s za użyteczne. Odwiedź %s, aby uzyskać więcej informacji o tym oprogramowaniu.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Użyj UPnP do mapowania portu nasłuchu (domyślnie: 1 gdy nasłuchuje i brak -proxy)</translation>
+ <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
+ <translation>Baza bloków zawiera blok, który wydaje się pochodzić z przyszłości. Może to wynikać z nieprawidłowego ustawienia daty i godziny Twojego komputera. Bazę danych bloków dobuduj tylko, jeśli masz pewność, że data i godzina twojego komputera są poprawne</translation>
</message>
<message>
- <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>Ostrzeżenie: Sieć nie wydaje się w pełni zgodna! Niektórzy górnicy wydają się doświadczać problemów.</translation>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation>To jest wersja testowa - używać na własne ryzyko - nie używać do kopania albo zastosowań komercyjnych.</translation>
</message>
<message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s uszkodzony, odtworzenie się nie powiodło</translation>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>To jest opłata transakcyjna jaką odrzucisz, jeżeli reszta jest mniejsza niż "dust" na tym poziomie</translation>
</message>
<message>
- <source>-maxmempool must be at least %d MB</source>
- <translation>-maxmempool musi być przynajmniej %d MB</translation>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>Nie można przetworzyć bloków. Konieczne będzie przebudowanie bazy danych za pomocą -reindex-chainstate.</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; mogą być:</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Nie można cofnąć bazy danych do stanu z przed forka. Konieczne jest ponowne pobranie łańcucha bloków</translation>
</message>
<message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Akceptuj połączenia z zewnątrz (domyślnie: 1 jeśli nie ustawiono -proxy lub -connect)</translation>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Ostrzeżenie: Sieć nie wydaje się w pełni zgodna! Niektórzy górnicy wydają się doświadczać problemów.</translation>
</message>
<message>
- <source>Append comment to the user agent string</source>
- <translation>Dodaj komentarz do pola user agent</translation>
+ <source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
+ <translation>Uwaga: Wygląda na to, że nie ma pełnej zgodności z naszymi węzłami! Możliwe, że potrzebujesz aktualizacji bądź inne węzły jej potrzebują</translation>
</message>
<message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Próbuj odzyskać klucze prywatne z uszkodzonego portfela podczas uruchamiania.</translation>
+ <source>%d of last 100 blocks have unexpected version</source>
+ <translation>%d z ostatnich 100 bloków ma nieoczekiwaną wersję</translation>
</message>
<message>
- <source>Block creation options:</source>
- <translation>Opcje tworzenia bloku:</translation>
+ <source>%s corrupt, salvage failed</source>
+ <translation>%s uszkodzony, odtworzenie się nie powiodło</translation>
</message>
<message>
- <source>Cannot resolve -%s address: '%s'</source>
- <translation>Nie można rozpoznać -%s adresu: '%s'</translation>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation>-maxmempool musi być przynajmniej %d MB</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Opcje zmiany łańcucha.</translation>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>Nie można rozpoznać -%s adresu: '%s'</translation>
</message>
<message>
<source>Change index out of range</source>
<translation>Index zmian poza zasięgiem.</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Opcje połączenia:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Prawa autorskie (C) %i-%i</translation>
</message>
@@ -3167,32 +3266,12 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Wykryto uszkodzoną bazę bloków</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opcje debugowania/testowania:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Nie ładuj portfela i wyłącz wywołania RPC portfela</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Czy chcesz teraz przebudować bazę bloków?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Włącz wyświetlanie hasha bloku w &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Umożliw publikacje tranzakcji haszowej w &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Włącz wyświetlanie hasha bloku w &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Umożliw publikację transakcji haszowej w &lt;address&gt;</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Błąd podczas tworzenia %s: nie można założyć portfela nie-HD tą wersją.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3207,6 +3286,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Błąd ładowania %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Błąd ładowania %s: Klucze prywatne mogą być wyłączone tylko podczas tworzenia</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Błąd ładowania %s: Uszkodzony portfel</translation>
</message>
@@ -3231,6 +3314,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Próba nasłuchiwania na jakimkolwiek porcie nie powiodła się. Użyj -listen=0 jeśli tego chcesz.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Nie udało się ponownie przeskanować portfela podczas inicjalizacji.</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importowanie…</translation>
</message>
@@ -3255,8 +3342,13 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Nieprawidłowa kwota dla -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Utrzymuj obszar pamięci dla transakcji poniżej &lt;n&gt; MB (default: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Podany folder bloków "%s" nie istnieje.
+</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Aktualizowanie bazy txindex</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3267,26 +3359,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Ładowanie listy zablokowanych...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Lokalizacja autoryzacyjnego pliku cookie (domyślnie: ścieżka danych)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Brak wystarczającej liczby deskryptorów plików. </translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Łącz z węzłami tylko w sieci &lt;net&gt; (ipv4, piv6 lub onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Wyświetl ten tekst pomocy i wyjdź</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Wyświetl wersję i wyjdź</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Przycinanie nie może być skonfigurowane z negatywną wartością.</translation>
</message>
@@ -3295,14 +3371,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Tryb ograniczony jest niekompatybilny z -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Odbuduj stan lańcucha i indeks bloków z obecnych na dysku plików blk*.dat</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Odbuduj stan łańcucha z aktualnie zindeksowanych bloków</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Weryfikacja bloków...</translation>
</message>
@@ -3311,14 +3379,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Przewijanie bloków...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Ustaw wielkość pamięci podręcznej w megabajtach (%d do %d, domyślnie: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Określ plik portfela (w obrębie folderu danych)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Kod źródłowy dostępny jest z %s.</translation>
</message>
@@ -3331,6 +3391,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Nie można przywiązać do %s na tym komputerze. %s prawdopodobnie jest już uruchomiony.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Nie można wygenerować kluczy</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Niewspierany argument -benchmark zignorowany, użyj -debug=bench.</translation>
</message>
@@ -3347,12 +3411,8 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Nieobsługiwana kategoria rejestrowania %s=%s.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Użyj UPnP do przekazania portu nasłuchu (domyślnie : %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Użyj łańcucha testowego</translation>
+ <source>Upgrading UTXO database</source>
+ <translation>Aktualizowanie bazy danych UTXO</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -3363,80 +3423,28 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Weryfikacja bloków...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opcje debugowania/testowania portfela:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Portfel wymaga przepisania: zrestartuj %s aby ukończyć</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Opcje portfela:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Pozwól na połączenia JSON-RPC z podanego źródła. Jako &lt;ip&gt; prawidłowe jest pojedyncze IP (np. 1.2.3.4), podsieć/maska (np. 1.2.3.4/255.255.255.0) lub sieć/CIDR (np. 1.2.3.4/24). Opcja ta może być użyta wiele razy.</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Podepnij się do podanego adresu i dodawaj do białej listy węzły łączące się z nim. Użyj notacji [host]:port dla IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Twórz nowe pliki z domyślnymi dla systemu uprawnieniami, zamiast umask 077 (skuteczne tylko przy wyłączonej funkcjonalności portfela)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Odkryj własny adres IP (domyślnie: 1 kiedy w trybie nasłuchu i brak -externalip lub -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Błąd: Nasłuchiwanie połączeń przychodzących nie powiodło się (nasłuch zwrócił błąd %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Uruchom polecenie przy otrzymaniu odpowiedniego powiadomienia lub gdy zobaczymy naprawdę długie rozgałęzienie (%s w poleceniu jest podstawiane za komunikat)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Opłaty (w %s/Kb) mniejsze niż ta, będą traktowane jako zerowe przy tworzeniu, przesyłaniu i zatwierdzaniu transakcji (domyślnie: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Jeżeli nie ustawiono paytxfee, dołącz wystarczająca opłatę, aby transakcja mogła zostać zatwierdzona w ciągu średniej ilości n bloków (domyślnie: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Niewłaściwa ilość dla -maxtxfee=&lt;ilość&gt;: '%s' (musi wynosić przynajmniej minimalną wielkość %s aby zapobiec utknięciu transakcji)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maksymalny rozmiar danych w transakcji przekazującej dane które przekazujemy i wydobywamy (domyślnie: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Zbyt niska kwota transakcji do wysłania po odjęciu opłaty</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Węzły z białej listy nie mogą zostać zbanowane za ataki DoS, a ich transakcje będą zawsze przekazywane, nawet jeżeli będą znajdywać się już w pamięci, przydatne np. dla bramek płatniczych</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(domyślnie: %u)</translation>
+ <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
+ <translation>Musisz przebudować bazę używając parametru -reindex aby wrócić do trybu pełnego. To spowoduje ponowne pobranie całego łańcucha bloków</translation>
</message>
<message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Akceptuj publiczne żądania REST (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Stwórz automatycznie ukrytą usługę Tora (domyślnie: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Połącz przez SOCKS5 proxy</translation>
+ <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
+ <translation>Błąd podczas ładowania %s: Nie można wyłączyć HD w już istniejącym portfelu HD</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
@@ -3447,14 +3455,18 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Błąd ładowania bazy bloków</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importuj bloki z zewnętrznego pliku blk000??.dat podczas uruchamiania programu</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informacja</translation>
</message>
<message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Niewłaściwy adres -onion lub nazwa hosta: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Nieprawidłowy adres -proxy lub nazwa hosta: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
<translation>Nieprawidłowa kwota dla -paytxfee=&lt;amount&gt;: '%s' (musi być co najmniej %s)</translation>
</message>
@@ -3463,44 +3475,28 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Nieprawidłowa maska sieci określona w -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Przechowuj w pamięci maksymalnie &lt;n&gt; transakcji nie możliwych do połączenia (domyślnie: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Musisz określić port z -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opcje przekaźnikowe węzła:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opcje serwera RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Zmniejszanie -maxconnections z %d do %d z powodu ograniczeń systemu.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Przeskanuj podczas ładowania programu łańcuch bloków w poszukiwaniu zaginionych transakcji portfela</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Wyślij informację/raport do konsoli zamiast do pliku debug.log.</translation>
+ <source>Signing transaction failed</source>
+ <translation>Podpisywanie transakcji nie powiodło się</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Pokaż wszystkie opcje odpluskwiania (użycie: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Podany -walletdir "%s" nie istnieje</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Zmniejsz plik debug.log przy starcie programu (domyślnie: 1 jeśli nie użyto -debug)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Podany -walletdir "%s" jest ścieżką względną</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>Podpisywanie transakcji nie powiodło się</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Podany -walletdir "%s" nie jest katalogiem</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3511,14 +3507,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>To oprogramowanie eksperymentalne.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Hasło zabezpieczające portu kontrolnego Tora (domyślnie: puste)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Port kontrolny sieci Tor jeśli onion listening jest włączone (domyślnie: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Zbyt niska kwota transakcji </translation>
</message>
@@ -3535,76 +3523,40 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Nie można przywiązać do %s na tym komputerze (bind zwrócił błąd %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Zaktualizuj portfel do najnowszego formatu podczas ładowania programu</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nazwa użytkownika dla połączeń JSON-RPC</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Nie można wygenerować kluczy początkowych</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Weryfikacja portfela...</translation>
</message>
<message>
- <source>Warning</source>
- <translation>Ostrzeżenie</translation>
- </message>
- <message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Usuwam wszystkie transakcje z portfela...</translation>
- </message>
- <message>
- <source>ZeroMQ notification options:</source>
- <translation>Opcje powiadomień ZeroMQ:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Hasło do połączeń JSON-RPC</translation>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Portfel %s znajduje się poza folderem portfeli %s</translation>
</message>
<message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Wykonaj polecenie kiedy najlepszy blok ulegnie zmianie (%s w komendzie zastanie zastąpione przez hash bloku)</translation>
+ <source>Warning</source>
+ <translation>Ostrzeżenie</translation>
</message>
<message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Zezwól -addnode, -seednode i -connect na łączenie się z serwerem DNS</translation>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <translation>Ostrzeżenie: aktywowano nieznane nowe reguły (versionbit %i)</translation>
</message>
<message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = zachowaj wysłane metadane np. właściciel konta i informacje o żądaniach płatności, 2 = porzuć wysłane metadane)</translation>
+ <source>Zapping all transactions from wallet...</source>
+ <translation>Usuwam wszystkie transakcje z portfela...</translation>
</message>
<message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee ma ustawioną badzo dużą wartość! Tak wysokie opłaty mogą być zapłacone w jednej transakcji.</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Nie trzymaj w pamięci transakcji starszych niż &lt;n&gt; godz. (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Opłaty (w %s/Kb) mniejsze niż ta będą traktowane jako bez opłaty przy tworzeniu transakcji (domyślnie: %s)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Jak dokładna jest weryfikacja bloków przy -checkblocks (0-4, domyślnie: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Utrzymuj pełny indeks transakcji, używany przy wywołaniu RPC getrawtransaction (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Czas w sekundach, przez jaki nietrzymające się zasad węzły nie będą mogły ponownie się podłączyć (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Wypuść informacje debugowania (domyślnie: %u, podanie &lt;category&gt; jest opcjonalne)</translation>
+ <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
+ <translation>Błąd podczas ładowania %s: Nie można włączyć HD w już istniejącym portfelu nie-HD</translation>
</message>
<message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Wspieraj filtrowanie bloków i transakcji używając Filtrów Blooma (domyślnie: %u)</translation>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>To jest opłata transakcyjna którą zapłacisz, gdy mechanizmy estymacji opłaty nie są dostępne.</translation>
</message>
<message>
<source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
@@ -3615,10 +3567,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Całkowita długość łańcucha wersji (%i) przekracza maksymalną dopuszczalną długość (%i). Zmniejsz ilość lub rozmiar parametru uacomment.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Próbuje utrzymać ruch wychodzący poniżej zadanego (w MiB na 24h), 0 = bez limitu (domyślnie: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Znaleziono niewspierany argument -socks. Wybieranie wersji SOCKS nie jest już możliwe, wsparcie programu obejmuje tylko proxy SOCKS5</translation>
</message>
@@ -3627,8 +3575,8 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Niewspierany argument -whitelistalwaysrelay zignorowany, użyj -whitelistrelay i/lub -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Użyj oddzielnego prozy SOCKS5 aby osiągnąć węzły w ukrytych usługach Tor (domyślnie: %s)</translation>
+ <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
+ <translation>Ostrzeżenie: wydobywane są nieznane wersje bloków! Możliwe, że obowiązują nieznane reguły.</translation>
</message>
<message>
<source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
@@ -3639,88 +3587,12 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>%s jest ustawione bardzo wysoko!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(domyślnie: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Zawsze wypytuj o adresy węzłów poprzez podejrzenie DNS (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Błąd wczytywania portfela %s. Nieprawidłowe znaki w pliku -wallet</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Ile bloków sprawdzić przy starcie (domyślnie: %u, 0 = wszystkie)</translation>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>Błąd wczytywania portfela %s. Podana powtórnie ta sama nazwa pliku w -wallet</translation>
</message>
<message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Dołącz adresy IP do logowania (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Nasłuchuj połączeń JSON-RPC na &lt;port&gt; (domyślnie: %u lub testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Nasłuchuj połączeń na &lt;port&gt; (domyślnie: %u lub testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Utrzymuj maksymalnie &lt;n&gt; połączeń z węzłami (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Spraw by portfel dokonał transmisji transakcji</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maksymalny bufor odbioru na połączenie, &lt;n&gt;*1000 bajtów (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maksymalny bufor wysyłania na połączenie, &lt;n&gt;*1000 bajtów (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Dołączaj znacznik czasu do logowania (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Przekazuj i wydobywaj transakcje zawierające dane (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Przekazuj transakcje multisig inne niż P2SH (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Ustaw rozmiar puli kluczy na &lt;n&gt; (domyślnie: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>ustawienie maksymalnego rozmiaru bloku BIP141 (domyślnie: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Ustaw liczbę wątków do obsługi RPC (domyślnie: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Wskaż plik konfiguracyjny (domyślnie: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Wskaż czas oczekiwania na połączenie w milisekundach (minimum: 1, domyślnie: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Wskaż plik pid (domyślnie: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Wydawaj niepotwierdzoną resztę podczas wysyłania transakcji (domyślnie: %u)</translation>
+ <source>Keypool ran out, please call keypoolrefill first</source>
+ <translation>Pula kluczy jest pusta, odwołaj się do puli kluczy.</translation>
</message>
<message>
<source>Starting network threads...</source>
@@ -3739,10 +3611,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>To jest opłata transakcyjna którą zapłacisz jeśli wyślesz transakcję. </translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Próg, po którym nastąpi rozłączenie węzłów nietrzymających się zasad (domyślnie: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Kwota transakcji musi być dodatnia</translation>
</message>
@@ -3763,6 +3631,26 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Niewystarczające środki</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Nie można wygenerować adresu reszty. Klucze prywatne są wyłączone w tym portfelu.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Nie można zaktualizować portfela rozdzielnego bez HD, bez aktualizacji obsługi podzielonej bazy kluczy. Użyj -upgradewallet = 169900 lub -upgradewallet bez określonej wersji.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Estymacja opłat nieudana. Domyślna opłata jest wyłączona. Poczekaj kilka bloków lub włącz -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Uwaga: Wykryto klucze prywatne w portfelu [%s] który ma wyłączone klucze prywatne</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Nie mogę zapisać do katalogu danych '%s'; sprawdź uprawnienia.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Ładowanie indeksu bloku...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts
index 2291b5df7f..9fa0f88ac3 100644
--- a/src/qt/locale/bitcoin_pt_BR.ts
+++ b/src/qt/locale/bitcoin_pt_BR.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Clique com o botão direito para editar o endereço ou rótulo</translation>
+ <translation>Clique com o botão direito para editar o endereço ou rótulo </translation>
</message>
<message>
<source>Create a new address</source>
@@ -23,13 +23,17 @@
</message>
<message>
<source>C&amp;lose</source>
- <translation>F&amp;char</translation>
+ <translation>Fe&amp;char</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
<translation>Excluir os endereços selecionados da lista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Procure um endereço ou rótulo</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar os dados na aba atual para um arquivo</translation>
</message>
@@ -47,7 +51,7 @@
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>Escolha o enereço para receber moedas</translation>
+ <translation>Escolha o endereço para receber moedas</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -193,7 +197,7 @@
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Falha na criptografia devido a um erro inerno. Sua carteira não foi criptografada.</translation>
+ <translation>Falha na criptografia devido a um erro interno. Sua carteira não foi criptografada.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
@@ -271,7 +275,7 @@
</message>
<message>
<source>&amp;About %1</source>
- <translation>&amp;About %1</translation>
+ <translation>&amp;Sobre %1</translation>
</message>
<message>
<source>Show information about %1</source>
@@ -318,6 +322,14 @@
<translation>Abrir &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Carteira:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>carteira padrão</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Clique para desativar a atividade de rede.</translation>
</message>
@@ -331,13 +343,17 @@
</message>
<message>
<source>Syncing Headers (%1%)...</source>
- <translation>Sincronizando cabeçahos (%1%)...</translation>
+ <translation>Sincronizando cabeçalhos (%1%)...</translation>
</message>
<message>
<source>Reindexing blocks on disk...</source>
<translation>Reindexando blocos no disco...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy &lt;b&gt;ativado&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Enviar moedas para um endereço bitcoin</translation>
</message>
@@ -491,7 +507,7 @@
</message>
<message>
<source>Catching up...</source>
- <translation>Recuperando o atraso ...</translation>
+ <translation>Recuperando o atraso...</translation>
</message>
<message>
<source>Date: %1
@@ -506,6 +522,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Carteira: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Tipo: %1
@@ -584,7 +606,7 @@
</message>
<message>
<source>Change:</source>
- <translation>trocar</translation>
+ <translation>Troco:</translation>
</message>
<message>
<source>(un)select all</source>
@@ -640,11 +662,11 @@
</message>
<message>
<source>Lock unspent</source>
- <translation>Boquear saída</translation>
+ <translation>Bloquear não-gasto</translation>
</message>
<message>
<source>Unlock unspent</source>
- <translation>Desboquear saída</translation>
+ <translation>Desbloquear não-gasto</translation>
</message>
<message>
<source>Copy quantity</source>
@@ -684,7 +706,7 @@
</message>
<message>
<source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Este texto fica vermelho se qualquer destinatário receber uma quantidade menor que que o dust.</translation>
+ <translation>Este texto fica vermelho se qualquer destinatário receber uma quantidade menor que o limite atual para poeira.</translation>
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
@@ -719,17 +741,13 @@
</message>
<message>
<source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>O endereço associado a esta lista de endereços de entrada. Isso só pode ser modificado para o envio de endereços.</translation>
+ <translation>O endereço associado a esta entrada na lista de endereços. Isso só pode ser modificado para endereços de envio.</translation>
</message>
<message>
<source>&amp;Address</source>
<translation>&amp;Endereço</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Novo endereço de recebimento</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Novo endereço de envio</translation>
</message>
@@ -746,16 +764,20 @@
<translation>O endereço digitado "%1" não é um endereço válido.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>O endereço digitado "%1" já se encontra no catálogo de endereços.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>O endereço "%1" já existe como endereço de recebimento com o rótulo "%2" e não pode ser adicionado como endereço de envio.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>O endereço inserido "%1" já está no catálogo de endereços com o rótulo "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation>Não foi possível desbloquear a carteira</translation>
+ <translation>Não foi possível desbloquear a carteira.</translation>
</message>
<message>
<source>New key generation failed.</source>
- <translation>Falha ao gerar chave</translation>
+ <translation>Falha ao gerar nova chave.</translation>
</message>
</context>
<context>
@@ -799,42 +821,6 @@
<source>Command-line options</source>
<translation>Opções da linha de comando</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uso:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opções da linha de comando</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opções de Interface:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Escolher diretório de dados na inicialização (padrão: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Definir idioma, por exemplo "de_DE" (padrão: idioma do sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Iniciar minimizado</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Definir certificados de root SSL para requisições de pagamento (padrão: -sistema-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Exibir tela de abertura na inicialização (padrão: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Resetar todas as configuraçãoes do GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -851,13 +837,16 @@
<translation>Como essa é a primeira vez que o programa é executado, você pode escolher onde %1 armazenará seus dados.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>Quando você clica OK, %1 vai começar a baixar e processar todos os %4 da block chain (%2GB) começando com a mais recente transação em %3 quando %4 inicialmente foi lançado.</translation>
+ </message>
+ <message>
<source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
- <translation>
-Esta sincronização inicial é muito exigente e pode expor problemas de hardware com o computador que passaram despercebidos anteriormente. Cada vez que você executar %1, continuará baixando onde ele saiu</translation>
+ <translation>Esta sincronização inicial é muito exigente e pode expor problemas de hardware com o computador que passaram despercebidos anteriormente. Cada vez que você executar o %1, irá continuar baixando de onde parou.</translation>
</message>
<message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation>Se você escolheu limitar o armazenamento da corrente de blocos (prunando), os dados históricos ainda devem ser baixados e processados, mas serão apagados no final para manter o uso de disco baixo.</translation>
+ <translation>Se você escolheu limitar o armazenamento da block chain (prunando), os dados históricos ainda devem ser baixados e processados, mas serão apagados no final para manter o uso de disco baixo.</translation>
</message>
<message>
<source>Use the default data directory</source>
@@ -881,7 +870,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 irá baixar e armazenar uma cópia da blockchain do Bitcoin</translation>
+ <translation>%1 irá baixar e armazenar uma cópia da block chain do Bitcoin.</translation>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
@@ -916,7 +905,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation>Gastar moedas de transações desconhecidas podem não ser aceitas pela rede.</translation>
+ <translation>Tentar gastar bitcoins que estão em transações ainda não exibidas, não vão ser aceitos pela rede.</translation>
</message>
<message>
<source>Number of blocks left</source>
@@ -963,7 +952,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Open payment request from URI or file</source>
- <translation>Cobrança aberta de URI ou arquivo</translation>
+ <translation>Abrir requisição de cobrança por URI ou arquivo</translation>
</message>
<message>
<source>URI:</source>
@@ -1017,6 +1006,10 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Mostra se o proxy padrão fornecido SOCKS5 é utilizado para encontrar participantes por este tipo de rede.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Use um proxy SOCKS&amp;5 separado para alcançar participantes via serviços ocultos Tor: </translation>
+ </message>
+ <message>
<source>Hide the icon from the system tray.</source>
<translation>Esconder ícone da bandeja do sistema.</translation>
</message>
@@ -1034,15 +1027,15 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Active command-line options that override above options:</source>
- <translation>Opções de linha de comando ativas que sobrescreve as opções acima:</translation>
+ <translation>Opções de linha de comando ativas que sobrescrevem as opções acima:</translation>
</message>
<message>
<source>Open the %1 configuration file from the working directory.</source>
- <translation>Abrir o arquivo de configuração %1 do diretório corrente</translation>
+ <translation>Abrir o arquivo de configuração %1 apartir do diretório trabalho.</translation>
</message>
<message>
<source>Open Configuration File</source>
- <translation>Abrir arquivo de configuração</translation>
+ <translation>Abrir Arquivo de Configuração</translation>
</message>
<message>
<source>Reset all client options to default.</source>
@@ -1057,8 +1050,24 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Rede</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Desativa alguns recursos avançados mas todos os blocos ainda serão totalmente validados. Reverter esta configuração requer baixar de novo a blockchain inteira. O uso de memória pode ser um pouco mais alto.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Fazer Prune &amp;da memória de blocos para</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Reverter esta configuração requer baixar de novo a blockchain inteira.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = automático, &lt;0 = número de cores deixados livres)</translation>
+ <translation>(0 = automático, &lt;0 = número de núcleos deixados livres)</translation>
</message>
<message>
<source>W&amp;allet</source>
@@ -1078,7 +1087,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
- <translation>Ga&amp;star mudança não confirmada</translation>
+ <translation>Ga&amp;star troco não confirmado</translation>
</message>
<message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
@@ -1090,11 +1099,11 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Accept connections from outside.</source>
- <translation>Aceite conexões exteriores.</translation>
+ <translation>Aceitar conexões externas.</translation>
</message>
<message>
<source>Allow incomin&amp;g connections</source>
- <translation>Permitir receber conexões</translation>
+ <translation>Permitir conexões de entrada</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
@@ -1118,7 +1127,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Used for reaching peers via:</source>
- <translation>Usado para alcançar participantes via:</translation>
+ <translation>Usado para alcançar pares via:</translation>
</message>
<message>
<source>IPv4</source>
@@ -1158,11 +1167,11 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>User Interface &amp;language:</source>
- <translation>&amp;Linguagem da interface:</translation>
+ <translation>&amp;Idioma da interface:</translation>
</message>
<message>
<source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>O idioma de interface do usuário pode ser definido aqui. Essa configuração terá efeito após reiniciar o %1</translation>
+ <translation>O idioma da interface pode ser definido aqui. Essa configuração terá efeito após reiniciar o %1.</translation>
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
@@ -1170,13 +1179,17 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Escolha a unidade padrão de subdivisão para interface mostrar quando enviar bitcoins.</translation>
+ <translation>Escolha a unidade de subdivisão padrão para exibição na interface ou quando enviando moedas.</translation>
</message>
<message>
<source>Whether to show coin control features or not.</source>
<translation>Mostrar ou não opções de controle da moeda.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;URLs de transação de terceiros</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1190,7 +1203,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>none</source>
- <translation>Nenhum</translation>
+ <translation>nenhum</translation>
</message>
<message>
<source>Confirm options reset</source>
@@ -1237,7 +1250,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
- <translation>A informação mostrada pode estar desatualizada. Sua carteira sincroniza automaticamente com a rede Bitcoin depois que a conexão é estabelecida, mas este processo pode não estar completo ainda.</translation>
+ <translation>A informação mostrada pode estar desatualizada. Sua carteira sincroniza automaticamente com a rede Bitcoin depois que a conexão é estabelecida, mas este processo ainda não está completo.</translation>
</message>
<message>
<source>Watch-only:</source>
@@ -1249,7 +1262,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Your current spendable balance</source>
- <translation>Seu saldo atual spendable</translation>
+ <translation>Seu saldo atual disponível para gasto</translation>
</message>
<message>
<source>Pending:</source>
@@ -1257,7 +1270,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Total de transações que ainda têm de ser confirmados, e ainda não contam para o equilíbrio spendable</translation>
+ <translation>Total de transações que ainda têm de ser confirmados, e ainda não estão disponíveis para gasto</translation>
</message>
<message>
<source>Immature:</source>
@@ -1265,7 +1278,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Mined balance that has not yet matured</source>
- <translation>Saldo minerado que ainda não maturou</translation>
+ <translation>Saldo minerado que ainda não está maduro</translation>
</message>
<message>
<source>Balances</source>
@@ -1281,7 +1294,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>Sua balança atual em endereços apenas visualizados</translation>
+ <translation>Seu saldo atual em endereços monitorados</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1297,7 +1310,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Saldo minerado de endereço monitorado ainda não foi implementado</translation>
+ <translation>Saldo minerado de endereço monitorado que ainda não está maduro</translation>
</message>
<message>
<source>Current total balance in watch-only addresses</source>
@@ -1319,6 +1332,10 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Manipulação de URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' não é um URI válido. Use 'bitcoin:'.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>URL de cobrança é inválida: %1</translation>
</message>
@@ -1328,7 +1345,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>URI não pode ser analisado! Isto pode ser causado por um endereço inválido ou parâmetros URI informados incorretamente.</translation>
+ <translation>A URI não pode ser analisada! Isto pode ser causado por um endereço inválido ou um parâmetro URI malformado.</translation>
</message>
<message>
<source>Payment request file handling</source>
@@ -1348,11 +1365,11 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Payment request expired.</source>
- <translation>Pedido de pagamento expirado</translation>
+ <translation>Pedido de pagamento expirado.</translation>
</message>
<message>
<source>Payment request is not initialized.</source>
- <translation>Pedido de pagamento não inicializado</translation>
+ <translation>Pedido de pagamento não inicializado.</translation>
</message>
<message>
<source>Unverified payment requests to custom payment scripts are unsupported.</source>
@@ -1364,7 +1381,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Valor do pagamento solicitado de %1 é muito pequeno (Considerado poeira).</translation>
+ <translation>Valor do pagamento solicitado de %1 é muito pequeno (considerado poeira).</translation>
</message>
<message>
<source>Refund from %1</source>
@@ -1516,12 +1533,16 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Erro ao analisar argumentos da linha de comando: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Erro: diretório de dados especificado "%1" não existe.</translation>
+ <translation>Erro: Diretório de dados especificado "%1" não existe.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Erro: Não foi possível interpretar arquivo de configuração: %1. Utilize apenas a sintaxe chave=valor.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Erro: Não é possível analisar o arquivo de configuração: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1532,7 +1553,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image...</source>
- <translation>&amp;Savar imagem</translation>
+ <translation>&amp;Salvar imagem...</translation>
</message>
<message>
<source>&amp;Copy Image</source>
@@ -1614,8 +1635,16 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Uso de memória</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Carteira:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(nada)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
- <translation>&amp;Reset</translation>
+ <translation>&amp;Limpar</translation>
</message>
<message>
<source>Received</source>
@@ -1635,7 +1664,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Select a peer to view detailed information.</source>
- <translation>Selecione um cliente para ver informações detalhadas.</translation>
+ <translation>Selecione um nó para ver informações detalhadas.</translation>
</message>
<message>
<source>Whitelisted</source>
@@ -1683,7 +1712,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Ban Score</source>
- <translation>Banir pontuação</translation>
+ <translation>Pontuação de Banimento</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1703,7 +1732,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>The duration of a currently outstanding ping.</source>
- <translation>A duração de um ping excepcional no momento.</translation>
+ <translation>A duração atual de um ping excepcional.</translation>
</message>
<message>
<source>Ping Wait</source>
@@ -1711,7 +1740,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Min Ping</source>
- <translation>Ping min</translation>
+ <translation>Ping minímo</translation>
</message>
<message>
<source>Time Offset</source>
@@ -1731,7 +1760,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>&amp;Network Traffic</source>
- <translation>Tráfico de Rede</translation>
+ <translation>&amp;Tráfico de Rede</translation>
</message>
<message>
<source>Totals</source>
@@ -1782,8 +1811,12 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>&amp;Desbanir</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>carteira padrão</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
- <translation>Bem-vindo ao console RPC do %1</translation>
+ <translation>Bem-vindo ao console RPC do %1.</translation>
</message>
<message>
<source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
@@ -1794,6 +1827,10 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Digite %1 para obter uma visão geral dos comandos disponíveis.</translation>
</message>
<message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Para maiores informações sobre como utilizar este console, digite %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>ATENÇÃO: Fraudadores tem solicitado a usuários que digitem comandos aqui, e assim roubando o conteúdo de suas carteiras. Não utilize este console sem antes conhecer os comandos e seus efeitos.</translation>
</message>
@@ -1802,6 +1839,14 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Atividade da rede disativada</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Executando comando sem nenhuma carteira</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Executando comando usando a carteira "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(id do nó: %1)</translation>
</message>
@@ -1846,7 +1891,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>&amp;Message:</source>
- <translation>&amp;Mensagem</translation>
+ <translation>&amp;Mensagem:</translation>
</message>
<message>
<source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
@@ -1854,7 +1899,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
- <translation>Um marcador opcional para associar ao novo endereço de recebimento.</translation>
+ <translation>Um rótulo opcional para associar ao novo endereço de recebimento.</translation>
</message>
<message>
<source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
@@ -1862,7 +1907,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation>Uma quantia opcional para cobrar. Deixe vazio ou em branco se o pagador puder especificar a quantia.</translation>
+ <translation>Uma quantia opcional para cobrar. Deixe vazio ou zero para não cobrar uma quantia específica.</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -1873,20 +1918,20 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Limpar</translation>
</message>
<message>
- <source>Requested payments history</source>
- <translation>Histórico de cobranças</translation>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Endereços segwit nativos (também conhecidos como Bench32 ou BIP-173) reduzem suas taxas de transação mais adiante e oferecem melhor proteção contra erros de digitação, porém carteiras antigas não têm suporte a eles. Quando não estiver rubricado, um endereço compatível com cateiras antigas será criado como alternativa.</translation>
</message>
<message>
- <source>&amp;Request payment</source>
- <translation>&amp;Requisitar Pagamento</translation>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Gere um endereço segwit (Bench32) nativo</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Os endereços Bech32 (BIP-173) são mais baratos de gastar e oferecem uma proteção melhor contra erros de digitação. Quando desmarcado, será criado um endereço SegWit envolvido em P2SH, compatível com carteiras antigas.</translation>
+ <source>Requested payments history</source>
+ <translation>Histórico de cobranças</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Gerar endereço Bech32</translation>
+ <source>&amp;Request payment</source>
+ <translation>&amp;Requisitar Pagamento</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1968,12 +2013,16 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Mensagem</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Carteira</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultante muito longa. Tente reduzir o texto do rótulo ou da mensagem.</translation>
</message>
<message>
<source>Error encoding URI into QR Code.</source>
- <translation>Erro ao codigicar o URI em código QR</translation>
+ <translation>Erro ao codificar o URI em código QR</translation>
</message>
</context>
<context>
@@ -2051,7 +2100,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Change:</source>
- <translation>troco</translation>
+ <translation>Troco:</translation>
</message>
<message>
<source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
@@ -2067,7 +2116,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Choose...</source>
- <translation>Escolher</translation>
+ <translation>Escolher...</translation>
</message>
<message>
<source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
@@ -2082,12 +2131,16 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Ocultar painel</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>por kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Especifique uma taxa personalizada por kB (1.000 bytes) do tamanho virtual da transação.
+
+Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por uma transação de 500 bytes (metade de 1 kB) teria uma taxa final de apenas 50 satoshis.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Se a taxa personalizada for definida em 1000 satoshis e a transação tiver somente 250 bytes, então "por kilobyte" somente paga 250 satoshis de taxa, enquanto "pelo menos" paga 1000 satoshis. Se a transação for maior que 1 kilobyte, ambos pagam por kilobyte.</translation>
+ <source>per kilobyte</source>
+ <translation>por kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2111,7 +2164,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(Smart fee não iniciado. Isso requer alguns blocos...)</translation>
+ <translation>(SmartFee não iniciado. Isso requer alguns blocos...)</translation>
</message>
<message>
<source>Send to multiple recipients at once</source>
@@ -2119,7 +2172,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Add &amp;Recipient</source>
- <translation>Adicionar destinatário</translation>
+ <translation>Adicionar &amp;Destinatário</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -2131,7 +2184,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Confirmation time target:</source>
- <translation>Confirmando tempo alvo:</translation>
+ <translation>Tempo alvo de confirmação:</translation>
</message>
<message>
<source>Enable Replace-By-Fee</source>
@@ -2143,7 +2196,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Clear &amp;All</source>
- <translation>Limpar Tudo</translation>
+ <translation>Limpar &amp;Tudo</translation>
</message>
<message>
<source>Balance:</source>
@@ -2155,7 +2208,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>S&amp;end</source>
- <translation>Enviar</translation>
+ <translation>&amp;Enviar</translation>
</message>
<message>
<source>Copy quantity</source>
@@ -2171,7 +2224,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Copy after fee</source>
- <translation>Copiar pós taxa</translation>
+ <translation>Copiar após taxa</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -2198,14 +2251,6 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Tem certeza que deseja enviar?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>adicionado como taxa da transação </translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Quantia tota %1</translation>
- </message>
- <message>
<source>or</source>
<translation>ou</translation>
</message>
@@ -2214,10 +2259,26 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Você pode aumentar a taxa depois (sinaliza Replace-By-Fee, BIP-125).</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>da carteira %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Revise a sua transação.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Taxa da transação</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>Não sinalizar Replace-By-Fee, BIP-125.</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>Valor total</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirme o envio de moedas</translation>
</message>
@@ -2231,11 +2292,11 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>The amount exceeds your balance.</source>
- <translation>A quantia excede o seu saldo</translation>
+ <translation>A quantia excede o seu saldo.</translation>
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>O total excede o seu saldo quando a taxa da transação %1 é incluída</translation>
+ <translation>O total excede o seu saldo quando a taxa da transação %1 é incluída.</translation>
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
@@ -2243,11 +2304,11 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Transaction creation failed!</source>
- <translation>Falha na criação da transação</translation>
+ <translation>Falha na criação da transação!</translation>
</message>
<message>
<source>The transaction was rejected with the following reason: %1</source>
- <translation>A transação foi negada pela seguinte razão: %1</translation>
+ <translation>A transação foi rejeitada com a seguinte razão: %1</translation>
</message>
<message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
@@ -2255,7 +2316,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Payment request expired.</source>
- <translation>Pedido de pagamento expirado</translation>
+ <translation>Pedido de pagamento expirado.</translation>
</message>
<message>
<source>Pay only the required fee of %1</source>
@@ -2263,15 +2324,15 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
- <translation><numerusform>Confirmação em %n bloco.</numerusform><numerusform>Confirmação em %n blocos.</numerusform></translation>
+ <translation><numerusform>Confirmação em %n bloco.</numerusform><numerusform>Início estimado para confirmação em %n blocos.</numerusform></translation>
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
- <translation>Aviso: Endereço inválido</translation>
+ <translation>Aviso: Endereço Bitcoin inválido</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
- <translation>Aviso: Endereço de troco inválido</translation>
+ <translation>Aviso: Endereço de troco desconhecido</translation>
</message>
<message>
<source>Confirm custom change address</source>
@@ -2310,7 +2371,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
- <translation>Endereço que enviará o pagamento</translation>
+ <translation>O endereço Bitcoin para enviar o pagamento</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2407,7 +2468,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
- <translation>O enderesso Bitcoin que assinará a mensagem</translation>
+ <translation>O endereço Bitcoin que assinará a mensagem</translation>
</message>
<message>
<source>Choose previously used address</source>
@@ -2427,7 +2488,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Enter the message you want to sign here</source>
- <translation>Entre a mensagem que você quer assinar aqui</translation>
+ <translation>Digite a mensagem que você quer assinar aqui</translation>
</message>
<message>
<source>Signature</source>
@@ -2443,7 +2504,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Sign &amp;Message</source>
- <translation>Assinar &amp;mensagem</translation>
+ <translation>Assinar &amp;Mensagem</translation>
</message>
<message>
<source>Reset all sign message fields</source>
@@ -2451,31 +2512,31 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Clear &amp;All</source>
- <translation>Limpar Tudo</translation>
+ <translation>Limpar &amp;Tudo</translation>
</message>
<message>
<source>&amp;Verify Message</source>
- <translation>&amp;Verificar mensagem</translation>
+ <translation>&amp;Verificar Mensagem</translation>
</message>
<message>
<source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation>Coloque o endereço do autor, a mensagem (certifique-se de copiar toda a mensagem, incluindo quebras de linha, espaços, tabulações, etc.) e a assinatura embaixo para verificar a mensagem. Cuidado para não ler mais da assinatura do que está assinado na mensagem, para evitar ser enganado pelo ataque man-in-the-middle. Note que isso somente prova a propriedade de um endereço, e não o remetende de qualquer transação.</translation>
+ <translation>Coloque o endereço do autor, a mensagem (certifique-se de copiar toda a mensagem, incluindo quebras de linha, espaços, tabulações, etc.) e a assinatura abaixo para verificar a mensagem. Cuidado para não compreender mais da assinatura do que está na mensagem assinada de fato, para evitar ser enganado por um ataque man-in-the-middle. Note que isso somente prova que o signatário recebe com este endereço, não pode provar que é o remetente de nenhuma transação!</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
- <translation>O enderesso Bitcoin que assionou a mesnagem</translation>
+ <translation>O endereço Bitcoin que foi usado para assinar a mensagem</translation>
</message>
<message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Verificar mensagem para se assegurar que ela foi assinada pelo dono de um endereço Bitcoin específico.</translation>
+ <translation>Verificar mensagem para se assegurar que ela foi assinada pelo dono de um endereço Bitcoin específico</translation>
</message>
<message>
<source>Verify &amp;Message</source>
- <translation>Verificar &amp;mensagem</translation>
+ <translation>Verificar &amp;Mensagem</translation>
</message>
<message>
<source>Reset all verify message fields</source>
- <translation>Limpar todos os campos de assinatura da mensagem</translation>
+ <translation>Limpar todos os campos da verificação de mensagem</translation>
</message>
<message>
<source>Click "Sign Message" to generate signature</source>
@@ -2483,11 +2544,11 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>The entered address is invalid.</source>
- <translation>O endereço digitado é inválido</translation>
+ <translation>O endereço digitado é inválido.</translation>
</message>
<message>
<source>Please check the address and try again.</source>
- <translation>Favor checar o endereço e tente novamente</translation>
+ <translation>Por gentileza, cheque o endereço e tente novamente.</translation>
</message>
<message>
<source>The entered address does not refer to a key.</source>
@@ -2495,39 +2556,39 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Wallet unlock was cancelled.</source>
- <translation>O desbloqueio da carteira foi cancelado</translation>
+ <translation>O desbloqueio da carteira foi cancelado.</translation>
</message>
<message>
<source>Private key for the entered address is not available.</source>
- <translation>A chave privada do endereço inserido não está disponível</translation>
+ <translation>A chave privada do endereço inserido não está disponível.</translation>
</message>
<message>
<source>Message signing failed.</source>
- <translation>Falha ao assinar mensagem</translation>
+ <translation>A assinatura da mensagem falhou.</translation>
</message>
<message>
<source>Message signed.</source>
- <translation>Mensagem assinada</translation>
+ <translation>Mensagem assinada.</translation>
</message>
<message>
<source>The signature could not be decoded.</source>
- <translation>A assinatura não pode ser descodificada</translation>
+ <translation>A assinatura não pode ser decodificada.</translation>
</message>
<message>
<source>Please check the signature and try again.</source>
- <translation>Favor checar a assinatura e tente novamente</translation>
+ <translation>Por gentileza, cheque a assinatura e tente novamente.</translation>
</message>
<message>
<source>The signature did not match the message digest.</source>
- <translation>A assinatura não corresponde a mensagem</translation>
+ <translation>A assinatura não corresponde a mensagem.</translation>
</message>
<message>
<source>Message verification failed.</source>
- <translation>Falha na verificação da mensagem</translation>
+ <translation>Falha na verificação da mensagem.</translation>
</message>
<message>
<source>Message verified.</source>
- <translation>Mensagem verificada</translation>
+ <translation>Mensagem verificada.</translation>
</message>
</context>
<context>
@@ -2559,20 +2620,16 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>conflitado com uma transação com %1 confirmações</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/não confirmado, %1</translation>
</message>
<message>
<source>in memory pool</source>
- <translation>na memória</translation>
+ <translation>no pool de memória</translation>
</message>
<message>
<source>not in memory pool</source>
- <translation>não na memóra</translation>
+ <translation>não está no pool de memóra</translation>
</message>
<message>
<source>abandoned</source>
@@ -2591,14 +2648,6 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, ainda não foi propagada na rede com êxito.</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, transmitido aravés de %n nó</numerusform><numerusform>, transmitido aravés de %n nós</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2624,7 +2673,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>own address</source>
- <translation>próprio endereço</translation>
+ <translation>endereço próprio</translation>
</message>
<message>
<source>watch-only</source>
@@ -2640,7 +2689,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
- <translation><numerusform>maduro em mais %n bloco</numerusform><numerusform>maduro em mais %n blocos</numerusform></translation>
+ <translation><numerusform>maduro em mais %n bloco</numerusform><numerusform>maduro em mais %n blocos</numerusform></translation>
</message>
<message>
<source>not accepted</source>
@@ -2683,6 +2732,10 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Tamanho tota da transação</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Tamanho virtual da transação</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Index da saída</translation>
</message>
@@ -2696,7 +2749,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Debug information</source>
- <translation>Depurar informação</translation>
+ <translation>Informações de depuração</translation>
</message>
<message>
<source>Transaction</source>
@@ -2753,10 +2806,6 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Aberto até %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Não confirmado</translation>
</message>
@@ -2781,20 +2830,16 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Recém-criado (%1 confirmações, disponível somente após %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Este bloco não foi recebido por nenhum outro participante da rede e provavelmente não será aceito!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Gerado mas não aceito</translation>
</message>
<message>
<source>Received with</source>
- <translation>Recebido</translation>
+ <translation>Recebido com</translation>
</message>
<message>
<source>Received from</source>
- <translation>Recebido</translation>
+ <translation>Recebido de</translation>
</message>
<message>
<source>Sent to</source>
@@ -2830,7 +2875,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Type of transaction.</source>
- <translation>Tipo de transação</translation>
+ <translation>Tipo de transação.</translation>
</message>
<message>
<source>Whether or not a watch-only address is involved in this transaction.</source>
@@ -2838,7 +2883,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>User-defined intent/purpose of the transaction.</source>
- <translation>Intenção/Propósito definido pelo usuário para a transação</translation>
+ <translation>Intenção/Propósito definido pelo usuário para a transação.</translation>
</message>
<message>
<source>Amount removed from or added to balance.</source>
@@ -2877,7 +2922,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Received with</source>
- <translation>Recebido</translation>
+ <translation>Recebido com</translation>
</message>
<message>
<source>Sent to</source>
@@ -3008,14 +3053,14 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<name>UnitDisplayStatusBarControl</name>
<message>
<source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Unidade para mostrar. Clique para selecionar outra unidade.</translation>
+ <translation>Unidade para mostrar quantidades. Clique para selecionar outra unidade.</translation>
</message>
</context>
<context>
<name>WalletFrame</name>
<message>
<source>No wallet has been loaded.</source>
- <translation>Nenhuma carteira carregada</translation>
+ <translation>Nenhuma carteira carregada.</translation>
</message>
</context>
<context>
@@ -3026,7 +3071,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Fee bump error</source>
- <translation>Taxa de erro</translation>
+ <translation>Erro no aumento de taxa</translation>
</message>
<message>
<source>Increasing transaction fee failed</source>
@@ -3050,7 +3095,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Confirm fee bump</source>
- <translation>Taxa de confirmação</translation>
+ <translation>Confirmação no aumento de taxa</translation>
</message>
<message>
<source>Can't sign transaction.</source>
@@ -3058,7 +3103,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Could not commit transaction</source>
- <translation>Não foi possível confirmar a transação</translation>
+ <translation>Não foi possível mandar a transação</translation>
</message>
</context>
<context>
@@ -3077,7 +3122,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Wallet Data (*.dat)</source>
- <translation>Dados da carteira (*.dat)</translation>
+ <translation>Carteira (*.dat)</translation>
</message>
<message>
<source>Backup Failed</source>
@@ -3095,44 +3140,24 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<source>The wallet data was successfully saved to %1.</source>
<translation>Os dados da carteira foram salvos com êxito em %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Cancelar</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opções:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Especificar o diretório de dados</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Conectar a um nó para receber endereços de participantes, e desconectar.</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especificar seu próprio endereço público</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aceitar linha de comando e comandos JSON-RPC</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
- <translation>Distribuído sob a MIT software license, veja o arquivo %s ou %s</translation>
- </message>
- <message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Se &lt;category&gt; não for suprida ou se &lt;category&gt; = 1, mostrar toda informação de depuração.</translation>
+ <translation>Distribuído sob a licença de software MIT, veja o arquivo %s ou %s</translation>
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>Prune configurado abaixo do mínimo de %d MiB. Por favor use um número mais alto.</translation>
+ <translation>Configuração de prune abaixo do mínimo de %d MiB.Por gentileza use um número mais alto.</translation>
</message>
<message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
- <translation>Prune: A ultima sincronização da carteira foi além do dado comprimido. Você precisa reindexar (fazer o download de toda a blockchain novamente)</translation>
+ <translation>Prune: A ultima sincronização da carteira foi além dos dados podados. Você precisa usar -reindex (fazer o download de toda a blockchain novamente no caso de nós com prune)</translation>
</message>
<message>
<source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
@@ -3143,20 +3168,12 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Erro: Um erro interno fatal ocorreu, veja debug.log para detalhes</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Taxa (em %s/kB) a ser adicionada às transações que você mandar (padrão: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
- <translation>Prunando os blocos existentes...</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Rodar em segundo plano como serviço e aceitar comandos</translation>
+ <translation>Podando os blocos existentes...</translation>
</message>
<message>
<source>Unable to start HTTP server. See debug log for details.</source>
- <translation>Não foi possível iniciar o servidor HTTP. Veja o log para detaihes.</translation>
+ <translation>Não foi possível iniciar o servidor HTTP. Veja o log de depuração para detaihes.</translation>
</message>
<message>
<source>Bitcoin Core</source>
@@ -3167,112 +3184,44 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Desenvolvedores do %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>A variação da taxa (em %s/kB) que será usada quando não houver dados suficientes para se estimar a taxa (default: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Aceita transações retransmitidas advindas de pares em lista branca, mesmo quando não estiver retransmitindo transações (padrão: %d)</translation>
- </message>
- <message>
- <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source>
- <translation>Adicione um node para se conectar e tentar manter a conexão aberta (consulte a ajuda do comando `addnode` RPC para obter mais informações)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Vincular ao endereço fornecido e sempre escutar nele. Use a notação [host]:port para IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Não foi possível obter exclusividade de escrita no endereço %s. O %s provavelmente já está sendo executado.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Apaga todas as transações da carteira e somente recupera essas partes da blockchain usando o comando -rescan na inicialização</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Não é possível fornecer conexões específicas e ter addrman procurando conexões ao mesmo tempo. </translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
- <translation>Erro ao ler arquivo %s! Todas as chaves foram lidas corretamente, mas os dados de transação ou o livro de endereos podem estar faltando ou incorretos.</translation>
- </message>
- <message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Excluir informações de depuração para uma categoria. Pode ser usado em conjunto com -debug=1 para exibir logs de depuração para todas as categorias, exceto uma ou mais categorias especificadas.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Executa um comando quando uma transação da carteira mudar (%s no comando será substituído por TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Transações extras para manter na memória para reconstruções de blocos compactos (padrão: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Se este bloco está no blockchain, assume-se que ele e seus ancestrais são válidos e podem ignorar a verificação de scripts (0 para verificar todos, padrão: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>A media máxima permitida de peer time compensa o ajuste. Perspectiva local de horário pode ser influenciada por pares à frente ou atrás neste montante. (padrão: %u segundos)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Preço máximo total (in %s) aplicado a uma única transação de carteira ou transação crua; aplicar isto tão baixo pode abortar grandes transações (padrão: %s)</translation>
+ <translation>Erro ao ler arquivo %s! Todas as chaves privadas foram lidas corretamente, mas os dados de transação ou o livro de endereços podem estar faltando ou incorretos.</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
- <translation>Por favor verifique que a data e o horário de seu computador estão corretos. Se o relógio de seu computador estiver incorreto, %s não funcionarão corretamente.</translation>
+ <translation>Por favor verifique se a data e o horário de seu computador estão corretos. Se o relógio de seu computador estiver incorreto, %s não funcionará corretamente.</translation>
</message>
<message>
<source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
<translation>Por favor contribua se você entender que %s é útil. Visite %s para mais informações sobre o software.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Buscar por endereços de peers via busca DNS, se estiver baixo em endereços (padrão: 1 a não ser que -connect)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Reduz o requerimente de espaço habiitando o pruning (apagando) blocos antigos. Isso permite o chamar o comando pruneblockchain via RPC para apagar blocos específicos, e habiita o pruning automático de blocos antigos se o tamanho em MiB for atingido. Esse modo é incompatíve com -txindex e -rescan. Aviso: Reverter essa configuração requer re-baixar o blockchain inteiro. (padrão: 0 = disabilitado, 1 = permite o pruning manua via RPC, &gt;%u = pruna os blocos para ficar abaixo do expecificado, em MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Taxa (em %s/KiB) a ser adicionada às transações que você mandar (padrão: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Define o número de threads de verificação de script (%u a %d, 0 = automático, &lt;0 = número de cores deixados livres, padrão: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>O banco de dados de blocos contém um bloco que parece ser do futuro. Isso pode ser devido à data e hora do seu computador estarem configuradas incorretamente. Apenas reconstrua o banco de dados de blocos se você estiver certo de que a data e hora de seu computador estão corretas.</translation>
</message>
<message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
- <translation>Este é um build de teste pré-lançamento - use por sua conta e risco - não use para mineração ou comércio.</translation>
+ <translation>Este é um build de teste pré-lançamento - use por sua conta e risco - não use para mineração ou comércio</translation>
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>Essa é a taxa de transação que você pode descartar se a alteração for menor que um cisco a esse nível</translation>
+ <translation>Essa é a taxa de transação que você pode descartar se o troco a esse ponto for menor que poeira</translation>
</message>
<message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation>Não é possível reproduzir blocos. Você precisará reconstruir o banco de dados usando -reindex-chainstate</translation>
+ <translation>Não é possível reproduzir blocos. Você precisará reconstruir o banco de dados usando -reindex-chainstate.</translation>
</message>
<message>
<source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
- <translation>Não foi possível reanalisar o banco de dados para o estado pre-fork. Você precisa rebaixar o blockchain</translation>
- </message>
- <message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Use UPnP para mapear a porta escutada (padrão: 1 quando escutando e sem -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Nome de usuário e hash da senha para conexões JSON-RPC. O campo &lt;userpw&gt; vem com o formato: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Um script python canônico é incluído em share/rpcuser. O cliente pode conectar normalmente usando o rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt;. Esta opção pode ser especificado multiplas vezes</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>A carteira não irá criar transações que vioem o imite de memória (padrão: %u)</translation>
+ <translation>Não foi possível rebobinar o banco de dados para um estado pre-fork. Você precisa fazer o re-download da blockchain</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -3280,7 +3229,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
- <translation>Atenção: Nós não parecemos concordar plenamente com nossos nós! Você pode precisar atualizar ou outros nós podem precisar atualizar.</translation>
+ <translation>Atenção: Nós não parecemos concordar plenamente com nossos pares! Você pode precisar atualizar ou outros pares podem precisar atualizar.</translation>
</message>
<message>
<source>%d of last 100 blocks have unexpected version</source>
@@ -3295,40 +3244,12 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>-maxmempool deve ser pelo menos %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; pode ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Aceitar conexões externas (padrão: 1 se opções -proxy ou -connect não estiverem presentes)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Adiciona comentário ao user-agent do navegador</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Tentando recuperar a chape privada da carteira corrompida ao inicializar</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opções de criação de blocos:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
- <translation>Impossível resolver -%s endereço: '%s'</translation>
- </message>
- <message>
- <source>Chain selection options:</source>
- <translation>Opções da rede:</translation>
+ <translation>Não foi possível encontrar o endereço de -%s: '%s'</translation>
</message>
<message>
<source>Change index out of range</source>
- <translation>Índice de mudança fora da faixa.</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Opções de conexão:</translation>
+ <translation>Índice de mudança fora do intervalo</translation>
</message>
<message>
<source>Copyright (C) %i-%i</source>
@@ -3339,38 +3260,10 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Detectado Banco de dados de blocos corrompido</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opções de depuração/teste:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Não carrega a carteira e desabilita as chamadas RPC para a carteira</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Você quer reconstruir o banco de dados de blocos agora?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Abilitar a publicação da hash do block em &lt;endereço&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Abilitar a publicação da hash da transação em &lt;endereço&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Abilitar a publicação dos dados brutos do block em &lt;endereço&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Abilitar a publicação dos dados brutos da transação em &lt;endereço&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Habilita substituição de transação em memória (padrão: %u)</translation>
- </message>
- <message>
<source>Error creating %s: You can't create non-HD wallets with this version.</source>
<translation>Erro ao criar %s: Você não pode criar carteiras não-HD com esta versão.</translation>
</message>
@@ -3387,6 +3280,10 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Erro ao carregar %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Erro ao carregar %s: Chaves privadas só podem ser desativadas durante a criação</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Erro ao carregar %s Carteira corrompida</translation>
</message>
@@ -3411,6 +3308,10 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Falha ao escutar em qualquer porta. Use -listen=0 se você quiser isso.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Falha ao escanear novamente a carteira durante a inicialização</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importando...</translation>
</message>
@@ -3424,7 +3325,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Valor inválido para -%s=&lt;amount&gt;: '%s'</translation>
+ <translation>Quantidade inválida para -%s=&lt;amount&gt;: '%s'</translation>
</message>
<message>
<source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
@@ -3432,11 +3333,16 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Valor inválido para -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ <translation>Quantidade inválida para -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>
+Diretório de blocos especificados "%s" não existe.</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Mantenha a mempool de transações abaixo de &lt;n&gt; megabytes (padrão: %u)</translation>
+ <source>Upgrading txindex database</source>
+ <translation>Atualizando banco de dados txindex</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3447,24 +3353,8 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Carregando lista de banidos...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Localização do cookie de autenticação (padrão: diretório de dados)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
- <translation>Decriptadores de arquivos disponíveis insuficientes.</translation>
- </message>
- <message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Somente conectar a clientes na rede &lt;net&gt; (ipv4, ipv6 ou onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Mostra essa mensagem de ajuda e sai</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Mostra a versão e fecha</translation>
+ <translation>Não há file descriptors suficientes disponíveis.</translation>
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
@@ -3475,14 +3365,6 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>O modo prune é incompatível com -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Reconstruir índice de cadeia de bloco a partir dos arquivos blk*.dat no disco</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Reconstruir estado a partir dos blocos indexados</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Reverificando blocos...</translation>
</message>
@@ -3491,20 +3373,20 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Reanalizando blocos...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Define o tamanho do cache do banco de dados em megabytes (%d para %d, padrão: %d)</translation>
+ <source>The source code is available from %s.</source>
+ <translation>O código fonte está disponível pelo %s.</translation>
</message>
<message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especifique o arquivo da carteira (dentro do diretório de dados)</translation>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>Taxa de transação e cálculo de troco falharam</translation>
</message>
<message>
- <source>The source code is available from %s.</source>
- <translation>O código fonte está disponível pelo %s</translation>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>Impossível vincular a %s neste computador. O %s provavelmente já está rodando.</translation>
</message>
<message>
- <source>Transaction fee and change calculation failed</source>
- <translation>Taxa de transação e cálculo de troco falharam.</translation>
+ <source>Unable to generate keys</source>
+ <translation>Não foi possível gerar chaves</translation>
</message>
<message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
@@ -3516,7 +3398,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Unsupported argument -tor found, use -onion.</source>
- <translation>Argumento não suportador encontrado: -tor. Use -onion.</translation>
+ <translation>Argumento não suportado encontrado: -tor. Use -onion.</translation>
</message>
<message>
<source>Unsupported logging category %s=%s.</source>
@@ -3527,14 +3409,6 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Atualizando banco de dados UTXO</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Use UPnP para mapear a porta de entrada (padrão: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Usar a rede de testes</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Comentário do Agente de Usuário (%s) contém caracteres inseguros.</translation>
</message>
@@ -3543,88 +3417,24 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Verificando blocos...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opções de depuração/teste da Carteira</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
- <translation>A Carteira precisou ser reescrita: reinicie o %s para completar</translation>
- </message>
- <message>
- <source>Wallet options:</source>
- <translation>Opções da carteira:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permitir conexões JSON-RPC de uma fonte específica. Válido para um único ip (ex. 1.2.3.4), até uma rede/máscara (ex. 1.2.3.4/255.255.255.0) ou uma rede/CIDR (ex. 1.2.3.4/24). Esta opção pode ser usada múltiplas vezes</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Vincular ao endereço fornecido e sempre escutar nele. Use a notação [host]:port para IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Criar novos arquivos com permissões padrão do sistema, em vez de umask 077 (apenas efetivo com funcionalidade de carteira desabilitada)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Descobrir o próprio IP (padrão: 1 enquanto aguardando conexões e sem -externalip ou -proxy)</translation>
+ <translation>A Carteira precisa ser reescrita: reinicie o %s para completar</translation>
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Erro: Aceitar conexões de entrada falhou (retornou erro %s)</translation>
- </message>
- <message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Executa um comando quando um alerta relevante é recebido ou vemos uma longa segregação (%s é substituída pela mensagem)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Comissões (em %s/kB) menores serão consideradas como zero para relaying, mineração e criação de transação (padrão %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Se paytxfee não estiver definida, incluir comissão suficiente para que as transações comecem a ter confirmações em média dentro de N blocos (padrão %u)</translation>
+ <translation>Erro: Escutar conexões de entrada falhou (vincular retornou erro %s)</translation>
</message>
<message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
- <translation>Valor inválido para -maxtxfee=&lt;valor&gt;: '%s' (precisa ser pelo menos a taxa mínima de %s para prevenir que a transação nunca seja confirmada)</translation>
- </message>
- <message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Tamanho máximo de dados em transações de dados de operadora (padrão %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Gerar credenciais aleatórias para cada conexão por proxy. Isto habilita o isolamento de stream do Tor (padrão: %u)</translation>
+ <translation>Valor inválido para -maxtxfee=&lt;valor&gt;: '%s' (precisa ser pelo menos a taxa de minrelay de %s para prevenir que a transação nunca seja confirmada)</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>A quantia da transação é muito pequena para mandar </translation>
- </message>
- <message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Peers permitidos não podem ser banidos do DoS e suas transações sempre são transmitidas, até mesmo se eles já estão no pool de memória, útil, por exemplo, para um gateway</translation>
+ <translation>A quantia da transação é muito pequena para mandar depois de deduzida a taxa</translation>
</message>
<message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
- <translation>Você precisa reconstruir o banco de dados usando -reindex para sair do modo prune. Isso irá rebaixar todo o blockchain.</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(padrão: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Aceitar pedidos restantes públicas (padrão: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Criar automaticamente serviços ocultos do Tor (padrão: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Connecte-se através de um proxy SOCKS5</translation>
+ <translation>Você precisa reconstruir o banco de dados usando -reindex para sair do modo prune. Isso irá causar o download de todo o blockchain novamente.</translation>
</message>
<message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
@@ -3632,15 +3442,11 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Error reading from database, shutting down.</source>
- <translation>Erro ao ler o banco de dados. Finalizando.</translation>
+ <translation>Erro ao ler o banco de dados. Encerrando.</translation>
</message>
<message>
<source>Error upgrading chainstate database</source>
- <translation>Erro ao atualizar banco de dados de cadeias</translation>
- </message>
- <message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importar blocos a partir de arquivo externo blk000??.dat durante a inicialização</translation>
+ <translation>Erro ao atualizar banco de dados do chainstate</translation>
</message>
<message>
<source>Information</source>
@@ -3663,44 +3469,28 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Máscara de rede especificada em -whitelist: '%s' é inválida</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Manter ao máximo &lt;n&gt; transações inconectáveis na memória (padrão: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Necessário informar uma porta com -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opções de relé nó :</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opções do servidor RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <translation>Reduzindo -maxconnections de %d para %d, devido a limitações do sistema</translation>
+ <translation>Reduzindo -maxconnections de %d para %d, devido a limitações do sistema.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Re-escanear a block-chain por transações faltantes na carteira durante a inicialização</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Mandar informação de trace/debug para o console em vez de para o arquivo debug.log</translation>
+ <source>Signing transaction failed</source>
+ <translation>Assinatura de transação falhou</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Exibir todas opções de depuração (uso: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>O -walletdir "%s" especificado não existe</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Encolher arquivo debug.log ao iniciar o cliente (padrão 1 se opção -debug não estiver presente)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>O -walletdir "%s" especificado é um caminho relativo</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>Assinatura de transação falhou</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>O -walletdir "%s" especificado não é um diretório</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3711,146 +3501,54 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Este é um software experimental.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Senha da porta de controle do Tor (padrão: vazio)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Porta de controle a ser usada se o monitoramento onion estiver habilitado (padrão: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
- <translation>Quantidade da transação muito pequena.</translation>
+ <translation>Quantidade da transação muito pequena</translation>
</message>
<message>
<source>Transaction too large for fee policy</source>
- <translation>Transação muito grande para enviar sem taxa</translation>
+ <translation>Transação muito grande para política de taxa</translation>
</message>
<message>
<source>Transaction too large</source>
- <translation>Transação muito larga</translation>
+ <translation>Transação muito grande</translation>
</message>
<message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>Impossível se ligar a %s neste computador (bind retornou erro %s)</translation>
+ <translation>Erro ao vincular em %s neste computador (bind retornou erro %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Atualizar a carteira para o último formato na inicialização</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nome de usuário para conexões JSON-RPC</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Não foi possível gerar as chaves iniciais</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Verificando carteira(s)...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Carteira %s reside fora do diretório da carteira %s</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Atenção</translation>
</message>
<message>
<source>Warning: unknown new rules activated (versionbit %i)</source>
- <translation>Aviso: Novas regras estranhas foram ativadas (versionbit %i)</translation>
- </message>
- <message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Quando operar em modo de blocos somente (padrãp: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Você precisa reconstruir o banco de dados usando -reindex para alterar -txindex</translation>
+ <translation>Aviso: Novas regras desconhecidas foram ativadas (versionbit %i)</translation>
</message>
<message>
<source>Zapping all transactions from wallet...</source>
<translation>Aniquilando todas as transações da carteira...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Opções de notificação ZeroMQ:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Senha para conexões JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Executa um comando quando o melhor bloco mudar (%s no comando será substituído pelo hash do bloco)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permitir consultas DNS para -addnode, -seednode e -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = manter metadados tx e.g. informação do dono da conta e requisição de pagamente, 2 = descartar metadados tx)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation>-maxtxfee é muito alto! Essa quantia poderia ser paga em uma única transação.</translation>
- </message>
- <message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Vincular o endereço especificado para escutar conexões JSON-RPC. Esta opção é ignorada a menos que -rpcallowip também seja especificada. A porta é opcional e sobrepõe -rpcport. Use a notação [host]:port para IPv6. Essa opção pode ser especificada múltiplas vezes (Padrão: 127.0.0.1 e ::1 apenas localhost, ou se -rpcallowip for especificado, 0.0.0.0 e :: todos os endereços)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Não manter transações na mempool por mais que &lt;n&gt; horas (padrão: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Número mínimo de bytes por assinatura em transações que transmitimos e mineramos (default: %u)</translation>
+ <translation>A valor especificado de -maxtxfee está muito alto! Taxas grandes assim podem ser atribuidas numa transação única.</translation>
</message>
<message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Erro carregando %s: Não é permitido habilitar HD em uma carteira não-HD já existente</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Erro ao carregar carteira %s. O parâmetro -wallet deve somente especificar um nome de arquivo (não um caminho).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Comissões (em %s/kB) menores serão consideradas como zero para criação de transação (padrão %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Força a retransmissão de transações de pares da lista branca, mesmo quando violam a política local de retransmissão (default: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Quão completa a verificação de blocos do -checkblocks é (0-4, padrão: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Mantém um índice completo de transações, usado pela chamada rpc getrawtransaction (padrão: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Número de segundos para impedir que peers mal comportados reconectem (padrão %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Informação de saída de debug (padrão: %u, definir &lt;category&gt; é opcional)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Define a criação do raw da transação ou bloco em modo não verbal, não segwit (0) ou segwit (1) (padrão: %d)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>Especificar local do arquivo do log de debug: pode ser um caminho absoluto ou um caminho relativo ao diretório de dados (padrão: "%s")</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Suportar filtragem de blocos e transações com filtros bloom (padrão: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>A taxa de imposto (em %s/kB) indica sua tolerância para descartar alterações, adicionando-a na comissão (padrão: %s). Nota: Uma saída é descartada, se for considerada sobra nesta taxa, mas sempre descartaremos no máximo a taxa de retransmissão. Uma comissão acima disso, será limitada pela comissão estimada para o destino mais longo. </translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Esta é a taxa que você deve pagar quando a taxa estimada não está disponível.</translation>
</message>
@@ -3860,11 +3558,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <translation>O tamanho total da string de versão da rede (%i) excede o tamanho máximo (%i). Reduza o numero ou tamanho de uacomments.</translation>
- </message>
- <message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Tenta manter tráfego fora dos limites dentro do alvo especificado (em MiB por 24h), 0 = sem limite (padrão: %d)</translation>
+ <translation>O tamanho total da string de versão da rede (%i) excede o tamanho máximo (%i). Reduza o número ou tamanho de uacomments.</translation>
</message>
<message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
@@ -3875,144 +3569,44 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Argumento não suportado -whitelistalwaysrelay foi ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Use um proxy SOCKS5 separado para alcançar participantes da rede via serviços ocultos Tor (padrão: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
- <translation>Aviso: Versões de bloco desconhecidas sendo mineradas! É possível que regras estranhas estejam ativas</translation>
+ <translation>Aviso: Versões de bloco desconhecidas sendo mineradas! É possível que regras desconhecidas estejam ativas</translation>
</message>
<message>
<source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
<translation>Atenção: Arquivo da carteira corrompido, dados recuperados! Original %s salvo como %s em %s; se seu saldo ou transações estiverem incorretos, você deve restaurar o backup.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Lista Branca de conecções do endereço IP informado (ex: 1.2.3.4) ou com máscara de rede (ex: 1.2.3.0/24). Pode ser especificado várias vezes.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
- <translation>%s está muito alto!</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(padrão: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Sempre pergunte pelo endereço de peer via pesquisa DNS (padrão: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Erro ao carregar carteira %s. Nome do arquivo de -wallet deve ser um arquivo regular.</translation>
+ <translation>%s está muito alto!</translation>
</message>
<message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Erro ao carregar carteira %s. Duplicado o nome do arquivo de -wallet.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Erro ao carregar carteira %s. Caracteres inválidos no nome do arquivo de -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Quantos blocos devem ser checados ao iniciar (padrão: %u, 0 = todos)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Incluir endereço IP na saída de depuração (padrão: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
- <translation>Erro na Keypool, favor executar keypoolrefill primeiro</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escutar por conexões JSON-RPC na porta &lt;port&gt; (padrão: %u ou testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Aguardar por conexões na porta &lt;port&gt; (padrão: %u ou testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Manter, no máximo, &lt;n&gt; conexões com peers (padrão: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Fazer a carteira transmitir transações</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Buffer máximo de recebimento por conexão, &lt;n&gt;*1000 bytes (padrão: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Buffer máximo de envio por conexão, &lt;n&gt;*1000 bytes (padrão: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Adiciona timestamp como prefixo no debug (padrão: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Transações de dados de operadora (padrão: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Retransmitir P2SH não multisig (padrão: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Defina o tamanho da chave para piscina&lt;n&gt; (padrão: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Define a altura máxima BIP141 do bloco (padrão: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Defina o número de threads para chamadas do serviço RPC (padrão: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Especificar arquivo de configuração (padrão: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Especificar tempo para desistência de conexões, em mili segundos (mínimo: 1, padrão: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Especificar arquivo pid (padrão: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Gastar troco não confirmado quando enviar transações (padrão: %u)</translation>
+ <translation>Keypool exaurida, por gentileza execute keypoolrefill primeiro</translation>
</message>
<message>
<source>Starting network threads...</source>
- <translation>Iniciando análise da rede...</translation>
+ <translation>Iniciando threads de rede...</translation>
</message>
<message>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>A carteira irá evitar pagar menos que a taxa mínima.</translation>
+ <translation>A carteira irá evitar pagar menos que a taxa mínima de retransmissão.</translation>
</message>
<message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Esta é a taxa mínima que você deve pagar em cada transação.</translation>
+ <translation>Esta é a taxa mínima que você paga em todas as transação.</translation>
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Esta é a taxa que você irá pagar se enviar a transação.</translation>
- </message>
- <message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Limite para desconectar peers mal comportados (padrão: %u)</translation>
+ <translation>Esta é a taxa que você irá pagar se enviar uma transação.</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
- <translation>As quantidades das transações devem ser positivas.</translation>
+ <translation>As quantidades nas transações não podem ser negativas.</translation>
</message>
<message>
<source>Transaction has too long of a mempool chain</source>
@@ -4020,7 +3614,7 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
</message>
<message>
<source>Transaction must have at least one recipient</source>
- <translation>A transação deve ter ao menos um destinatário</translation>
+ <translation>A transação deve ter ao menos um destinatário</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
@@ -4031,6 +3625,26 @@ Esta sincronização inicial é muito exigente e pode expor problemas de hardwar
<translation>Saldo insuficiente</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Não é possível gerar um endereço de troco. Chaves privadas estão desabilitadas para essa carteira.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Não é possível fazer upgrade de uma carteira dividida não HD sem fazer upgrade para ser compatível com a keypool antes da divisão. Use -upgradewallet=169900 ou -upgradewallet sem especificar nenhuma versão.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Falha na estimativa de taxa. Fallbackfee desativada. Espere alguns blocos ou ative -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Aviso: Chaves privadas detectadas na carteira {%s} com chaves privadas desativadas</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Não foi possível escrever no diretório de dados '%s': verifique as permissões.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Carregando índice de blocos...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts
index ab01aa23f4..d203c490e9 100644
--- a/src/qt/locale/bitcoin_pt_PT.ts
+++ b/src/qt/locale/bitcoin_pt_PT.ts
@@ -30,6 +30,10 @@
<translation>Eliminar o endereço selecionado da lista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Digite o endereço ou o rótulo para pesquisar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportar os dados no separador atual para um ficheiro</translation>
</message>
@@ -67,7 +71,7 @@
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Estes são os seus endereços Bitcoin para receber pagamentos. É recomendado que utilize um endereço novo para cada transacção.</translation>
+ <translation>Estes são os seus endereços Bitcoin para receber pagamentos. É recomendado que utilize um endereço novo para cada transação.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -185,7 +189,7 @@
</message>
<message>
<source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 irá agora ser fechado para terminar o processo de encriptação. Recorde que a encriptação da sua carteira não protegerá totalmente os seus bitcoins de serem roubados por programas maliciosos que infectem o seu computador.</translation>
+ <translation>%1 irá agora ser fechado para terminar o processo de encriptação. Recorde que a encriptação da sua carteira não protegerá totalmente os seus bitcoins de serem roubados por programas maliciosos que infetem o seu computador.</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
@@ -322,6 +326,14 @@
<translation>Abrir &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Carteira:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>carteira predefinida</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Clique para desativar a atividade de rede.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>A reindexar os blocos no disco...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy está &lt;b&gt;ativado&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Enviar moedas para um endereço Bitcoin</translation>
</message>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Carteira: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Tipo: %1
@@ -730,10 +752,6 @@
<translation>E&amp;ndereço</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Novo endereço de depósito</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Novo endereço de envio</translation>
</message>
@@ -750,10 +768,6 @@
<translation>O endereço introduzido "%1" não é um endereço bitcoin válido.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>O endereço introduzido "%1" já se encontra no livro de endereços.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Não foi possível desbloquear a carteira.</translation>
</message>
@@ -766,7 +780,7 @@
<name>FreespaceChecker</name>
<message>
<source>A new data directory will be created.</source>
- <translation>Será criada uma nova diretoria de dados.</translation>
+ <translation>Será criada uma nova pasta de dados.</translation>
</message>
<message>
<source>name</source>
@@ -778,11 +792,11 @@
</message>
<message>
<source>Path already exists, and is not a directory.</source>
- <translation>O caminho já existe, e este não é uma pasta.</translation>
+ <translation>O caminho já existe, e não é uma pasta.</translation>
</message>
<message>
<source>Cannot create data directory here.</source>
- <translation>Não é possível criar aqui uma diretoria de dados.</translation>
+ <translation>Não é possível criar aqui uma pasta de dados.</translation>
</message>
</context>
<context>
@@ -803,42 +817,6 @@
<source>Command-line options</source>
<translation>Opções da linha de comando</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Utilização:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>opções da linha de comando</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opções da IU:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Escolher a pasta de dados no arranque (predefinição: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Definir idioma, por exemplo "pt_PT" (predefinição: idioma do sistema)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Iniciar minimizado</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Definir certificados de raiz SSL para pedidos de pagamento (predefinição: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Mostrar o ecrã de abertura no arranque (predefinição: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Redefinir todas as definições alteradas na GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -851,6 +829,18 @@
<translation>Bem-vindo ao %1.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>Quando clicar OK, %1 vai começar a descarregar e processar a cadeia de blocos %4 completa (%2GB) começando com as transações mais antigas em %3 quando a %4 foi inicialmente lançada.</translation>
+ </message>
+ <message>
+ <source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
+ <translation>Esta sincronização inicial é muito exigente, e pode expor problemas com o seu computador que previamente podem ter passado despercebidos. Cada vez que corre %1, este vai continuar a descarregar de onde deixou. </translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>Se escolheu limitar o armazenamento da cadeia de blocos (poda), a data histórica ainda tem de ser descarregada e processada, mas irá ser apagada no final para manter uma utilização baixa do espaço de disco.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>Utilizar a pasta de dados predefinida</translation>
</message>
@@ -863,12 +853,20 @@
<translation>Bitcoin</translation>
</message>
<message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>No mínimo %1 GB de dados irão ser armazenados nesta pasta. </translation>
+ </message>
+ <message>
<source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Aproximadamente %1 GB de dados irão ser guardados nesta directoria. </translation>
+ <translation>Aproximadamente %1 GB de dados irão ser guardados nesta pasta. </translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>%1 irá descarregar e armazenar uma cópia da cadeia de blocos da Bitcoin.</translation>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation>A carteira também será guardada nesta directoria.</translation>
+ <translation>A carteira também será guardada nesta pasta.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
@@ -996,6 +994,18 @@
<translation>Endereço de IP do proxy (exemplo, IPv4: 127.0.0.1 / IPv6: ::1)</translation>
</message>
<message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation>Mostra se o padrão fornecido SOCKS5 proxy, está a ser utilizado para alcançar utilizadores participantes através deste tipo de rede. </translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Utilize um proxy SOCKS&amp;5 separado para alcançar utilizadores participantes através dos serviços ocultos do Tor.</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Esconder o ícone da barra de ferramentas.</translation>
+ </message>
+ <message>
<source>&amp;Hide tray icon</source>
<translation>&amp;Ocultar ícone da bandeja</translation>
</message>
@@ -1013,6 +1023,10 @@
<translation>Ativar as opções da linha de comando que se sobrepõem às opções acima:</translation>
</message>
<message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Abrir o ficheiro de configuração %1 da pasta aberta.</translation>
+ </message>
+ <message>
<source>Open Configuration File</source>
<translation>Abrir Ficheiro de Configuração</translation>
</message>
@@ -1029,6 +1043,10 @@
<translation>&amp;Rede</translation>
</message>
<message>
+ <source>GB</source>
+ <translation>PT</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = automático, &lt;0 = deixar essa quantidade de núcleos livre)</translation>
</message>
@@ -1082,11 +1100,11 @@
</message>
<message>
<source>&amp;Port:</source>
- <translation>&amp;Porto:</translation>
+ <translation>&amp;Porta:</translation>
</message>
<message>
<source>Port of the proxy (e.g. 9050)</source>
- <translation>Porto do proxy (p.ex. 9050)</translation>
+ <translation>Porta do proxy (por ex. 9050)</translation>
</message>
<message>
<source>Used for reaching peers via:</source>
@@ -1185,6 +1203,10 @@
<translation>Opções da configuração</translation>
</message>
<message>
+ <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
+ <translation>O ficheiro de configuração é usado para especificar opções de utilizador avançado, que sobrescrevem as configurações do interface gráfico. Adicionalmente, qualquer opção da linha de comandos vai sobrescrever este ficheiro de configuração. </translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Erro</translation>
</message>
@@ -1213,7 +1235,7 @@
</message>
<message>
<source>Watch-only:</source>
- <translation>Modo-verificação:</translation>
+ <translation>Apenas vigiar:</translation>
</message>
<message>
<source>Available:</source>
@@ -1241,7 +1263,7 @@
</message>
<message>
<source>Balances</source>
- <translation>Balanços</translation>
+ <translation>Saldos</translation>
</message>
<message>
<source>Total:</source>
@@ -1249,11 +1271,11 @@
</message>
<message>
<source>Your current total balance</source>
- <translation>O seu saldo total actual</translation>
+ <translation>O seu saldo total atual</translation>
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>O seu balanço atual em endereços de apenas observação</translation>
+ <translation>O seu balanço atual em endereços de apenas vigiar</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1265,15 +1287,15 @@
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Transações não confirmadas para endereços modo-verificação</translation>
+ <translation>Transações não confirmadas para endereços de apenas vigiar</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Saldo minado ainda não disponivél de endereços modo-verificação</translation>
+ <translation>Saldo minado ainda não disponível de endereços de apenas vigiar</translation>
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation>Saldo disponivél em enderços modo-verificação</translation>
+ <translation>Saldo disponível em endereços de apenas vigiar</translation>
</message>
</context>
<context>
@@ -1291,6 +1313,10 @@
<translation>Manuseamento de URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' não é um URI válido. Utilize 'bitcoin:'.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>O URL do pedido de pagamento é inválido: %1</translation>
</message>
@@ -1300,7 +1326,7 @@
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>URI não foi lido correctamente! Isto pode ser causado por um endereço Bitcoin inválido ou por parâmetros URI malformados.</translation>
+ <translation>URI não foi lido corretamente! Isto pode ser causado por um endereço Bitcoin inválido ou por parâmetros URI malformados.</translation>
</message>
<message>
<source>Payment request file handling</source>
@@ -1402,7 +1428,7 @@
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Entre um endereço Bitcoin (ex. %1)</translation>
+ <translation>Introduza um endereço Bitcoin (ex. %1)</translation>
</message>
<message>
<source>%1 d</source>
@@ -1488,12 +1514,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Erro ao analisar os argumentos da linha de comando: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Erro: Pasta de dados especificada "%1" não existe.</translation>
+ <translation>Erro: a pasta de dados especificada "%1" não existe.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Erro: não é possível analisar o ficheiro de configuração: %1. Utilize apenas a sintaxe key=value.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Erro: não é possível analisar o ficheiro de configuração: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1571,7 +1601,7 @@
</message>
<message>
<source>Current number of blocks</source>
- <translation>Número actual de blocos</translation>
+ <translation>Número atual de blocos</translation>
</message>
<message>
<source>Memory Pool</source>
@@ -1579,13 +1609,21 @@
</message>
<message>
<source>Current number of transactions</source>
- <translation>Número actual de transacções</translation>
+ <translation>Número atual de transações</translation>
</message>
<message>
<source>Memory usage</source>
<translation>Utilização de memória</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Carteira:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(nenhuma)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Reiniciar</translation>
</message>
@@ -1615,7 +1653,7 @@
</message>
<message>
<source>Direction</source>
- <translation>Direcção</translation>
+ <translation>Direção</translation>
</message>
<message>
<source>Version</source>
@@ -1639,7 +1677,7 @@
</message>
<message>
<source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
- <translation>Abrir o ficheiro de registo de depuração %1 da pasta de dados actual. Isto pode demorar alguns segundos para ficheiros de registo maiores.</translation>
+ <translation>Abrir o ficheiro de registo de depuração %1 da pasta de dados atual. Isto pode demorar alguns segundos para ficheiros de registo maiores.</translation>
</message>
<message>
<source>Decrease font size</source>
@@ -1663,11 +1701,11 @@
</message>
<message>
<source>Last Send</source>
- <translation>Ultimo Envio</translation>
+ <translation>Último Envio</translation>
</message>
<message>
<source>Last Receive</source>
- <translation>Ultimo Recebimento</translation>
+ <translation>Último Recebimento</translation>
</message>
<message>
<source>Ping Time</source>
@@ -1750,18 +1788,42 @@
<translation>&amp;Desbanir</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>carteira predefinida</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Bem-vindo à consola RPC da %1.</translation>
</message>
<message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>Use as setas para cima e para baixo para navegar a história e %1 para limpar o ecrã.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Digite %1 para uma visão geral dos comandos disponíveis.</translation>
+ </message>
+ <message>
<source>For more information on using this console type %1.</source>
<translation>Para mais informação em como utilizar esta consola, digite %1.</translation>
</message>
<message>
+ <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
+ <translation>AVISO: alguns burlões têm estado ativos, dizendo a utilizadores para digitarem comandos aqui, roubando assim os conteúdos das suas carteiras. Não utilize esta consola sem perceber perfeitamente as ramificações de um comando.</translation>
+ </message>
+ <message>
<source>Network activity disabled</source>
<translation>Atividade de rede desativada</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>A executar o comando sem qualquer carteira</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>A executar o comando utilizando a carteira "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(id nó: %1)</translation>
</message>
@@ -1833,6 +1895,14 @@
<translation>Limpar</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Endereços nativos SegWit (também conhecidos como Bech32 ou BIP-173) reduzem as taxas da sua transação mais tarde e oferecem melhor proteção contra erros, mas carteiras antigas não os suportam. Quando não selecionado, um endereço compatível com carteiras antigas irá ser criado em vez.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Gerar endereço nativo SegWit (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Histórico de pagamentos solicitados</translation>
</message>
@@ -1842,7 +1912,7 @@
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Mostrar o pedido seleccionado (faz o mesmo que clicar 2 vezes numa entrada)</translation>
+ <translation>Mostrar o pedido selecionado (faz o mesmo que clicar 2 vezes numa entrada)</translation>
</message>
<message>
<source>Show</source>
@@ -1850,7 +1920,7 @@
</message>
<message>
<source>Remove the selected entries from the list</source>
- <translation>Remover as entradas seleccionadas da lista</translation>
+ <translation>Remover as entradas selecionadas da lista</translation>
</message>
<message>
<source>Remove</source>
@@ -1920,6 +1990,10 @@
<translation>Mensagem</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Carteira</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI resultante muito longo. Tente reduzir o texto do rótulo / mensagem.</translation>
</message>
@@ -2034,16 +2108,12 @@
<translation>por kilobyte</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Se a taxa personalizada estiver definida para 1.000 satoshis e a transação é de apenas 250 bytes, então paga apenas 250 satoshis "por kilobyte" na taxa, enquanto em "total pelo menos" paga 1.000 satoshis. Para transações superiores a um kilobyte ambos pagam por kilobyte.</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Esconder</translation>
</message>
<message>
<source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation>Pode pagar somente a taxa minima desde que haja um volume de transações inferior ao espaço nos blocos. No entanto tenha em atenção que esta opção poderá acabar em uma transação nunca confirmada assim que os pedidos de transações excedam a capacidade de processamento da rede.</translation>
+ <translation>Pode pagar somente a taxa mínima desde que haja um volume de transações inferior ao espaço nos blocos. No entanto tenha em atenção que esta opção poderá acabar em uma transação nunca confirmada assim que os pedidos de transações excedam a capacidade de processamento da rede.</translation>
</message>
<message>
<source>(read the tooltip)</source>
@@ -2055,7 +2125,7 @@
</message>
<message>
<source>Custom:</source>
- <translation>Uso:</translation>
+ <translation>Personalizado:</translation>
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
@@ -2126,6 +2196,10 @@
<translation>Copiar troco</translation>
</message>
<message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blocos)</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 para %2</translation>
</message>
@@ -2134,16 +2208,24 @@
<translation>Tem a certeza que deseja enviar?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>adicionado como taxa de transação</translation>
+ <source>or</source>
+ <translation>ou</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Quantia Total %1</translation>
+ <source>from wallet %1</source>
+ <translation>da carteira %1</translation>
</message>
<message>
- <source>or</source>
- <translation>ou</translation>
+ <source>Please, review your transaction.</source>
+ <translation>Por favor, reveja a sua transação.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Taxa de transação</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Valor Total</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2360,7 +2442,7 @@
</message>
<message>
<source>Copy the current signature to the system clipboard</source>
- <translation>Copiar a assinatura actual para a área de transferência</translation>
+ <translation>Copiar a assinatura atual para a área de transferência</translation>
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
@@ -2384,7 +2466,7 @@
</message>
<message>
<source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation>Introduza o endereço de assinatura, mensagem (assegure-se que copia quebras de linha, espaços, tabulações, etc. exactamente) e assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem.</translation>
+ <translation>Introduza o endereço de assinatura, mensagem (assegure-se que copia quebras de linha, espaços, tabulações, etc. exatamente) e assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem.</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
@@ -2476,10 +2558,6 @@
<translation>Aberto até %1</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/off-line</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/não confirmada, %1</translation>
</message>
@@ -2508,10 +2586,6 @@
<translation>Estado</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, ainda não foi transmitido com sucesso</translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2541,7 +2615,7 @@
</message>
<message>
<source>watch-only</source>
- <translation>vigiar apenas</translation>
+ <translation>apenas vigiar</translation>
</message>
<message>
<source>label</source>
@@ -2551,6 +2625,10 @@
<source>Credit</source>
<translation>Crédito</translation>
</message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>matura em %n bloco</numerusform><numerusform>matura em %n blocos</numerusform></translation>
+ </message>
<message>
<source>not accepted</source>
<translation>não aceite</translation>
@@ -2592,6 +2670,10 @@
<translation>Tamanho total da transição</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Tamanho da transação virtual</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Índex de saída</translation>
</message>
@@ -2600,6 +2682,10 @@
<translation>Comerciante</translation>
</message>
<message>
+ <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation>As moedas geradas precisam amadurecer %1 blocos antes que possam ser gastas. Quando gerou este bloco, ele foi transmitido para a rede para ser adicionado à cadeia de blocos. Se este não conseguir entrar na cadeia, seu estado mudará para "não aceite" e não poderá ser gasto. Isto pode acontecer ocasionalmente se outro nó gerar um bloco dentro de alguns segundos do seu.</translation>
+ </message>
+ <message>
<source>Debug information</source>
<translation>Informação de depuração</translation>
</message>
@@ -2658,10 +2744,6 @@
<translation>Aberto até %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Off-line</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Não confirmado</translation>
</message>
@@ -2670,6 +2752,10 @@
<translation>Abandonada</translation>
</message>
<message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>Confirmando (%1 de %2 confirmações recomendadas)</translation>
+ </message>
+ <message>
<source>Confirmed (%1 confirmations)</source>
<translation>Confirmada (%1 confirmações)</translation>
</message>
@@ -2678,8 +2764,8 @@
<translation>Incompatível</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Este bloco não foi recepcionado por outro nó e provavelente não será aceite!</translation>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>Imaturo (%1 confirmações, estarão disponível após %2)</translation>
</message>
<message>
<source>Generated but not accepted</source>
@@ -2707,7 +2793,7 @@
</message>
<message>
<source>watch-only</source>
- <translation>vigiar apenas</translation>
+ <translation>apenas vigiar</translation>
</message>
<message>
<source>(n/a)</source>
@@ -2730,6 +2816,14 @@
<translation>Tipo de transação.</translation>
</message>
<message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>Se um endereço de apenas vigiar está ou não envolvido nesta transação.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>Intenção do utilizador/motivo da transação</translation>
+ </message>
+ <message>
<source>Amount removed from or added to balance.</source>
<translation>Montante retirado ou adicionado ao saldo</translation>
</message>
@@ -2785,6 +2879,10 @@
<translation>Outras</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Escreva endereço, identificação de transação ou rótulo para procurar</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Valor mín.</translation>
</message>
@@ -2842,7 +2940,7 @@
</message>
<message>
<source>Watch-only</source>
- <translation>Vigiar apenas</translation>
+ <translation>Apenas vigiar</translation>
</message>
<message>
<source>Date</source>
@@ -2869,6 +2967,10 @@
<translation>Exportação Falhou</translation>
</message>
<message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>Ocorreu um erro ao tentar guardar o histórico de transações em %1.</translation>
+ </message>
+ <message>
<source>Exporting Successful</source>
<translation>Exportação Bem Sucedida</translation>
</message>
@@ -2902,6 +3004,18 @@
<translation>Enviar Moedas</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>Erro no aumento de taxa</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Aumento da taxa de transação falhou</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>Quer aumentar a taxa?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Taxa atual:</translation>
</message>
@@ -2914,10 +3028,18 @@
<translation>Nova taxa:</translation>
</message>
<message>
+ <source>Confirm fee bump</source>
+ <translation>Confirme aumento de taxa</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Não é possível assinar a transação.</translation>
</message>
- </context>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>Não foi possível cometer a transação</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -2948,32 +3070,20 @@
<source>Backup Successful</source>
<translation>Cópia de Segurança Bem Sucedida</translation>
</message>
- </context>
-<context>
- <name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opções:</translation>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>Os dados da carteira foram guardados com sucesso em %1.</translation>
</message>
<message>
- <source>Specify data directory</source>
- <translation>Especificar pasta de dados</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Ligar a um nó para recuperar endereços de pontos, e desligar</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Especifique o seu endereço público</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Aceitar comandos de linha de comandos e JSON-RPC</translation>
+ <source>Cancel</source>
+ <translation>Cancelar</translation>
</message>
+</context>
+<context>
+ <name>bitcoin-core</name>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Se &lt;category&gt; não é fornecida ou &lt;category&gt; = 1, imprimir toda a informação de depuração.</translation>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation>Distribuído sob licença de software MIT, veja o ficheiro %s ou %s</translation>
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
@@ -2981,29 +3091,21 @@
</message>
<message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
- <translation>Suprimir: a última sincronização da carteira vai além dos dados suprimidos. O que precisa para -reindex (transferir novamente toda a cadeia de blocos, no caso de nó suprimido)</translation>
+ <translation>Poda: a última sincronização da carteira vai além dos dados podados. Precisa de -reindex (descarregar novamente a cadeia de blocos completa em caso de nó podado)</translation>
</message>
<message>
<source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Reanálises não são possíveis no modo de suprimir. Para isso terá de utilizar -reindex que irá transferir novamente toda a cadeia de blocos.</translation>
+ <translation>Reanálises não são possíveis em modo poda. Terá de utilizar -reindex que irá descarregar novamente a cadeia de blocos completa</translation>
</message>
<message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>Erro: Um erro fatal interno ocorreu, verificar debug.log para mais informação</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Taxa (em %s/kB) para adicionar às transações que envia (predefinição: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>A podar a blockstore...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Correr o processo em segundo plano e aceitar comandos</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Não é possível iniciar o servidor HTTP. Verifique o debug.log para detalhes.</translation>
</message>
@@ -3016,44 +3118,32 @@
<translation>Os programadores de %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Uma percentagem da taxa (em %s/kB) que será utilizada quando a estimativa da taxa tiver dados insuficientes (predefinição: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Aceitar as transações retransmitidas recebidas dos pontos na lista branca, mesmo quando não retransmitir as transações (predefinição: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Associar a endereço específico e escutar sempre nele. Use a notação [anfitrião]:porta para IPv6</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Apague todas as transações da carteira e somente restore aquelas que façam parte do blockchain através de re-scan ao reiniciar o programa</translation>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>Não foi possível obter o bloqueio de escrita no da pasta de dados %s. %s provavelmente já está a ser executado.</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Executar o comando quando uma transação da carteira muda (no comando, %s é substituído pela Id. da Transação)</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Não é possível fornecer conexões específicas e ter o addrman a procurar conexões de saída ao mesmo tempo.</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>Por favor verifique que a data e hora do seu computador estão certos! Se o relógio não estiver certo, o %s não funcionará corretamente.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Consultar por endereços de ponto via procura de DNS, se tiver poucos endereços (predefinição: 1, a menos que use -connect)</translation>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Por favor, contribua se achar que %s é útil. Visite %s para mais informação sobre o software.</translation>
</message>
<message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Defina o número de processos de verificação (%u até %d, 0 = automático, &lt;0 = ldisponibiliza esse número de núcleos livres, por defeito: %d)</translation>
+ <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
+ <translation>A base de dados de blocos contém um bloco que aparenta ser do futuro. Isto pode ser causado por uma data incorreta definida no seu computador. Reconstrua apenas a base de dados de blocos caso tenha a certeza de que a data e hora do seu computador estão corretos.</translation>
</message>
<message>
- <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
- <translation>A base de dados de blocos contém um bloco que aparenta ser do futuro. Isto pode ser causado por uma data incorrecta definida no seu computador. Reconstrua apenas a base de dados de blocos caso tenha a certeza de que a data e hora do seu computador estão correctos.</translation>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>Esta é a taxa de transação que poderá descartar, se o troco for menor que o pó a este nível</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Utilizar UPnP para mapear a porta de escuta (predefinição: 1 quando escutar e sem -proxy)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Não é possível rebobinar a base de dados para um estado antes da divisão da cadeia de blocos. Necessita descarregar novamente a cadeia de blocos </translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -3072,78 +3162,22 @@
<translation>- máximo do banco de memória deverá ser pelo menos %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;categoria&gt; pode ser:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Aceitar ligações externas (padrão: 1 sem -proxy ou -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Anexar um comentário para a entrada de agente do utilizador</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Tentar reuperar as chaves privadas de um "wallet" ao iniciar</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opções da criação de bloco:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Não é possível resolver -%s endereço '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Opções de seleção da cadeia:</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Opções de ligação:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Direitos de Autor (C) %i-%i</translation>
</message>
<message>
<source>Corrupted block database detected</source>
- <translation>Cadeia de blocos corrompida detectada</translation>
- </message>
- <message>
- <source>Debugging/Testing options:</source>
- <translation>Opções de Depuração/Teste:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Não carregar a carteira e desativar as chamadas de RPC da carteira.</translation>
+ <translation>Detetada cadeia de blocos corrompida</translation>
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
<translation>Deseja reconstruir agora a base de dados de blocos.</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Activar publicação do hash do bloco em &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Activar publicação do hash da transacção em &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Activar publicação de dados brutos do bloco em &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Activar publicação de dados brutos da transacção em &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Ativar substituição da transação no banco de memória (predefinição: %u)</translation>
- </message>
- <message>
<source>Error initializing block database</source>
<translation>Erro ao inicializar a cadeia de blocos</translation>
</message>
@@ -3180,6 +3214,10 @@
<translation>Falhou a escutar em qualquer porta. Use -listen=0 se quiser isto.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Reexaminação da carteira falhou durante a inicialização</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>A importar...</translation>
</message>
@@ -3188,6 +3226,10 @@
<translation>Bloco génese incorreto ou nenhum bloco génese encontrado. Pasta de dados errada para a rede?</translation>
</message>
<message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>Verificação de integridade inicial falhou. O %s está a desligar-se.</translation>
+ </message>
+ <message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
<translation>Valor inválido para -%s=&lt;amount&gt;: '%s'</translation>
</message>
@@ -3196,8 +3238,9 @@
<translation>Valor inválido para -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Manter o banco de memória da transação abaixo de &lt;n&gt; megabytes (predefinição: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>
+A pasta de blocos especificados "%s" não existe.</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3208,26 +3251,10 @@
<translation>A carregar a lista de banir...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Localização de cookie de autorização (predefinição: diretoria de dados)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Os descritores de ficheiros disponíveis são insuficientes.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Somente conectar aos nodes na rede &lt;net&gt; (ipv4, ipv6 ou onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Imprimir esta mensagem de ajuda e sair</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Imprimir versão e sair</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Poda não pode ser configurada com um valor negativo.</translation>
</message>
@@ -3236,12 +3263,20 @@
<translation>Modo poda é incompatível com -txindex.</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Definir o tamanho da cache de base de dados em megabytes (%d a %d, padrão: %d)</translation>
+ <source>Replaying blocks...</source>
+ <translation>Repetindo blocos...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>A rebobinar blocos...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>O código fonte está disponível pelo %s.</translation>
</message>
<message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Especifique ficheiro de carteira (dentro da pasta de dados)</translation>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>Cálculo da taxa de transação e de troco falhou</translation>
</message>
<message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
@@ -3260,14 +3295,6 @@
<translation>A atualizar a base de dados UTXO</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Utilizar UPnP para mapear a porta de escuta (predefinição: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Utilize a cadeia de testes</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Comentário no User Agent (%s) contém caracteres inseguros.</translation>
</message>
@@ -3276,94 +3303,30 @@
<translation>A verificar blocos...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opções de depuração/testes da carteira:</translation>
- </message>
- <message>
- <source>Wallet options:</source>
- <translation>Opções da carteira:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permitir conexções JSON-RPC de fontes especificas. Valido para &lt;ip&gt; um unico IP (ex. 1.2.3.4), uma rede/netmask (ex. 1.2.3.4/255.255.255.0) ou uma rede/CIDR (ex. 1.2.3.4/24). Esta opção pode ser especificada varias vezes</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Associar ao endereço indicado e pontos da lista branca ligando-se a ele. Utilize a notação [anfitrião]:porta para IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Crie ficheiros novos com as permisões predefinidas do sistema, em vez de umask 077 (apenas eficaz caso a funcionalidade carteira esteja desactivada)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Descobrir o próprio endereço IP (padrão: 1 ao escutar e sem -externalip ou -proxy)</translation>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>A carteira precisou de ser reescrita: reinicie %s para completar</translation>
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Erro: A escuta de ligações de entrada falhou (escuta devolveu erro %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Executar comando quando um alerta relevante for recebido ou em caso de uma divisão longa da cadeia de blocos (no comando, %s é substituído pela mensagem)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Taxas (em %s/kB) inferiores a este valor são consideradas nulas para propagação, mineração e criação de transações (predefinição: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Caso o paytxfee não seja definido, inclua uma taxa suficiente para que as transacções comecem a ser confirmadas, em média, dentro de n blocos (padrão: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Montante inválido para -maxtxfee=&lt;amount&gt;: '%s' (deverá ser, no mínimo , a taxa mínima de propagação de %s, de modo a evitar transações bloqueadas)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Tamanho máximo dos dados em transacções que incluem dados que propagamos e mineramos (padrão: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Usar credenciais aleatórias por cada ligação proxy. Permite que o Tor use stream isolation (padrão: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>O montante da transacção é demasiado baixo após a dedução da taxa</translation>
- </message>
- <message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Os pontos enviados para a lista branca não podem ser DoS banidos e as suas transações são sempre retransmitidas, mesmo que já estejam no banco de memória, útil, por exemplo, para um acesso</translation>
+ <translation>O montante da transação é demasiado baixo após a dedução da taxa</translation>
</message>
<message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
- <translation>É necessário reconstruir a base de dados, utilizando -reindex para voltar ao modo de suprimir. Isto irá transferir novamente a cadeia de blocos completa</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(predefinição: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Aceitar pedidos REST públicos (predefinição: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Criar automaticamente o serviço Tor oculto (predefinição: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Ligar através de um proxy SOCKS5</translation>
+ <translation>Necessita reconstruir a base de dados, utilizando -reindex para voltar ao modo sem poda. Isto irá descarregar novamente a cadeia de blocos completa</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
<translation>Erro ao ler da base de dados, encerrando.</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importar blocos de um ficheiro blk000??.dat externo ao iniciar</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informação</translation>
</message>
@@ -3380,68 +3343,36 @@
<translation>Máscara de rede inválida especificada em -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Manter no máximo &lt;n&gt; transacções órfãs em memória (padrão: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Necessário especificar uma porta com -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Opções da transmissão de nós:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opções do servidor RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reduzindo -maxconnections de %d para %d, devido a limitações no sistema.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Procurar transacções em falta na cadeia de blocos ao iniciar</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Enviar informação de rastreio/depuração para a consola e não para o ficheiro debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Mostrar todas as opções de depuração (utilização: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Encolher ficheiro debug.log ao iniciar o cliente (por defeito: 1 sem -debug definido)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Falhou assinatura da transação</translation>
</message>
<message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>O -walletdir "%s" especificado não é uma pasta</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to pay the fee</source>
- <translation>O montante da transacção é demasiado baixo para pagar a taxa</translation>
+ <translation>O montante da transação é demasiado baixo para pagar a taxa</translation>
</message>
<message>
<source>This is experimental software.</source>
<translation>Isto é software experimental.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Palavra-passe da porta de controlo Tor (predefinição: vazio)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Porta de controlo Tor a utilizar se a escuta cebola estiver ativada (predefinição: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Quantia da transação é muito baixa</translation>
</message>
<message>
<source>Transaction too large for fee policy</source>
- <translation>Transacção demasiado grande para a política de taxas</translation>
+ <translation>Transação demasiado grande para a política de taxas</translation>
</message>
<message>
<source>Transaction too large</source>
@@ -3452,18 +3383,18 @@
<translation>Incapaz de vincular à porta %s neste computador (vínculo retornou erro %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Actualizar carteira para o formato mais recente ao iniciar</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Nome de utilizador para ligações JSON-RPC</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Incapaz de gerar as chaves iniciais</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>A verificar a(s) carteira(s)...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>A carteira %s reside fora da pasta da carteira %s</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Aviso</translation>
</message>
@@ -3472,64 +3403,12 @@
<translation>Aviso: ativadas novas regras desconhecidas (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Se operar apenas num modo de blocos (predefinição: %u)</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>A limpar todas as transações da carteira...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Opções de notificação ZeroMQ:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Palavra-passe para ligações JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Executar o comando quando o melhor bloco muda (no comando, %s é substituído pela hash do bloco)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permitir procuras DNS para -addnode, -seednode e -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = guardar metadados da transacção ex: proprietário da conta e informação do pedido de pagamento, 2 = descartar metadados da transacção)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation>-maxtxfee está definido com um valor muito alto! Taxas desta magnitude podem ser pagas numa única transacção.</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Não guardar transações no banco de memória por mais de &lt;n&gt; horas (predefinição: %u)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Taxas (em %s/kB) abaixo deste valor são consideradas nulas para a criação de transacções (padrão: %s)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Minuciosidade da verificação de blocos para -checkblocks é (0-4, padrão: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Manter um índice de transacções completo, usado pela chamada RPC getrawtransaction (padrão: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Número de segundos a impedir que os pontos com mau comportamento se religuem (predefinição: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Informação de depuração (padrão: %u, fornecer uma &lt;category&gt; é opcional)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Suportar filtragem de blocos e transacções com fitros bloom (padrão: %u)</translation>
+ <translation>-maxtxfee está definido com um valor muito alto! Taxas desta magnitude podem ser pagas numa única transação.</translation>
</message>
<message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
@@ -3544,10 +3423,6 @@
<translation>Comprimento total da entrada da versão de rede (%i) excede o comprimento máximo (%i). Reduzir o número ou o tamanho de uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Tenta manter o tráfego externo abaixo do limite especificado (em MiB por 24h), 0 = sem limite (padrão: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Encontrado um argumento não suportado -socks. Definir a versão do SOCKS já não é possível, apenas proxies SOCKS5 são suportados.</translation>
</message>
@@ -3556,10 +3431,6 @@
<translation>Argumento não suportado -whitelistalwaysrelay ignorado, utilize -whitelistrelay e/ou -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Utilize um proxy SOCKS5 separado para alcançar os pontos via serviços ocultos do Tor (predefinição: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Atenção: Versões desconhecidas de blocos estão a ser mineradas! É possível que regras desconhecias estão a ser efetuadas</translation>
</message>
@@ -3568,94 +3439,18 @@
<translation>%s está demasiado elevado!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(predefinição: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Consultar sempre os endereços de ponto via procura de DNS (predefinição: %u)</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Quantos blocos para verificar no arranque (predefinição: %u, 0 = todos)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Incluir endereços de IP na informação de depuração (predefinição: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escutar por ligações JSON-RPC na porta &lt;port&gt; (predefinição: %u ou rede de testes: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Escute ligações na porta &lt;port&gt; (por defeito: %u ou testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Manter no máximo &lt;n&gt; ligações para os pontos (predefinição: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Colocar a carteira a transmitir transacções</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximo armazenamento intermédio de recepção por ligação, &lt;n&gt;*1000 bytes (por defeito: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximo armazenamento intermédio de envio por ligação, &lt;n&gt;*1000 bytes (por defeito: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Adicionar data e hora à informação de depuração (por defeito: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Propagar e minerar transacções que incluem dados (padrão: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Propagar não P2SH multisig (predefinição: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Definir tamanho do banco de memória da chave para &lt;n&gt; (predefinição: %u)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Defina o número de processos para servir as chamadas RPC (por defeito: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Especificar ficheiro de configuração (por defeito: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Especificar tempo de espera da ligação em milissegundos (mínimo 1, por defeito: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Especificar ficheiro pid (padrão: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Gastar o troco não confirmado quando enviar transações (predefinição: %u)</translation>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>A carteira evitará pagar menos que a taxa minima de propagação.</translation>
</message>
<message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>É a taxa de transação mínima que paga em cada transação.</translation>
+ <translation>Esta é a taxa minima de transação que paga em cada transação.</translation>
</message>
<message>
<source>This is the transaction fee you will pay if you send a transaction.</source>
<translation>Esta é a taxa de transação que irá pagar se enviar uma transação.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Tolerância para desligar pontos com mau comportamento (predefinição: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Os valores da transação não devem ser negativos</translation>
</message>
@@ -3676,6 +3471,10 @@
<translation>Fundos insuficientes</translation>
</message>
<message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Não foi possível escrever na pasta de dados '%s': verifique as permissões.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>A carregar o índice de blocos...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ro.ts b/src/qt/locale/bitcoin_ro.ts
index 5308e0e191..bef83e831a 100644
--- a/src/qt/locale/bitcoin_ro.ts
+++ b/src/qt/locale/bitcoin_ro.ts
@@ -133,7 +133,7 @@
</message>
<message>
<source>Encrypt wallet</source>
- <translation>Incripteaza portofelul</translation>
+ <translation>Criptează portofelul</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
@@ -176,10 +176,22 @@
<translation>Portofel criptat</translation>
</message>
<message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 se va inchide pentru a termina procesul de criptare. Aduți aminte că prin criptarea portofelului tău virtual, nu îți poți proteja complet monedele virtuale de a fi furate când te-ai infectat cu un virus de tip malware pe calculatorul tau.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>IMPORTANT: Fiecare backup anterior pe care l-ai facut portofelului tău virtual trebuie înlocuit cu cel nou. Din motive de securitate, backup-urile anteroiare făcute portofelului tău, care nu sunt criptate vor deveni inutilizabile și inutile când vei începe să utilizezi portofelul criptat.</translation>
+ </message>
+ <message>
<source>Wallet encryption failed</source>
<translation>Criptarea portofelului a eșuat</translation>
</message>
<message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Criptarea portofelului a eșuat din cauza unei erori interne. Portofelul tău nu a fost criptat.</translation>
+ </message>
+ <message>
<source>The supplied passphrases do not match.</source>
<translation>Parola furnizată nu se potrivește.</translation>
</message>
@@ -188,6 +200,10 @@
<translation>Deblocarea portofelului a eșuat</translation>
</message>
<message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Parola pe care ai introdus-o pentru decripatrea portofelului nu este corectă.</translation>
+ </message>
+ <message>
<source>Wallet decryption failed</source>
<translation>Decriptarea portofelului a eșuat</translation>
</message>
@@ -215,7 +231,7 @@
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>Semnează &amp;mesajul...</translation>
+ <translation>Semnează și trimite...</translation>
</message>
<message>
<source>Synchronizing with network...</source>
@@ -242,10 +258,22 @@
<translation>Navighează în istoricul tranzacțiilor</translation>
</message>
<message>
+ <source>E&amp;xit</source>
+ <translation>Ieși din...</translation>
+ </message>
+ <message>
<source>Quit application</source>
<translation>Părăsește aplicația</translation>
</message>
<message>
+ <source>&amp;About %1</source>
+ <translation>&amp;Despre %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Arată informații despre %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>Despre &amp;Qt</translation>
</message>
@@ -473,6 +501,10 @@
<translation>Schimbă:</translation>
</message>
<message>
+ <source>(un)select all</source>
+ <translation>(de)selectează tot</translation>
+ </message>
+ <message>
<source>Tree mode</source>
<translation>Mod arbore</translation>
</message>
@@ -544,10 +576,6 @@
<translation>&amp;Adresa</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Adresă de primire nouă</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Adresă nouă de livrare</translation>
</message>
@@ -585,19 +613,7 @@
<source>(%1-bit)</source>
<translation>(%1-bit)</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Utilizare:</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Pornește minimalizat</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Resetează toate setările modificate în Interfața Grafică.</translation>
- </message>
-</context>
+ </context>
<context>
<name>Intro</name>
<message>
@@ -655,6 +671,10 @@
<source>calculating...</source>
<translation>Se calculează...</translation>
</message>
+ <message>
+ <source>Hide</source>
+ <translation>Ascunde</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -754,6 +774,10 @@
<translation>Clientul va fi oprit. Dorești sa continui?</translation>
</message>
<message>
+ <source>Configuration options</source>
+ <translation>Optiuni de configuratie</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Eroare</translation>
</message>
@@ -988,6 +1012,14 @@
<source>Label</source>
<translation>Etichetă</translation>
</message>
+ <message>
+ <source>Message</source>
+ <translation>Mesaj</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Portofel</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -996,6 +1028,10 @@
<translation>Etichetă</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Mesaj</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(fără etichetă)</translation>
</message>
@@ -1027,6 +1063,10 @@
<translation>Schimbă:</translation>
</message>
<message>
+ <source>Hide</source>
+ <translation>Ascunde</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>Copiază cantitatea</translation>
</message>
@@ -1054,30 +1094,94 @@
</context>
<context>
<name>SignVerifyMessageDialog</name>
- </context>
+ <message>
+ <source>Message verified.</source>
+ <translation>Mesaj verificat.</translation>
+ </message>
+</context>
<context>
<name>SplashScreen</name>
</context>
<context>
<name>TrafficGraphWidget</name>
- </context>
+ <message>
+ <source>KB/s</source>
+ <translation>KB/s</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
+ <source>Generated</source>
+ <translation>Generat</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De la</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>La</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Credit</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Credit total</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mesaj</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Comentariu</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>Transactiune ID</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transactiune</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Cantitate</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>Adevarat</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>Fals</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Type</source>
+ <translation>tip</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Etichetă</translation>
</message>
<message>
+ <source>Received with</source>
+ <translation>Obtinut cu</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(fără etichetă)</translation>
</message>
@@ -1085,6 +1189,42 @@
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Tot</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Astazi</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Saptamana aceasta</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Luna aceasta</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Luna trecuta</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Anul acesta</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Obtinut cu</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Pentru tine</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Altru</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>Copiază adresa</translation>
</message>
@@ -1105,6 +1245,14 @@
<translation>Fisier text separat prin virgule (*.csv)</translation>
</message>
<message>
+ <source>Confirmed</source>
+ <translation>Confirmat</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>tip</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Etichetă</translation>
</message>
@@ -1113,6 +1261,10 @@
<translation>Adresă</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>Exportul a eșuat</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts
index e0cfff119b..e5b17cfbad 100644
--- a/src/qt/locale/bitcoin_ro_RO.ts
+++ b/src/qt/locale/bitcoin_ro_RO.ts
@@ -23,13 +23,17 @@
</message>
<message>
<source>C&amp;lose</source>
- <translation>Închide</translation>
+ <translation>Î&amp;nchide</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
<translation>Şterge adresa selectată din listă</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Introduceţi adresa sau eticheta pentru căutare</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportă datele din tab-ul curent într-un fişier</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Repetaţi noua frază de acces</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Arata parola</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Introduceţi noua parolă a portofelului electronic.&lt;br/&gt;Vă rugăm să folosiţi o parolă de&lt;b&gt;minimum 10 caractere aleatoare&lt;/b&gt;, sau &lt;b&gt;minimum 8 cuvinte&lt;/b&gt;.</translation>
</message>
@@ -318,6 +326,14 @@
<translation>Deschide &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Portofel:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>portofel implicit</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Click pentru a opri activitatea retelei.</translation>
</message>
@@ -338,6 +354,10 @@
<translation>Se reindexează blocurile pe disc...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy este&lt;b&gt;activat&lt;/b&gt;:%1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Trimite monede către o adresă Bitcoin</translation>
</message>
@@ -506,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Portofel: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Tip: %1
@@ -722,10 +748,6 @@
<translation>&amp;Adresă</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Noua adresă de primire</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Noua adresă de trimitere</translation>
</message>
@@ -742,8 +764,12 @@
<translation>Adresa introdusă "%1" nu este o adresă Bitcoin validă.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Adresa introdusă "%1" se află deja în lista de adrese.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adresa "%1" exista deja ca si adresa de primire cu eticheta "%2" si deci nu poate fi folosita ca si adresa de trimitere.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Adresa introdusa "%1" este deja in lista de adrese cu eticheta "%2"</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -795,42 +821,6 @@
<source>Command-line options</source>
<translation>Opţiuni linie de comandă</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uz:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>Opţiuni linie de comandă</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Opţiuni UI:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Alege dosarul de date la pornire (implicit: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Setează limba, de exemplu: "ro_RO" (implicit: sistem local)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Porniţi minimizat</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Setare rădăcină certificat SSL pentru cerere de plată (implicit: -sistem- )</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Afişează ecran splash la pornire (implicit: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Resetează toate schimbările făcute în GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1016,6 +1006,18 @@
<translation>Arata daca proxy-ul SOCKS5 furnizat implicit este folosit pentru a gasi parteneri via acest tip de retea.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Foloseste un proxy SOCKS&amp;5 separat pentru a gasi parteneri via servicii TOR ascunse</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Ascunde icon-ul din system tray.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Ascunde icon-ul din system tray.</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Minimizează fereastra în locul părăsirii programului în momentul închiderii ferestrei. Cînd acestă opţiune e activă, aplicaţia se va opri doar în momentul selectării comenzii 'Închide aplicaţia' din menu.</translation>
</message>
@@ -1048,6 +1050,22 @@
<translation>Reţea</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Dezactiveaza unele caracteristici avansate insa toate blocurile vor fi validate pe deplin. Inversarea acestei setari necesita re-descarcarea intregului blockchain. Utilizarea reala a discului poate fi ceva mai mare.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Reductie &amp;block storage la </translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation> Inversarea acestei setari necesita re-descarcarea intregului blockchain.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = automat, &lt;0 = lasă atîtea nuclee libere)</translation>
</message>
@@ -1080,6 +1098,14 @@
<translation>Mapare port folosind &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Acceptă conexiuni din exterior</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Permite conexiuni de intrar&amp;e</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Conectare la reţeaua Bitcoin printr-un proxy SOCKS.</translation>
</message>
@@ -1160,6 +1186,10 @@
<translation>Arată controlul caracteristicilor monedei sau nu.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>URL-uri tranzacţii &amp;terţe părţi</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1302,6 +1332,10 @@
<translation>Gestionare URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' nu este un URI valid. Folositi 'bitcoin:' in loc.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>URL-ul cererii de plată preluat nu este valid: %1</translation>
</message>
@@ -1499,12 +1533,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Eroare la analiza argumentelor linie de comanda: %1</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Eroare: Directorul de date specificat "%1" nu există.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Eroare: Nu se poate procesa fişierul de configuraţie: %1. Folosiţi doar sintaxa cheie=valoare.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Eroare: Nu se poate analiza fişierul de configuraţie: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1597,6 +1635,14 @@
<translation>Memorie folosită</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Portofel:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(nimic)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Resetare</translation>
</message>
@@ -1765,6 +1811,10 @@
<translation>&amp;Unban</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>portofel implicit</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Bun venit la consola %1 RPC.</translation>
</message>
@@ -1773,6 +1823,14 @@
<translation>Folosiţi săgetile sus şi jos pentru a naviga în istoric şi %1 pentru a curăţa ecranul.</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Tastati %1 pentru o recapitulare a comenzilor disponibile.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Pentru mai multe informatii despre folosirea acestei console tastati %1.</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>ATENTIONARE: Sunt excroci care instruiesc userii sa introduca aici comenzi, pentru a le fura continutul portofelelor. Nu folositi aceasta consolă fara a intelege pe deplin ramificatiile unei comenzi.</translation>
</message>
@@ -1781,6 +1839,14 @@
<translation>Activitatea retelei a fost oprita.</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Executarea comenzii fara nici un portofel.</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Executarea comenzii folosind portofelul "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(node id: %1)</translation>
</message>
@@ -1852,6 +1918,14 @@
<translation>Curăţă</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Adresele native segwit (aka Bech32 sau BIP-173) vor reduce mai tarziu comisioanele de tranzactionare si vor oferi o mai buna protectie impotriva introducerii gresite, dar portofelele vechi nu sunt compatibile. Daca optiunea nu e bifata, se va crea o adresa compatibila cu portofelele vechi.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Genereaza adresa nativa segwit (Bech32)</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Istoricul plăţilor cerute</translation>
</message>
@@ -1939,6 +2013,10 @@
<translation>Mesaj</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Portofel</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI rezultat este prea lung, încearcă să reduci textul pentru etichetă / mesaj.</translation>
</message>
@@ -2053,12 +2131,16 @@
<translation>inchide setarile de taxare</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>per kilooctet</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Specificati o taxa anume pe kB (1000 byte) din marimea virtuala a tranzactiei.
+
+Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o tranzactie de 500 byte (jumatate de kB) va produce o taxa de doar 50 satoshi.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Daca taxa personalizata este setata la 1000 satoshi si tranzactia este doar de 250 bytes, atunci "per kilobyte" plateste o taxa de doar 250 satoshi, in timp ce "total minim" plateste 1000 satoshi. Pentru tranzactii mai mari de un kilobyte ambele platesc per kilobyte. </translation>
+ <source>per kilobyte</source>
+ <translation>per kilooctet</translation>
</message>
<message>
<source>Hide</source>
@@ -2105,6 +2187,14 @@
<translation>Timp confirmare tinta:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Autorizeaza Replace-By-Fee</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Cu Replace-By-Fee (BIP-125) se poate creste taxa unei tranzactii dupa ce a fost trimisa. Fara aceasta optiune, o taxa mai mare e posibil sa fie recomandata pentru a compensa riscul crescut de intarziere a tranzactiei.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Curăţă to&amp;ate</translation>
</message>
@@ -2161,16 +2251,32 @@
<translation>Sigur doriţi să trimiteţi?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>adăugat ca taxă de tranzacţie</translation>
+ <source>or</source>
+ <translation>sau</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Suma totală %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Puteti creste taxa mai tarziu (semnaleaza Replace-By-Fee, BIP-125).</translation>
</message>
<message>
- <source>or</source>
- <translation>sau</translation>
+ <source>from wallet %1</source>
+ <translation>de la portofelul %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Va rugam sa revizuiti tranzactia.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Taxă tranzacţie</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Nu se semnalizeaza Replace-By-Fee, BIP-125</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Suma totală</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2292,6 +2398,10 @@
<translation>S&amp;cade taxa din suma</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>Folosește balanța disponibilă</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Mesaj:</translation>
</message>
@@ -2510,10 +2620,6 @@
<translation>in conflict cu o tranzactie cu %1 confirmari</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/neconfirmat, %1</translation>
</message>
@@ -2542,14 +2648,6 @@
<translation>Stare</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, nu a fost încă publicată</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, difuzare printr-un nod</numerusform><numerusform>, difuzare prin %n noduri</numerusform><numerusform>, difuzare prin %n noduri</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -2634,6 +2732,10 @@
<translation>Dimensiune totala tranzacţie</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Dimensiune virtuala a tranzactiei</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Index debit</translation>
</message>
@@ -2700,10 +2802,6 @@
<translation>Deschis pînă la %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Deconectat</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Neconfirmat</translation>
</message>
@@ -2728,10 +2826,6 @@
<translation>Imatur (%1 confirmari, va fi disponibil după %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Acest bloc nu a fost recepţionat de nici un alt nod şi probabil nu va fi acceptat!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generat dar neacceptat</translation>
</message>
@@ -2843,6 +2937,10 @@
<translation>Altele</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Introduceți adresa, ID-ul tranzacției, sau eticheta pentru a căuta</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Suma minimă</translation>
</message>
@@ -3038,38 +3136,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Datele portofelului s-au salvat cu succes la %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Anulare</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opţiuni:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Specificaţi dosarul de date</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Se conectează la un nod pentru a obţine adresele partenerilor, şi apoi se deconectează</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Specificaţi adresa dvs. publică</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Acceptă comenzi din linia de comandă şi comenzi JSON-RPC</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distribuit sub licenţa de programe MIT, vezi fişierul însoţitor %s sau %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Dacă &lt;category&gt; nu este furnizat sau &lt;category&gt;=1, produce toate informaţiile de depanare.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Reductia e configurata sub minimul de %d MiB. Rugam folositi un numar mai mare.</translation>
</message>
@@ -3086,18 +3164,10 @@
<translation>Eroare: S-a produs o eroare interna fatala, vedeti debug.log pentru detalii</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Taxa (în %s/kB) de adăugat la tranzacţiile pe care le trimiteţi(implicit: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Reductie blockstore...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Rulează în fundal ca un demon şi acceptă comenzi</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Imposibil de pornit serverul HTTP. Pentru detalii vezi logul de depanare.</translation>
</message>
@@ -3110,52 +3180,20 @@
<translation>Dezvoltatorii %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>O rata de taxare (in %s/kB) ce va fi folosita atunci cand estimarea taxei are date insuficiente (implicit: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Accepta retransmiterea tranzactiilor primite de la parteneri din whitelist chiar si atunci cand nu se retransmit tranzactii (implicit: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Ataşaţi adresei date şi ascultaţi totdeauna pe ea. Folosiţi notaţia [host]:port pentru IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Nu se poate obține o blocare a directorului de date %s. %s probabil rulează deja.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Sterge toate tranzactiile din portofel si recupereaza doar acele parti din blockchain prin -rescan la startup</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Nu se pot furniza conexiuni specifice in acelasi timp in care addrman este folosit pentru a gasi conexiuni de iesire.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Eroare la citirea %s! Toate cheile sînt citite corect, dar datele tranzactiei sau anumite intrări din agenda sînt incorecte sau lipsesc.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Exclude informatia de depanare pentru o categorie. Poate fi folosit impreuna cu -debug=1 pentru a produce loguri de depanare pentru toate categoriile mai ptin una sau mai multe categorii specificate.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Execută comanda cînd o tranzacţie a portofelului se schimbă (%s în cmd este înlocuit de TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Extra tranzactii de tinut in memorie pentru reconstructia compacta a blocurilor (implicit: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Daca acest bloc este in lant se asuma ca el si predecesorii sai sunt valizi si potential se sare peste verificarea scriptului (0 pentru a verifica tot, implicit %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Timpul mediu maxim permis pentru ajustarea intarzierii partenerilor din retea. Perspectiva temporala locala poate fi influentata de parteneri aflati inainte sau inapoi cu aceasta valoare. (implicit: %u secunde)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Valoarea maxima totala a taxelor (in %s) care va fi folosita intr-o singura tranzactie din portofel sau tranzactie bruta; daca valoarea este prea mica poate conduce la esuarea tranzactiilor mari (implicit: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Gruparea a iesirilor pe adrese, selectand totul sau nimic, in loc de selectarea bazata per-iesire. Intimitatea este imbunatatita deoarece o adresa este folosita doar o singura data (cu exceptia cuiva care trimite catre aceiasi adresa dup ce cheltuie din ea), dar se pot genera taxe mai mari deoarece poate rezulta o selectare suboptimala a monedelor datorata limitarii impuse (implicit: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3166,22 +3204,6 @@
<translation>Va rugam sa contribuiti daca apreciati ca %s va este util. Vizitati %s pentru mai multe informatii despre software.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Găseşte parteneri folosind căutarea DNS, daca adresele sunt reduse (implicit: 1 doar dacă nu s-a folosit -connect)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Micsorarea cerintelor de stocare prin activarea reductiei (stergerii) blocurilor vechi. Aceasta permite RPC pruneblockchain sa fie solicitata pentru a sterge anumite blocuri, si permite reductia automata a blocurilor vechi daca este furnizata o valoare anume in MiB. Acest mod este incompatibil cu -txindex si -rescan. Atentie: Inversarea acestei setari necesita re-descarcarea intregului blockchain. (implicit: 0 = dezactiveaza reductia blocurilor, 1 = permite reductia manuala via RPC, &gt;%u = reductie automata a fisierelor blocurilor pentru a ramane sub valoarea specificata in MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Seteaza cea mai mica taxa (în %s/kB) pentru tranzactiile de adăugat la crearea blocului (implicit: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Setează numărul de thread-uri de verificare a script-urilor (%u la %d, 0 = auto, &lt;0 = lasă atîtea nuclee libere, implicit: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Baza de date a blocurilor contine un bloc ce pare a fi din viitor. Acest lucru poate fi cauzat de setarea incorecta a datei si orei in computerul dvs. Reconstruiti baza de date a blocurilor doar daca sunteti sigur ca data si ora calculatorului dvs sunt corecte.</translation>
</message>
@@ -3202,18 +3224,6 @@
<translation>Imposibil de a readuce baza de date la statusul pre-fork. Va trebui redescarcat blockchainul.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Foloseşte UPnP pentru a vedea porturile (implicit: 1 cînd ascultă si fara -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Nume utilizator si hash al parolei pentru conexiuni JSON-RPC. Campul &lt;userpw&gt;vine in formatul: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Un script python canonic este inclus in share/rpcuser. Clientul se conecteaza normal folosind perechea de argumente rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt;. Aceasta optiune poate fi specificata de mai multe ori</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Portofelul nu va crea tranzactii care violeaza limitele mempool chain (implicit: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Atenţie: Reţeaua nu pare să fie de acord în totalitate! Aparent nişte mineri au probleme.</translation>
</message>
@@ -3222,10 +3232,6 @@
<translation>Atenţie: Aparent, nu sîntem de acord cu toţi partenerii noştri! Va trebui să faceţi o actualizare, sau alte noduri necesită actualizare.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Daca se salveaza mempool la shutdown si se incarca la restart (implicit: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d din ultimele 100 blocuri a o versiune neasteptata</translation>
</message>
@@ -3238,42 +3244,14 @@
<translation>-maxmempool trebuie sa fie macar %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; poate fi:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Acceptă conexiuni din afară (implicit: 1 dacă nu se foloseşte -proxy sau -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Ataseaza comentariul la string-ul agentului utilizator</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Încercare de recuperare a cheilor private dintr-un portofel corupt la initiere</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Opţiuni creare bloc:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Nu se poate rezolva adresa -%s: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Optiuni de selectie a chain-ului:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Indexul de schimbare este iesit din parametrii</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Opţiuni conexiune:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3282,36 +3260,12 @@
<translation>Bloc defect din baza de date detectat</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Opţiuni Depanare/Test:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Nu încarcă portofelul şi dezactivează solicitările portofel RPC</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Doriţi să reconstruiţi baza de date blocuri acum?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Activeaza publicarea hashului blocului in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Activeaza publicarea hashului tranzactiei in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Activeaza publicarea blocului brut in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Activeaza publicarea tranzactiei brute in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Activeaza inlocuirea tranzactiei in mempool (implicit: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Eroare la crearea %s: Nu se pot crea portofele non-HD cu aceasta versiune.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3326,6 +3280,10 @@
<translation>Eroare la încărcarea %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Eroare la incarcarea %s: Cheile private pot fi dezactivate doar in momentul crearii</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Eroare la încărcarea %s: Portofel corupt</translation>
</message>
@@ -3350,6 +3308,10 @@
<translation>Nu s-a reuşit ascultarea pe orice port. Folosiţi -listen=0 dacă vreţi asta.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Rescanarea portofelului in timpul initializarii a esuat.</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Import...</translation>
</message>
@@ -3374,8 +3336,12 @@
<translation>Suma nevalidă pentru -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Pastreaza tranzactia in mempool sub &lt;n&gt; megaocteti (implicit: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Directorul de blocuri "%s" specificat nu exista.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Actualizarea bazei de date txindex</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3386,26 +3352,10 @@
<translation>Încărcare banlist...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Locatia cookie-ului auth (implicit: data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Nu sînt destule descriptoare disponibile.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Se conectează doar la noduri în reţeaua &lt;net&gt; (ipv4, ipv6 sau onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Tipareste acest mesaj de ajutor si iesi</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Tipareste versiunea si iesi</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Reductia nu poate fi configurata cu o valoare negativa.</translation>
</message>
@@ -3414,14 +3364,6 @@
<translation>Modul redus este incompatibil cu -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Reconstruieste statusul chainului si indexul blocurilor din fisierele blk*.dat de pe disc.</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Reconstruieste statusul chainului din blocurile indexate in acest moment.</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Se reiau blocurile...</translation>
</message>
@@ -3430,14 +3372,6 @@
<translation>Se deruleaza blocurile...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Setează mărimea bazei de date cache în megaocteţi (%d la %d, implicit: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Specifică fişierul portofel (în dosarul de date)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Codul sursa este disponibil la %s.</translation>
</message>
@@ -3450,6 +3384,10 @@
<translation>Nu se poate efectua legatura la %s pe acest computer. %s probabil ruleaza deja.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Nu s-au putut genera cheile</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Argumentul nesuportat -benchmark este ignorat, folositi debug=bench.</translation>
</message>
@@ -3470,14 +3408,6 @@
<translation>Actualizarea bazei de date UTXO</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Foloseşte mapare UPnP pentru asculatere port (implicit: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Utilizează reţeaua de test</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Comentariul (%s) al Agentului Utilizator contine caractere nesigure.</translation>
</message>
@@ -3486,86 +3416,22 @@
<translation>Se verifică blocurile...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Opţiuni depanare/testare portofel:</translation>
- </message>
- <message>
- <source>Wallet options:</source>
- <translation>Opţiuni portofel:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Permite conexiunile JSON-RPC din sursa specificată. Valid pentru &lt;ip&gt; sînt IP singulare (ex. 1.2.3.4), o reţea/mască-reţea (ex. 1.2.3.4/255.255.255.0) sau o reţea/CIDR (ex. 1.2.3.4/24). Această opţiune poate fi specificată de mai multe ori</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Legare la o adresa anume si whitelisting pentru toti partenerii conectati la ea. Folositi notatia [host]:port pentru IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Creare de fisiere noi cu permisiunile implicite de sistem, in loc de umask 077 (in efect doar cu dezactivarea functionalitatii portofelului)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Descoperă propriile adrese IP (inţial: 1 cand asculta si fara -proxy sau -externalip)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Eroare: Ascultarea conexiunilor de intrare nu a reuşit (ascultarea a reurnat eroarea %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Execută comanda cînd o alertă relevantă este primită sau vedem o bifurcaţie foarte lungă (%s în cmd este înlocuit de mesaj)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Taxe (in %s/kB) mai mici decît aceasta sumă sînt considerate taxe nule pentru transmiterea, minarea si crearea tranzacţiilor (implicit: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Daca nu este stabilita paytxfee, includeti o taxa suficienta pentru ca tranzactiile sa inceapa sa fie confirmate in medie in n blocuri (implicit: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Sumă nevalidă pentru -maxtxfee=&lt;amount&gt;: '%s' (trebuie să fie cel puţin taxa minrelay de %s pentru a preveni blocarea tranzactiilor)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Marimea maxima a datelor in operațiunile de transport de date de tranzactii pe care le retransmitem si le minam (implicit: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Randomizati acreditarile pentru fiecare conexiune proxy. Aceasta permite izolarea fluxului Tor (implicit: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Suma tranzactiei este prea mica pentru a fi trimisa dupa ce se scade taxa.</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Partenerii din whitelist nu pot fi interzisi DoS si tranzactiile lor sunt intotdeauna retransmise, chiar daca sunt deja in mempool, folositor spre exemplu pentru un gateway</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Trebuie reconstruita intreaga baza de date folosind -reindex pentru a va intoarce la modul non-redus. Aceasta va determina descarcarea din nou a intregului blockchain</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(implicit: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Acceptă cererile publice REST (implicit: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Crează automat un serviciu Tor ascuns (implicit: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Conectare prin proxy SOCKS5</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Eroare la incarcarea %s: Nu se poate dezactiva HD la un portofel care este deja HD.</translation>
</message>
@@ -3578,10 +3444,6 @@
<translation>Eroare la actualizarea bazei de date chainstate</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importa blocuri de la un fisier extern blk000??.dat la pornire</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informaţie</translation>
</message>
@@ -3602,44 +3464,24 @@
<translation>Mască reţea nevalidă specificată în -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Menţine cel mult &lt;n&gt; tranzactii neconectabile in memorie (implicit: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Trebuie să specificaţi un port cu -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Optiuni de releu pentru nod</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Opţiuni server RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Se micsoreaza -maxconnections de la %d la %d, datorita limitarilor de sistem.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Rescanează lanţul de blocuri pentru tranzacţiile lipsa la pornire</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Trimite informaţiile trace/debug la consolă în locul fişierului debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Arată toate opţiunile de depanare (uz: --help -help-debug)</translation>
+ <source>Signing transaction failed</source>
+ <translation>Nu s-a reuşit semnarea tranzacţiei</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Micşorează fişierul debug.log la pornirea clientului (implicit: 1 cînd nu se foloseşte -debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Nu exista -walletdir "%s" specificat</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>Nu s-a reuşit semnarea tranzacţiei</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>-walletdir "%s" specificat este o cale relativa</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3650,14 +3492,6 @@
<translation>Acesta este un program experimental.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Parola portului de control Tor (implicit: fara parola)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Portul de control Tor de folosit daca se activeaza ascultarea onion (implicit: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Suma tranzacţionată este prea mică</translation>
</message>
@@ -3674,18 +3508,18 @@
<translation>Nu se poate lega la %s pe acest calculator. (Legarea a întors eroarea %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Actualizează portofelul la ultimul format la pornire</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Utilizator pentru conexiunile JSON-RPC</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Nu s-au putut genera cheile initiale</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Se verifică portofelul(ele)...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Portofelul %s se află în afara directorului portofelului %s</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Avertisment</translation>
</message>
@@ -3694,98 +3528,18 @@
<translation>Atentie: se activeaza reguli noi necunoscute (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Setare daca se opereaza in modul exclusiv blocuri (implicit: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Trebuie să reconstruiţi baza de date folosind -reindex pentru a schimba -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Şterge toate tranzacţiile din portofel...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Optiuni de notificare ZeroMQ:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Parola pentru conexiunile JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Execută comanda cînd cel mai bun bloc se modifică (%s în cmd este înlocuit cu hash-ul blocului)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Permite căutări DNS pentru -addnode, -seednode şi -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = pastreaza tx meta data ex. detinator cont si informatie cerere plata, 2 = elimina tx meta data)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee este setata foarte sus! Se pot plati taxe de aceasta marime pe o singura tranzactie.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Legarre la o anumita adresa pentru a asculta dupa conexiuni JSON-RPC. Aceasta actiune este ignorata, mai putin cand -rpcallowip e si el trecut. Portul este optional si nu tine cont de -rpcport. Foloseste notatia pentru IPv6 [host]:port. Aceasta optiune poate fi folosita de mai multe ori (implicit:127.0.0.1 si ::1 adica localhost, sau daca -rpcallowip a fost specificat, 0.0.0.0 si :: adica toate adresele)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Nu pastra in mempool tranzactii mai mult de &lt;n&gt;ore (implicit: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Echivalent octeti per sigop in tranzactii pentru retransmitere si minat (implicit: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Eroare la incarcarea %s: Nu se poate activa HD la un portofel care este deja non-HD.</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Eroare la incarcarea portofelului %s. Parametrul -wallet trebuie sa specifice doar un nume de fisier (nu o cale)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Taxe (in %s/kB) mai mici decît aceasta sumă sînt considerate taxe nule pentru crearea tranzacţiilor (implicit: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Forteaza retransmiterea tranzactiilor primite de la parteneri din whitelist chiar si atunci cand violeaza politica locala de restransmitere (implicit: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Cît de minuţioasă este verificatea blocurilor prin -checkblocks (0-4, implicit: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Păstrează un index complet al tranzacţiilor folosite de functia rpc getrawtransaction (implicit: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Numărul de secunde pentru a preveni reconectarea partenerilor care nu se comporta corect (implicit: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Produce toate informaţiile de depanare (implicit: %u &lt;category&gt; furnizată este opţională)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Stabileste serializarea tranzactiilor brute sau hexul blocurile returnate in mod non-verbose, non-segwit(0) sau segwit(1) (implicit: %d)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Suport pentru filtrarea blocurilor si tranzactiilor cu filtre bloom (implicit: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Nivelul taxei (in %s/kB) care indica toleranta personala pentru renuntarea la rest prin adaugarea restului la taxa (implicit: %s). Nota: o tranzactie este inlaturata daca este praf la acest nivel, dar vom inlatura intotdeauna suma pana la taxa de retransmitere a prafului si o taxa de inlaturare peste aceasta valoare este limitata de estimarea taxei pentru tinta cea mai indepartata.</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Aceasta este taxa de tranzactie pe care este posibil sa o platiti daca estimarile de taxe nu sunt disponibile.</translation>
</message>
@@ -3798,10 +3552,6 @@
<translation>Lungimea totala a sirului versiunii retelei (%i) depaseste lungimea maxima (%i). Reduceti numarul sa dimensiunea uacomments. </translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Incearca sa mentina traficul de iesire sub tinta stabilita (in MiB per 24h), 0 = no limit (implicit: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>S-a gasit un argument -socks nesuportat. Setarea versiunii SOCKS nu mai este posibila, sunt suportate doar proxiurile SOCKS5.</translation>
</message>
@@ -3810,10 +3560,6 @@
<translation>Se ignora argumentul nesuportat -whitelistalwaysrelay, folositi -whitelistrelay si/sau -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Foloseste un proxy SOCKS5 separat pentru a gasi parteneri via servicii TOR ascunse (implicit: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Atentie: se mineaza blocuri cu versiune necunoscuta! Este posibil sa fie in vigoare reguli necunoscute.</translation>
</message>
@@ -3822,110 +3568,18 @@
<translation>Atenţie: fişierul portofelului este corupt, date salvate! Fişierul %s a fost salvat ca %s in %s; dacă balanta sau tranzactiile sunt incorecte ar trebui să restauraţi dintr-o copie de siguranţă.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Parteneri din whitelist ce se conecteaza de la adresa IP specificata (ex. 1.2.3.4) sau o retea cu notatia CIDR (ex. 1.2.3.0/24). Poate fi specificat de mai multe ori.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s este setata foarte sus!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(implicit: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Cauta intotdeauna adrese de parteneri via cautare DNS (implicit:%u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Eroare la incarcarea portofelului %s. Fisierul cu numele -wallet trebuie sa fie un fisier normal. </translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Eroare la incarcarea portofelului %s. Este specificat un fisier -wallet duplicat.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Eroare la incarcarea portofelului %s. Sunt caractere invalide in numele fisierului -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Cîte blocuri verifică la pornire (implicit: %u, 0 = toate)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Include adresele IP in rezultatul depanarii (default: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Keypool epuizat, folositi intai functia keypoolrefill</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Ascultă pentru conexiuni JSON-RPC pe &lt;port&gt; (implicit: %u sau testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Ascultă pentru conexiuni pe &lt;port&gt; (implicit: %u sau testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Menţine cel mult &lt;n&gt; conexiuni cu partenerii (implicit: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Seteaza portofelul sa difuzeze tranzactii</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Tampon maxim pentru recepţie per conexiune, &lt;n&gt;*1000 octeti (implicit: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Tampon maxim pentru transmitere per conexiune, &lt;n&gt;*1000 octeti (implicit: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Prefixeaza rezultatul depanarii cu marcaj de timp (implicit: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Retransmitere si minare a tranzactiilor de transport de date (implicit: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Retransmite multisig non-P2SH (implicit: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Setează mărimea keypool la &lt;n&gt; (implicit: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Seteaza greutatea maxima a blocurilor BIP141 (implicit: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Seteaza numarul de thread-uri care deservesc functii RPC (implicit: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Specificaţi fişierul configuraţie (implicit: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Specificati expirarea timpului conexiunii in milisecunde (minim: 1, implicit %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Specifică fişierul pid (implicit: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Cheltuie restul neconfirmat la trimiterea tranzacţiilor (implicit: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Se pornesc threadurile retelei...</translation>
</message>
@@ -3942,10 +3596,6 @@
<translation>Aceasta este taxa de tranzactie pe care o platiti cand trimiteti o tranzactie.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Prag pentru deconectarea partenerilor care nu se comporta corect (implicit: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Sumele tranzactionate nu pot fi negative</translation>
</message>
@@ -3966,6 +3616,22 @@
<translation>Fonduri insuficiente</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Nu se poate genera o adresa pentru rest. Cheile private sunt dezactivate pentru acest portofel.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Estimarea taxei a esuat. Taxa implicita este dezactivata. Asteptati cateva blocuri, sau activati -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Atentie: S-au detectat chei private in portofelul {%s} cu cheile private dezactivate</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Nu se poate scrie in directorul de date '%s"; verificati permisiunile.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Încărcare index bloc...</translation>
</message>
@@ -3990,4 +3656,4 @@
<translation>Eroare</translation>
</message>
</context>
-</TS> \ No newline at end of file
+</TS>
diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts
index b2b4491f2c..9c81fe9cdb 100644
--- a/src/qt/locale/bitcoin_ru.ts
+++ b/src/qt/locale/bitcoin_ru.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Клик правой кнопкой для редактирования адреса или метки</translation>
+ <translation>Кликните правой кнопкой для редактирования адреса или метки</translation>
</message>
<message>
<source>Create a new address</source>
@@ -27,11 +27,15 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>Удалить выбранный адрес из списка</translation>
+ <translation>Удалить текущий выбранный адрес из списка</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Введите адрес или метку для поиска</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>Экспортировать данные из вкладки в файл</translation>
+ <translation>Экспортировать данные текущей вкладки в файл</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -63,7 +67,7 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Это ваши адреса Bitcoin для отправки платежей. Всегда проверяйте сумму и адрес получателя перед отправкой перевода.</translation>
+ <translation>Это ваши адреса Bitcoin для отправки платежей. Всегда проверяйте количество и адрес получателя перед отправкой перевода.</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
@@ -95,7 +99,7 @@
</message>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Произошла ошибка при сохранении списка адресов в %1. Пожалуйста, попробуйте еще раз.</translation>
+ <translation>Произошла ошибка сохранения списка адресов в %1. Пожалуйста, повторите попытку.</translation>
</message>
</context>
<context>
@@ -117,7 +121,7 @@
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
- <translation>Диалог ввода пароля</translation>
+ <translation>Пароль</translation>
</message>
<message>
<source>Enter passphrase</source>
@@ -141,11 +145,11 @@
</message>
<message>
<source>Encrypt wallet</source>
- <translation>Зашифровать бумажник</translation>
+ <translation>Зашифровать электронный кошелёк</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Для выполнения операции требуется пароль вашего бумажника.</translation>
+ <translation>Для выполнения операции требуется пароль от вашего кошелька.</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -153,7 +157,7 @@
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Для выполнения операции требуется пароль вашего бумажника.</translation>
+ <translation>Данная операция требует введения пароля для расшифровки вашего бумажника.</translation>
</message>
<message>
<source>Decrypt wallet</source>
@@ -161,15 +165,15 @@
</message>
<message>
<source>Change passphrase</source>
- <translation>Сменить пароль</translation>
+ <translation>Изменить пароль</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Введите старый и новый пароль для бумажника.</translation>
+ <translation>Введите старый и новый пароль для кошелька.</translation>
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation>Подтвердите шифрование бумажника</translation>
+ <translation>Подтвердить шифрование кошелька</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
@@ -177,58 +181,30 @@
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation>Вы уверены, что хотите зашифровать ваш бумажник?</translation>
+ <translation>Вы уверены, что хотите зашифровать ваш кошелёк?</translation>
</message>
<message>
<source>Wallet encrypted</source>
- <translation>Бумажник зашифрован</translation>
- </message>
- <message>
- <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>Сейчас %1 закроется для завершения процесса шифрования. Помните, что шифрование вашего бумажника не может полностью защитить ваши биткоины от кражи с помощью инфицирования вашего компьютера вредоносным ПО.</translation>
- </message>
- <message>
- <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation>ВАЖНО: все предыдущие резервные копии вашего бумажника должны быть заменены новым зашифрованным файлом. В целях безопасности предыдущие резервные копии незашифрованного бумажника станут бесполезны, как только вы начнёте использовать новый зашифрованный бумажник.</translation>
+ <translation>Кошелёк зашифрован</translation>
</message>
<message>
<source>Wallet encryption failed</source>
<translation>Не удалось зашифровать бумажник</translation>
</message>
<message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Шифрование бумажника не удалось из-за внутренней ошибки. Ваш бумажник не был зашифрован.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation>Введённые пароли не совпадают.</translation>
- </message>
- <message>
<source>Wallet unlock failed</source>
<translation>Разблокировка бумажника не удалась</translation>
</message>
<message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Неверный пароль для расшифровки бумажника.</translation>
- </message>
- <message>
<source>Wallet decryption failed</source>
- <translation>Расшифровка бумажника не удалась</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation>Пароль бумажника успешно изменён.</translation>
+ <translation>Расшифровка кошелька не удалась</translation>
</message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation>Внимание: Caps Lock включен!</translation>
- </message>
-</context>
+ </context>
<context>
<name>BanTableModel</name>
<message>
<source>IP/Netmask</source>
- <translation>IP/префикс</translation>
+ <translation>IP/Маска подсети</translation>
</message>
<message>
<source>Banned Until</source>
@@ -239,7 +215,7 @@
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>&amp;Подписать сообщение...</translation>
+ <translation>Подписать &amp;сообщение...</translation>
</message>
<message>
<source>Synchronizing with network...</source>
@@ -254,16 +230,12 @@
<translation>Узел</translation>
</message>
<message>
- <source>Show general overview of wallet</source>
- <translation>Показать общий обзор действий с бумажником</translation>
- </message>
- <message>
<source>&amp;Transactions</source>
<translation>&amp;Транзакции</translation>
</message>
<message>
<source>Browse transaction history</source>
- <translation>Показать историю транзакций</translation>
+ <translation>Просмотр истории транзакций</translation>
</message>
<message>
<source>E&amp;xit</source>
@@ -275,15 +247,11 @@
</message>
<message>
<source>&amp;About %1</source>
- <translation>&amp;О %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation>Показать информацию о %1</translation>
+ <translation>&amp;Около %1</translation>
</message>
<message>
<source>About &amp;Qt</source>
- <translation>О &amp;Qt</translation>
+ <translation>O &amp;Qt</translation>
</message>
<message>
<source>Show information about Qt</source>
@@ -295,2694 +263,164 @@
</message>
<message>
<source>Modify configuration options for %1</source>
- <translation>Изменить конфигурационные настройки для %1</translation>
+ <translation>Изменить параметры конфигурации для %1</translation>
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Зашифровать бумажник...</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet...</source>
- <translation>&amp;Сделать резервную копию бумажника...</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase...</source>
- <translation>&amp;Изменить пароль...</translation>
- </message>
- <message>
- <source>&amp;Sending addresses...</source>
- <translation>&amp;Адреса отправки...</translation>
- </message>
- <message>
- <source>&amp;Receiving addresses...</source>
- <translation>Адреса &amp;получения...</translation>
- </message>
- <message>
- <source>Open &amp;URI...</source>
- <translation>Открыть &amp;URI...</translation>
- </message>
- <message>
- <source>Click to disable network activity.</source>
- <translation>Кликните, чтобы запретить сетевую активность.</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <translation>Сетевая активность запрещена.</translation>
- </message>
- <message>
- <source>Click to enable network activity again.</source>
- <translation>Кликните, чтобы снова разрешить сетевую активность.</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)...</source>
- <translation>Синхронизация заголовков (%1%)...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk...</source>
- <translation>Идёт переиндексация блоков на диске...</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation>Отправить монеты на указанный адрес Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation>Сделать резервную копию бумажника в другом месте</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation>Изменить пароль шифрования бумажника</translation>
- </message>
- <message>
- <source>&amp;Debug window</source>
- <translation>&amp;Окно отладки</translation>
- </message>
- <message>
- <source>Open debugging and diagnostic console</source>
- <translation>Открыть консоль отладки и диагностики</translation>
- </message>
- <message>
- <source>&amp;Verify message...</source>
- <translation>&amp;Проверить сообщение...</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
+ <translation>&amp;Зашифровать кошелёк...</translation>
</message>
<message>
<source>Wallet</source>
- <translation>Бумажник</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation>&amp;Отправить</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation>&amp;Получить</translation>
- </message>
- <message>
- <source>&amp;Show / Hide</source>
- <translation>&amp;Показать / Скрыть</translation>
- </message>
- <message>
- <source>Show or hide the main Window</source>
- <translation>Показать или скрыть главное окно</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation>Зашифровать приватные ключи, принадлежащие вашему бумажнику</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Подписать сообщения вашим адресом Bitcoin, чтобы доказать, что вы им владеете</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Проверить сообщения, чтобы удостовериться, что они были подписаны определённым адресом Bitcoin</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation>&amp;Файл</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation>&amp;Настройки</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation>&amp;Помощь</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation>Панель вкладок</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Запросить платежи (создаёт QR-коды и bitcoin: ссылки)</translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation>Показать список использованных адресов и меток отправки</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation>Показать список использованных адресов и меток получения</translation>
- </message>
- <message>
- <source>Open a bitcoin: URI or payment request</source>
- <translation>Открыть bitcoin: URI или запрос платежа</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation>&amp;Параметры командной строки</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n активных соединений с сетью Bitcoin</numerusform><numerusform>%n активных соединений с сетью Bitcoin</numerusform><numerusform>%n активных соединений с сетью Bitcoin</numerusform><numerusform>%n активных соединений с сетью Bitcoin</numerusform></translation>
- </message>
- <message>
- <source>Indexing blocks on disk...</source>
- <translation>Индексация блоков на диске...</translation>
- </message>
- <message>
- <source>Processing blocks on disk...</source>
- <translation>Обработка блоков на диске...</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>Обработан %n блок истории транзакций.</numerusform><numerusform>Обработано %n блока истории транзакций.</numerusform><numerusform>Обработано %n блоков истории транзакций.</numerusform><numerusform>Обработано %n блоков истории транзакций.</numerusform></translation>
- </message>
- <message>
- <source>%1 behind</source>
- <translation>%1 позади</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation>Последний полученный блок был сгенерирован %1 назад.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation>Транзакции после него пока не будут видны.</translation>
+ <translation>Кошелёк</translation>
</message>
<message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
- <message>
- <source>Warning</source>
- <translation>Внимание</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Информация</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation>Синхронизировано</translation>
- </message>
- <message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation>Показать помощь по %1, чтобы получить список доступных параметров командной строки</translation>
- </message>
- <message>
- <source>%1 client</source>
- <translation>%1 клиент</translation>
- </message>
- <message>
- <source>Connecting to peers...</source>
- <translation>Подключение к пирам...</translation>
- </message>
- <message>
- <source>Catching up...</source>
- <translation>Синхронизируется...</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation>Дата: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation>Количество: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation>Тип: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation>Метка: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation>Адрес: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation>Исходящая транзакция</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation>Входящая транзакция</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation>Генерация HD-ключей &lt;b&gt;разрешена&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>Генерация HD-ключей &lt;b&gt;запрещена&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>Бумажник &lt;b&gt;зашифрован&lt;/b&gt; и в настоящее время &lt;b&gt;разблокирован&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>Бумажник &lt;b&gt;зашифрован&lt;/b&gt; и в настоящее время &lt;b&gt;заблокирован&lt;/b&gt;</translation>
- </message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Произошла неисправимая ошибка. Bitcoin не может безопасно продолжать работу и будет закрыт.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
- <source>Coin Selection</source>
- <translation>Выбор монет</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Количество:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Байт:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Сумма:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Комиссия:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Пыль:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>После комиссии:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Сдача:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation>Отменить выбор всего</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation>Режим дерева</translation>
- </message>
- <message>
- <source>List mode</source>
- <translation>Режим списка</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Сумма</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation>Получено с пометкой</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation>Получено с адреса</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation>Подтверждений</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation>Подтверждено</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Копировать адрес</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Копировать метку</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Копировать сумму</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Копировать ID транзакции</translation>
- </message>
- <message>
- <source>Lock unspent</source>
- <translation>Заблокировать непотраченное</translation>
- </message>
- <message>
- <source>Unlock unspent</source>
- <translation>Разблокировать непотраченное</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Копировать количество</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Копировать комиссию</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Копировать после комиссии</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Копировать байты</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Копировать пыль</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Копировать сдачу</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation>(%1 заблокировано)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation>да</translation>
- </message>
- <message>
- <source>no</source>
- <translation>нет</translation>
- </message>
- <message>
- <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Эта метка станет красной, если любой получатель получит сумму меньше, чем текущий порог пыли.</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation>Может отличаться на +/- %1 сатоши на вход.</translation>
- </message>
- <message>
<source>(no label)</source>
<translation>(нет метки)</translation>
</message>
- <message>
- <source>change from %1 (%2)</source>
- <translation>сдача с %1 (%2)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation>(сдача)</translation>
- </message>
-</context>
+ </context>
<context>
<name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation>Изменить адрес</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation>&amp;Метка</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation>Метка, связанная с этой записью списка адресов</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Адрес, связанный с этой записью списка адресов. Он может быть изменён только для адресов отправки.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation>&amp;Адрес</translation>
- </message>
- <message>
- <source>New receiving address</source>
- <translation>Новый адрес получения</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation>Новый адрес отправки</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation>Изменить адрес получения</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation>Изменить адрес отправки</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>Введённый адрес "%1" не является правильным Bitcoin-адресом.</translation>
- </message>
- <message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Введённый адрес "%1" уже находится в адресной книге.</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation>Не удается разблокировать бумажник.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation>Генерация нового ключа не удалась.</translation>
- </message>
-</context>
+ </context>
<context>
<name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation>Будет создан новый каталог данных.</translation>
- </message>
- <message>
- <source>name</source>
- <translation>имя</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation>Каталог уже существует. Добавьте %1, если вы хотите создать здесь новый каталог.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation>Путь уже существует и не является каталогом.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation>Не удаётся создать здесь каталог данных.</translation>
- </message>
-</context>
+ </context>
<context>
<name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation>версия</translation>
- </message>
- <message>
- <source>(%1-bit)</source>
- <translation>(%1-бит)</translation>
- </message>
- <message>
- <source>About %1</source>
- <translation>О %1</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation>Параметры командной строки</translation>
- </message>
- <message>
- <source>Usage:</source>
- <translation>Использование:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>параметры командной строки</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Настройки интерфейса:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Выбрать каталог данных при запуске (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Выберите язык, например "de_DE" (по умолчанию: как в системе)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Запускать свёрнутым</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Указать корневые SSL-сертификаты для запроса платежа (по умолчанию: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Показывать экран-заставку при запуске (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Сбросить все настройки, измененные в графическом интерфейсе</translation>
- </message>
-</context>
+ </context>
<context>
<name>Intro</name>
<message>
- <source>Welcome</source>
- <translation>Добро пожаловать</translation>
- </message>
- <message>
- <source>Welcome to %1.</source>
- <translation>Добро пожаловать в %1</translation>
- </message>
- <message>
- <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
- <translation>При первом запуске программы вы можете выбрать где %1 будет хранить свои данные.</translation>
- </message>
- <message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation>Когда вы нажимаете ОК, %1 начнет загружать и обрабатывать полную цепочку блоков %4 (%2 ГБ), начиная с самых ранних транзакций в %3, когда первоначально запускался %4.</translation>
- </message>
- <message>
- <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation>©Если вы решили ограничить хранение цепочки блоков (обрезка), исторические данные должны быть загружены и обработаны, но впоследствии будут удалены, чтобы поддерживать низкий уровень использования вашего диска.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation>Использовать каталог данных по умолчанию</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation>Использовать другой каталог данных:</translation>
- </message>
- <message>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
- </message>
- <message>
- <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>Минимум %1 Гб данных будет храниться в этом каталоге, и со временем объем данных будет увеличиваться.</translation>
- </message>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation>Приблизительно %1 Гб данных будет храниться в этом каталоге.</translation>
- </message>
- <message>
- <source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 будет загружать и хранить копию цепочки блоков Bitcoin.</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation>Кошелек будет также храниться в этом каталоге.</translation>
- </message>
- <message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Ошибка: не удалось создать указанный каталог данных "%1".</translation>
- </message>
- <message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
- <message numerus="yes">
- <source>%n GB of free space available</source>
- <translation><numerusform>%n ГБ свободного места доступно</numerusform><numerusform>%n ГБ свободного места доступно</numerusform><numerusform>%n ГБ свободного места доступно</numerusform><numerusform>%n ГБ свободного места доступно</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>(of %n GB needed)</source>
- <translation><numerusform>(из необходимых %n ГБ)</numerusform><numerusform>(из необходимых %n ГБ)</numerusform><numerusform>(из необходимых %n ГБ)</numerusform><numerusform>(из необходимых %n ГБ)</numerusform></translation>
- </message>
-</context>
+ </context>
<context>
<name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation>Форма</translation>
- </message>
- <message>
- <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation>Недавние транзакции могут быть пока не видны, поэтому ваш баланс может отображаться некорректно. Эта информация станет корректной, как только ваш бумажник будет синхронизирован с сетью, см. подробности ниже.</translation>
- </message>
- <message>
- <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation>Попытка потратить биткоины из ещё не отображённых транзакций будет отвергнута сетью.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation>Число оставшихся блоков</translation>
- </message>
- <message>
- <source>Unknown...</source>
- <translation>Неизвестно...</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Время последнего блока</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation>Прогресс</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation>Прогресс за час</translation>
- </message>
- <message>
- <source>calculating...</source>
- <translation>расчёт...</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation>Примерное время до завершения синхронизации</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Скрыть</translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1)...</source>
- <translation>Неизвестно. Синхронизация заголовков (%1)...</translation>
- </message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
- <message>
- <source>Open URI</source>
- <translation>Открыть URI</translation>
- </message>
- <message>
- <source>Open payment request from URI or file</source>
- <translation>Открыть запрос платежа из URI или файла</translation>
- </message>
- <message>
- <source>URI:</source>
- <translation>URI:</translation>
- </message>
- <message>
- <source>Select payment request file</source>
- <translation>Выбрать файл запроса платежа</translation>
- </message>
- <message>
- <source>Select payment request file to open</source>
- <translation>Выберите файл запроса платежа</translation>
- </message>
-</context>
+ </context>
<context>
<name>OptionsDialog</name>
<message>
- <source>Options</source>
- <translation>Параметры</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation>&amp;Главная</translation>
- </message>
- <message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation>Автоматически запускать %1 после входа в систему.</translation>
- </message>
- <message>
- <source>&amp;Start %1 on system login</source>
- <translation>&amp;Запускать %1 при входе в систему</translation>
- </message>
- <message>
- <source>Size of &amp;database cache</source>
- <translation>Размер кэша &amp;БД</translation>
- </message>
- <message>
- <source>MB</source>
- <translation>МБ</translation>
- </message>
- <message>
- <source>Number of script &amp;verification threads</source>
- <translation>Число потоков проверки &amp;сценария</translation>
- </message>
- <message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>IP-адрес прокси (например IPv4: 127.0.0.1 / IPv6: ::1)</translation>
- </message>
- <message>
- <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
- <translation>Показывает, используется ли SOCKS5 прокси по умолчанию для подключения к другим участникам по этому типу сети.</translation>
- </message>
- <message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Использовать отдельный прокси SOCKS&amp;5 для соединения с участниками через скрытые сервисы Tor:</translation>
- </message>
- <message>
- <source>Hide the icon from the system tray.</source>
- <translation>Скрыть иконку из системного трея.</translation>
- </message>
- <message>
- <source>&amp;Hide tray icon</source>
- <translation>Скрыть иконку из трея</translation>
- </message>
- <message>
- <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
- <translation>Сворачивать вместо закрытия. Если данная опция будет выбрана — приложение закроется только после выбора соответствующего пункта в меню.</translation>
- </message>
- <message>
- <source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
- <translation>Сторонние URL (например, block explorer), которые отображаются на вкладке транзакций как пункты контекстного меню. %s в URL заменяется хэшем транзакции. URL отделяются друг от друга вертикальной чертой |.</translation>
- </message>
- <message>
- <source>Active command-line options that override above options:</source>
- <translation>Активные опции командной строки, которые перекрывают вышеуказанные опции:</translation>
- </message>
- <message>
- <source>Open the %1 configuration file from the working directory.</source>
- <translation>Откройте файл конфигурации %1 из рабочего каталога.</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation>Открыть конфигурационный файл</translation>
- </message>
- <message>
- <source>Reset all client options to default.</source>
- <translation>Сбросить все настройки клиента на значения по умолчанию.</translation>
- </message>
- <message>
- <source>&amp;Reset Options</source>
- <translation>&amp;Сбросить параметры</translation>
- </message>
- <message>
- <source>&amp;Network</source>
- <translation>&amp;Сеть</translation>
- </message>
- <message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation>(0 = автоматически, &lt;0 = оставить столько незагруженных ядер)</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation>Б&amp;умажник</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation>Эксперт</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation>Включить управление входами</translation>
- </message>
- <message>
- <source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
- <translation>При отключении траты неподтверждённой сдачи, сдача от транзакции не может быть использована до тех пор пока у этой транзакции не будет хотя бы одно подтверждение. Это также влияет как ваш баланс рассчитывается.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation>&amp;Тратить неподтверждённую сдачу</translation>
- </message>
- <message>
- <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
- <translation>Автоматически открыть порт для Bitcoin-клиента на роутере. Работает только если Ваш роутер поддерживает UPnP, и данная функция включена.</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation>Пробросить порт через &amp;UPnP</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation>Разрешать соединения извне</translation>
- </message>
- <message>
- <source>Allow incomin&amp;g connections</source>
- <translation>Разрешить входящие подключения</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Подключаться к сети Bitcoin через прокси SOCKS5</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>&amp;Подключаться к сети Bitcoin через прокси SOCKS5 (прокси по умолчанию):</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation>&amp;IP Прокси: </translation>
- </message>
- <message>
- <source>&amp;Port:</source>
- <translation>По&amp;рт: </translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation>Порт прокси-сервера (например, 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation>Используется для достижения участников через:</translation>
- </message>
- <message>
- <source>IPv4</source>
- <translation>IPv4</translation>
- </message>
- <message>
- <source>IPv6</source>
- <translation>IPv6</translation>
- </message>
- <message>
- <source>Tor</source>
- <translation>Tor</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Подключаться к сети Bitcoin через прокси SOCKS5 для скрытых сервисов Tor.</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation>&amp;Окно</translation>
- </message>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation>Показывать только иконку в системном лотке после сворачивания окна.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>&amp;Cворачивать в системный лоток вместо панели задач</translation>
- </message>
- <message>
- <source>M&amp;inimize on close</source>
- <translation>С&amp;ворачивать при закрытии</translation>
- </message>
- <message>
- <source>&amp;Display</source>
- <translation>О&amp;тображение</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation>&amp;Язык интерфейса:</translation>
- </message>
- <message>
- <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation>Здесь можно установить язык пользовательского интерфейса. Настройки вступят в силу после перезагрузки %1</translation>
- </message>
- <message>
- <source>&amp;Unit to show amounts in:</source>
- <translation>&amp;Отображать суммы в единицах: </translation>
- </message>
- <message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation>Выберите единицу измерения монет при отображении и отправке.</translation>
- </message>
- <message>
- <source>Whether to show coin control features or not.</source>
- <translation>Показывать ли функции контроля монет или нет.</translation>
- </message>
- <message>
- <source>&amp;Third party transaction URLs</source>
- <translation>Сторонние URL адреса транзакций.</translation>
- </message>
- <message>
- <source>&amp;OK</source>
- <translation>&amp;OK</translation>
- </message>
- <message>
- <source>&amp;Cancel</source>
- <translation>&amp;Отмена</translation>
- </message>
- <message>
- <source>default</source>
- <translation>по умолчанию</translation>
- </message>
- <message>
- <source>none</source>
- <translation>ничего</translation>
- </message>
- <message>
- <source>Confirm options reset</source>
- <translation>Подтвердите сброс параметров</translation>
- </message>
- <message>
- <source>Client restart required to activate changes.</source>
- <translation>Для применения изменений требуется перезапуск клиента.</translation>
- </message>
- <message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation>Клиент будет выключен. Желаете продолжить?</translation>
- </message>
- <message>
- <source>Configuration options</source>
- <translation>Параметры конфигурации</translation>
- </message>
- <message>
- <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
- <translation>Файл конфигурации используется для задания расширенных опций, которые имеют приоритет над настройками в GUI. Аналогично, опции командной строки будут иметь приоритет над этим файлом конфигурации.</translation>
- </message>
- <message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
- <message>
- <source>The configuration file could not be opened.</source>
- <translation>Не удалось открыть файл конфигурации.</translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation>Это изменение потребует перезапуска клиента.</translation>
- </message>
- <message>
- <source>The supplied proxy address is invalid.</source>
- <translation>Адрес прокси неверен.</translation>
- </message>
-</context>
+ </context>
<context>
<name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation>Форма</translation>
- </message>
- <message>
- <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
- <translation>Отображаемая информация может быть устаревшей. Ваш бумажник автоматически синхронизируется с сетью Bitcoin после подключения, но этот процесс пока не завершён.</translation>
- </message>
- <message>
- <source>Watch-only:</source>
- <translation>Только наблюдение:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation>Доступно:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation>Ваш текущий расходный баланс</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation>В ожидании:</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation>Общая сумма всех транзакций, которые до сих пор не подтверждены, и до сих пор не учитываются в расходном балансе</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation>Незрелые:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation>Баланс добытых монет, который ещё не созрел</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation>Балансы</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation>Итого:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation>Ваш текущий общий баланс</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation>Ваш текущий баланс в адресах наблюдения</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation>Доступно:</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation>Последние транзакции</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Неподтверждённые транзакции на адреса наблюдения</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Баланс добытых монет на адресах наблюдения, который ещё не созрел</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation>Текущий общий баланс на адресах наблюдения</translation>
- </message>
-</context>
+ </context>
<context>
<name>PaymentServer</name>
- <message>
- <source>Payment request error</source>
- <translation>Ошибка запроса платежа</translation>
- </message>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Не удаётся запустить bitcoin: обработчик click-to-pay</translation>
- </message>
- <message>
- <source>URI handling</source>
- <translation>Обработка URI</translation>
- </message>
- <message>
- <source>Payment request fetch URL is invalid: %1</source>
- <translation>Неверный URL запроса платежа: %1</translation>
- </message>
- <message>
- <source>Invalid payment address %1</source>
- <translation>Неверный адрес платежа %1</translation>
- </message>
- <message>
- <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>Не удалось обработать URI! Это может быть связано с неверным адресом Bitcoin или неправильными параметрами URI.</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation>Обработка файла запроса платежа</translation>
- </message>
- <message>
- <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Файл запроса платежа не может быть прочитан! Обычно это происходит из-за неверного файла запроса платежа.</translation>
- </message>
- <message>
- <source>Payment request rejected</source>
- <translation>Запрос платежа отклонён</translation>
- </message>
- <message>
- <source>Payment request network doesn't match client network.</source>
- <translation>Сеть запроса платежа не совпадает с сетью клиента.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Запрос платежа просрочен.</translation>
- </message>
- <message>
- <source>Payment request is not initialized.</source>
- <translation>Запрос платежа не инициализирован.</translation>
- </message>
- <message>
- <source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Непроверенные запросы платежей с нестандартными платёжными сценариями не поддерживаются.</translation>
- </message>
- <message>
- <source>Invalid payment request.</source>
- <translation>Неверный запрос платежа.</translation>
- </message>
- <message>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
- <translation>Запрошенная сумма платежа %1 слишком мала (считается пылью).</translation>
- </message>
- <message>
- <source>Refund from %1</source>
- <translation>Возврат от %1</translation>
- </message>
- <message>
- <source>Payment request %1 is too large (%2 bytes, allowed %3 bytes).</source>
- <translation>Запрос платежа %1 слишком большой (%2 байтов, разрешено %3 байтов).</translation>
- </message>
- <message>
- <source>Error communicating with %1: %2</source>
- <translation>Ошибка связи с %1: %2</translation>
- </message>
- <message>
- <source>Payment request cannot be parsed!</source>
- <translation>Запрос платежа не может быть разобран!</translation>
- </message>
- <message>
- <source>Bad response from server %1</source>
- <translation>Плохой ответ сервера %1</translation>
- </message>
- <message>
- <source>Network request error</source>
- <translation>Ошибка сетевого запроса</translation>
- </message>
- <message>
- <source>Payment acknowledged</source>
- <translation>Платёж принят</translation>
- </message>
-</context>
+ </context>
<context>
<name>PeerTableModel</name>
- <message>
- <source>User Agent</source>
- <translation>Юзер-агент</translation>
- </message>
- <message>
- <source>Node/Service</source>
- <translation>Узел/сервис</translation>
- </message>
- <message>
- <source>NodeId</source>
- <translation>Id узла</translation>
- </message>
- <message>
- <source>Ping</source>
- <translation>Пинг</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Отправлено</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Получено</translation>
- </message>
-</context>
+ </context>
<context>
<name>QObject</name>
- <message>
- <source>Amount</source>
- <translation>Сумма</translation>
- </message>
- <message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Введите адрес Bitcoin (например, %1)</translation>
- </message>
- <message>
- <source>%1 d</source>
- <translation>%1 д</translation>
- </message>
- <message>
- <source>%1 h</source>
- <translation>%1 ч</translation>
- </message>
- <message>
- <source>%1 m</source>
- <translation>%1 мин</translation>
- </message>
- <message>
- <source>%1 s</source>
- <translation>%1 с</translation>
- </message>
- <message>
- <source>None</source>
- <translation>Ничего</translation>
- </message>
- <message>
- <source>N/A</source>
- <translation>Н/Д</translation>
- </message>
- <message>
- <source>%1 ms</source>
- <translation>%1 мс</translation>
- </message>
- <message numerus="yes">
- <source>%n second(s)</source>
- <translation><numerusform>%n секунда</numerusform><numerusform>%n секунды</numerusform><numerusform>%n секунд</numerusform><numerusform>%n секунд</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n minute(s)</source>
- <translation><numerusform>%n минута</numerusform><numerusform>%n минут</numerusform><numerusform>%n минут</numerusform><numerusform>%n минут</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n hour(s)</source>
- <translation><numerusform>%n час</numerusform><numerusform>%n часа</numerusform><numerusform>%n часов</numerusform><numerusform>%n часов</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n day(s)</source>
- <translation><numerusform>%n день</numerusform><numerusform>%n дня</numerusform><numerusform>%n дней</numerusform><numerusform>%n дней</numerusform></translation>
- </message>
- <message numerus="yes">
- <source>%n week(s)</source>
- <translation><numerusform>%n неделя</numerusform><numerusform>%n недели</numerusform><numerusform>%n недель</numerusform><numerusform>%n недель</numerusform></translation>
- </message>
- <message>
- <source>%1 and %2</source>
- <translation>%1 и %2</translation>
- </message>
- <message numerus="yes">
- <source>%n year(s)</source>
- <translation><numerusform>%n год</numerusform><numerusform>%n года</numerusform><numerusform>%n лет</numerusform><numerusform>%n лет</numerusform></translation>
- </message>
- <message>
- <source>%1 B</source>
- <translation>%1 Б</translation>
- </message>
- <message>
- <source>%1 KB</source>
- <translation>%1 КБ</translation>
- </message>
- <message>
- <source>%1 MB</source>
- <translation>%1 МБ</translation>
- </message>
- <message>
- <source>%1 GB</source>
- <translation>%1 ГБ</translation>
- </message>
- <message>
- <source>%1 didn't yet exit safely...</source>
- <translation>%1 ещё не завершился безопасно...</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>неизвестно</translation>
- </message>
-</context>
+ </context>
<context>
<name>QObject::QObject</name>
- <message>
- <source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Ошибка: указанный каталог "%1" не существует.</translation>
- </message>
- <message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Ошибка: не удалось разобрать конфигурационный файл: %1. Используйте синтаксис вида ключ=значение.</translation>
- </message>
- <message>
- <source>Error: %1</source>
- <translation>Ошибка: %1</translation>
- </message>
-</context>
+ </context>
<context>
<name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Сохранить изображение...</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation>Копировать &amp;изображение</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation>Сохранить QR-код</translation>
- </message>
- <message>
- <source>PNG Image (*.png)</source>
- <translation>Изображение PNG (*.png)</translation>
- </message>
-</context>
+ </context>
<context>
<name>RPCConsole</name>
- <message>
- <source>N/A</source>
- <translation>Н/Д</translation>
- </message>
- <message>
- <source>Client version</source>
- <translation>Версия клиента</translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation>&amp;Информация</translation>
- </message>
- <message>
- <source>Debug window</source>
- <translation>Окно отладки</translation>
- </message>
- <message>
- <source>General</source>
- <translation>Общие</translation>
- </message>
- <message>
- <source>Using BerkeleyDB version</source>
- <translation>Используется версия BerkeleyDB</translation>
- </message>
- <message>
- <source>Datadir</source>
- <translation>Каталог для данных</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation>Время запуска</translation>
- </message>
- <message>
- <source>Network</source>
- <translation>Сеть</translation>
- </message>
- <message>
- <source>Name</source>
- <translation>Имя</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation>Число подключений</translation>
- </message>
- <message>
- <source>Block chain</source>
- <translation>Цепь блоков</translation>
- </message>
- <message>
- <source>Current number of blocks</source>
- <translation>Текущее число блоков</translation>
- </message>
- <message>
- <source>Memory Pool</source>
- <translation>Пул памяти</translation>
- </message>
- <message>
- <source>Current number of transactions</source>
- <translation>Текущее число транзакций</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation>Использование памяти</translation>
- </message>
- <message>
- <source>&amp;Reset</source>
- <translation>&amp;Сброс</translation>
- </message>
- <message>
- <source>Received</source>
- <translation>Получено</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation>Отправлено</translation>
- </message>
- <message>
- <source>&amp;Peers</source>
- <translation>&amp;Участники</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation>Заблокированные участники</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <translation>Выберите участника для просмотра подробностей.</translation>
- </message>
- <message>
- <source>Whitelisted</source>
- <translation>Доверенный</translation>
- </message>
- <message>
- <source>Direction</source>
- <translation>Направление</translation>
- </message>
- <message>
- <source>Version</source>
- <translation>Версия</translation>
- </message>
- <message>
- <source>Starting Block</source>
- <translation>Начальный блок</translation>
- </message>
- <message>
- <source>Synced Headers</source>
- <translation>Синхронизировано заголовков</translation>
- </message>
- <message>
- <source>Synced Blocks</source>
- <translation>Синхронизировано блоков</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation>Юзер-агент</translation>
- </message>
- <message>
- <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
- <translation>Открыть отладочный лог-файл %1 из текущего каталога данных. Это может занять несколько секунд для больших лог-файлов.</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation>Уменьшить размер текста</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation>Увеличить размер текста</translation>
- </message>
- <message>
- <source>Services</source>
- <translation>Сервисы</translation>
- </message>
- <message>
- <source>Ban Score</source>
- <translation>Очков бана</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation>Время соединения</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation>Последняя отправка</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation>Последний раз получено</translation>
- </message>
- <message>
- <source>Ping Time</source>
- <translation>Время задержки</translation>
- </message>
- <message>
- <source>The duration of a currently outstanding ping.</source>
- <translation>Длительность текущего пинга.</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation>Время задержки</translation>
- </message>
- <message>
- <source>Min Ping</source>
- <translation>Мин. пинг</translation>
- </message>
- <message>
- <source>Time Offset</source>
- <translation>Смещение времени</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation>Время последнего блока</translation>
- </message>
- <message>
- <source>&amp;Open</source>
- <translation>&amp;Открыть</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation>Консоль</translation>
- </message>
- <message>
- <source>&amp;Network Traffic</source>
- <translation>Сетевой &amp;трафик</translation>
- </message>
- <message>
- <source>Totals</source>
- <translation>Всего</translation>
- </message>
- <message>
- <source>In:</source>
- <translation>Вход:</translation>
- </message>
- <message>
- <source>Out:</source>
- <translation>Выход:</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation>Отладочный лог-файл</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation>Очистить консоль</translation>
- </message>
- <message>
- <source>1 &amp;hour</source>
- <translation>1 &amp;час</translation>
- </message>
- <message>
- <source>1 &amp;day</source>
- <translation>1 &amp;день</translation>
- </message>
- <message>
- <source>1 &amp;week</source>
- <translation>1 &amp;неделю</translation>
- </message>
- <message>
- <source>1 &amp;year</source>
- <translation>1 &amp;год</translation>
- </message>
- <message>
- <source>&amp;Disconnect</source>
- <translation>&amp;Отключиться</translation>
- </message>
- <message>
- <source>Ban for</source>
- <translation>Бан на</translation>
- </message>
- <message>
- <source>&amp;Unban</source>
- <translation>&amp;Разбанить</translation>
- </message>
- <message>
- <source>Welcome to the %1 RPC console.</source>
- <translation>Добро пожаловать в консоль RPC %1.</translation>
- </message>
- <message>
- <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
- <translation>Используйте стрелки вверх и вниз для просмотра истории и %1 для очистки экрана</translation>
- </message>
- <message>
- <source>Type %1 for an overview of available commands.</source>
- <translation>Напишите %1 help для просмотра доступных команд.</translation>
- </message>
- <message>
- <source>For more information on using this console type %1.</source>
- <translation>Для получения дополнительной информации по использованию этой консоли напишите %1.</translation>
- </message>
- <message>
- <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
- <translation>ПРЕДУПРЕЖДЕНИЕ: Были замечены мошенники, предлагающие пользователям вводить здесь команды, крадя содержимое их кошелька. Не используйте эту консоль, не понимая полностью последствия команды.</translation>
- </message>
- <message>
- <source>Network activity disabled</source>
- <translation>Сетевая активность запрещена</translation>
- </message>
- <message>
- <source>(node id: %1)</source>
- <translation>(номер узла: %1)</translation>
- </message>
- <message>
- <source>via %1</source>
- <translation>через %1</translation>
- </message>
- <message>
- <source>never</source>
- <translation>никогда</translation>
- </message>
- <message>
- <source>Inbound</source>
- <translation>Входящие</translation>
- </message>
- <message>
- <source>Outbound</source>
- <translation>Исходящие</translation>
- </message>
- <message>
- <source>Yes</source>
- <translation>Да</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Нет</translation>
- </message>
- <message>
- <source>Unknown</source>
- <translation>Неизвестно</translation>
- </message>
-</context>
+ </context>
<context>
<name>ReceiveCoinsDialog</name>
<message>
- <source>&amp;Amount:</source>
- <translation>&amp;Сумма:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Метка:</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation>&amp;Сообщение</translation>
- </message>
- <message>
- <source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
- <translation>Необязательное сообщение для запроса платежа, которое будет показано при открытии запроса. Заметьте: сообщение не будет отправлено вместе с платежом через сеть Bitcoin.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation>Необязательная метка для нового адреса получения.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Заполните форму для запроса платежей. Все поля &lt;b&gt;необязательны&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation>Необязательная сумма для запроса. Оставьте пустым или укажите ноль, чтобы запросить неопределённую сумму.</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Очистить все поля формы.</translation>
- </message>
- <message>
<source>Clear</source>
<translation>Очистить</translation>
</message>
- <message>
- <source>Requested payments history</source>
- <translation>История запрошенных платежей</translation>
- </message>
- <message>
- <source>&amp;Request payment</source>
- <translation>&amp;Запросить платёж</translation>
- </message>
- <message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Bech32 адреса (BIP-173) дешевле в коммисиях и предлагают лучшую защиту от опечаток. Когда пункт P2SH не отмечен, будет создан связанный SegWit адрес, совместимый со старыми кошельками.</translation>
- </message>
- <message>
- <source>Generate Bech32 address</source>
- <translation>Создать Bech32 адрес</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation>Показать выбранный запрос (то же самое, что и двойной клик по записи)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation>Показать</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation>Удалить выбранные записи из списка</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation>Удалить</translation>
- </message>
- <message>
- <source>Copy URI</source>
- <translation>Копировать URI</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Копировать метку</translation>
- </message>
- <message>
- <source>Copy message</source>
- <translation>Копировать сообщение</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Копировать сумму</translation>
- </message>
-</context>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR код</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Копировать &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Копировать &amp;адрес</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Сохранить изображение...</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation>Запросить платёж на %1</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Информация платежа</translation>
- </message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
<source>Address</source>
<translation>Адрес</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Сумма</translation>
- </message>
- <message>
<source>Label</source>
<translation>Метка</translation>
</message>
<message>
- <source>Message</source>
- <translation>Сообщение</translation>
- </message>
- <message>
- <source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation>Получившийся URI слишком длинный, попробуйте сократить текст метки / сообщения.</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation>Ошибка кодирования URI в QR-код</translation>
+ <source>Wallet</source>
+ <translation>Кошелёк</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
<source>Label</source>
<translation>Метка</translation>
</message>
<message>
- <source>Message</source>
- <translation>Сообщение</translation>
- </message>
- <message>
<source>(no label)</source>
<translation>(нет метки)</translation>
</message>
- <message>
- <source>(no message)</source>
- <translation>(нет сообщения)</translation>
- </message>
- <message>
- <source>(no amount requested)</source>
- <translation>(нет запрошенной суммы)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation>Запрошено</translation>
- </message>
-</context>
+ </context>
<context>
<name>SendCoinsDialog</name>
<message>
- <source>Send Coins</source>
- <translation>Отправка</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation>Функции Контроля Монет</translation>
- </message>
- <message>
- <source>Inputs...</source>
- <translation>Входы...</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation>автоматически выбрано</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation>Недостаточно средств!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation>Количество:</translation>
- </message>
- <message>
- <source>Bytes:</source>
- <translation>Байт:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation>Сумма:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation>Комиссия:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation>После комиссии:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation>Размен:</translation>
- </message>
- <message>
- <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
- <translation>Если это выбрано, но адрес сдачи пустой или неверный, сдача будет отправлена на новый сгенерированный адрес.</translation>
- </message>
- <message>
- <source>Custom change address</source>
- <translation>Свой адрес для сдачи</translation>
- </message>
- <message>
- <source>Transaction Fee:</source>
+ <source>Transaction fee</source>
<translation>Комиссия</translation>
</message>
<message>
- <source>Choose...</source>
- <translation>Выберите...</translation>
- </message>
- <message>
- <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
- <translation>Использование резервной комиссии может привести к подтверждению транзакции в течение нескольких часов или дней (или она никогда не будет подтверждена). Советуем выбрать комиссию вручную или дождаться полной валидации цепи.</translation>
- </message>
- <message>
- <source>Warning: Fee estimation is currently not possible.</source>
- <translation>Внимание: оценка размера комиссии в настоящее время невозможна.</translation>
- </message>
- <message>
- <source>collapse fee-settings</source>
- <translation>Свернуть настройки комиссии</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation>за килобайт</translation>
- </message>
- <message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Если комиссия установлена в 1000 сатоши, а транзакция составляет лишь 250 байт, тогда комиссия "на килобайт" составит 250 сатоши, а "всего как минимум" — 1000 сатоши. Для транзакций крупнее килобайта в обоих случаях будет использоваться платёж "на килобайт".</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation>Скрыть</translation>
- </message>
- <message>
- <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation>Уплата минимальной комиссии — не проблема, пока объём транзакций меньше, чем свободное место в блоках. Учтите, однако, что такая транзакция может никогда не подтвердиться, если спрос на транзакции превышает возможности сети по их обработке.</translation>
- </message>
- <message>
- <source>(read the tooltip)</source>
- <translation>(прочтите подсказку)</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation>Рекомендовано:</translation>
- </message>
- <message>
- <source>Custom:</source>
- <translation>Выборочно:</translation>
- </message>
- <message>
- <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(Умная комиссия пока не инициализирована. Обычно для этого требуется несколько блоков...)</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation>Отправить нескольким получателям одновременно</translation>
- </message>
- <message>
- <source>Add &amp;Recipient</source>
- <translation>&amp;Добавить получателя</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation>Очистить все поля формы</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation>Пыль:</translation>
- </message>
- <message>
- <source>Confirmation time target:</source>
- <translation>Время подтверждения:</translation>
- </message>
- <message>
- <source>Enable Replace-By-Fee</source>
- <translation>Включить Replace-By-Fee (возможность замены комиссии)</translation>
- </message>
- <message>
- <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
- <translation>С опцией Replace-By-Fee (BIP-125) вы можете увеличить комиссию за транзакцию уже после отправки. Без этого, рекомендуем вам отправлять заведомо с более высокой комиссией, чтобы компенсировать риск задержки подтверждения.</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Очистить &amp;всё</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation>Баланс:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation>Подтвердить отправку</translation>
- </message>
- <message>
- <source>S&amp;end</source>
- <translation>&amp;Отправить</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation>Копировать количество</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Копировать сумму</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation>Копировать комиссию</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation>Копировать после комиссии</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation>Копировать байты</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation>Копировать пыль</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation>Копировать сдачу</translation>
- </message>
- <message>
- <source>%1 (%2 blocks)</source>
- <translation>%1 (%2 блоков)</translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation>С %1 на %2</translation>
- </message>
- <message>
- <source>Are you sure you want to send?</source>
- <translation>Вы уверены, что хотите отправить?</translation>
- </message>
- <message>
- <source>added as transaction fee</source>
- <translation>добавлено как комиссия</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Общая сумма %1</translation>
- </message>
- <message>
- <source>or</source>
- <translation>или</translation>
- </message>
- <message>
- <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
- <translation>Вы можете увеличить комиссию позже (опция Replace-By-Fee, BIP-125).</translation>
- </message>
- <message>
- <source>Not signalling Replace-By-Fee, BIP-125.</source>
- <translation>Не используется Replace-By-Fee, BIP-125.</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation>Подтвердите отправку монет</translation>
- </message>
- <message>
- <source>The recipient address is not valid. Please recheck.</source>
- <translation>Адрес получателя неверный. Пожалуйста, перепроверьте.</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation>Сумма для отправки должна быть больше 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation>Сумма превышает ваш баланс.</translation>
- </message>
- <message>
- <source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>Сумма с учётом комиссии %1 превысит ваш баланс.</translation>
- </message>
- <message>
- <source>Duplicate address found: addresses should only be used once each.</source>
- <translation>Обнаружен дублирующийся адрес: используйте каждый адрес только один раз.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation>Не удалось создать транзакцию!</translation>
- </message>
- <message>
- <source>The transaction was rejected with the following reason: %1</source>
- <translation>Транзакция была отвергнута по следующей причине: %1</translation>
- </message>
- <message>
- <source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation>Комиссия больше чем %1 считается невероятно большой.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation>Запрос платежа просрочен.</translation>
- </message>
- <message>
- <source>Pay only the required fee of %1</source>
- <translation>Заплатить только обязательную комиссию %1</translation>
- </message>
- <message numerus="yes">
- <source>Estimated to begin confirmation within %n block(s).</source>
- <translation><numerusform>Начало подтверждения ожидается через %n блок.</numerusform><numerusform>Начало подтверждения ожидается через %n блока.</numerusform><numerusform>Начало подтверждения ожидается через %n блоков.</numerusform><numerusform>Начало подтверждения ожидается через %n блоков.</numerusform></translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation>Внимание: неверный адрес Bitcoin</translation>
- </message>
- <message>
- <source>Warning: Unknown change address</source>
- <translation>Внимание: неизвестный адрес для сдачи</translation>
- </message>
- <message>
- <source>Confirm custom change address</source>
- <translation>Подтвердите свой адрес для сдачи</translation>
- </message>
- <message>
- <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
- <translation>Выбранный вами адрес для сдачи не принадлежит этому кошельку. Часть или все средства могут быть отправлены на этот адрес. Вы уверены?</translation>
- </message>
- <message>
<source>(no label)</source>
<translation>(нет метки)</translation>
</message>
</context>
<context>
<name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation>Ко&amp;личество:</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation>Полу&amp;чатель:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation>&amp;Метка:</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Выберите ранее использованный адрес</translation>
- </message>
- <message>
- <source>This is a normal payment.</source>
- <translation>Это нормальный платёж.</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation>Адрес Bitcoin, на который отправить платёж</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Вставить адрес из буфера обмена</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation>Удалить эту запись</translation>
- </message>
- <message>
- <source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
- <translation>С отправляемой суммы будет удержана комиссия. Получателю придёт меньше биткоинов, чем вы вводите в поле количества. Если выбрано несколько получателей, комиссия распределяется поровну.</translation>
- </message>
- <message>
- <source>S&amp;ubtract fee from amount</source>
- <translation>Вычесть комиссию из суммы</translation>
- </message>
- <message>
- <source>Use available balance</source>
- <translation>Использовать весь баланс</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation>Сообщение:</translation>
- </message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation>Это неавторизованный запрос платежа.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation>Это авторизованный запрос платежа.</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Введите метку для этого адреса, чтобы добавить его в список использованных</translation>
- </message>
- <message>
- <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
- <translation>К bitcoin: URI было прикреплено сообщение, которое будет сохранено вместе с транзакцией для вашего сведения. Заметьте: сообщение не будет отправлено через сеть Bitcoin.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation>Получатель:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation>Примечание:</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to your address book</source>
- <translation>Введите метку для данного адреса, чтобы добавить его в адресную книгу</translation>
- </message>
-</context>
+ </context>
<context>
<name>SendConfirmationDialog</name>
- <message>
- <source>Yes</source>
- <translation>Да</translation>
- </message>
-</context>
+ </context>
<context>
<name>ShutdownWindow</name>
- <message>
- <source>%1 is shutting down...</source>
- <translation>%1 выключается...</translation>
- </message>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation>Не выключайте компьютер, пока это окно не исчезнет.</translation>
- </message>
-</context>
+ </context>
<context>
<name>SignVerifyMessageDialog</name>
- <message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation>Подписи - подписать/проверить сообщение</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation>&amp;Подписать сообщение</translation>
- </message>
- <message>
- <source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
- <translation>Вы можете подписывать сообщения/соглашения своими адресами, чтобы доказать свою возможность получать биткоины на них. Будьте осторожны, не подписывайте что-то неопределённое или случайное, так как фишинговые атаки могут обманным путём заставить вас подписать нежелательные сообщения. Подписывайте только те сообщения, с которыми вы согласны вплоть до мелочей.</translation>
- </message>
- <message>
- <source>The Bitcoin address to sign the message with</source>
- <translation>Адрес Bitcoin, которым подписать сообщение</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation>Выберите ранее использованный адрес</translation>
- </message>
- <message>
- <source>Alt+A</source>
- <translation>Alt+A</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation>Вставить адрес из буфера обмена</translation>
- </message>
- <message>
- <source>Alt+P</source>
- <translation>Alt+P</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation>Введите сообщение для подписи</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation>Подпись</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation>Скопировать текущую подпись в системный буфер обмена</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Подписать сообщение, чтобы доказать владение адресом Bitcoin</translation>
- </message>
- <message>
- <source>Sign &amp;Message</source>
- <translation>Подписать &amp;Сообщение</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation>Сбросить значения всех полей подписывания сообщений</translation>
- </message>
- <message>
- <source>Clear &amp;All</source>
- <translation>Очистить &amp;всё</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation>&amp;Проверить сообщение</translation>
- </message>
- <message>
- <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation>Введите ниже адрес получателя, сообщение (убедитесь, что переводы строк, пробелы, табы и т.п. в точности скопированы) и подпись, чтобы проверить сообщение. Убедитесь, что не скопировали лишнего в подпись, по сравнению с самим подписываемым сообщением, чтобы не стать жертвой атаки "man-in-the-middle". Заметьте, что эта операция удостоверяет лишь авторство подписавшего, но не может удостоверить отправителя транзакции.</translation>
- </message>
- <message>
- <source>The Bitcoin address the message was signed with</source>
- <translation>Адрес Bitcoin, которым было подписано сообщение</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Проверить сообщение, чтобы убедиться, что оно было подписано указанным адресом Bitcoin</translation>
- </message>
- <message>
- <source>Verify &amp;Message</source>
- <translation>Проверить &amp;Сообщение</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation>Сбросить все поля проверки сообщения</translation>
- </message>
- <message>
- <source>Click "Sign Message" to generate signature</source>
- <translation>Нажмите "Подписать сообщение" для создания подписи</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation>Введённый адрес неверен.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation>Пожалуйста, проверьте адрес и попробуйте ещё раз.</translation>
- </message>
- <message>
- <source>The entered address does not refer to a key.</source>
- <translation>Введённый адрес не связан с ключом.</translation>
- </message>
- <message>
- <source>Wallet unlock was cancelled.</source>
- <translation>Разблокировка бумажника была отменена.</translation>
- </message>
- <message>
- <source>Private key for the entered address is not available.</source>
- <translation>Недоступен секретный ключ для введённого адреса.</translation>
- </message>
- <message>
- <source>Message signing failed.</source>
- <translation>Не удалось подписать сообщение.</translation>
- </message>
- <message>
- <source>Message signed.</source>
- <translation>Сообщение подписано.</translation>
- </message>
- <message>
- <source>The signature could not be decoded.</source>
- <translation>Подпись не может быть раскодирована.</translation>
- </message>
- <message>
- <source>Please check the signature and try again.</source>
- <translation>Пожалуйста, проверьте подпись и попробуйте ещё раз.</translation>
- </message>
- <message>
- <source>The signature did not match the message digest.</source>
- <translation>Подпись не соответствует отпечатку сообщения.</translation>
- </message>
- <message>
- <source>Message verification failed.</source>
- <translation>Сообщение не прошло проверку.</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation>Сообщение проверено.</translation>
- </message>
-</context>
+ </context>
<context>
<name>SplashScreen</name>
- <message>
- <source>[testnet]</source>
- <translation>[тестовая сеть]</translation>
- </message>
-</context>
+ </context>
<context>
<name>TrafficGraphWidget</name>
- <message>
- <source>KB/s</source>
- <translation>КБ/сек</translation>
- </message>
-</context>
+ </context>
<context>
<name>TransactionDesc</name>
- <message numerus="yes">
- <source>Open for %n more block(s)</source>
- <translation><numerusform>Открыто для ещё %n блока</numerusform><numerusform>Открыто для ещё %n блоков</numerusform><numerusform>Открыто для ещё %n блоков</numerusform><numerusform>Открыто для ещё %n блоков</numerusform></translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Открыто до %1</translation>
- </message>
- <message>
- <source>conflicted with a transaction with %1 confirmations</source>
- <translation>конфликт с транзакцией с %1 подтверждений</translation>
- </message>
- <message>
- <source>%1/offline</source>
- <translation>%1/отключен</translation>
- </message>
- <message>
- <source>0/unconfirmed, %1</source>
- <translation>0/не подтверждено, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation>В памяти</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation>Не в памяти</translation>
- </message>
- <message>
- <source>abandoned</source>
- <translation>заброшено</translation>
- </message>
- <message>
- <source>%1/unconfirmed</source>
- <translation>%1/не подтверждено</translation>
- </message>
- <message>
- <source>%1 confirmations</source>
- <translation>%1 подтверждений</translation>
- </message>
- <message>
- <source>Status</source>
- <translation>Статус</translation>
- </message>
- <message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, ещё не было успешно разослано</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, разослано через %n узел</numerusform><numerusform>, разослано через %n узла</numerusform><numerusform>, разослано через %n узлов</numerusform><numerusform>, разослано через %n узлов</numerusform></translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Source</source>
- <translation>Источник</translation>
- </message>
- <message>
- <source>Generated</source>
- <translation>Сгенерированно</translation>
- </message>
- <message>
- <source>From</source>
- <translation>От</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation>неизвестно</translation>
- </message>
- <message>
- <source>To</source>
- <translation>Для</translation>
- </message>
- <message>
- <source>own address</source>
- <translation>свой адрес</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>только наблюдение</translation>
- </message>
- <message>
- <source>label</source>
- <translation>метка</translation>
- </message>
- <message>
- <source>Credit</source>
- <translation>Кредит</translation>
- </message>
- <message numerus="yes">
- <source>matures in %n more block(s)</source>
- <translation><numerusform>будет доступно через %n блок</numerusform><numerusform>будет доступно через %n блока</numerusform><numerusform>будет доступно через %n блоков</numerusform><numerusform>будет доступно через %n блоков</numerusform></translation>
- </message>
- <message>
- <source>not accepted</source>
- <translation>не принято</translation>
- </message>
- <message>
- <source>Debit</source>
- <translation>Дебет</translation>
- </message>
- <message>
- <source>Total debit</source>
- <translation>Всего дебет</translation>
- </message>
- <message>
- <source>Total credit</source>
- <translation>Всего кредит</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation>Комиссия</translation>
- </message>
- <message>
- <source>Net amount</source>
- <translation>Чистая сумма</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Сообщение</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation>Комментарий</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation>ID транзакции</translation>
- </message>
- <message>
- <source>Transaction total size</source>
- <translation>Общий размер транзакции</translation>
- </message>
- <message>
- <source>Output index</source>
- <translation>Номер выхода</translation>
- </message>
- <message>
- <source>Merchant</source>
- <translation>Продавец</translation>
- </message>
- <message>
- <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation>Сгенерированные монеты должны подождать %1 блоков, прежде чем они могут быть потрачены. Когда вы сгенерировали этот блок, он был отправлен в сеть для добавления в цепочку блоков. Если он не попадёт в цепь, его статус изменится на "не принят", и монеты будут недействительны. Это иногда происходит в случае, если другой узел сгенерирует блок на несколько секунд раньше вас.</translation>
- </message>
- <message>
- <source>Debug information</source>
- <translation>Отладочная информация</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation>Транзакция</translation>
- </message>
- <message>
- <source>Inputs</source>
- <translation>Входы</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Сумма</translation>
- </message>
- <message>
- <source>true</source>
- <translation>истина</translation>
- </message>
- <message>
- <source>false</source>
- <translation>ложь</translation>
- </message>
-</context>
+ </context>
<context>
<name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation>Эта панель отображает детальное описание транзакции.</translation>
- </message>
- <message>
- <source>Details for %1</source>
- <translation>Подробности %1</translation>
- </message>
-</context>
+ </context>
<context>
<name>TransactionTableModel</name>
<message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Тип</translation>
- </message>
- <message>
<source>Label</source>
<translation>Метка</translation>
</message>
- <message numerus="yes">
- <source>Open for %n more block(s)</source>
- <translation><numerusform>Открыто для ещё %n блока</numerusform><numerusform>Открыто для ещё %n блоков</numerusform><numerusform>Открыто для ещё %n блоков</numerusform><numerusform>Открыто для ещё %n блоков</numerusform></translation>
- </message>
- <message>
- <source>Open until %1</source>
- <translation>Открыто до %1</translation>
- </message>
- <message>
- <source>Offline</source>
- <translation>Отключен</translation>
- </message>
- <message>
- <source>Unconfirmed</source>
- <translation>Не подтверждено</translation>
- </message>
- <message>
- <source>Abandoned</source>
- <translation>Заброшено</translation>
- </message>
- <message>
- <source>Confirming (%1 of %2 recommended confirmations)</source>
- <translation>Подтверждается (%1 из %2 рекомендуемых подтверждений)</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation>Подтверждено (%1 подтверждений)</translation>
- </message>
- <message>
- <source>Conflicted</source>
- <translation>В противоречии</translation>
- </message>
- <message>
- <source>Immature (%1 confirmations, will be available after %2)</source>
- <translation>Незрелый (%1 подтверждений, будет доступно после %2)</translation>
- </message>
- <message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Этот блок не был получен другими узлами и, возможно, не будет принят!</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation>Сгенерировано, но не принято</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Получено на</translation>
- </message>
- <message>
- <source>Received from</source>
- <translation>Получено от</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Отправлено на</translation>
- </message>
- <message>
- <source>Payment to yourself</source>
- <translation>Отправлено себе</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Добыто</translation>
- </message>
- <message>
- <source>watch-only</source>
- <translation>только наблюдение</translation>
- </message>
- <message>
- <source>(n/a)</source>
- <translation>(недоступно)</translation>
- </message>
<message>
<source>(no label)</source>
<translation>(нет метки)</translation>
</message>
- <message>
- <source>Transaction status. Hover over this field to show number of confirmations.</source>
- <translation>Статус транзакции. Подведите курсор к этому полю, чтобы увидеть количество подтверждений.</translation>
- </message>
- <message>
- <source>Date and time that the transaction was received.</source>
- <translation>Дата и время получения транзакции.</translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation>Тип транзакции.</translation>
- </message>
- <message>
- <source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>Использовался ли в транзакции адрес для наблюдения.</translation>
- </message>
- <message>
- <source>User-defined intent/purpose of the transaction.</source>
- <translation>Определяемое пользователем намерение/цель транзакции.</translation>
- </message>
- <message>
- <source>Amount removed from or added to balance.</source>
- <translation>Снятая или добавленная к балансу сумма.</translation>
- </message>
-</context>
+ </context>
<context>
<name>TransactionView</name>
<message>
- <source>All</source>
- <translation>Все</translation>
- </message>
- <message>
- <source>Today</source>
- <translation>Сегодня</translation>
- </message>
- <message>
- <source>This week</source>
- <translation>На этой неделе</translation>
- </message>
- <message>
- <source>This month</source>
- <translation>В этом месяце</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation>В прошлом месяце</translation>
- </message>
- <message>
- <source>This year</source>
- <translation>В этом году</translation>
- </message>
- <message>
- <source>Range...</source>
- <translation>Диапазон...</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation>Получено на</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation>Отправлено на</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation>Себе</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation>Добыто</translation>
- </message>
- <message>
- <source>Other</source>
- <translation>Другое</translation>
- </message>
- <message>
- <source>Enter address, transaction id, or label to search</source>
- <translation>Введите адрес, ID транзакции или метку для поиска</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation>Мин. сумма</translation>
- </message>
- <message>
- <source>Abandon transaction</source>
- <translation>Отказаться от транзакции</translation>
- </message>
- <message>
- <source>Increase transaction fee</source>
- <translation>Увеличить комиссию</translation>
- </message>
- <message>
- <source>Copy address</source>
- <translation>Копировать адрес</translation>
- </message>
- <message>
- <source>Copy label</source>
- <translation>Копировать метку</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation>Копировать сумму</translation>
- </message>
- <message>
- <source>Copy transaction ID</source>
- <translation>Копировать ID транзакции</translation>
- </message>
- <message>
- <source>Copy raw transaction</source>
- <translation>Копировать исходный код транзакции</translation>
- </message>
- <message>
- <source>Copy full transaction details</source>
- <translation>Копировать все подробности транзакции</translation>
- </message>
- <message>
- <source>Edit label</source>
- <translation>Изменить метку</translation>
- </message>
- <message>
- <source>Show transaction details</source>
- <translation>Показать подробности транзакции</translation>
- </message>
- <message>
- <source>Export Transaction History</source>
- <translation>Экспортировать историю транзакций</translation>
- </message>
- <message>
<source>Comma separated file (*.csv)</source>
<translation>Текст, разделённый запятыми (*.csv)</translation>
</message>
<message>
- <source>Confirmed</source>
- <translation>Подтверждено</translation>
- </message>
- <message>
- <source>Watch-only</source>
- <translation>Для наблюдения</translation>
- </message>
- <message>
- <source>Date</source>
- <translation>Дата</translation>
- </message>
- <message>
- <source>Type</source>
- <translation>Тип</translation>
- </message>
- <message>
<source>Label</source>
<translation>Метка</translation>
</message>
@@ -2991,91 +429,19 @@
<translation>Адрес</translation>
</message>
<message>
- <source>ID</source>
- <translation>ID</translation>
- </message>
- <message>
<source>Exporting Failed</source>
<translation>Экспорт не удался</translation>
</message>
- <message>
- <source>There was an error trying to save the transaction history to %1.</source>
- <translation>Произошла ошибка при сохранении истории транзакций в %1.</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation>Экспорт успешно завершён</translation>
- </message>
- <message>
- <source>The transaction history was successfully saved to %1.</source>
- <translation>История транзакций была успешно сохранена в %1.</translation>
- </message>
- <message>
- <source>Range:</source>
- <translation>Диапазон:</translation>
- </message>
- <message>
- <source>to</source>
- <translation>до</translation>
- </message>
-</context>
+ </context>
<context>
<name>UnitDisplayStatusBarControl</name>
- <message>
- <source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Единица измерения количества монет. Щёлкните для выбора другой единицы.</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>Не был загружен ни один бумажник.</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation>Отправка</translation>
- </message>
- <message>
- <source>Fee bump error</source>
- <translation>Ошибка повышения комиссии</translation>
- </message>
- <message>
- <source>Increasing transaction fee failed</source>
- <translation>Увеличение комиссии не удалось</translation>
- </message>
- <message>
- <source>Do you want to increase the fee?</source>
- <translation>Вы хотите увеличить комиссию?</translation>
- </message>
- <message>
- <source>Current fee:</source>
- <translation>Текущая комиссия</translation>
- </message>
- <message>
- <source>Increase:</source>
- <translation>Увеличение:</translation>
- </message>
- <message>
- <source>New fee:</source>
- <translation>Новая комиссия:</translation>
- </message>
- <message>
- <source>Confirm fee bump</source>
- <translation>Подтвердите увеличение комиссии</translation>
- </message>
- <message>
- <source>Can't sign transaction.</source>
- <translation>Невозможно подписать транзакцию.</translation>
- </message>
- <message>
- <source>Could not commit transaction</source>
- <translation>Не удалось совершить транзакцию</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletView</name>
<message>
@@ -3086,1012 +452,24 @@
<source>Export the data in the current tab to a file</source>
<translation>Экспортировать данные текущей вкладки в файл</translation>
</message>
- <message>
- <source>Backup Wallet</source>
- <translation>Резервная копия бумажника</translation>
- </message>
- <message>
- <source>Wallet Data (*.dat)</source>
- <translation>Данные бумажника (*.dat)</translation>
- </message>
- <message>
- <source>Backup Failed</source>
- <translation>Резервное копирование не удалось</translation>
- </message>
- <message>
- <source>There was an error trying to save the wallet data to %1.</source>
- <translation>Произошла ошибка при сохранении данных бумажника в %1.</translation>
- </message>
- <message>
- <source>Backup Successful</source>
- <translation>Резервное копирование успешно завершено</translation>
- </message>
- <message>
- <source>The wallet data was successfully saved to %1.</source>
- <translation>Данные бумажника были успешно сохранены в %1.</translation>
- </message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Параметры:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Задать каталог данных</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Подключиться к участнику, чтобы получить список адресов других участников и отключиться</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Укажите ваш собственный публичный адрес</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Принимать командную строку и команды JSON-RPC</translation>
- </message>
- <message>
- <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
- <translation>Распространяется под лицензией MIT, см. приложенный файл %s или %s</translation>
- </message>
- <message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Если &lt;category&gt; не предоставлена или равна 1, выводить всю отладочную информацию.</translation>
- </message>
- <message>
- <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation>Удаление блоков выставлено ниже, чем минимум в %d Мб. Пожалуйста, используйте большее значение.</translation>
- </message>
- <message>
- <source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
- <translation>Удаление: последняя синхронизация кошелька вышла за рамки удаленных данных. Вам нужен -reindex (скачать всю цепь блоков в случае удаленного узла)</translation>
- </message>
- <message>
- <source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>Повторное сканирование не возможно в режиме удаления. Вам надо будет использовать -reindex, который загрузит заново всю цепь блоков.</translation>
- </message>
- <message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Ошибка: произошла неустранимая ошибка, подробности в debug.log</translation>
- </message>
- <message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Комиссия (в %s/Кб) для добавления к вашим транзакциям (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Pruning blockstore...</source>
- <translation>Очистка хранилища блоков...</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Запускаться в фоне как демон и принимать команды</translation>
- </message>
- <message>
- <source>Unable to start HTTP server. See debug log for details.</source>
- <translation>Невозможно запустить HTTP сервер. Смотри debug лог для подробностей.</translation>
- </message>
- <message>
- <source>Bitcoin Core</source>
- <translation>Bitcoin Core</translation>
- </message>
- <message>
- <source>The %s developers</source>
- <translation>Разработчики %s</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Принимать транзакции пересылаемые от узлов из белого списка даже если они не удовлетворяют требованиям ретрансляции (по умолчанию: %d)</translation>
- </message>
- <message>
- <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source>
- <translation>Добавить узел сети для соединения и для возможности сохранять соединение открытым (см. команду RPC `addnode` в справочном разделе)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Привязаться к указанному адресу и всегда прослушивать только его. Используйте [хост]:порт для IPv6</translation>
- </message>
- <message>
- <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
- <translation>Невозможно заблокировать каталог данных %s. %s возможно уже работает.</translation>
- </message>
- <message>
- <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>Не удалось предоставить определённые подключения, и в то же время найти исходящие подключения через addrman.</translation>
- </message>
- <message>
- <source>Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)</source>
- <translation>Подключаться только к указанному узлу(ам); -connect=0 отключает автоматические подключения (правила для этого участника такие же, как и для -addnode)</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Удалить все транзакции бумажника с возможностью восстановить эти части цепи блоков с помощью -rescan при запуске</translation>
- </message>
- <message>
- <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
- <translation>Ошибка чтения %s! Все ключи прочитаны верно, но данные транзакций или записи адресной книги могут отсутствовать или быть неправильными.</translation>
- </message>
- <message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Исключить отладочную информацию для категории. Может быть использовано вместе с -debug=1 для вывода отладочных логов по всем категориям, кроме одной или более указанных категорий.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Выполнить команду, когда меняется транзакция в бумажнике (%s в команде заменяется на TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Хранить в памяти дополнительные транзакции для реконструкции компактных блоков (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Если этот блок в цепи, считать его и последующие блоки верными и потенциально пропускать проверку их скриптов (0 для проверки всех, по умолчанию: %s, тестовая сеть: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Максимально допустимое среднее отклонение времени участников. Локальное представление времени может меняться вперед или назад на это количество. (по умолчанию: %u секунд)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Максимальная сумма комиссий (%s) для одной транзакции в бумажнике или сырой транзакции; слишком низкое значение может вызвать прерывание больших транзакций (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
- <translation>Пожалуйста убедитесь в корректности установки времени и даты на вашем компьютере! Если время установлено неверно, %s не будет работать правильно.</translation>
- </message>
- <message>
- <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>Пожалуйста, внести свой вклад, если вы найдете %s полезными. Посетите %s для получения дополнительной информации о программном обеспечении.</translation>
- </message>
- <message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Запрашивать адреса участников с помощью DNS, если адресов мало (по умолчанию: 1, если не указан -connect)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Уменьшить размер хранилища за счёт обрезания (удаления) старых блоков. Будет разрешён вызов RPC метода pruneblockchain для удаления определённых блоков и разрешено автоматическое обрезание старых блоков, если указан целевой размер в Мб. Этот режим несовместим с -txindex и -rescan. Внимание: переключение этой опции обратно потребует полной загрузки цепи блоков. (по умолчанию: 0 = отключить обрезание блоков, 1 = разрешить ручное обрезание через RPC, &gt;%u = автоматически обрезать файлы блоков, чтобы они были меньше указанного размера в Мб)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Задать минимальный курс комиссии (в %s/Кб) для транзакцийб включаемых в создаваемый блок. (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Задать число потоков проверки скрипта (от %u до %d, 0=авто, &lt;0 = оставить столько ядер свободными, по умолчанию: %d)</translation>
- </message>
- <message>
- <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
- <translation>База данных блоков содержит блок, который появляется из будущего. Это может из-за некорректно установленных даты и времени на вашем компьютере. Остается только перестроивать базу блоков, если вы уверены, что дата и время корректны.</translation>
- </message>
- <message>
- <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
- <translation>Это пре-релизная тестовая сборка - используйте на свой страх и риск - не используйте для добычи или торговых приложений</translation>
- </message>
- <message>
- <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>Это комиссия, которую можно отбросить, если сдача окажется меньше пыли</translation>
- </message>
- <message>
- <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation>Не удалось воспроизвести блоки. Вам необходимо пересобрать базу данных с помощью -reindex-chainstate.</translation>
- </message>
- <message>
- <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
- <translation>Невозможно отмотать базу данных до пред-форкового состояния. Вам будет необходимо перекачать цепочку блоков.</translation>
- </message>
- <message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Использовать UPnP для проброса порта (по умолчанию: 1, если используется прослушивание и нет -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Имя пользователя и хэш пароля для JSON-RPC соединений. Поле &lt;userpw&gt; использует формат: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Каноничный пример скрипта на питоне находится в share/rpcuser. Эта опция может быть указана несколько раз</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Бумажник не будет создавать транзакции, которые нарушают лимиты цепочки пула в памяти (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>Внимание: похоже, в сети нет полного согласия! Некоторые майнеры, возможно, испытывают проблемы.</translation>
- </message>
- <message>
- <source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
- <translation>Внимание: мы не полностью согласны с подключенными участниками! Вам или другим участникам, возможно, следует обновиться.</translation>
- </message>
- <message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Сохранять ли mempool при выключении и загружать ли его при запуске (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d из последних 100 блоков имеют непредвиденную версию</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s поврежден, восстановить не удалось</translation>
- </message>
- <message>
- <source>-maxmempool must be at least %d MB</source>
- <translation>-maxmempool должен быть как минимум %d MB</translation>
- </message>
- <message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; может быть:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Принимать подключения извне (по умолчанию: 1, если не используется -proxy или -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Добавить комментарий к строке пользовательского агента</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Попытаться восстановить приватные ключи из повреждённого бумажника при запуске</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Параметры создания блоков:</translation>
- </message>
- <message>
- <source>Cannot resolve -%s address: '%s'</source>
- <translation>Не удаётся разрешить адрес в параметре -%s: '%s'</translation>
- </message>
- <message>
- <source>Chain selection options:</source>
- <translation>Параметры выбора цепочки:</translation>
- </message>
- <message>
- <source>Change index out of range</source>
- <translation>Изменение индекса вне диапазона</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Параметры подключения:</translation>
- </message>
- <message>
- <source>Copyright (C) %i-%i</source>
- <translation>Copyright (C) %i-%i</translation>
- </message>
- <message>
- <source>Corrupted block database detected</source>
- <translation>БД блоков повреждена</translation>
- </message>
- <message>
- <source>Debugging/Testing options:</source>
- <translation>Параметры отладки/тестирования:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Не загружать бумажник и запретить обращения к нему через RPC</translation>
- </message>
- <message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Пересобрать БД блоков прямо сейчас?</translation>
- </message>
- <message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Включить публичный хеш блока в &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Включить публичный хеш транзакции в &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Включить публичный сырой блок в &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Включить публичную сырую транзакцию в &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Включить замену транзакций в пуле памяти (по умолчанию:%u)</translation>
- </message>
- <message>
- <source>Error creating %s: You can't create non-HD wallets with this version.</source>
- <translation>Ошибка создания %s: Вы не можете создавать не-HD бумажники с помощью этой версии.</translation>
- </message>
- <message>
<source>Error initializing block database</source>
<translation>Ошибка инициализации БД блоков</translation>
</message>
<message>
- <source>Error initializing wallet database environment %s!</source>
- <translation>Ошибка инициализации окружения БД бумажника %s!</translation>
- </message>
- <message>
- <source>Error loading %s</source>
- <translation>Ошибка загрузки %s</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet corrupted</source>
- <translation>Ошибка загрузки %s: Бумажник поврежден</translation>
- </message>
- <message>
- <source>Error loading %s: Wallet requires newer version of %s</source>
- <translation>Ошибка загрузки %s: Для бумажника требуется более новая версия %s</translation>
- </message>
- <message>
- <source>Error loading block database</source>
- <translation>Ошибка чтения базы данных блоков</translation>
- </message>
- <message>
- <source>Error opening block database</source>
- <translation>Не удалось открыть БД блоков</translation>
- </message>
- <message>
- <source>Error: Disk space is low!</source>
- <translation>Ошибка: мало места на диске!</translation>
- </message>
- <message>
- <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation>Не удалось начать прослушивание на порту. Используйте -listen=0 если вас это устраивает.</translation>
- </message>
- <message>
- <source>Failed to rescan the wallet during initialization</source>
- <translation>Не удалось пересканировать бумажник во время инициализации</translation>
- </message>
- <message>
- <source>Importing...</source>
- <translation>Импорт ...</translation>
- </message>
- <message>
- <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
- <translation>Неверный или отсутствующий начальный блок. Неправильный каталог данных для сети?</translation>
- </message>
- <message>
- <source>Initialization sanity check failed. %s is shutting down.</source>
- <translation>Начальная проверка исправности не удалась. %s завершает работу.</translation>
- </message>
- <message>
- <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Неверная сумма для -%s=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation>Неверная сумма для -discardfee=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Недопустимая сумма для -fallbackfee=&lt;amount&gt;: '%s'</translation>
- </message>
- <message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Сбрасывать транзакции из памяти на диск каждые &lt;n&gt; мегабайт (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Loading P2P addresses...</source>
- <translation>Загрузка P2P адресов...</translation>
- </message>
- <message>
- <source>Loading banlist...</source>
- <translation>Загрузка банлиста...</translation>
- </message>
- <message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Расположение куки входы(по умолчанию: data dir)</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation>Недостаточно файловых дескрипторов.</translation>
- </message>
- <message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Соединяться только по сети &lt;net&gt; (ipv4, ipv6 или onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Вывести эту справку и выйти</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Написать версию и выйти</translation>
- </message>
- <message>
- <source>Prune cannot be configured with a negative value.</source>
- <translation>Удаление блоков не может использовать отрицательное значение.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -txindex.</source>
- <translation>Режим удаления блоков несовместим с -txindex.</translation>
- </message>
- <message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Перестроить состояние цепи блоков и индекс блоков из blk*.dat файлов с диска</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Перестроить индекс цепи из текущих индексированных блоков</translation>
- </message>
- <message>
- <source>Replaying blocks...</source>
- <translation>Воспроизведение блоков...</translation>
- </message>
- <message>
- <source>Rewinding blocks...</source>
- <translation>Перемотка блоков...</translation>
- </message>
- <message>
- <source>Send transactions with full-RBF opt-in enabled (RPC only, default: %u)</source>
- <translation>Отправлять транзакции с включенным full-RBF (только RPC, по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Установить размер кэша БД в мегабайтах(от %d до %d, по умолчанию: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Укажите файл бумажника (внутри каталога данных)</translation>
- </message>
- <message>
- <source>The source code is available from %s.</source>
- <translation>Исходный код доступен в %s.</translation>
- </message>
- <message>
- <source>Transaction fee and change calculation failed</source>
- <translation>Не удалось рассчитать комиссию и сдачу</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation>Невозможно привязаться к %s на этом компьютере. Возможно, %s уже работает.</translation>
- </message>
- <message>
- <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
- <translation>Неподдерживаемый аргумент -benchmark проигнорирован, используйте -debug=bench.</translation>
- </message>
- <message>
- <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
- <translation>Неподдерживаемый аргумент -debugnet проигнорирован, используйте -debug=net.</translation>
- </message>
- <message>
- <source>Unsupported argument -tor found, use -onion.</source>
- <translation>Обнаружен не поддерживаемый параметр -tor, используйте -onion.</translation>
- </message>
- <message>
- <source>Unsupported logging category %s=%s.</source>
- <translation>Неподдерживаемая категория лога %s=%s.</translation>
- </message>
- <message>
- <source>Upgrading UTXO database</source>
- <translation>Модернизация базы данных UTXO</translation>
- </message>
- <message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Использовать UPnP для проброса порта (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Использовать тестовую цепочку</translation>
- </message>
- <message>
- <source>User Agent comment (%s) contains unsafe characters.</source>
- <translation>Комментарий пользователя (%s) содержит небезопасные символы.</translation>
- </message>
- <message>
- <source>Verifying blocks...</source>
- <translation>Проверка блоков...</translation>
- </message>
- <message>
- <source>Wallet debugging/testing options:</source>
- <translation>Параметры отладки/тестирования бумажника:</translation>
- </message>
- <message>
- <source>Wallet needed to be rewritten: restart %s to complete</source>
- <translation>Необходимо перезаписать бумажник, перезапустите %s для завершения операции.</translation>
- </message>
- <message>
- <source>Wallet options:</source>
- <translation>Настройки бумажника:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Разрешить подключения JSON-RPC с указанного источника. Разрешённые значения для &lt;ip&gt; — отдельный IP (например, 1.2.3.4), сеть/маска сети (например, 1.2.3.4/255.255.255.0) или сеть/CIDR (например, 1.2.3.4/24). Эту опцию можно использовать многократно</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Привязаться к указанному адресу и внести в белый список подключающихся к нему участников. Используйте [хост]:порт для IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Создавать новые файлы с системными правами по умолчанию вместо umask 077 (эффективно только при отключенном бумажнике)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Обнаруживать собственный IP адрес (по умолчанию: 1 при прослушивании и без -externalip или -proxy)</translation>
- </message>
- <message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Ошибка: не удалось начать прослушивание входящих подключений (прослушивание вернуло ошибку %s)</translation>
- </message>
- <message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Выполнить команду, когда приходит соответствующее сообщение о тревоге или наблюдается очень длинное расщепление цепи (%s в команде заменяется на сообщение)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Комиссии (в %s/Кб) меньшие этого значения считаются нулевыми для создания, ретрансляции, получения транзакции (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Если paytxfee не задан, включить достаточную комиссию для подтверждения транзакции в среднем за n блоков (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
- <translation>Неверное значение для -maxtxfee=&lt;amount&gt;: '%s' (минимальная комиссия трансляции %s для предотвращения зависания транзакций)</translation>
- </message>
- <message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Наибольший размер данных в носителе данных транзакций, которые мы передаем и генерируем (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Использовать случайные учётные данные для каждого прокси-подключения. Эта функция позволяет изолировать потоки Tor (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation>Сумма транзакции за вычетом комиссии слишком мала</translation>
- </message>
- <message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Участники из белого списка не могуть быть забанены за DoS, и их транзакции всегда транслируются, даже если они уже содержатся в памяти. Полезно, например, для шлюза.</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
- <translation>Вам необходимо пересобрать базу данных с помощью -reindex, чтобы вернуться к полному режиму. Это приведёт к перезагрузке всей цепи блоков</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Принимать публичные REST-запросы (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Автоматически создавать скрытый Tor сервис (по умолчанию: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Подключаться через SOCKS5 прокси</translation>
- </message>
- <message>
- <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
- <translation>Ошибка загрузки %s: Вы не можете выключить HD в уже существующем HD кошельке</translation>
- </message>
- <message>
- <source>Error reading from database, shutting down.</source>
- <translation>Ошибка чтения базы данных, работа завершается.</translation>
- </message>
- <message>
- <source>Error upgrading chainstate database</source>
- <translation>Ошибка модернизации базы блокчейна</translation>
- </message>
- <message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Импортировать блоки из внешнего файла blk000?.dat при запуске</translation>
- </message>
- <message>
- <source>Information</source>
- <translation>Информация</translation>
- </message>
- <message>
- <source>Invalid -onion address or hostname: '%s'</source>
- <translation>Неверный адрес или имя -onion: '%s'</translation>
- </message>
- <message>
- <source>Invalid -proxy address or hostname: '%s'</source>
- <translation>Неверный адрес или имя -proxy: '%s'</translation>
- </message>
- <message>
- <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation>Неверное количество в параметре -paytxfee=&lt;кол-во&gt;: '%s' (должно быть как минимум %s)</translation>
- </message>
- <message>
- <source>Invalid netmask specified in -whitelist: '%s'</source>
- <translation>Указана неверная сетевая маска в -whitelist: '%s'</translation>
- </message>
- <message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Держать в памяти до &lt;n&gt; несвязных транзакций (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Need to specify a port with -whitebind: '%s'</source>
- <translation>Необходимо указать порт с помощью -whitebind: '%s'</translation>
- </message>
- <message>
- <source>Node relay options:</source>
- <translation>Параметры трансляции узла:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Параметры сервера RPC:</translation>
- </message>
- <message>
- <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <translation>Уменьшите -maxconnections с %d до %d, из-за ограничений системы.</translation>
- </message>
- <message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Перепроверить цепь блоков на предмет отсутствующих в бумажнике транзакций при запуске</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Выводить информацию трассировки/отладки на консоль вместо файла debug.log</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Показать все отладочные параметры (использование: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Сжимать файл debug.log при запуске клиента (по умолчанию: 1, если нет -debug)</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Не удалось подписать транзакцию</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" does not exist</source>
- <translation>Указанный -walletdir "%s" не существует</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" is a relative path</source>
- <translation>Указанный путь -walletdir "%s" является относительным</translation>
- </message>
- <message>
- <source>Specified -walletdir "%s" is not a directory</source>
- <translation>Указанный -walletdir "%s" не является директорией</translation>
- </message>
- <message>
- <source>The transaction amount is too small to pay the fee</source>
- <translation>Сумма транзакции слишком мала для уплаты комиссии</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation>Это экспериментальное ПО.</translation>
- </message>
- <message>
- <source>Tor control port password (default: empty)</source>
- <translation>Пароль от порта управления Tor (по умолчанию: пустой)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Порт управления Tor используется, если включено прослушивание onion (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation>Сумма транзакции слишком мала</translation>
- </message>
- <message>
- <source>Transaction too large for fee policy</source>
- <translation>Транзакция слишком большая для правил комиссии.</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation>Транзакция слишком большая</translation>
- </message>
- <message>
- <source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation>Невозможно привязаться к %s на этом компьютере (bind вернул ошибку %s)</translation>
- </message>
- <message>
- <source>Unable to generate initial keys</source>
- <translation>Невозможно создать ключи инициализации</translation>
- </message>
- <message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Обновить бумажник до последнего формата при запуске</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Имя для подключений JSON-RPC</translation>
- </message>
- <message>
- <source>Verifying wallet(s)...</source>
- <translation>Проверка кошелька(ов) ...</translation>
- </message>
- <message>
- <source>Wallet %s resides outside wallet directory %s</source>
- <translation>Кошелёк %s расположен за пределами директории кошелька %s</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation>Внимание</translation>
- </message>
- <message>
- <source>Warning: unknown new rules activated (versionbit %i)</source>
- <translation>Внимание: неизвестные правила вступили в силу(versionbit %i)</translation>
- </message>
- <message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Будет работать в режиме только блоков (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Вам необходимо пересобрать базу данных с помощью -reindex, чтобы изменить -txindex</translation>
- </message>
- <message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Стираем все транзакции из кошелька...</translation>
- </message>
- <message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ параметры оповещения:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Пароль для подключений JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Выполнить команду, когда появляется новый блок (%s в команде заменяется на хэш блока)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Разрешить поиск в DNS для -addnode, -seednode и -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = сохранять метаданные транзакции: например, владельца аккаунта и информацию запроса платежа; 2 = отбросить метаданные)</translation>
- </message>
- <message>
- <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation>Установлено очень большое значение -maxtxfee. Такие большие комиссии могут быть уплачены в отдельной транзакции.</translation>
- </message>
- <message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Привязаться к указанному адресу для прослушивания JSON-RPC подключений. Этот параметр игнорируется, если не задан -rpcallowip. Порт необязателен и имеет приоритет над -rpcport. Используйте запись [хост]:порт для IPv6. Эту опцию можно использовать многократно (по умолчанию: 127.0.0.1 и ::1, т.е. localhost, или, если указан -rpcallowip, 0.0.0.0 и ::, т.е. все адреса)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Не хранить транзакции в памяти дольше, чем &lt;n&gt; часов (по умолчанию %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Эквивалентных байт на sigop в транзакциях для ретрансляции или добычи (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
- <translation>Ошибка загрузки %s: Вы не можете включить HD в уже существующем не-HD кошельке</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Ошибка загрузки бумажника %s. -wallet должен содержать лишь имя файла, а не путь.</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Комиссии (в %s/Кб) меньшие этого значения считаются нулевыми при создании транзакций (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Всегда ретранслировать транзакции, полученные из белого списка участников, даже если они нарушают локальную политику ретрансляции (по умолчанию: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Насколько тщательна проверка контрольных блоков -checkblocks (0-4, по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Держать полный индекс транзакций, используемый RPC-запросом getrawtransaction (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Число секунд блокирования неправильно ведущих себя узлов (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Выводить отладочную информацию (по умолчанию: %u, указание &lt;category&gt; необязательно)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight</source>
- <translation>Задать максимальный вес BIP141 блока как это * 4. Устарело, используйте blockmaxweight</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Задаёт сериализацию сырой транзакции или хекса блока, возвращённого в не подробном режиме, non-segwit(0) или segwit(1) (по умолчанию: %d)</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>Укажите папку для хранения бумажников (по умолчанию: &lt;datadir&gt;/wallets если она существует, иначе &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>Укажите расположение файла журнала отладки: это может быть абсолютный путь или путь относительно папки данных (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Поддерживать фильтрацию блоков и транзакций с помощью фильтра Блума (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Доля комиссии (в %s/Кб), которая означает допустимость отбрасывания сдачи путём добавления её к комиссии (по умолчанию: %s).</translation>
- </message>
- <message>
- <source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation>Это комиссия за транзакцию, которую вы можете заплатить, когда расчёт комиссии недоступен.</translation>
- </message>
- <message>
- <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
- <translation>Этот продукт включает ПО, разработанное OpenSSL Project для использования в OpenSSL Toolkit %s и криптографическое ПО, написанное Eric Young и ПО для работы с UPnP, написанное Thomas Bernard.</translation>
- </message>
- <message>
- <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <translation>Текущая длина строки версии сети (%i) превышает максимальную длину (%i). Увеливается количество или размер uacomments.</translation>
- </message>
- <message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Пытается ограничить исходящий трафик до (в МБ за 24ч), 0 = не ограничивать (по умолчанию: %d)</translation>
- </message>
- <message>
- <source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
- <translation>Обнаружен не поддерживаемый аргумент -socks. Выбор версии SOCKS более невозможен, поддерживаются только прокси SOCKS5.</translation>
- </message>
- <message>
- <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
- <translation>Не поддерживаемый аргумент -whitelistalwaysrelay игнорируется, используйте -whitelistrelay и/или -whitelistforcerelay.</translation>
- </message>
- <message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Использовать отдельный прокси SOCKS5 для соединения с участниками через скрытые сервисы Tor (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
- <translation>Внимание: Получена неизвестная версия блока! Возможно неизвестные правила вступили в силу.</translation>
- </message>
- <message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Внимание: Файл бумажника поврежден, данные восстановлены! Оригинальный %s сохранен как %s в %s; Если баланс или транзакции некорректны, вы должны восстановить файл из резервной копии.</translation>
- </message>
- <message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Вносить в белый список участников, подключающихся с указанного IP (напр. 1.2.3.4) или CIDR-адреса сети (напр. 1.2.3.0/24). Можно использовать многократно.</translation>
- </message>
- <message>
- <source>%s is set very high!</source>
- <translation>%s задан слишком высоким!</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Всегда запрашивать адреса участников с помощью DNS (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Ошибка загрузки бумажника %s. Имя в параметре -wallet должно быть именем обычного файла.</translation>
- </message>
- <message>
- <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
- <translation>Ошибка загрузки бумажника %s. В параметре -wallet указано повторяющееся имя файла.</translation>
- </message>
- <message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Ошибка загрузки бумажника %s. Неверные символы в параметре -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Сколько блоков проверять при запуске (по умолчанию: %u, 0 = все)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Включить IP-адреса в отладочный вывод (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Keypool ran out, please call keypoolrefill first</source>
- <translation>Пул ключей опустел, пожалуйста, выполните keypoolrefill</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Прослушивать подключения JSON-RPC на &lt;порту&gt; (по умолчанию: %u или %u в тестовой сети)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Принимать входящие подключения на &lt;port&gt; (по умолчанию: %u или %u в тестовой сети)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Поддерживать не более &lt;n&gt; подключений к узлам (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Рассылать транзакции из бумажника</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Максимальный размер буфера приёма на соединение, &lt;n&gt;*1000 байт (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Максимальный размер буфера отправки на соединение, &lt;n&gt;*1000 байт (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Дописывать отметки времени к отладочному выводу (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Транслировать и генерировать транзакции носителей данных (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Транслировать не-P2SH мультиподпись (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Установить размер пула ключей в &lt;n&gt; (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Задать максимальное BIP141 значение блока (по умолчанию: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Задать число потоков выполнения запросов RPC (по умолчанию: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Указать конфигурационный файл (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Указать тайм-аут соединения в миллисекундах (минимум: 1, по умолчанию: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Указать pid-файл (по умолчанию: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Тратить неподтвержденную сдачу при отправке транзакций (по умолчанию: %u)</translation>
- </message>
- <message>
- <source>Starting network threads...</source>
- <translation>Запускаем сетевые потоки...</translation>
- </message>
- <message>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>Бумажник постарается не платить меньше, чем минимальная комиссия передачи.</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation>Это минимальная комиссия, которую вы платите с каждой транзакцией.</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>Это комиссия, которую вы заплатите за эту транзакцию.</translation>
- </message>
- <message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Порог для отключения неправильно ведущих себя узлов (по умолчанию: %u)</translation>
+ <translation>Кошелёк постарается не платить меньше, чем минимальная комиссия передачи.</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
- <translation>Сумма транзакции не должна быть негативной</translation>
- </message>
- <message>
- <source>Transaction has too long of a mempool chain</source>
- <translation>У транзакции слишком длинная цепочка в пуле в памяти.</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation>У транзакции должен быть как минимум один получатель</translation>
- </message>
- <message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation>В параметре -onlynet указана неизвестная сеть: '%s'</translation>
+ <translation>Сумма транзакции не должна быть отрицательной</translation>
</message>
<message>
<source>Insufficient funds</source>
- <translation>Недостаточно монет</translation>
+ <translation>Недостаточно средств</translation>
</message>
<message>
<source>Loading block index...</source>
@@ -4099,11 +477,11 @@
</message>
<message>
<source>Loading wallet...</source>
- <translation>Загрузка бумажника...</translation>
+ <translation>Загрузка электронного кошелька...</translation>
</message>
<message>
<source>Cannot downgrade wallet</source>
- <translation>Не удаётся понизить версию бумажника</translation>
+ <translation>Не удаётся понизить версию электронного кошелька</translation>
</message>
<message>
<source>Rescanning...</source>
diff --git a/src/qt/locale/bitcoin_ru_RU.ts b/src/qt/locale/bitcoin_ru_RU.ts
index ef6c755711..430f2e4191 100644
--- a/src/qt/locale/bitcoin_ru_RU.ts
+++ b/src/qt/locale/bitcoin_ru_RU.ts
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>Скопировать текущий выбранный адрес в буфер обмена системы</translation>
+ <translation>Скопировать выбранный адрес в буфер обмена</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -30,6 +30,10 @@
<translation>Удалить выбранный адрес из списка</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Введите адрес или метку для поиска</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Экспортировать данные текущей вкладки в файл</translation>
</message>
@@ -51,7 +55,7 @@
</message>
<message>
<source>C&amp;hoose</source>
- <translation>В&amp;ыбрать</translation>
+ <translation>Выбрать</translation>
</message>
<message>
<source>Sending addresses</source>
@@ -63,11 +67,11 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Это ваши биткойн адреса для отправки платежа. Всегда проверяйте сумму и адрес получателя перед отправкой платежа.</translation>
+ <translation>Это ваши Bitcoin адреса для отправки платежа. Всегда проверяйте сумму и адрес получателя перед отправкой платежа.</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Это ваши биткойн адреса для получения платежей. Настоятельно рекомендуем использовать новые адреса для получения каждой транзакции.</translation>
+ <translation>Это ваши Bitcoin адреса для получения платежей. Настоятельно рекомендуем использовать новые адреса для получения каждой транзакции.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -128,20 +132,24 @@
<translation>Повторите новый пароль</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Отобразить пароль</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
- <translation>Введите новый пароль для кошелька.&lt;br/&gt; Пожалуйста используйте пароль из &lt;b&gt; десяти или более произвольных символов&lt;/b&gt;, или &lt;b&gt;восемь или боле слов&lt;/b&gt;</translation>
+ <translation>Введите новый пароль для кошелька.&lt;br/&gt; Пожалуйста используйте пароль из &lt;b&gt; десяти или более произвольных символов&lt;/b&gt;, или &lt;b&gt;восемь или более слов&lt;/b&gt;</translation>
</message>
<message>
<source>Encrypt wallet</source>
- <translation>Зашифровать бумажник</translation>
+ <translation>Зашифровать кошелек</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Эта операция требует вашего пароля для разблокировки бумажника</translation>
+ <translation>Эта операция требует вашего пароля для разблокировки кошелька</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation>Разблокировать бумажник</translation>
+ <translation>Разблокировать кошелек</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
@@ -149,7 +157,7 @@
</message>
<message>
<source>Decrypt wallet</source>
- <translation>Расшифровать бумажник</translation>
+ <translation>Расшифровать кошелек</translation>
</message>
<message>
<source>Change passphrase</source>
@@ -157,11 +165,11 @@
</message>
<message>
<source>Enter the old passphrase and new passphrase to the wallet.</source>
- <translation>Введите старый и новый пароль для кошелька.</translation>
+ <translation>Введите старый и новый пароль к кошельку.</translation>
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation>Подтвердите шифрование бумажника</translation>
+ <translation>Подтвердите шифрование кошелька</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
@@ -173,13 +181,17 @@
</message>
<message>
<source>Wallet encrypted</source>
- <translation>Бумажник зашифрован</translation>
+ <translation>Кошелек зашифрован</translation>
</message>
<message>
<source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
<translation>%1 закроется сейчас для завершения процесса шифрования. Запомните что шифрование вашего кошелька не сможет полностью защитить ваши биткойны от кражи при помощи вредоносного ПО, заразившего ваш компьютер.</translation>
</message>
<message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>ВАЖНО: любые предыдущие резервные копия вашего кошелька, выполненные вами, необходимо заменить новым сгенерированным, зашифрованным файлом кошелька. В целях безопасности, предыдущие резервные копии незашифрованного файла кошелька утратят пригодность после начала использования нового зашифрованного кошелька.</translation>
+ </message>
+ <message>
<source>Wallet encryption failed</source>
<translation>Шифрование кошелька завершилось неудачно.</translation>
</message>
@@ -188,6 +200,10 @@
<translation>Шифрование кошелька завершилось неудачно из-за внутренней ошибки. Ваш кошелек не был зашифрован.</translation>
</message>
<message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Пароли не совпадают.</translation>
+ </message>
+ <message>
<source>Wallet unlock failed</source>
<translation>Ошибка разблокировки кошелька</translation>
</message>
@@ -210,7 +226,15 @@
</context>
<context>
<name>BanTableModel</name>
- </context>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP / маска подсети</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Заблокировано до</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
@@ -222,10 +246,18 @@
<translation>Синхронизация с сетью...</translation>
</message>
<message>
+ <source>&amp;Overview</source>
+ <translation>&amp;Обзор</translation>
+ </message>
+ <message>
<source>Node</source>
<translation>Узел</translation>
</message>
<message>
+ <source>Show general overview of wallet</source>
+ <translation>Отобразить главное окно кошелька</translation>
+ </message>
+ <message>
<source>&amp;Transactions</source>
<translation>&amp;Транзакции</translation>
</message>
@@ -262,12 +294,16 @@
<translation>&amp;Опции...</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Изменить опции конфигурации для %1</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Зашифровать кошелёк</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>&amp;Создать резервную копию бумажника</translation>
+ <translation>&amp;Создать резервную копию кошелька</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
@@ -286,6 +322,14 @@
<translation>Открыть &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Кошелек:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Кошелек по умолчанию</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Нажмите для отключения взаимодействия с сетью.</translation>
</message>
@@ -306,10 +350,18 @@
<translation>Реиндексация блоков на диске...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Прокси &lt;b&gt;включен&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Послать средства на биткойн адрес</translation>
</message>
<message>
+ <source>Backup wallet to another location</source>
+ <translation>Выполнить резервное копирование кошелька в другом месте расположения</translation>
+ </message>
+ <message>
<source>Change the passphrase used for wallet encryption</source>
<translation>Изменить пароль, используемый для шифрования кошелька</translation>
</message>
@@ -318,6 +370,10 @@
<translation>&amp;Окно отладки</translation>
</message>
<message>
+ <source>Open debugging and diagnostic console</source>
+ <translation>Открыть консоль отладки и диагностики</translation>
+ </message>
+ <message>
<source>&amp;Verify message...</source>
<translation>&amp;Проверить сообщение...</translation>
</message>
@@ -350,6 +406,14 @@
<translation>Зашифровать приватные ключи, принадлежащие вашему кошельку</translation>
</message>
<message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Подписывайте сообщения Bitcoin адресами чтобы подтвердить что это написали именно Вы</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Проверяйте сообщения чтобы убедиться что они подписаны конкретными Bitcoin адресами</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Файл</translation>
</message>
@@ -362,9 +426,57 @@
<translation>&amp;Помощь</translation>
</message>
<message>
+ <source>Tabs toolbar</source>
+ <translation>Панель вкладок</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Запросить платеж</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Показать список использованных адресов и меток получателей</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Показать список использованных адресов и меток получателей</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI or payment request</source>
+ <translation>Открыть биткойн: URI или запрос платежа</translation>
+ </message>
+ <message>
<source>&amp;Command-line options</source>
<translation>Опции командной строки</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n активное подключение к сети Bitcoin</numerusform><numerusform>%n активных подключения к сети Bitcoin</numerusform><numerusform>%n активных подключений к сети Bitcoin</numerusform><numerusform>%n активных подключений к сети Bitcoin</numerusform></translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Выполняется индексирование блоков на диске...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Выполняется обработка блоков на диске...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Обработан %n блок истории транзакций.</numerusform><numerusform>Обработано %n блока истории транзакций.</numerusform><numerusform>Обработано %n блоков истории транзакций.</numerusform><numerusform>Обработано %n блоков истории транзакций.</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>Выполнено %1</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Последний полученный блок был сгенерирован %1 назад.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>После этого транзакции больше не будут видны.</translation>
+ </message>
<message>
<source>Error</source>
<translation>Ошибка</translation>
@@ -385,10 +497,78 @@
<source>Connecting to peers...</source>
<translation>Подключение к пирам...</translation>
</message>
- </context>
+ <message>
+ <source>Catching up...</source>
+ <translation>Синхронизация...</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Дата: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Объем: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>Кошелек: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Тип: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Ярлык: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Адрес: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Отправленная транзакция</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Входящая транзакция</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation>Кошелек &lt;b&gt;зашифрован&lt;/b&gt; и сейчас &lt;b&gt;разблокирован&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation>Кошелек &lt;b&gt;зашифрован&lt;/b&gt; и сейчас &lt;b&gt;заблокирован&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Произошла критическая ошибка. Bitcoin больше не может продолжать безопасную работу и будет закрыт.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation>Выбор коинов</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Количество:</translation>
+ </message>
+ <message>
<source>Bytes:</source>
<translation>Байтов:</translation>
</message>
@@ -401,6 +581,42 @@
<translation>Комиссия:</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>Пыль:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>После комиссии:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Сдача:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>Выбрать все</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Режим дерева</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Режим списка</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Количество</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>Получено с меткой</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Получено с адресом</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Дата</translation>
</message>
@@ -429,6 +645,38 @@
<translation>Копировать ID транзакции</translation>
</message>
<message>
+ <source>Lock unspent</source>
+ <translation>Заблокировать непотраченное</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Разблокировать непотраченное</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Копировать количество</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Скопировать комиссию</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Скопировать после комиссии</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Скопировать байты</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Скопировать пыль</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Скопировать сдачу</translation>
+ </message>
+ <message>
<source>yes</source>
<translation>да</translation>
</message>
@@ -440,17 +688,73 @@
<source>(no label)</source>
<translation>(нет метки)</translation>
</message>
- </context>
+ <message>
+ <source>(change)</source>
+ <translation>(сдача)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
<translation>Изменить адрес</translation>
</message>
- </context>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;Метка</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;Адрес</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>Новый адрес отправки</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Изменить адрес получения</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Изменить адрес отправки</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Введённый адрес "%1" уже существует в адресной книге с меткой "%2".</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Невозможно разблокировать кошелек.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Произошла ошибка при генерации нового ключа.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
- </context>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>Будет создана новая директория данных.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>имя</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Каталог уже существует. Добавьте %1, если хотите создать новую директорию здесь.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>Данный путь уже существует и это не каталог.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>Невозможно создать директорию данных здесь.</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
<message>
@@ -458,18 +762,14 @@
<translation>версия</translation>
</message>
<message>
- <source>Command-line options</source>
- <translation>Опции командной строки</translation>
+ <source>About %1</source>
+ <translation>Около %1</translation>
</message>
<message>
- <source>command-line options</source>
+ <source>Command-line options</source>
<translation>Опции командной строки</translation>
</message>
- <message>
- <source>Start minimized</source>
- <translation>Запускать свернутым</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -481,10 +781,42 @@
<translation>Добро пожаловать в %1.</translation>
</message>
<message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation>Поскольку программа запущена впервые, вы должны указать где %1 будет хранить данные.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>Если вы указали сокращать объём хранимого блокчейна (pruning), все исторические данные все равно должны быть скачаны и обработаны, но впоследствии они будут удалены для экономии места на диске.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>Использовать стандартную директорию данных</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>Использовать пользовательскую директорию данных</translation>
+ </message>
+ <message>
<source>Bitcoin</source>
<translation>Bitcoin Core</translation>
</message>
<message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>Как минимум %1 ГБ данных будет сохранен в эту директорию. Со временем размер будет увеличиваться.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>Приблизительно %1 ГБ данных будет сохранено в эту директорию.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Кошелек также будет сохранен в эту директорию.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>Ошибка: невозможно создать указанную директорию данных "%1".</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
@@ -492,14 +824,54 @@
<context>
<name>ModalOverlay</name>
<message>
+ <source>Form</source>
+ <translation>Форма</translation>
+ </message>
+ <message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation>Последние транзакции пока могут быть не видны, поэтому вы можете видеть некорректный баланс ваших кошельков. Отображаемая информация будет верна после завершения синхронизации. Прогресс синхронизации вы можете видеть ниже.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation>Попытка потратить средства, использованные в транзакциях, которые ещё не синхронизированы, будет отклонена сетью.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Количество оставшихся блоков</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Неизвестно...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Время последнего блока</translation>
+ </message>
+ <message>
<source>Progress</source>
<translation>Прогресс</translation>
</message>
<message>
+ <source>Progress increase per hour</source>
+ <translation>Прогресс за час</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>выполняется вычисление...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Расчетное время, оставшееся до синхронизации</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation>Спрятать</translation>
</message>
- </context>
+ <message>
+ <source>Unknown. Syncing Headers (%1)...</source>
+ <translation>Не известно. Синхронизация заголовков (%1)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -510,7 +882,15 @@
<source>URI:</source>
<translation>URI:</translation>
</message>
- </context>
+ <message>
+ <source>Select payment request file</source>
+ <translation>Выберите файл запроса платежа</translation>
+ </message>
+ <message>
+ <source>Select payment request file to open</source>
+ <translation>Выберите файл запроса платежа для открытия</translation>
+ </message>
+</context>
<context>
<name>OptionsDialog</name>
<message>
@@ -518,10 +898,42 @@
<translation>Опции</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Автоматически запускать %1 после входа в систему.</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Размер кеша &amp;базы данных</translation>
+ </message>
+ <message>
<source>MB</source>
<translation>МБ</translation>
</message>
<message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>IP-адрес прокси-сервера (к примеру, IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Использовать отдельные SOCKS&amp;5 прокси для подключения к пирам через Tor hidden services:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Убрать значок с области уведомлений.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Спрятать иконку в трее</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Открыть файл конфигурации</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>Сбросить все опции клиента к значениям по умолчанию.</translation>
+ </message>
+ <message>
<source>&amp;Reset Options</source>
<translation>&amp;Сбросить опции</translation>
</message>
@@ -530,6 +942,18 @@
<translation>&amp;Сеть</translation>
</message>
<message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Сокращать объём хранимого блокчейна до</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>ГБ</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Отмена этой настройки требует повторного скачивания всего блокчейна.</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation>К&amp;ошелёк</translation>
</message>
@@ -538,14 +962,34 @@
<translation>Эксперт</translation>
</message>
<message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Включить возможность &amp;управления монетами</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation>&amp;Тратить неподтвержденную сдачу</translation>
+ </message>
+ <message>
<source>Map port using &amp;UPnP</source>
<translation>Пробросить порт через &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Принимать внешние подключения</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Разрешить входящие соединения</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Подключится к сети Bitcoin через SOCKS5 прокси.</translation>
</message>
<message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;Выполнить подключение через прокси-сервер SOCKS5 (прокси-сервер по умолчанию):</translation>
+ </message>
+ <message>
<source>Proxy &amp;IP:</source>
<translation>IP прокси:</translation>
</message>
@@ -558,6 +1002,10 @@
<translation>Порт прокси: (напр. 9050)</translation>
</message>
<message>
+ <source>Used for reaching peers via:</source>
+ <translation>Используется для подключения к пирам по:</translation>
+ </message>
+ <message>
<source>IPv4</source>
<translation>IPv4</translation>
</message>
@@ -570,10 +1018,34 @@
<translation>Tor</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>Соединяться к Биткоин-сети через отдельные SOCKS5 прокси через Tor hidden services:</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;Окно</translation>
</message>
<message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation>Отобразить только значок в области уведомлений после сворачивания окна.</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation>З&amp;акрыть при сворачивании</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation>Язык пользовательского интерфейса:</translation>
+ </message>
+ <message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation>Здесь можно выбрать язык пользовательского интерфейса. Параметры будут применены после перезапуска %1</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>Показывать ли опцию управления монетами.</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;ОК</translation>
</message>
@@ -582,13 +1054,65 @@
<translation>&amp;Отмена</translation>
</message>
<message>
+ <source>default</source>
+ <translation>по умолчанию</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>Подтвердить сброс опций</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Для активации изменений необходим перезапуск клиента.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>Клиент будет закрыт. Продолжить далее?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Опции конфигурации</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
- </context>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation>Невозможно открыть файл конфигурации.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Это изменение потребует перезапуск клиента.</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>Введенный адрес прокси-сервера недействителен.</translation>
+ </message>
+</context>
<context>
<name>OverviewPage</name>
<message>
+ <source>Form</source>
+ <translation>Форма</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>Только просмотр:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Доступно:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>Ваш доступный баланс</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>В ожидании:</translation>
+ </message>
+ <message>
<source>Immature:</source>
<translation>Незрелые:</translation>
</message>
@@ -609,16 +1133,72 @@
<translation>Ваш текущий баланс (только чтение):</translation>
</message>
<message>
+ <source>Spendable:</source>
+ <translation>Доступно:</translation>
+ </message>
+ <message>
<source>Recent transactions</source>
<translation>Последние транзакции</translation>
</message>
</context>
<context>
<name>PaymentServer</name>
- </context>
+ <message>
+ <source>Payment request error</source>
+ <translation>Ошибка запроса платежа</translation>
+ </message>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' не верный URI. Используйте 'bitcoin:' вместо этого.</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Неверный адрес %1</translation>
+ </message>
+ <message>
+ <source>Payment request rejected</source>
+ <translation>Запрос платежа отклонен</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Истекло время ожидания запроса платежа</translation>
+ </message>
+ <message>
+ <source>Payment request is not initialized.</source>
+ <translation>Запрос платежа не инициализирован</translation>
+ </message>
+ <message>
+ <source>Invalid payment request.</source>
+ <translation>Неверный запрос платежа.</translation>
+ </message>
+ <message>
+ <source>Error communicating with %1: %2</source>
+ <translation>Ошибка связи с %1: %2</translation>
+ </message>
+ <message>
+ <source>Bad response from server %1</source>
+ <translation>Неправильный ответ от сервера %1</translation>
+ </message>
+ <message>
+ <source>Payment acknowledged</source>
+ <translation>Оплата подтверждена</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>User Agent</source>
+ <translation>Пользовательский агент</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>Узел/служба</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>Идентификатор узла</translation>
+ </message>
+ <message>
<source>Sent</source>
<translation>Отправлено</translation>
</message>
@@ -630,10 +1210,34 @@
<context>
<name>QObject</name>
<message>
+ <source>Amount</source>
+ <translation>Количество</translation>
+ </message>
+ <message>
<source>Enter a Bitcoin address (e.g. %1)</source>
<translation>Введите биткоин-адрес (напр. %1)</translation>
</message>
<message>
+ <source>%1 d</source>
+ <translation>%1 д</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 ч</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 м</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 с</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>Н/Д</translation>
+ </message>
+ <message>
<source>%1 and %2</source>
<translation>%1 и %2</translation>
</message>
@@ -653,10 +1257,18 @@
<source>%1 GB</source>
<translation>%1 ГБ</translation>
</message>
- </context>
+ <message>
+ <source>unknown</source>
+ <translation>неизвестно</translation>
+ </message>
+</context>
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>Ошибка: указанная директория данных "%1" не существует.</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>Ошибка: %1</translation>
</message>
@@ -664,6 +1276,14 @@
<context>
<name>QRImageWidget</name>
<message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Сохранить изображение...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Копировать изображение</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>Сохранить QR-код</translation>
</message>
@@ -675,6 +1295,14 @@
<context>
<name>RPCConsole</name>
<message>
+ <source>N/A</source>
+ <translation>Н/Д</translation>
+ </message>
+ <message>
+ <source>Client version</source>
+ <translation>Версия клиента</translation>
+ </message>
+ <message>
<source>&amp;Information</source>
<translation>Информация</translation>
</message>
@@ -683,6 +1311,46 @@
<translation>Окно отладки</translation>
</message>
<message>
+ <source>Network</source>
+ <translation>Сеть</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>Название</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation>Количество соединений</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation>Блокчейн</translation>
+ </message>
+ <message>
+ <source>Current number of blocks</source>
+ <translation>Текущее количество блоков</translation>
+ </message>
+ <message>
+ <source>Memory Pool</source>
+ <translation>Пул памяти</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>Текущее количество транзакций</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>Использование памяти</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation>Кошелек:</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Сбросить</translation>
+ </message>
+ <message>
<source>Received</source>
<translation>Получено</translation>
</message>
@@ -699,10 +1367,62 @@
<translation>Заблокированные пиры</translation>
</message>
<message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>Выберите пира для просмотра детальной информации.</translation>
+ </message>
+ <message>
<source>Version</source>
<translation>Версия</translation>
</message>
<message>
+ <source>Synced Headers</source>
+ <translation>Синхронизировано заголовков</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>Синхронизировано блоков</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>Пользовательский агент</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>Уменьшить размер шрифта</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>Увеличить размер шрифта</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>Сервисы</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>Время соединения</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation>Последние отправленные</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>Последние полученные</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>Время отклика Ping</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>Минимальное время отклика Ping</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Время последнего блока</translation>
+ </message>
+ <message>
<source>&amp;Open</source>
<translation>&amp;Открыть</translation>
</message>
@@ -711,6 +1431,18 @@
<translation>&amp;Консоль</translation>
</message>
<message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;Сетевой трафик</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>Вход:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Выход:</translation>
+ </message>
+ <message>
<source>1 &amp;hour</source>
<translation>1 &amp;час</translation>
</message>
@@ -727,6 +1459,14 @@
<translation>1 &amp;год</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>Кошелек по умолчанию</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Ввести %1 для обзора доступных команд.</translation>
+ </message>
+ <message>
<source>never</source>
<translation>никогда</translation>
</message>
@@ -746,14 +1486,50 @@
<context>
<name>ReceiveCoinsDialog</name>
<message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Метка:</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>&amp;Сообщение:</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Очистить все поля формы.</translation>
+ </message>
+ <message>
<source>Clear</source>
<translation>Отчистить</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>"Родные" segwit адреса (Bech32 или BIP-173) в дальнейшем уменьшат комиссии ваших транзакций и предоставят улучшенную защиту от опечаток, однако старые кошельки не поддерживают эти адреса. Если не выбрано, будет создан совместимый со старыми кошелёк.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Создать "родной" segwit (Bech32) адрес </translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation>История платежных запросов</translation>
+ </message>
+ <message>
+ <source>&amp;Request payment</source>
+ <translation>&amp;Запросить платеж</translation>
+ </message>
+ <message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation>Отобразить выбранный запрос (выполняет то же, что и двойной щелчок на записи)</translation>
+ </message>
+ <message>
<source>Show</source>
<translation>Показать</translation>
</message>
<message>
+ <source>Remove the selected entries from the list</source>
+ <translation>Удалить выбранные записи со списка</translation>
+ </message>
+ <message>
<source>Remove</source>
<translation>Удалить</translation>
</message>
@@ -777,28 +1553,112 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>QR Code</source>
+ <translation>QR-код</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation>Копировать &amp;URI</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Address</source>
+ <translation>Копировать &amp;Адрес</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Сохранить изображение...</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>Информация о платеже</translation>
+ </message>
+ <message>
+ <source>URI</source>
+ <translation>URI</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>Адрес</translation>
</message>
<message>
+ <source>Amount</source>
+ <translation>Количество</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Метка</translation>
</message>
- </context>
+ <message>
+ <source>Message</source>
+ <translation>Сообщение</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Кошелек</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Ошибка преобразования URI в QR-код.</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Метка</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Сообщение</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(нет метки)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation>(нет сообщений)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(не указана запрашиваемая сумма)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Запрошено</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
+ <source>Send Coins</source>
+ <translation>Отправить монеты</translation>
+ </message>
+ <message>
+ <source>Coin Control Features</source>
+ <translation>Опции управления монетами</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>Входы...</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>выбрано автоматически</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>Недостаточно средств!</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Количество:</translation>
+ </message>
+ <message>
<source>Bytes:</source>
<translation>Байтов:</translation>
</message>
@@ -811,28 +1671,200 @@
<translation>Комиссия:</translation>
</message>
<message>
+ <source>After Fee:</source>
+ <translation>После комиссии:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Сдача:</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation>Указать адрес для сдачи</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>Комиссия за транзакцию:</translation>
+ </message>
+ <message>
<source>Choose...</source>
<translation>Выбрать...</translation>
</message>
<message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Предупреждение: оценка комиссии в данный момент невозможна.</translation>
+ </message>
+ <message>
+ <source>collapse fee-settings</source>
+ <translation>свернуть настройки комиссионных</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>за килобайт</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation>Спрятать</translation>
</message>
<message>
+ <source>Recommended:</source>
+ <translation>Рекомендованное значение:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>Пользовательское значение:</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>Отправить нескольким получателям сразу</translation>
+ </message>
+ <message>
+ <source>Add &amp;Recipient</source>
+ <translation>Добавить &amp;получателя</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Очистить все поля формы.</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Пыль:</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>Целевое время подтверждения</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Включить Replace-By-Fee</translation>
+ </message>
+ <message>
<source>Balance:</source>
<translation>Баланс:</translation>
</message>
<message>
+ <source>Confirm the send action</source>
+ <translation>Подтвердить отправку</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Копировать количество</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>Копировать сумму</translation>
</message>
<message>
+ <source>Copy fee</source>
+ <translation>Скопировать комиссию</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Скопировать после комиссии</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Скопировать байты</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Скопировать пыль</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Скопировать сдачу</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Вы действительно хотите выполнить отправку?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>или</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Комиссия</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Подтвердить отправку монет</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Сумма оплаты должна быть больше 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Количество превышает ваш баланс.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Создание транзакции завершилось неудачей!</translation>
+ </message>
+ <message>
+ <source>The transaction was rejected with the following reason: %1</source>
+ <translation>Транзакция была отменена по следующей причине: %1</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>Комиссия более чем в %1 считается абсурдно высокой.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Истекло время ожидания запроса платежа</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Предупреждение: Неверный Bitcoin адрес</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Предупреждение: Неизвестный адрес сдачи</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(нет метки)</translation>
</message>
</context>
<context>
<name>SendCoinsEntry</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Метка:</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Выбрать предыдущий использованный адрес</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Вставить адрес из буфера обмена</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation>Удалить эту запись</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Использовать доступный баланс</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Сообщение:</translation>
+ </message>
+ <message>
+ <source>Pay To:</source>
+ <translation>Выполнить оплату в пользу:</translation>
+ </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -843,13 +1875,57 @@
</context>
<context>
<name>ShutdownWindow</name>
+ <message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 завершает работу...</translation>
+ </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Choose previously used address</source>
+ <translation>Выбрать предыдущий использованный адрес</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Вставить адрес из буфера обмена</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
<source>Signature</source>
<translation>Подпись</translation>
</message>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>Скопировать текущую подпись в буфер обмена системы</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>Введенный адрес недействителен.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Необходимо проверить адрес и выполнить повторную попытку.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>Разблокирование кошелька было отменено.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Сообщение подписано.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>Невозможно расшифровать подпись.</translation>
+ </message>
</context>
<context>
<name>SplashScreen</name>
@@ -859,24 +1935,180 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message>
+ <source>in memory pool</source>
+ <translation>в мемпуле</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>не в мемпуле</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Статус</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>Источник</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>От</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>неизвестно</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>только просмотр</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Комиссия</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Сообщение</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Комментарий</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>ID транзакции</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Транзакция</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Количество</translation>
+ </message>
</context>
<context>
<name>TransactionDescDialog</name>
- </context>
+ <message>
+ <source>Details for %1</source>
+ <translation>Детальная информация по %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Тип</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Метка</translation>
</message>
<message>
+ <source>Received with</source>
+ <translation>Получено на</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Отправить</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Добыто</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>только просмотр</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(нет метки)</translation>
</message>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Статус транзакции. Для отображения количества подтверждений необходимо навести курсор на это поле.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Дата и время получения транзакции.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Тип транзакции.</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Все</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Сегодня</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Эта неделя</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Этот месяц</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Последний месяц</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Этот год</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Диапазон...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Получено на</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Отправить</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>Себе</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Добыто</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Введите адрес, ID транзакции или метку для поиска</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Минимальное количество</translation>
+ </message>
+ <message>
+ <source>Abandon transaction</source>
+ <translation>Отказ от транзакции</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>Увеличить комиссию за транзакцию</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>Копировать адрес</translation>
</message>
@@ -893,6 +2125,34 @@
<translation>Копировать ID транзакции</translation>
</message>
<message>
+ <source>Copy raw transaction</source>
+ <translation>Копировать raw транзакцию</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>Копировать все детали транзакции</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Изменить метку</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Отобразить детали транзакции</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Подтвержденные</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Дата</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Тип</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Метка</translation>
</message>
@@ -901,9 +2161,25 @@
<translation>Адрес</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ИН</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>Экспорт не удался</translation>
</message>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>При попытке сохранения истории транзакций в %1 произошла ошибка.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Экспорт выполнен успешно</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>Историю транзакций было успешно сохранено в %1.</translation>
+ </message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
@@ -913,35 +2189,215 @@
</context>
<context>
<name>WalletModel</name>
- </context>
+ <message>
+ <source>Send Coins</source>
+ <translation>Отправить монеты</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Увеличение комиссии за транзакцию завершилось неудачей</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>Желаете увеличить комиссию?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>Текущее значение комиссии</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>Увеличить</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>Новое значение комиссии:</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>Невозможно подписать транзакцию</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>Не удалось выполнить транзакцию</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
<source>&amp;Export</source>
<translation>Экспортировать</translation>
</message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Экспортировать данные в текущей вкладке в файл</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Создать резервную копию кошелька</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Данные кошелька (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Создание резервной копии кошелька завершилось неудачей</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>При попытке сохранения данных кошелька в %1 произошла ошибка.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Резервное копирование выполнено успешно</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>Данные кошелька были успешно сохранены в %1.</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Error: A fatal internal error occurred, see debug.log for details</source>
+ <translation>Ошибка: произошла критическая внутренняя ошибка, для получения деталей см. debug.log</translation>
+ </message>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>Невозможно запустить HTTP-сервер. Для получения более детальной информации необходимо обратиться к журналу отладки.</translation>
+ </message>
+ <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>bitcoin-core</translation>
+ <source>The %s developers</source>
+ <translation>Разработчики %s</translation>
+ </message>
+ <message>
+ <source>%d of last 100 blocks have unexpected version</source>
+ <translation>%d из последних 100 блоков имеют неожиданную версию</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Авторское право (©) %i-%i</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>Ошибка загрузки %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Ошибка загрузки %s: кошелек поврежден</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Ошибка загрузки %s: кошелек требует более поздней версии %s</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low!</source>
+ <translation>Ошибка: место на диске заканчивается!</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>Выполняется импорт...</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>Выполняется загрузка P2P-адресов...</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>Загрузка черного списка...</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation>Недоступно достаточного количества дескрипторов файла.</translation>
+ </message>
+ <message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>Не удалось рассчитать комиссию и сдачу для транзакции </translation>
+ </message>
+ <message>
+ <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
+ <translation>Неподдерживаемый аргумент -debugnet пропущен, необходимо использовать -debug=net.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -tor found, use -onion.</source>
+ <translation>Обнаружен неподдерживаемый аргумент -tor, необходимо использовать -onion.</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>Проверка блоков...</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation>Ошибка чтения с базы данных, выполняется закрытие.</translation>
</message>
<message>
<source>Information</source>
<translation>Информация</translation>
</message>
<message>
+ <source>Signing transaction failed</source>
+ <translation>Подписание транзакции завершилось неудачей</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>Размер транзакции слишком мал</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>Транзакция слишком большая</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Предупреждение</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</translation>
+ <source>Starting network threads...</source>
+ <translation>Запуск сетевых потоков...</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>Это минимальная комиссия, которую вы платите для любой транзакции</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>Это размер комиссии, которую вы заплатите при отправке транзакции </translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>Размер транзакции не может быть отрицательным</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>Транзакция должна иметь хотя бы одного получателя</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation>Недостаточно средств</translation>
+ </message>
+ <message>
+ <source>Loading block index...</source>
+ <translation>Загрузка индекса блоков...</translation>
+ </message>
+ <message>
+ <source>Loading wallet...</source>
+ <translation>Выполняется загрузка кошелька...</translation>
+ </message>
+ <message>
+ <source>Cannot downgrade wallet</source>
+ <translation>Невозможно выполнить переход на более раннюю версию кошелька</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>Выполняется повторное сканирование...</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation>Загрузка завершена</translation>
</message>
<message>
<source>Error</source>
diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts
index 09cf552e6b..89ed850da3 100644
--- a/src/qt/locale/bitcoin_sk.ts
+++ b/src/qt/locale/bitcoin_sk.ts
@@ -30,6 +30,10 @@
<translation>Vymaž vybranú adresu zo zoznamu</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Zadajte adresu alebo popis pre hľadanie</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Exportovať tento náhľad do súboru</translation>
</message>
@@ -322,6 +326,14 @@
<translation>Otvoriť &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Peňaženka:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>predvolená peňaženka</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Kliknite pre zakázanie sieťovej aktivity.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Preindexúvam bloky na disku...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy je &lt;b&gt;zapnuté&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Poslať bitcoins na adresu</translation>
</message>
@@ -439,7 +455,7 @@
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n aktívne pripojenie do siete Bitcoin</numerusform><numerusform>%n aktívne pripojenia do siete Bitcoin</numerusform><numerusform>%n aktívnych pripojení do siete Bitcoin</numerusform></translation>
+ <translation><numerusform>%n aktívne pripojenie do siete Bitcoin</numerusform><numerusform>%n aktívne pripojenia do siete Bitcoin</numerusform><numerusform>%n aktívnych pripojení do siete Bitcoin</numerusform><numerusform>%n aktívnych pripojení do siete Bitcoin</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
@@ -451,7 +467,7 @@
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>Spracovaných %n blok transakčnej histórie.</numerusform><numerusform>Spracovaných %n bloky transakčnej histórie.</numerusform><numerusform>Spracovaných %n blokov transakčnej histórie.</numerusform></translation>
+ <translation><numerusform>Spracovaných %n blok transakčnej histórie.</numerusform><numerusform>Spracovaných %n bloky transakčnej histórie.</numerusform><numerusform>Spracovaných %n blokov transakčnej histórie.</numerusform><numerusform>Spracovaných %n blokov transakčnej histórie.</numerusform></translation>
</message>
<message>
<source>%1 behind</source>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Peňaženka: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Typ: %1
@@ -730,10 +752,6 @@
<translation>&amp;Adresa</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Nová adresa pre prijímanie</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Nová adresa pre odoslanie</translation>
</message>
@@ -750,8 +768,12 @@
<translation>Vložená adresa "%1" nieje platnou adresou Bitcoin.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Vložená adresa "%1" sa už nachádza v adresári.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adresa "%1" už existuje ako prijímacia adresa s označením "%2" .Nemôže tak byť pridaná ako odosielacia adresa.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Zadaná adresa "%1" sa už nachádza v zozname adries s označením "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>Voľby príkazového riadku</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Použitie:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>voľby príkazového riadku</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Možnosti používateľského rozhrania:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Vyberte dátový priečinok pri štarte (predvolené: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Nastavte jazyk, napríklad "de_DE" (predvolené: podľa systému)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Spustiť minimalizované</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Nastaviť SSL root certifikáty pre vyžiadanie platby (predvolené: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Zobraziť uvítaciu obrazovku pri štarte (predvolené: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Zrušiť všetky zmeny v GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -904,11 +890,11 @@
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>%n GB voľného miesta</numerusform><numerusform>%n GB voľného miesta</numerusform><numerusform>%n GB voľného miesta</numerusform></translation>
+ <translation><numerusform>%n GB voľného miesta</numerusform><numerusform>%n GB voľného miesta</numerusform><numerusform>%n GB voľného miesta</numerusform><numerusform>%n GB voľného miesta</numerusform></translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
- <translation><numerusform>(z %n GB potrebného)</numerusform><numerusform>(z %n GB potrebných)</numerusform><numerusform>(z %n GB potrebných)</numerusform></translation>
+ <translation><numerusform>(z %n GB potrebného)</numerusform><numerusform>(z %n GB potrebných)</numerusform><numerusform>(z %n GB potrebných)</numerusform><numerusform>(z %n GB potrebných)</numerusform></translation>
</message>
</context>
<context>
@@ -1068,6 +1054,22 @@
<translation>&amp;Sieť</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Zakáže niektoré pokročilé funkcie, ale všetky bloky budú stále plne overené. Obnovenie tohto nastavenia vyžaduje opätovné prevzatie celého blockchainu. Skutočné využitie disku môže byť o niečo vyššie.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Redukovať priestor pre &amp;bloky na</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Obnovenie tohto nastavenia vyžaduje opätovné prevzatie celého blockchainu.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt;0 = nechať toľko jadier voľných)</translation>
</message>
@@ -1334,6 +1336,10 @@
<translation>URI manipulácia</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' je neplatná URI. Použite 'bitcoin:'</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>URL pre stiahnutie výzvy na zaplatenie je neplatné: %1</translation>
</message>
@@ -1477,23 +1483,23 @@
</message>
<message numerus="yes">
<source>%n second(s)</source>
- <translation><numerusform>%n sekunda</numerusform><numerusform>%n sekundy</numerusform><numerusform>%n sekúnd</numerusform></translation>
+ <translation><numerusform>%n sekunda</numerusform><numerusform>%n sekundy</numerusform><numerusform>%n sekúnd</numerusform><numerusform>%n sekúnd</numerusform></translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
- <translation><numerusform>%n minúta</numerusform><numerusform>%n minúty</numerusform><numerusform>%n minút</numerusform></translation>
+ <translation><numerusform>%n minúta</numerusform><numerusform>%n minúty</numerusform><numerusform>%n minút</numerusform><numerusform>%n minút</numerusform></translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
- <translation><numerusform>%n hodina</numerusform><numerusform>%n hodiny</numerusform><numerusform>%n hodín</numerusform></translation>
+ <translation><numerusform>%n hodina</numerusform><numerusform>%n hodiny</numerusform><numerusform>%n hodín</numerusform><numerusform>%n hodín</numerusform></translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
- <translation><numerusform>%n deň</numerusform><numerusform>%n dni</numerusform><numerusform>%n dní</numerusform></translation>
+ <translation><numerusform>%n deň</numerusform><numerusform>%n dni</numerusform><numerusform>%n dní</numerusform><numerusform>%n dní</numerusform></translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
- <translation><numerusform>%n týždeň</numerusform><numerusform>%n týždne</numerusform><numerusform>%n týždňov</numerusform></translation>
+ <translation><numerusform>%n týždeň</numerusform><numerusform>%n týždne</numerusform><numerusform>%n týždňov</numerusform><numerusform>%n týždňov</numerusform></translation>
</message>
<message>
<source>%1 and %2</source>
@@ -1501,7 +1507,7 @@
</message>
<message numerus="yes">
<source>%n year(s)</source>
- <translation><numerusform>%n rok</numerusform><numerusform>%n roky</numerusform><numerusform>%n rokov</numerusform></translation>
+ <translation><numerusform>%n rok</numerusform><numerusform>%n roky</numerusform><numerusform>%n rokov</numerusform><numerusform>%n rokov</numerusform></translation>
</message>
<message>
<source>%1 B</source>
@@ -1531,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Chyba pri spracovaní argumentov príkazového riadku: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>Chyba: Zadaný adresár pre dáta „%1“ neexistuje.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Chyba: Nemôžem spracovať konfiguračný súbor: %1. Používajte iba syntax klúč=hodnota.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Chyba: Konfiguračný súbor sa nedá spracovať: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1629,6 +1639,14 @@
<translation>Využitie pamäte</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Peňaženka:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(žiadna)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Vynulovať</translation>
</message>
@@ -1798,6 +1816,10 @@
<translation>&amp;Zrušiť zákaz</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>predvolená peňaženka</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Vitajte v %1 RPC konzole</translation>
</message>
@@ -1822,6 +1844,14 @@
<translation>Sieťová aktivita zakázaná</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Príkaz sa vykonáva bez peňaženky</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Príkaz sa vykonáva s použitím peňaženky "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(ID uzlu: %1)</translation>
</message>
@@ -1893,20 +1923,20 @@
<translation>Vyčistiť</translation>
</message>
<message>
- <source>Requested payments history</source>
- <translation>História vyžiadaných platieb</translation>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Natívne segwit adresy (Bech32 or BIP-173) znižujú Vaše budúce transakčné poplatky and ponúkajú lepšiu ochranu pred preklepmi, avšak staré peňaženky ich nepodporujú. Ak je toto pole nezaškrtnuté, bude vytvorená adresa kompatibilná so staršími peňaženkami.</translation>
</message>
<message>
- <source>&amp;Request payment</source>
- <translation>&amp;Vyžiadať platbu</translation>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generovať natívnu segwit adresu (Bech32)</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Je lacnejšie míňať z Bech32 adries (BIP-173), ktoré tiež ponúkajú lepšiu ochranu voči preklepom. Ak túto možnosť nevyberiete, bude vytvorená adresa typu P2SH so SegWit, kompatibilná so staršími peňaženkami.</translation>
+ <source>Requested payments history</source>
+ <translation>História vyžiadaných platieb</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Generovať adresu Bech32</translation>
+ <source>&amp;Request payment</source>
+ <translation>&amp;Vyžiadať platbu</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1988,6 +2018,10 @@
<translation>Správa</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Peňaženka</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Výsledné URI je príliš dlhé, skúste skrátiť text pre popis alebo správu.</translation>
</message>
@@ -2102,12 +2136,16 @@
<translation>zbaliť nastavenia poplatkov</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>za kilobajt</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Špecifikujte vlastný poplatok za kB (1000 bajtov) virtuálnej veľkosti transakcie.
+
+Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 satoshi za kB" a veľkosti transakcie 500 bajtov (polovica z 1 kB) by stál len 50 satoshi.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Ak je poplatok nastavený na 1000 satoshi a transakcia je veľká len 250 bajtov, potom "za kilobajt" zaplatí poplatok 250 satoshi, ale "spolu aspoň" zaplatí 1000 satoshi. Pre transakcie väčšie ako kilobajt platia oba spôsoby za každý kilobajt.</translation>
+ <source>per kilobyte</source>
+ <translation>za kilobajt</translation>
</message>
<message>
<source>Hide</source>
@@ -2158,6 +2196,10 @@
<translation>Povoliť dodatočné navýšenie poplatku (tzv. „Replace-By-Fee“)</translation>
</message>
<message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>S dodatočným navýšením poplatku (BIP-125, tzv. „Replace-By-Fee“), môžete zvýšiť poplatok aj po odoslaní. Bez toho, by mohol byť navrhnutý väčší transakčný poplatok, aby kompenzoval zvýšené riziko omeškania transakcie.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>&amp;Zmazať všetko</translation>
</message>
@@ -2214,14 +2256,6 @@
<translation>Určite chcete odoslať transakciu?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>pridané ako poplatok za transakciu</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Celková suma %1</translation>
- </message>
- <message>
<source>or</source>
<translation>alebo</translation>
</message>
@@ -2230,10 +2264,26 @@
<translation>Poplatok môžete navýšiť neskôr (vysiela sa "Replace-By-Fee" - nahradenie poplatkom, BIP-125).</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>z peňaženky %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Prosím, skontrolujte Vašu transakciu.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transakčný poplatok</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>Nevysiela sa "Replace-By-Fee" - nahradenie poplatkom, BIP-125.</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>Celková suma</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Potvrďte odoslanie mincí</translation>
</message>
@@ -2279,7 +2329,7 @@
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
- <translation><numerusform>Odhadovaný začiatok potvrdzovania po %n bloku.</numerusform><numerusform>Odhadovaný začiatok potvrdzovania po %n blokoch.</numerusform><numerusform>Odhadovaný začiatok potvrdzovania po %n blokoch.</numerusform></translation>
+ <translation><numerusform>Odhadovaný začiatok potvrdzovania po %n bloku.</numerusform><numerusform>Odhadovaný začiatok potvrdzovania po %n blokoch.</numerusform><numerusform>Odhadovaný začiatok potvrdzovania po %n blokoch.</numerusform><numerusform>Odhadovaný začiatok potvrdzovania po %n blokoch.</numerusform></translation>
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
@@ -2564,7 +2614,7 @@
<name>TransactionDesc</name>
<message numerus="yes">
<source>Open for %n more block(s)</source>
- <translation><numerusform>Otvoriť pre %n ďalší blok</numerusform><numerusform>Otvoriť pre %n ďalšie bloky</numerusform><numerusform>Otvoriť pre %n ďalších blokov</numerusform></translation>
+ <translation><numerusform>Otvoriť pre %n ďalší blok</numerusform><numerusform>Otvoriť pre %n ďalšie bloky</numerusform><numerusform>Otvoriť pre %n ďalších blokov</numerusform><numerusform>Otvoriť pre %n ďalších blokov</numerusform></translation>
</message>
<message>
<source>Open until %1</source>
@@ -2575,10 +2625,6 @@
<translation>koliduje s transakciou s %1 potvrdeniami</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/nepotvrdené, %1</translation>
</message>
@@ -2607,14 +2653,6 @@
<translation>Stav</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, ešte nebola úspešne odoslaná</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, vysielať cez %n uzol</numerusform><numerusform>, vysielať cez %n uzle </numerusform><numerusform>, vysielať cez %n uzolov</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Dátum</translation>
</message>
@@ -2656,7 +2694,7 @@
</message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
- <translation><numerusform>dozreje za %n ďalší blok</numerusform><numerusform>dozreje za %n ďalšie bloky</numerusform><numerusform>dozreje za %n ďalších blokov</numerusform></translation>
+ <translation><numerusform>dozreje za %n ďalší blok</numerusform><numerusform>dozreje za %n ďalšie bloky</numerusform><numerusform>dozreje za %n ďalších blokov</numerusform><numerusform>dozreje za %n ďalších blokov</numerusform></translation>
</message>
<message>
<source>not accepted</source>
@@ -2699,6 +2737,10 @@
<translation>Celková veľkosť transakcie</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Virtuálna veľkosť transakcie</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Index výstupu</translation>
</message>
@@ -2762,17 +2804,13 @@
</message>
<message numerus="yes">
<source>Open for %n more block(s)</source>
- <translation><numerusform>Otvoriť pre %n ďalší blok</numerusform><numerusform>Otvoriť pre %n ďalšie bloky</numerusform><numerusform>Otvoriť pre %n ďalších blokov</numerusform></translation>
+ <translation><numerusform>Otvoriť pre %n ďalší blok</numerusform><numerusform>Otvoriť pre %n ďalšie bloky</numerusform><numerusform>Otvoriť pre %n ďalších blokov</numerusform><numerusform>Otvoriť pre %n ďalších blokov</numerusform></translation>
</message>
<message>
<source>Open until %1</source>
<translation>Otvorené do %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Nepotvrdené</translation>
</message>
@@ -2797,10 +2835,6 @@
<translation>Nezrelé (%1 potvrdení, bude dostupné po %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Ten blok nebol prijatý žiadnym iným uzlom a pravdepodobne nebude akceptovaný!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Vypočítané ale neakceptované</translation>
</message>
@@ -3111,38 +3145,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Dáta peňaženky boli úspešne uložené do %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Zrušiť</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Možnosti:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Určiť priečinok s dátami</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Pripojiť sa k uzlu, získať adresy ďalších počítačov v sieti a odpojiť sa</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Určite vašu vlastnú verejnú adresu</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Prijímať príkazy z príkazového riadku a JSON-RPC</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distribuované pod softvérovou licenciou MIT, viď sprievodný súbor %s alebo %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Pokiaľ &lt;category&gt; nie je nastavená, alebo &lt;category&gt; = 1, vypíš všetky informácie pre ladenie.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Redukcia nastavená pod minimálnu hodnotu %d MiB. Prosím použite vyššiu hodnotu.</translation>
</message>
@@ -3159,18 +3173,10 @@
<translation>Chyba: Vyskytla sa interná chyba, pre viac informácií zobrazte debug.log</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Poplatok (za %s/kB) pridaný do transakcie, ktorú posielate (predvolené: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Redukovanie blockstore...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Bežať na pozadí ako démon a prijímať príkazy</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Nepodarilo sa spustiť HTTP server. Pre viac detailov zobrazte debug log.</translation>
</message>
@@ -3183,56 +3189,20 @@
<translation>Vývojári %s</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Sadzba poplatku (v %s/kB), ktorá sa použije, ak nebude k dispozícii dostatok dát pre automatický odhad poplatku (predvolené: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Akceptovať postúpené transakcie od povolených partnerov aj keď normálne nepostupujete transakcie (predvolené: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Spojiť s danou adresou a vždy na nej počúvať. Použite zápis [host]:port pre IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Nemožné uzamknúť zložku %s. %s pravdepodobne už beží.</translation>
</message>
<message>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
- <translation>Nemôžete zadať konkrétne spojenia a zároveň mať nastavený addrman pre hľadanie odchádzajúcich spojení.</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Vymazať všetky transakcie z peňaženky a pri spustení znova získať z reťazca blokov iba tie získané pomocou -rescan</translation>
+ <translation>Nemôžete zadať konkrétne spojenia a zároveň mať nastavený addrman pre hľadanie odchádzajúcich spojení.</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Nastala chyba pri čítaní súboru %s! Všetkz kľúče sa prečítali správne, ale dáta o transakcíách alebo záznamy v adresári môžu chýbať alebo byť nesprávne.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Vylúčiť ladiacu informáciu danej kategórie. Dá se zkombinovať s -debug=1, aby sa zaznamenávali ladice informácie všetkých kategórií pkrem jednej alebo niekolkých zvolených.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Vykonaj príkaz keď sa zmení transakcia peňaženky (%s v príkaze je nahradená TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Počet extra transakcíí, ktoré sa majú držať v pamäti pre účely rekonštrukcie kompaktných blokov (predvolené: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Pokiaľ je tento blok v reťazci blokov, tak predpokladať, že on i jeho následníci sú platní, a potenciálne preskočiť overovanie ich skriptov (0 = overovať všetko, predvolené: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Maximálne povolené upravovanie času mediánom časov peerov. Miestne vnímanie času môže byť ovplivnené peerami, a to dopredu alebo dozadu až o toto množstvo. (predvolené: %u sekund)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Horná hranica pre celkový poplatok (v %s) za jednu transakciu z peňaženky alebo jednu nespracovanú transakciu. Príliš nízká hodnota môže zmariť velké transakcie (predvolené: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Zoskupenie výstupov podľa adresy, pri vybratí všetkých alebo žiadnych, namiesto vybratia na báze za výstup. Zlepší sa súkromie, keďže adresa je použitá len raz (pokiaľ nikto na túto adresu už nič nepošle po minutí), ale môže vyústiť v trochu väčšie poplatky keďže ne-optimalizovaný výber mincí môže vyústiť v pridané obmedzenia (predvolené: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3243,22 +3213,6 @@
<translation>Keď si myslíte, že %s je užitočný, podporte nás. Pre viac informácií o software navštívte %s.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Pri nedostatku adries získať ďalších peerov z DNS (predvolené: 1, ak nie je použité -connect)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Obmedziť nároky na úložný priestor prerezáváním (mazaním) starých blokov. Táto volba tiež umožní použiť RPC volanie pruneblockchain na zmazanie konkrétnych blokov a ďalej automatické prerezávanie starých blokov, ak je zadána cieľová velikosť súborov z blokmi v MiB. Tento režim nie je zlúčiteľný s -txindex ani -rescan. Upozornenie: opätovná zmena tohoto nastavenia bude vyžadovať nové stiahnutie celého reťazca blokov. (predvolené: 0 = bloky neprerezávať, 1 = povoliť ručné prerezávanie cez RPC, &gt;%u = automatické prerezávanie blokov tak, aby bola udržaná cieľová velikosť súborov s blokmi v MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Nastaviť nejnižší akceptovateľný poplatok (v %s/kB) pre transakcie, ktoré majú byť zahrnutý do nových blokov. (predvolené: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Nastaviť počeť vlákien overujúcich skripty (%u až %d, 0 = auto, &lt;0 = nechať toľkoto jadier voľných, prednastavené: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Databáza blokov obsahuje blok, ktorý vyzerá byť z budúcnosti. Toto môže byť spôsobené nesprávnym systémovým časom vášho počítača. Obnovujte databázu blokov len keď ste si istý, že systémový čas je nastavený správne.</translation>
</message>
@@ -3279,18 +3233,6 @@
<translation>Nedará sa vrátiť databázu do stavu pred rozdelením. Budete musieť znovu stiahnuť celý reťaztec blokov</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Skúsiť použiť UPnP pre mapovanie počúvajúceho portu (predvolené: 1 počas počúvania a bez -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Užívateľské meno a zahašované heslo pre JSON-RPC spojenie. Pole &lt;userpw&gt; má formát: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Pomocný python skript je priložený v share/rpcuser. Klient sa potom už pripojuje normálne pomocou páru argumentov rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt;. Túto voľbu môžete použiť i viackrát</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Peňaženka nebude vytvárať transakcie, ktoré by porušovali limity transakčného zásobníku reťazcov (predvolené: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Varovanie: Javí sa že sieť sieť úplne nesúhlasí! Niektorí mineri zjavne majú ťažkosti.</translation>
</message>
@@ -3299,10 +3241,6 @@
<translation>Varovanie: Zjavne sa úplne nezhodujeme s našimi peer-mi! Možno potrebujete prejsť na novšiu verziu alebo ostatné uzly potrebujú vyššiu verziu.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Či uchovať transakčný zásobník medzi vypnutím a zapnutím (predvolené: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d z poslednźých 100 blokov má neočakávanú verziu</translation>
</message>
@@ -3315,42 +3253,14 @@
<translation>-maxmempool musí byť najmenej %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; môže byť:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Prijať spojenia zvonku (predvolené: 1 ak žiadne -proxy alebo -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Pripojiť komentár k typu klienta</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Pokúsiť sa o obnovenie privátnych kľúčov z poškodenej peňaženky pri spustení</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Voľby vytvorenia bloku:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Nedá preložiť -%s adresu: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Možnosti výberu reťzca blokov:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Menný index mimo rozsah</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Možnosti pripojenia:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3359,38 +3269,10 @@
<translation>Zistená poškodená databáza blokov</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Možnosti ladenia/testovania:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Nenahrat peňaženku a zablokovať volania RPC.</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Chcete znovu zostaviť databázu blokov?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Povoliť zverejneneie hash blokov pre &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Povoliť zverejnenie hash transakcií pre &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Povoliť zverejnenie raw bloku pre &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Povoliť publikovať hrubý prevod v &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Povoliť výmenu transakcií v transakčnom zásobníku (predvolené: %u)</translation>
- </message>
- <message>
<source>Error creating %s: You can't create non-HD wallets with this version.</source>
<translation>Chyba počas vytvárania %s: S touto verziou nemôžete vytvoriť ne-HD peňaženky.</translation>
</message>
@@ -3407,6 +3289,10 @@
<translation>Chyba načítania %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Chyba pri načítaní %s: Súkromné kľúče môžu byť zakázané len počas vytvárania</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Chyba načítania %s: Peňaženka je poškodená</translation>
</message>
@@ -3431,6 +3317,10 @@
<translation>Chyba počúvania na ktoromkoľvek porte. Použi -listen=0 ak toto chcete.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Počas inicializácie sa nepodarila pre-skenovať peňaženka</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Prebieha import ...</translation>
</message>
@@ -3455,8 +3345,12 @@
<translation>Neplatná suma pre -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Udržovať zasobník transakcií menší než &lt;n&gt; megabajtov (predvolené: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Zadaný adresár blokov "%s" neexistuje.</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Inovuje sa txindex databáza</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3467,26 +3361,10 @@
<translation>Načítavam banlist...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Umiestnenie overovacieho cookie súboru (predvolená: Priečinok s dátami)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Nedostatok kľúčových slov súboru.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Pripojiť iba k uzlom v sieti &lt;net&gt; (ipv4, ipv6, alebo onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Vytlačiť túto pomocnú správu a ukončiť</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Vytlačiť verziu a ukončiť</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Redukovanie nemôže byť nastavené na zápornú hodnotu.</translation>
</message>
@@ -3495,14 +3373,6 @@
<translation>Redukovanie je nekompatibilné s -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Obnoviť stav reťazca a index blokov zo súborov blk*.dat na disku.</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Obnoviť stav reťazca z aktuálne indexovaných blokov.</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Znovu sa aplikujú bloky…</translation>
</message>
@@ -3511,18 +3381,6 @@
<translation>Vracajú sa bloky dozadu…</translation>
</message>
<message>
- <source>Send transactions with full-RBF opt-in enabled (RPC only, default: %u)</source>
- <translation>Posielať transakcie so zapnutým plným RBF (Replace-By-Fee) (iba RPC, predvolené: %u)</translation>
- </message>
- <message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Nastaviť veľkosť pomocnej pamäti databázy v megabajtoch (%d do %d, prednastavené: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Označ súbor peňaženky (v priečinku s dátami)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Zdrojový kód je dostupný z %s</translation>
</message>
@@ -3535,6 +3393,10 @@
<translation>Nemožné pripojiť k %s na tomto počíťači. %s už pravdepodobne beží.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Nepodarilo sa vygenerovať kľúče</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Nepodporovaný parameter -benchmark bol ignorovaný, použite -debug=bench.</translation>
</message>
@@ -3555,14 +3417,6 @@
<translation>Vylepšuje sa databáza neminutých výstupov (UTXO)</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Použiť UPnP pre mapovanie počúvajúceho portu (predvolené: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Použiť testovaciu sieť</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Komentár u typu klienta (%s) obsahuje riskantné znaky.</translation>
</message>
@@ -3571,86 +3425,26 @@
<translation>Overujem bloky...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Ladiace / testovacie možnosti peňaženky.</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Peňaženka musí byť prepísaná: pre dokončenie reštartujte %s</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Voľby peňaženky:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Povoliť JSON-RPC pripojenia zo zadaného zdroja. Pre &lt;ip&gt; sú platné jednoduché IP (napr. 1.2.3.4), sieť/netmask (napr. 1.2.3.4/255.255.255.0) alebo sieť/CIDR (napr. 1.2.3.4/24). Táto možnosť môže byť zadaná niekoľko krát</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Spojiť s danou adresou a povolenými partnerskými zariadeniami ktoré sa tam pripájajú. Použite zápis [host]:port pre IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Vytvoriť nové súbory z predvolenými systémovými právami, namiesto umask 077 (funguje iba z vypnutou funkcionalitou peňaženky)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Zisti vlastnú IP adresu (predvolené: 1 pre listen a -externalip alebo -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Chyba: Počúvanie prichádzajúcich spojení zlyhalo (vrátená chyba je %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Vykonať príkaz po prijatí patričného varovania alebo uvidíme veľmi dlhé rozdvojenie siete (%s v cmd je nahradené správou)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Poplatky (v %s/kB) menšie ako toto, sú považované za nulový transakčný poplatok (predvolené: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Ak nie je nastavené paytxfee, pridať dostatočný poplatok aby sa transakcia začala potvrdzovať priemerne v rámci bloku (predvolené: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Neplatná suma pre -maxtxfee=&lt;amount&gt;: '%s' (aby sa transakcia nezasekla, minimálny prenosový poplatok musí byť aspoň %s)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maximálna veľkosť dát v transakciách nosných dát, ktoré prenášame a ťažíme (predvolené: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Suma je príliš malá pre odoslanie transakcie</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Uzle na zoznam povolených nemôžu byť DoS zakázané a ich transakcie vždy postúpené ďalej, aj v prípade, ak sú už pamäťovej fronte. Užitočné napr. pre brány</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>K návratu k neprerezávaciemu režimu je treba prestavať databázu použitím -reindex. Tiež sa znova stiahne celý reťazec blokov</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(predvolené: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Akceptovať verejné REST žiadosti (predvolené: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Automaticky vytvoriť skrytú službu Tor (predvolené: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Pripojiť cez proxy server SOCKS5</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Chyba pri načítání %s: nemôžeš vypnúť HD u existujúcej HD peňaženky</translation>
</message>
@@ -3663,10 +3457,6 @@
<translation>Chyba pri vylepšení databáze reťzcov blokov</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importovať bloky z externého súboru blk000??.dat pri štarte</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informácia</translation>
</message>
@@ -3687,42 +3477,14 @@
<translation>Nadaná neplatná netmask vo -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>V pamäti udržiavať najviac &lt;n&gt; nepotvrdených transakcií (predvolené: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Je potrebné zadať port s -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Prenosové možnosti uzla:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Možnosti servra RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Obmedzuje sa -maxconnections z %d na %d kvôli systémovým obmedzeniam.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Pri spustení skontrolovať reťaz blokov pre chýbajúce transakcie peňaženky</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Odoslať trace/debug informácie na konzolu namiesto debug.info žurnálu</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Zobraziť všetky možnosti ladenia (použitie: --help --help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Zmenšiť debug.log pri spustení klienta (predvolené: 1 ak bez -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Podpísanie správy zlyhalo</translation>
</message>
@@ -3747,14 +3509,6 @@
<translation>Toto je experimentálny softvér.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Heslo na kontrolu portu pre Tor (predvolené: žiadne)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Ovládací port Toru, ak je zapnuté onion počúvanie (predvolené: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Suma transakcie príliš malá</translation>
</message>
@@ -3775,14 +3529,6 @@
<translation>Nepodarilo sa vygenerovať úvodné kľúče</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Aktualizovať peňaženku na posledný formát pri štarte</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Užívateľské meno pre JSON-RPC spojenia</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>Kontrolujem peňaženku(y)…</translation>
</message>
@@ -3799,110 +3545,18 @@
<translation>Upozornenie: aktivovaná neznáme nové pravidlá (verzový bit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Či fungovat iba v čistom blokovom režime (predvolené: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Je teeba prestavať databázu použitím -reindex, aby bolo možné zmeniť -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Zmazať všetky transakcie z peňaženky...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Možnosti pripojenia ZeroMQ:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Heslo pre JSON-rPC spojenia</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Vykonaj príkaz, ak zmeny v najlepšom bloku (%s v príkaze nahradí blok hash)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Povoliť vyhľadávanie DNS pre pridanie nódy a spojenie</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = zachovať metaúdaje tx napr. vlastníka účtu a informácie o platobných príkazoch, 2 = zahodiť metaúdaje tx)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee je nastavené veľmi vysoko! Takto vysoký poplatok môže byť zaplatebý v jednej transakcii.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Čakať na zadanej adrese na JSON-RPC spojenie. Táto volba sa ignoruje, ak súčastne nezadáš aj volbu -rpcallowip. Port je voliteľný a má prednosť pred -rpcport. Pre zápis IPv6 adresy použite notáciu [adresa]:port. Túto volbu je možné použiť i viackrát (predvolené: 127.0.0.1 a ::1, tzn. localhost, alebo ak je zadané -rpcallowip, tak 0.0.0.0 a ::, tzn. všetky adresy)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Nedržať transakcie v zásobníku dlhšie ako &lt;n&gt; hodín (predvolené: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Ekvivalent bajtov za každý sigop v transakciach pre účely preposielania a ťaženia (predvolené: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Chyba pri načítaní %s: nemôžeš zapnúť HD u existujúcej nie-HD peňaženky</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Chyba pri načítaní peňaženky %s. Parameter -wallet môže obsahovať iba názov súboru (nie cestu k nemu).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Poplatky (v %s/kB) menšie ako toto, sú považované za nulový transakčný poplatok (predvolené: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Vynútiť preposíelanie transakcií od vždy vítaných peerov, aj keď porušujú míestne zásady pre preposielanie (predvolené: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Ako dôkladné je -checkblocks overenie blokov (0-4, predvolené: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Udržiavať kompletný transakčný index, využíva getrawtransaction rpc volanie (predvolené: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Počet sekúnd, počas ktorých nepripájať zle správajúce sa uzle (predvolené: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Výstupné ladiace informácie (predvolené: %u, dodanie &lt;category&gt; je voliteľné)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight</source>
- <translation>Nastaviť maximálnu váhu bloku pre BIP141 na toto * 4. Zastaralé, použite blockmaxweight</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Nastaví serializáciu nespracovaných transakcií alebo bloov, ak sú vrátené v nehovoriacom móde: nie-segwit (0) alebo segwit (1) (predvolené: %d)</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>Určiť cestu pre peňaženky (predvolená: &lt;datadir&gt;/wallets ak existuje, inak &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>Zadajte cestu k súboru debug.log: tá môže byť buď absolútna alebo relatívna ku priečinku s dátami (predvolená: %s)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Umožniť filtrovanie blokov a transakcií pomocou Bloom filtra (predvolené: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>Sadzba poplatku (v %s/kB), ktorá určuje Vašu ochotu v prípade potreby premeniť drobné v poplatok (predvolené: %s). Poznámka: výstup sa premení, ak sa pri tejto sadzbe zmení v prach. Každopádne meniť budeme do výške poplatku pre prenos prachu a premenený poplatok nad túto výšku bude obmedzený odhadom poplatku na nejdlhší čas</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Toto je poplatok za transakciu keď odhad poplatkov ešte nie je k dispozícii.</translation>
</message>
@@ -3915,10 +3569,6 @@
<translation>Celková dĺžka verzie sieťového reťazca (%i) prekračuje maximálnu dĺžku (%i). Znížte počet a veľkosť komentárov.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Sa snaží držať odchádzajúce prevádzku v rámci daného cieľa (v MB za 24h), 0 = žiadny limit (predvolený: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Nepodporovaný argument -socks nájdený. Nastavenie SOCKS verzie už nie je viac moźné, iba SOCKS5 proxies sú podporované.</translation>
</message>
@@ -3927,10 +3577,6 @@
<translation>Nepodporovaný argument -whitelistalwaysrelay ignorovaný, použite -whitelistrelay a/alebo -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Použiť samostatný SOCKS5 proxy server na dosiahnutie počítačov cez skryté služby Tor (predvolené: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Varovanie: Neznáma verzia blokov sa doluje! Je možné, že neznáme pravidlá majú efekt</translation>
</message>
@@ -3939,110 +3585,18 @@
<translation>Varovanie: Peňaženka poškodená, dáta boli zachránené! Originálna %s ako %s v %s; ak váš zostatok alebo transakcie sú nesprávne, mali by ste obnoviť zálohu.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Povoliť partnerov pripájajúcich sa z danej IP adresy (napr. 1.2.3.4) alebo zo siete vo formáte CIDR (napr. 1.2.3.0/24). Môže byť zadané viackrát.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>Hodnota %s je nastavená veľmi vysoko!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(predvolené: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Vždy sa dotazovať adresy partnerských uzlov cez vyhľadávanie DNS (predvolené: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Chyba pri načítaní peňaženky %s. -wallet musí byť obyčajný súbor.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Chyba pri načítaní peňaženky %s. Zadaný duplicitný názov súboru -wallet.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Chyba pri načítaní peňaženky %s. Neplatné znaky v názvu souboru -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Koľko blokov overiť pri spustení (predvolené: %u, 0 = všetky)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Zahrnúť IP adresy v ladiacom výstupe (predvolené: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Vyčerpal sa zásobník kľúčov, zavolať najskôr keypoolrefill</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Počúvať JSON-RPC pripojenia na &lt;port&gt; (predvolené: %u alebo testovacia sieť: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Počúvať pripojenia na &lt;port&gt; (predvolené: %u alebo testovacia sieť: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Udržiavať najviac &lt;n&gt; spojení s inými počítačmi (predvolené: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Vysielať transakcie z peňaženky</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximálna prijímajúca medzipamäť pre pripojenie, &lt;n&gt;*1000 bajtov (predvolené: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximálna odosielajúca medzipamäť pre pripojenie, &lt;n&gt;*1000 bajtov (predvolené: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Na začiatok pripojiť časovú známku k ladiacemu výstupu (predvolené: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Prenášať a ťažiť transakcie nosných dát (predvolené: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Prenášať non-P2SH multi-podpis (predvolené: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Nastaviť veľkosť kľúča fronty na &lt;n&gt; (predvolené: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Nastaviť maximálnu váhu bloku pre BIP141 (predvolené: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Nastaviť počet vlákien na obsluhu RPC volaní (predvolené: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Zadať konfiguračný súbor (predvolené: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Zadajte časový limit pripojenia v milisekundách (minimum: 1, predvolené: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Zadať pid súbor (predvolené: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Minúť nepotvrdené zmenu pri posielaní transakcií (predvolené: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Spúšťajú sa sieťové vlákna...</translation>
</message>
@@ -4059,10 +3613,6 @@
<translation>Toto je poplatok za transakciu pri odoslaní transakcie.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Hranica pre odpájanie zle sa správajúcim partnerským uzlom (predvolené: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Sumy transakcií nesmú byť záporné</translation>
</message>
@@ -4083,6 +3633,22 @@
<translation>Nedostatok prostriedkov</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Nie je možné vygenerovať kľúč na zmenu adresy. Súkromné kľúče sú pre túto peňaženku zakázané.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Nie je možné vylepšiť peňaženku bez HD bez aktualizácie, ktorá podporuje delenie keypoolu. Použite prosím -upgradewallet=169900 alebo -upgradewallet bez špecifikovania verzie.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Odhad poplatku sa nepodaril. Fallbackfee je zakázaný. Počkajte niekoľko blokov alebo povoľte -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Upozornenie: Boli zistené súkromné kľúče v peňaženke {%s} so zakázanými súkromnými kľúčmi.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Načítavanie zoznamu blokov...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts
index 36e90aae5c..08b00984c0 100644
--- a/src/qt/locale/bitcoin_sl_SI.ts
+++ b/src/qt/locale/bitcoin_sl_SI.ts
@@ -30,6 +30,10 @@
<translation>Izbriši trenutno označeni naslov iz seznama</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Iščite po naslovu ali oznaki</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Izvozi podatke v trenutnem zavihku v datoteko</translation>
</message>
@@ -62,10 +66,34 @@
<translation>Imenik naslovov za prejemanje</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>To so vaši Bitcoin naslovi za pošiljanje. Pred pošiljanjem vedno preverite količino in prejemnikov naslov.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>To so vaši Bitcoin naslovi za prejemanje. Priporočeno je, da za vsako transakcijo uporabite nov naslov.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Kopiraj naslov</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Kopiraj &amp;oznako</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Uredi</translation>
+ </message>
+ <message>
<source>Export Address List</source>
<translation>Izvozi seznam naslovov</translation>
</message>
<message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Podatki ločenimi z vejico (*.csv)</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>Podatkov ni bilo mogoče izvoziti.</translation>
</message>
@@ -104,14 +132,98 @@
<translation>Ponovite novo geslo</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Pokaži geslo</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Vnesite novo geslo za dostop do denarnice. Prosimo, da uporabite geslo sestavljeno iz &lt;b&gt;desetih ali več&lt;/b&gt; naključnih znakov ali &lt;b&gt;osmih ali večih&lt;/b&gt; besed.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Šifriraj denarnico</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>To dejanje zahteva geslo za odklepanje vaše denarnice.</translation>
+ </message>
+ <message>
<source>Unlock wallet</source>
<translation>Odkleni denarnico</translation>
</message>
<message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>To dejanje zahteva geslo za dešifriranje vaše denarnice.</translation>
+ </message>
+ <message>
<source>Decrypt wallet</source>
<translation>Odšifriraj denarnico</translation>
</message>
- </context>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Spremeni geslo</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Vnesite staro in novo geslo denarnice.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Potrdi šifriranje denarnice</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Opozorilo: V primeru izgube gesla šifrirane denarnice, boste &lt;b&gt;IZGUBILI VSE SVOJE BITCOINE&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Ali ste prepričani, da želite šifrirati svojo denarnico?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Denarnica šifrirana</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 se bo zaprl, da bi dokončal postopek šifriranja. Zapomnite si, da šifriranje vaše denarnice vaših ne more popolnoma zaščititi vaših bitcoinov pred krajami zlonamernih programov, ki bi lahko bili nameščeni na vašem računalniku.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>POMEMBNO: Vse starejše varnostne kopije denarnice je potrebno zamenjati z novoizdelano, šifrirano, varnostno kopijo. Zaradi varnosti bodo stare varnostne kopije postale neuporabne takoj, ko začnete uporabljati novo, šifrirano denarnico.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Šifriranje denarnice ni uspelo</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Šifriranje denarnice ni uspelo zaradi notranje napake. Vaša denarnica ni bila šifrirana.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Navedeni gesli se ne ujemata.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Denarnice ni bilo mogoče odkleniti.</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Geslo za dešifriranje denarnice, ki ste ga vnesli, ni pravilno.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Dešifriranje denarnice ni uspelo</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Geslo za dostop do denarnice je bilo uspešno spremenjeno.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Opozorilo: Vključena je tipka Caps Lock!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
<message>
@@ -162,6 +274,14 @@
<translation>Ustavite program</translation>
</message>
<message>
+ <source>&amp;About %1</source>
+ <translation>&amp;O nas%1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Prikaži informacije o %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>O &amp;Qt</translation>
</message>
@@ -174,6 +294,10 @@
<translation>&amp;Možnosti ...</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Spremeni možnosti konfiguracije za %1</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Šifriraj denarnico ...</translation>
</message>
@@ -198,10 +322,38 @@
<translation>Odpri &amp;URI ...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Denarnica:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>privzeta denarnica</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Kliknite, da onemogočite omrežno aktivnosti.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Omrežna aktivnost onemogočena.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Kliknite, da ponovno vključite omrežno aktivnost.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Sinhronizacija glav (%1%)...</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>Poustvarjam kazalo blokov na disku ...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Namestniški strežnik je omogočen&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Izvedite plačilo na naslov Bitcoin</translation>
</message>
@@ -535,27 +687,7 @@
<source>Command-line options</source>
<translation>Možnosti ukazne vrstice</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Uporaba:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>možnosti ukazne vrstice</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>UI možnosti:</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Nastavi jezik, na primer "sl_SI" (privzeto: sistemsko)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Začni minimizirano</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -1117,6 +1249,10 @@
<translation>Počisti konzolo</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>privzeta denarnica</translation>
+ </message>
+ <message>
<source>via %1</source>
<translation>preko %1</translation>
</message>
@@ -1234,6 +1370,10 @@
<source>Label</source>
<translation>Oznaka</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Denarnica</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1317,10 +1457,6 @@
<translation>na KiB</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Če je nastavitev zneska provizije po meri enaka 1000 satoshijev, transakcija pa je velika samo 250 bajtov, je obračunani znesek provizije pri nastavitvi "za KiB" samo 250 satoshijev, medtem ko je pri nastavitvi "skupno vsaj" ta znesek 1000 satoshijev. Za transakcije, večje od 1 KiB, se končni znesek pri obeh nastavitvah obračuna na KiB.</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Skrij</translation>
</message>
@@ -1377,6 +1513,10 @@
<translation>&amp;Pošlji</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Provizija transakcije</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(brez oznake)</translation>
</message>
@@ -1595,6 +1735,10 @@
<context>
<name>TransactionView</name>
<message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Podatki ločenimi z vejico (*.csv)</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Oznaka</translation>
</message>
@@ -1630,74 +1774,14 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Možnosti:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Izberite podatkovno mapo</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Povežite se z vozliščem za pridobitev naslovov soležnikov in nato prekinite povezavo.</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Določite vaš lasten javni naslov</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Sprejemaj ukaze iz ukazne vrstice in preko JSON-RPC</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Teci v ozadju in sprejemaj ukaze</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Veži dani naslov in tam vedno poslušaj. Za naslove protokola IPv6 uporabite zapis [gostitelj]:vrata.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Izvedi ukaz, ko bo transakcija denarnice se spremenila (V cmd je bil TxID zamenjan za %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Nastavi število niti za preverjanje skript (%u do %d, 0 = samodejno, &lt;0 toliko procesorskih jeder naj ostane prostih, privzeto: %d)</translation>
- </message>
- <message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; je lahko:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Sprejemaj zunanje povezave (privzeto: 1, razen če ste vklopili opciji -proxy ali -connect)</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Možnosti ustvarjanja blokov:</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Izbire povezave:</translation>
- </message>
- <message>
<source>Corrupted block database detected</source>
<translation>Podatkovna baza blokov je okvarjena</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Možnosti razhroščevanja in testiranja:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Ne naloži denarnice in onemogoči s tem povezane klice RPC</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Želite zdaj obnoviti podatkovno bazo blokov?</translation>
</message>
@@ -1738,10 +1822,6 @@
<translation>Na voljo ni dovolj deskriptorjev datotek.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Povezuj se samo z vozlišči na omrežju tipa &lt;net&gt; (IPv4, IPv6 ali onion)</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Negativne vrednosti parametra funkcije obrezovanja niso sprejemljive.</translation>
</message>
@@ -1750,66 +1830,14 @@
<translation>Funkcija obrezovanja ni združljiva z opcijo -txindex.</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Nastavitev velikosti predpomnilnik podatkovne baze v MiB (%d do %d, privzeto: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Ime datoteke z denarnico (znotraj podatkovne mape)</translation>
- </message>
- <message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Uporabi protokol UPnP za preslikavo vrat za poslušanje (privzeto: %u)</translation>
- </message>
- <message>
<source>Verifying blocks...</source>
<translation>Preverjam celovitost blokov ...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Izbire denarnice:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Iz navedenega vira dovoli povezave na JSON-RPC. Veljavne oblike vrednosti parametra &lt;ip&gt; so: edinstven naslov IP (npr.: 1.2.3.4), kombinacija omrežje/netmask (npr.: 1.2.3.4/255.255.255.0), ali pa kombinacija omrežje/CIDR (1.2.3.4/24). To opcijo lahko navedete večkrat.</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Veži dani naslov in sprejemaj povezave samo od navedenih soležnikov. Za naslove protokola IPv6 uporabite zapis [gostitelj]:vrata.</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Ustvarjaj nove datoteke s privzetimi sistemskimi dovoljenji, namesto z umask 077. (To pride v poštev samo, kadar imate izklopljeno funkcijo denarnice.)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Odkrij svoj naslov IP (privzeto: 1, če poslušate in sta opciji -externalip in -proxy neaktivni)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Napaka: Ni mogoče sprejemati dohodnih povezav (vrnjena napaka: %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Ko bo prejeto ustrezno opozorilo, ali ko bo opažena zelo dolga razvejitev, izvedi navedeni ukazni niz. (Niz %s bo nadomeščen z vsebino sporočila.)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Če opcija -paytxfee ni nastavljena, nastavi znesek provizije tako visoko, da bodo transakcije potrjene v povprečno n blokih. (privzeto: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Na vsak posredniški strežnik se prijavi z drugimi naključnimi podatki. Tako je omogočena osamitev tokov v omrežju Tor (privzeto: %u)</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(privzeto: %u)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Poveži se preko posredniškega strežnika SOCKS5</translation>
- </message>
- <message>
<source>Information</source>
<translation>Informacije</translation>
</message>
@@ -1818,14 +1846,6 @@
<translation>Pri opciji -whitebind morate navesti vrata: %s</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Pošilja sledilne/razhroščevalne informacije na konzolo namesto v datoteko debug.log</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Ob zagonu skrajšaj datoteko debug.log (privzeto: 1, če ni vklopljena opcija -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Transakcije ni bilo mogoče podpisati.</translation>
</message>
@@ -1846,10 +1866,6 @@
<translation>Na tem računalniku ni bilo mogoče vezati naslova %s (vrnjena napaka: %s)</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>Uporabniško ime za povezave na JSON-RPC</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Opozorilo</translation>
</message>
@@ -1858,48 +1874,8 @@
<translation>Brišem vse transakcije iz denarnice ...</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Geslo za povezave na JSON-RPC</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Izvedi ukaz, ko je najden najboljši blok (niz %s v ukazu bo zamenjan s hash vrednostjo bloka)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Omogoči poizvedbe DNS za opcije -addnode, -seednode in -connect.</translation>
- </message>
- <message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Za dostop do soležnikov preko skritih storitev Tor uporabi drug posredniški strežnik SOCKS5 (privzeto: %s)</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(privzeto: %s)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Posreduj transakcije tipa multisig, ki niso hkrati tipa P2SH. (privzeto: %u)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Za shranjevanje konfiguracije uporabi navedeno datoteko. (privzeto: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Vzpostavljanje nove povezave poteče po navedenem št. pretečenih milisekund. (najmanj: 1, privzeto: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Za shranjevanje PID uporabi navedeno datoteko. (privzeto: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Pri odlivnih transakcijah omogoči trošenje drobiža iz še nepotrjenih plačil (privzeto: %u)</translation>
- </message>
- <message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Prekini povezavo s soležnikom, ko št. njegovih kazenskih točk preseže navedeni prag. (privzeto: %u)</translation>
+ <source>Transaction must have at least one recipient</source>
+ <translation>Transakcija mora imeti vsaj enega prejemnika.</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
diff --git a/src/qt/locale/bitcoin_sn.ts b/src/qt/locale/bitcoin_sn.ts
new file mode 100644
index 0000000000..895962cb45
--- /dev/null
+++ b/src/qt/locale/bitcoin_sn.ts
@@ -0,0 +1,367 @@
+<TS language="sn" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Create a new address</source>
+ <translation>Gadzira Kero Itsva</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>Itsva</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Kopera</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>Vhara</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>Dzima</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Makero ekutumira</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Makero ekutambira</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>Kopera Kero</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Gadzirisa</translation>
+ </message>
+ </context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Zita</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Kero</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(hapana zita)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ </context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>Banned Until</source>
+ <translation>Wakavharirwa Kusvika</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>Buda</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Vhara Application</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;Kuma %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Taridza ruzivo rwekuma %1</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Taridza ruzivo rwe Qt</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses...</source>
+ <translation>&amp;Makero ekutumira nawo</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses...</source>
+ <translation>&amp;Makero ekutambira nawo</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Vhura &amp;URI</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Chikwama</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;Tumira</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Tambira</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Taridza/Usataridza</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;Faira</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>&amp;Rubatsiro</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 kumashure</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Hokoyo</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Ruzivo</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Amount</source>
+ <translation>Marii </translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Zuva</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(hapana zita)</translation>
+ </message>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Marii </translation>
+ </message>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Nyora kero ye Bitcoin (sekuti %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 d</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 h</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 m</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 s</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>Hapana</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>Hapana </translation>
+ </message>
+ </context>
+<context>
+ <name>QObject::QObject</name>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>N/A</source>
+ <translation>Hapana </translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Address</source>
+ <translation>Kero</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Marii </translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Zita</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Chikwama</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Zuva</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Zita</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(hapana zita)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>(no label)</source>
+ <translation>(hapana zita)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ </context>
+<context>
+ <name>SendConfirmationDialog</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ </context>
+<context>
+ <name>SplashScreen</name>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation>Zuva</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Marii </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Zuva</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Zita</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(hapana zita)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Date</source>
+ <translation>Zuva</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Zita</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Kero</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ </context>
+<context>
+ <name>WalletView</name>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Information</source>
+ <translation>Ruzivo</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Hokoyo</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts
index ecffc2df0a..b550f20541 100644
--- a/src/qt/locale/bitcoin_sq.ts
+++ b/src/qt/locale/bitcoin_sq.ts
@@ -38,6 +38,14 @@
<translation>Zgjidh adresen ku do te dergoni monedhat</translation>
</message>
<message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Zgjidh adresën ku do të merrni monedhat</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>Zgjidh</translation>
+ </message>
+ <message>
<source>Sending addresses</source>
<translation>Duke derguar adresen</translation>
</message>
@@ -101,15 +109,19 @@
<name>AskPassphraseDialog</name>
<message>
<source>Enter passphrase</source>
- <translation>Futni frazkalimin</translation>
+ <translation>Futni fjalëkalimin</translation>
</message>
<message>
<source>New passphrase</source>
- <translation>Frazkalim i ri</translation>
+ <translation>Fjalëkalimi i ri</translation>
</message>
<message>
<source>Repeat new passphrase</source>
- <translation>Përsërisni frazkalimin e ri</translation>
+ <translation>Përsërisni fjalëkalimin e ri</translation>
+ </message>
+ <message>
+ <source>Show password</source>
+ <translation>Trego fjalëkalimin</translation>
</message>
<message>
<source>Encrypt wallet</source>
@@ -117,11 +129,11 @@
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Ky veprim ka nevojë per frazkalimin e portofolit tuaj që të ç'kyç portofolin.</translation>
+ <translation>Ky veprim ka nevojë per fjalëkalimin e portofolit tuaj që të hapë portofolin.</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation>ç'kyç portofolin.</translation>
+ <translation>Hap portofolin.</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
@@ -133,7 +145,11 @@
</message>
<message>
<source>Change passphrase</source>
- <translation>Ndrysho frazkalimin</translation>
+ <translation>Ndrysho fjalëkalimin</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Fusni fjalëkalimin e vjetër dhe fjalëkalimin e ri që të hapni portofolin.</translation>
</message>
<message>
<source>Confirm wallet encryption</source>
@@ -336,10 +352,6 @@
<translation>&amp;Adresa</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Adresë e re pritëse</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Adresë e re dërgimi</translation>
</message>
@@ -352,10 +364,6 @@
<translation>ndrysho adresën dërguese</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Adresa e dhënë "%1" është e zënë në librin e adresave. </translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Nuk mund të ç'kyçet portofoli.</translation>
</message>
@@ -504,6 +512,10 @@
<source>Label</source>
<translation>Etiketë</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Portofol</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -640,10 +652,6 @@
<translation>%1 konfirmimet</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, nuk është transmetuar me sukses deri tani</translation>
- </message>
- <message>
<source>Date</source>
<translation>Data</translation>
</message>
@@ -690,10 +698,6 @@
<translation>I/E konfirmuar(%1 konfirmime)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Ky bllok është marrë nga ndonjë nyje dhe ka shumë mundësi të mos pranohet! </translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>I krijuar por i papranuar</translation>
</message>
@@ -788,10 +792,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opsionet:</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Berthama Bitcoin</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts
index e432f1d334..c6c6a07700 100644
--- a/src/qt/locale/bitcoin_sr.ts
+++ b/src/qt/locale/bitcoin_sr.ts
@@ -3,71 +3,127 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Desni klik za izmenu adrese ili oznake</translation>
+ <translation>Десни клик за измену адресе или ознаке</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>Napravite novu adresu</translation>
+ <translation>Направите нову адресу</translation>
</message>
<message>
<source>&amp;New</source>
- <translation>Novo</translation>
+ <translation>&amp;Ново</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>Kopirajte trenutno izabranu adresu</translation>
+ <translation>Копирај тренутно одабрану адресу</translation>
</message>
<message>
<source>&amp;Copy</source>
- <translation>Kopirajte</translation>
+ <translation>&amp;Копирај</translation>
</message>
<message>
<source>C&amp;lose</source>
- <translation>Zatvorite</translation>
+ <translation>&amp;Затвори</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>Izbrisite trenutno izabranu adresu sa liste</translation>
+ <translation>Обришите тренутно одабрану адресу са листе</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Navedite adresu ili naziv koji bi ste potražili</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>Eksportuj podatke iz izabrane kartice u fajl</translation>
+ <translation>Извези податке из одабране картице у фајлj</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation>&amp;Izvedi</translation>
+ <translation>&amp;Извези</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation>&amp;Izbriši</translation>
+ <translation>&amp;Обриши</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Izbirajte adresu za slanje</translation>
+ <translation>Изаберите адресу за слање</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>Izbirajte adresu za primanje</translation>
+ <translation>Изаберите адресу за примање</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>&amp;Изабери</translation>
</message>
<message>
<source>Sending addresses</source>
- <translation>Adresa za slanje</translation>
+ <translation>Адресе за слање</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation>Adresa za primanje</translation>
+ <translation>Адресе за примање</translation>
</message>
- </context>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Ово су ваше Биткоин адресе за слање уплата. Увек добро проверите износ и адресу на коју шаљете пре него што пошаљете уплату.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Ово су ваше Биткоин адресе за примање уплате. Препоручује се да се за сваку трансакцију користи нова адреса.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Копирај Адресу</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Копирај &amp; Обележи</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Измени</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Извези Листу Адреса</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Зарезом одвојене вредности (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Извоз Неуспешан</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Десила се грешка приликом покушаја да се листа адреса упамти на %1. Молимо покушајте поново.</translation>
+ </message>
+</context>
<context>
<name>AddressTableModel</name>
<message>
+ <source>Label</source>
+ <translation>Етикета</translation>
+ </message>
+ <message>
<source>Address</source>
- <translation>Adresa</translation>
+ <translation>Адреса</translation>
</message>
- </context>
+ <message>
+ <source>(no label)</source>
+ <translation>(без етикете)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
+ <source>Passphrase Dialog</source>
+ <translation>Прозор за унос лозинке</translation>
+ </message>
+ <message>
<source>Enter passphrase</source>
<translation>Унесите лозинку</translation>
</message>
@@ -79,13 +135,117 @@
<source>Repeat new passphrase</source>
<translation>Поновите нову лозинку</translation>
</message>
- </context>
+ <message>
+ <source>Show password</source>
+ <translation>Прикажи лозинку</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Унесите нову лозинку за приступ новчанику. &lt;br/&gt;Молимо да користите лозинку од &lt;b&gt;десет или више насумично одабраних карактера, или &lt;b&gt;осам или више речи&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Шифрирај новчаник</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Ова операција захтева да унесете лозинку новчаника како би откључали новчаник.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Откључај новчаник</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Ова операција захтева да унесете лозинку новчаника како би дешифровали новчаник.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Дешифруј новчаник</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Измену лозинку</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Унеси стару лозинку и нову лозинку новчаника.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Потврди шифрирање новчаника</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Упозорење: Уколико шифрирате новчаник и изгубите своју лозинку, &lt;b&gt;ИЗГУБИЋЕТЕ СВЕ СВОЈЕ БИТКОИНЕ&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Да ли сте сигурни да желите да шифрирате свој новчаник?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Новчаник шифриран</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 ће се сада затворити како би се завршио процес шифрирања. Запамтите да шифрирањем свог новчаника не можете у потпуности заштити своје биткоине од крађе од стране злоћудних програма и компјутерских инфекција.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>ВАЖНО: Свакa претходнa резерва новчаника коју сте имали треба да се замени новим, шифрираним фајлом новчаника. Из сигурносних разлога, свака претходна резерва нешифрираног фајла новчаника постаће сувишна, чим почнете да користите нови, шифрирани новчаник.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Шифрирање новчаника неуспешно.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Шифрирање новчаника није успело због интерне грешке. Ваш новчаник није шифриран.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Лозинке које сте унели нису исте.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Отључавање новчаника није успело.</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Лозинка коју сте унели за дешифровање новчаника је погрешна.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Дешифровање новчаника неуспешно.</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Лозинка новчаника успешно је промењена.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Упозорање Caps Lock дугме укључено.</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
- </context>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>ИП/Нетмаск</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Забрањен до</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
+ <source>Sign &amp;message...</source>
+ <translation>Потпиши &amp;поруку...</translation>
+ </message>
+ <message>
<source>Synchronizing with network...</source>
<translation>Синхронизација са мрежом у току...</translation>
</message>
@@ -94,6 +254,10 @@
<translation>&amp;Општи преглед</translation>
</message>
<message>
+ <source>Node</source>
+ <translation>Ноде</translation>
+ </message>
+ <message>
<source>Show general overview of wallet</source>
<translation>Погледајте општи преглед новчаника</translation>
</message>
@@ -107,13 +271,21 @@
</message>
<message>
<source>E&amp;xit</source>
- <translation>I&amp;zlaz</translation>
+ <translation>И&amp;злаз</translation>
</message>
<message>
<source>Quit application</source>
<translation>Напустите програм</translation>
</message>
<message>
+ <source>&amp;About %1</source>
+ <translation>&amp;О %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Прикажи информације о %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>О &amp;Qt-у</translation>
</message>
@@ -126,34 +298,126 @@
<translation>П&amp;оставке...</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Измени конфигурацију поставки за %1</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Шифровање новчаника...</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>&amp;Backup новчаника</translation>
+ <translation>&amp;Резерна копија новчаника</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
<translation>Промени &amp;лозинку...</translation>
</message>
<message>
+ <source>&amp;Sending addresses...</source>
+ <translation>&amp;Адресе за слање...</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses...</source>
+ <translation>&amp;Адресе за пријем</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Отвори &amp;УРИ...</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Новчаник</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>подразумевани новчаник</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Кликни да искључиш активност на мрежи.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Активност на мрежи искључена.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Кликни да поново омогућиш активност на мрежи.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Синхронизовање Заглавља (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Поново идексирање блокова на диску.</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Прокси је &lt;b&gt;омогућен&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
- <translation>Пошаљите новац на bitcoin адресу</translation>
+ <translation>Пошаљите новац на Биткоин адресу</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>Направите резервну копију новчаника на другој локацији</translation>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
<translation>Мењање лозинке којом се шифрује новчаник</translation>
</message>
<message>
+ <source>&amp;Debug window</source>
+ <translation>&amp;Прозор за отклањање грешке</translation>
+ </message>
+ <message>
+ <source>Open debugging and diagnostic console</source>
+ <translation>Отвори конзолу за отклањање грешака и дијагностику</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Верификовање поруке...</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Биткоин</translation>
+ </message>
+ <message>
<source>Wallet</source>
- <translation>новчаник</translation>
+ <translation>Новчаник</translation>
</message>
<message>
<source>&amp;Send</source>
<translation>&amp;Пошаљи</translation>
</message>
<message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Прими</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Прикажи / Сакриј</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Прикажи или сакрији главни прозор</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Шифрирај приватни клуљ који припада новчанику.</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Потписуј поруку са своје Биткоин адресе као доказ да си њихов власник</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Верификуј поруке и утврди да ли су потписане од стране спецификованих Биткоин адреса</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Фајл</translation>
</message>
@@ -163,25 +427,125 @@
</message>
<message>
<source>&amp;Help</source>
- <translation>П&amp;омоћ</translation>
+ <translation>&amp;Помоћ</translation>
</message>
<message>
<source>Tabs toolbar</source>
<translation>Трака са картицама</translation>
</message>
<message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Затражи плаћање (генерише QR кодове и биткоин: URI-е)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Прегледајте листу коришћених адреса и етикета за слање уплата</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Прегледајте листу коришћених адреса и етикета за пријем уплата</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI or payment request</source>
+ <translation>Отворите биткоин: URI или захтев за плаћање</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>&amp;Опције командне линије</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n aктивна веза са Биткоин мрежом</numerusform><numerusform>%n aктивних веза са Биткоин мрежом</numerusform><numerusform>%n aктивних веза са Биткоин мрежом</numerusform></translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Идексирање блокова на диску...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Обрада блокова на диску...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Обрађенo %n блокова историјата трансакција.</numerusform><numerusform>Обрађенo %n блокова историјата трансакција.</numerusform><numerusform>Обрађенo је %n блокова историјата трансакција.</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 уназад</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Последњи примљени блок је направљен пре %1.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Трансакције након овога још неће бити видљиве.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Greška</translation>
</message>
<message>
+ <source>Warning</source>
+ <translation>Упозорење</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Информације</translation>
+ </message>
+ <message>
<source>Up to date</source>
<translation>Ажурно</translation>
</message>
<message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Прикажи поруку помоћи %1 за листу са могућим опцијама Биткоин командне линије</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 клијент</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Ажурирање у току...</translation>
</message>
<message>
+ <source>Date: %1
+</source>
+ <translation>Датум: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Износ: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>Новчаник: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Тип: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Етикета: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Адреса: %1
+</translation>
+ </message>
+ <message>
<source>Sent transaction</source>
<translation>Послана трансакција</translation>
</message>
@@ -190,6 +554,14 @@
<translation>Придошла трансакција</translation>
</message>
<message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>Генерисање ХД кључа је &lt;b&gt;омогућено&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Генерисање ХД кључа је &lt;b&gt;онеомогућено&lt;/b&gt;</translation>
+ </message>
+ <message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>Новчаник јс &lt;b&gt;шифрован&lt;/b&gt; и тренутно &lt;b&gt;откључан&lt;/b&gt;</translation>
</message>
@@ -197,26 +569,143 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Новчаник јс &lt;b&gt;шифрован&lt;/b&gt; и тренутно &lt;b&gt;закључан&lt;/b&gt;</translation>
</message>
- </context>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Дошло је до критичне грешке. Биткоин не може безбедно да настави са радом и искључиће се.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation>Избор новчића</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Количина:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Бајта:</translation>
+ </message>
+ <message>
<source>Amount:</source>
- <translation>Iznos:</translation>
+ <translation>Износ:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Накнада:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Прашина:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Након накнаде:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Промени:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>изаберите / поништите све
+</translation>
</message>
<message>
<source>Amount</source>
- <translation>iznos</translation>
+ <translation>Износ</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>Примљено са етикетом</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Примљено са адресом</translation>
</message>
<message>
<source>Date</source>
<translation>datum</translation>
</message>
<message>
+ <source>Confirmations</source>
+ <translation>Потврде</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation>Potvrdjen</translation>
</message>
- </context>
+ <message>
+ <source>Copy address</source>
+ <translation>Копирај адресу</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Копирај налепницу</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Копирај износ</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Копирај идентификациони број трансакције</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Закључај непотрошено</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Откључај непотрошено</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Копирај количину</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Копирај провизију</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Копирај након провизије</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Копирај бајтове</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Копирај прашину</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Копирај промену</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 закључан)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>да</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>не</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(без налепнице)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(промени)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -228,13 +717,61 @@
<translation>&amp;Етикета</translation>
</message>
<message>
+ <source>The label associated with this address list entry</source>
+ <translation>Етикета повезана са овом ставком из листе адреса</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>Адреса повезана са овом ставком из листе адреса. Ово можете променити једини у случају адреса за плаћање.</translation>
+ </message>
+ <message>
<source>&amp;Address</source>
<translation>&amp;Адреса</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Нова адреса за слање</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Измени адресу за примање</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Измени адресу за слање</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Новчаник није могуће откључати.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Генерисање новог кључа није успело.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
- </context>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>Нови директоријум података ће бити креиран.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>име</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Директоријум већ постоји. Додајте %1 ако намеравате да креирате нови директоријум овде.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>Путања већ постоји и није директоријум.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>Не можете креирати директоријум података овде.</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
<message>
@@ -242,13 +779,57 @@
<translation>верзија</translation>
</message>
<message>
- <source>Usage:</source>
- <translation>Korišćenje:</translation>
+ <source>(%1-bit)</source>
+ <translation>(%1-bit)</translation>
</message>
- </context>
+ <message>
+ <source>About %1</source>
+ <translation>Приближно %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>Опције командне линије</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
<message>
+ <source>Welcome</source>
+ <translation>Добродошли</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation>Добродошли на %1.</translation>
+ </message>
+ <message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation>Пошто је ово први пут да је програм покренут, можете изабрати где ће %1 чувати своје податке.</translation>
+ </message>
+ <message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>Када кликнете на ОК, %1 ће почети с преузимањем и процесирањем целокупног ланца блокова %4 (%2GB), почевши од најранијих трансакција у %3 када је %4 покренут.</translation>
+ </message>
+ <message>
+ <source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
+ <translation>Ова иницијална синхронизација је веома захтевна и може изложити ваш рачунар хардверским проблемима који раније нису били примећени. Сваки пут када покренете %1, преузимање ће се наставити тамо где је било прекинуто.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>Ако сте одлучили да ограничите складиштење ланаца блокова (тримовање), историјски подаци се ипак морају преузети и обрадити, али ће након тога бити избрисани како би се ограничила употреба диска.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>Користите подразумевани директоријум података</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>Користите прилагођени директоријум података:</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Биткоин</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Greška</translation>
</message>
@@ -259,6 +840,30 @@
<source>Form</source>
<translation>Форма</translation>
</message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Остала количина блокова</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Непознато...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Време последњег блока</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>Напредак</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>Рачунање</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Сакриј</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -270,16 +875,40 @@
<translation>Поставке</translation>
</message>
<message>
+ <source>Open Configuration File</source>
+ <translation>Отвори Конфигурациону Датотеку</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation>новчаник</translation>
</message>
<message>
+ <source>Expert</source>
+ <translation>Експерт</translation>
+ </message>
+ <message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Тор</translation>
+ </message>
+ <message>
<source>&amp;Unit to show amounts in:</source>
<translation>&amp;Јединица за приказивање износа:</translation>
</message>
<message>
<source>&amp;OK</source>
- <translation>&amp;OK</translation>
+ <translation>&amp;Уреду</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>&amp;Откажи</translation>
</message>
<message>
<source>Error</source>
@@ -292,6 +921,18 @@
<source>Form</source>
<translation>Форма</translation>
</message>
+ <message>
+ <source>Available:</source>
+ <translation>Доступно:</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>На чекању:</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Укупно:</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -319,6 +960,14 @@
<context>
<name>RPCConsole</name>
<message>
+ <source>Last block time</source>
+ <translation>Време последњег блока</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>подразумевани новчаник</translation>
+ </message>
+ <message>
<source>Yes</source>
<translation>Da</translation>
</message>
@@ -345,7 +994,16 @@
<source>Show</source>
<translation>Prikaži</translation>
</message>
- </context>
+ <message>
+ <source>Copy label</source>
+ <translation>Копирај налепницу
+</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>к</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
@@ -356,9 +1014,29 @@
<source>Address</source>
<translation>Adresa</translation>
</message>
+ <message>
+ <source>Amount</source>
+ <translation>Износ</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Налепница</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Новчаник</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Налепница</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(без налепнице)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -367,10 +1045,38 @@
<translation>Слање новца</translation>
</message>
<message>
+ <source>Quantity:</source>
+ <translation>Количина:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Бајта:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>Iznos:</translation>
</message>
<message>
+ <source>Fee:</source>
+ <translation>Накнада:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Након накнаде:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Промени:</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Сакриј</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Прашина:</translation>
+ </message>
+ <message>
<source>Confirm the send action</source>
<translation>Потврди акцију слања</translation>
</message>
@@ -378,7 +1084,35 @@
<source>S&amp;end</source>
<translation>&amp;Пошаљи</translation>
</message>
- </context>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Копирај количину</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>к</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Копирај провизију</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Копирај бајтове</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Копирај прашину</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Копирај промену</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(без налепнице)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
<message>
@@ -435,6 +1169,10 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message>
+ <source>Amount</source>
+ <translation>Износ</translation>
+ </message>
</context>
<context>
<name>TransactionDescDialog</name>
@@ -445,13 +1183,50 @@
</context>
<context>
<name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Налепница</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(без налепнице)</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
<message>
+ <source>Copy address</source>
+ <translation>Копирај адресу</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Копирај налепницу
+</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>к</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Копирај идентификациони број трансакције</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Фајл раздојен тачком (*.csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Налепница</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>Adresa</translation>
</message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Извоз Неуспешан</translation>
+ </message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
@@ -468,32 +1243,20 @@
<source>&amp;Export</source>
<translation>&amp;Izvedi</translation>
</message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Извези податке из одабране картице у фајлj</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Opcije</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Gde je konkretni data direktorijum </translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Prihvati komandnu liniju i JSON-RPC komande</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Radi u pozadini kao daemon servis i prihvati komande</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Korisničko ime za JSON-RPC konekcije</translation>
+ <source>Information</source>
+ <translation>Информације</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>Lozinka za JSON-RPC konekcije</translation>
+ <source>Warning</source>
+ <translation>Упозорење</translation>
</message>
<message>
<source>Insufficient funds</source>
diff --git a/src/qt/locale/bitcoin_sr@latin.ts b/src/qt/locale/bitcoin_sr@latin.ts
index 30c14de0a1..6e4e5933ea 100644
--- a/src/qt/locale/bitcoin_sr@latin.ts
+++ b/src/qt/locale/bitcoin_sr@latin.ts
@@ -582,6 +582,10 @@
<source>Label</source>
<translation>Oznaka</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Novčanik</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -613,6 +617,10 @@
<translation>Nakon Naknade:</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Taksa transakcije</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(bez oznake)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts
index 39d9be2505..405cde3c99 100644
--- a/src/qt/locale/bitcoin_sv.ts
+++ b/src/qt/locale/bitcoin_sv.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Högerklicka för att ändra adressen eller etiketten.</translation>
+ <translation>Högerklicka för att redigera adressen eller etiketten.</translation>
</message>
<message>
<source>Create a new address</source>
@@ -30,8 +30,12 @@
<translation>Ta bort den valda adressen från listan</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Ange en adress eller etikett att söka efter</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
- <translation>Exportera informationen i den nuvarande fliken till en fil</translation>
+ <translation>Exportera informationen i aktuell flik till en fil</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -43,11 +47,11 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Välj en adress att sända betalning till</translation>
+ <translation>Välj en adress att skicka transaktionen till</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>Välj en adress att ta emot betalning till</translation>
+ <translation>Välj en adress att ta emot transaktionen med</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -63,11 +67,11 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>Detta är dina Bitcoin adresser för att skicka betalningar. Kolla alltid summan och den mottagande adressen innan du skickar Bitcoins.</translation>
+ <translation>Detta är dina Bitcoin-adresser för att skicka betalningar. Kontrollera alltid summan och den mottagande adressen innan du skickar bitcoin.</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>Detta är dina Bitcoin adresser för att ta emot betalningar. Det rekommenderas att använda en ny mottagningsadress för varje transaktion.</translation>
+ <translation>Detta är dina Bitcoin-adresser för att ta emot betalningar. Det rekommenderas att använda en ny mottagningsadress för varje transaktion.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -95,7 +99,7 @@
</message>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>Det inträffade ett fel när adresslistan skulle sparas till %1.
+ <translation>Ett fel inträffade när adresslistan skulle sparas till %1.
Var vänlig och försök igen.</translation>
</message>
</context>
@@ -133,6 +137,10 @@ Var vänlig och försök igen.</translation>
<translation>Upprepa nytt lösenord</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Visa lösenord</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Ange plånbokens nya lösenord. &lt;br/&gt; Använd ett lösenord på &lt;b&gt;tio eller fler slumpmässiga tecken,&lt;/b&gt; eller &lt;b&gt;åtta eller fler ord.&lt;/b&gt;.</translation>
</message>
@@ -182,11 +190,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 kommer nu att stänga ner för att färdigställa krypteringen. Tänk på att en krypterad plånbok inte skyddar mot stöld om din dator är infekterad med en keylogger.</translation>
+ <translation>%1 kommer nu att stänga ner för att slutföra krypteringen. Tänk på att en krypterad plånbok inte skyddar mot stöld om din dator är infekterad med en keylogger.</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation>VIKTIGT: Alla tidigare säkerhetskopior du har gjort av plånboksfilen ska ersättas med den nya genererade, krypterade plånboksfilen. Av säkerhetsskäl kommer tidigare säkerhetskopior av den okrypterade plånboksfilen blir oanvändbara när du börjar använda en ny, krypterad plånbok.</translation>
+ <translation>VIKTIGT: Alla tidigare säkerhetskopior du har skapat av plånboksfilen ska ersättas med den nyss skapade, krypterade plånboksfilen. Av säkerhetsskäl kommer tidigare säkerhetskopior av den okrypterade plånboksfilen att bli oanvändbara när du börjar använda den nya, krypterade plånboken.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
@@ -194,7 +202,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>Kryptering av plånbok misslyckades på grund av ett internt fel. Din plånbok blev inte krypterad.</translation>
+ <translation>Kryptering av plånbok misslyckades på grund av ett internt fel. Din plånbok krypterades inte.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
@@ -206,7 +214,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>Lösenordet för dekryptering av plånboken var felaktig.</translation>
+ <translation>Lösenordet för dekryptering av plånboken var felaktigt.</translation>
</message>
<message>
<source>Wallet decryption failed</source>
@@ -214,7 +222,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation>Plånbokens lösenord har ändrats.</translation>
+ <translation>Plånbokens lösenord ändrades.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
@@ -304,7 +312,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
- <translation>&amp;Byt lösenord...</translation>
+ <translation>&amp;Ändra lösenord...</translation>
</message>
<message>
<source>&amp;Sending addresses...</source>
@@ -319,6 +327,14 @@ Var vänlig och försök igen.</translation>
<translation>Öppna &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Plånbok:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Standardplånbok</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Klicka för att inaktivera nätverksaktivitet.</translation>
</message>
@@ -339,8 +355,12 @@ Var vänlig och försök igen.</translation>
<translation>Återindexerar block på disken...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy är &lt;b&gt; aktiverad &lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
- <translation>Skicka bitcoins till en Bitcoin-adress</translation>
+ <translation>Skicka bitcoin till en Bitcoin-adress</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -392,11 +412,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Signera meddelanden med din Bitcoin-adress för att bevisa att du äger dem</translation>
+ <translation>Signera meddelanden med dina Bitcoin-adresser för att bevisa att du äger dem</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Verifiera meddelanden för att vara säker på att de var signerade med specificerade Bitcoin-adresser</translation>
+ <translation>Verifiera meddelanden för att vara säker på att de signerades med angivna Bitcoin-adresser</translation>
</message>
<message>
<source>&amp;File</source>
@@ -416,15 +436,15 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation>Begär betalning (genererar QR-koder och bitcoin-URI)</translation>
+ <translation>Begär betalningar (skapar QR-koder och bitcoin: -URIer)</translation>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
- <translation>Visa listan av använda avsändaradresser och etiketter</translation>
+ <translation>Visa listan med använda avsändaradresser och etiketter</translation>
</message>
<message>
<source>Show the list of used receiving addresses and labels</source>
- <translation>Visa listan av använda mottagningsadresser och etiketter</translation>
+ <translation>Visa listan med använda mottagningsadresser och etiketter</translation>
</message>
<message>
<source>Open a bitcoin: URI or payment request</source>
@@ -456,7 +476,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
- <translation>Senast mottagna block genererades för %1 sen.</translation>
+ <translation>Senast mottagna block skapades för %1 sedan.</translation>
</message>
<message>
<source>Transactions after this will not yet be visible.</source>
@@ -507,6 +527,12 @@ Var vänlig och försök igen.</translation>
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Plånbok: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Typ: %1
@@ -685,7 +711,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>Denna etikett blir röd om någon mottagare får en betalning som är mindre än aktuella dammtröskeln.</translation>
+ <translation>Denna etikett blir röd om någon mottagare får en betalning som är mindre än aktuell dammtröskel.</translation>
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
@@ -716,21 +742,17 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>The label associated with this address list entry</source>
- <translation>Etiketten associerad med denna adresslistas post</translation>
+ <translation>Etiketten associerad med denna post i adresslistan</translation>
</message>
<message>
<source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>Adressen associerad med denna adresslistas post. Detta kan bara ändras för sändningsadresser.</translation>
+ <translation>Adressen associerad med denna post i adresslistan. Den kan bara ändras för sändningsadresser.</translation>
</message>
<message>
<source>&amp;Address</source>
<translation>&amp;Adress</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Ny mottagaradress</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Ny avsändaradress</translation>
</message>
@@ -747,8 +769,12 @@ Var vänlig och försök igen.</translation>
<translation>Den angivna adressen "%1" är inte en giltig Bitcoin-adress.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Den angivna adressen "%1" finns redan i adressboken.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adress "%1" finns redan som en mottagande adress med etikett "%2" och kan därför anges som utgående adress.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Den angivna adressen "%1" finns redan i adressboken med etikett "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -800,42 +826,6 @@ Var vänlig och försök igen.</translation>
<source>Command-line options</source>
<translation>Kommandoradsalternativ</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Användning:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>kommandoradsalternativ</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>UI-inställningar:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Välj datakatalog vid uppstart (standard: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Ange språk, till exempel "de_DE" (standard: systemspråk)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Starta minimerad</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Ange SSL rotcertifikat för betalningsansökan (standard: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Visa startbild vid uppstart (standard: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Återställ alla inställningar som gjorts i GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -852,10 +842,18 @@ Var vänlig och försök igen.</translation>
<translation>Eftersom detta är första gången programmet startas får du välja var %1 skall lagra sitt data.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>När du trycker OK kommer %1 påbörja nedladdning och bearbetning av den fulla %4-blockkedjan (%2GB), med start vid de första transaktionerna i %3 när %4 först lanserades.</translation>
+ </message>
+ <message>
<source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
<translation>Denna första synkronisering är väldigt krävande, och kan påvisa hårdvaruproblem med din dator som tidigare inte visats sig. Varje gång du kör %1, kommer nerladdningen att fortsätta där den avslutades.</translation>
</message>
<message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>Om du valt att begränsa storleken på blockkedjan (pruning), måste historisk data fortfarande bli nedladdad och processerad, men kommer bli borttagen för att minimera hårddiskutrymme.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>Använd den förvalda datakatalogen</translation>
</message>
@@ -877,7 +875,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 kommer att hämta och lagra en kopia av Bitcoin-blockkedjan.</translation>
+ <translation>%1 kommer att ladda ner och lagra en kopia av Bitcoin-blockkedjan.</translation>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
@@ -885,7 +883,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
- <translation>Fel: Den angivna datakatalogen "%1" kan inte skapas.</translation>
+ <translation>Fel: Angiven datakatalog "%1" kan inte skapas.</translation>
</message>
<message>
<source>Error</source>
@@ -908,11 +906,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation>Nyligen gjorda transaktioner visas inte korrekt och därför kan din plånboks saldo visas felaktigt. Denna information kommer att visas korrekt så snart din plånbok har synkroniserat klart med bitcoin nätverket enligt detaljer nedan.</translation>
+ <translation>Nyligen gjorda transaktioner visas inte korrekt och därför kan din plånboks saldo visas felaktigt. Denna information kommer att visas korrekt så snart din plånbok har synkroniserat klart med Bitcoin-nätverket enligt detaljer nedan.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation>Försöka sig på att spendera bitcoins som påverkas av transaktioner som ännu inte visas kommer inte bli accepterade av nätverket. </translation>
+ <translation>Att försöka spendera bitcoin som påverkas av transaktioner som ännu inte visas kommer inte accepteras av nätverket. </translation>
</message>
<message>
<source>Number of blocks left</source>
@@ -971,7 +969,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Select payment request file to open</source>
- <translation>Välj betalningsförfrågningsfil som ska öppnas</translation>
+ <translation>Välj betalningsbegäransfil som ska öppnas</translation>
</message>
</context>
<context>
@@ -1013,6 +1011,18 @@ Var vänlig och försök igen.</translation>
<translation>Visas, om den angivna standard-SOCKS5-proxyn används för att nå noder via den här nätverkstypen.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Använd separata SOCKS&amp;5-proxy för att nå noder via Tors dolda tjänster:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Göm ikonen från aktivitetsfältet.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Göm ikonen</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Minimera istället för att stänga programmet när fönstret stängs. När detta alternativ är aktiverat stängs programmet endast genom att välja Stäng i menyn.</translation>
</message>
@@ -1045,6 +1055,22 @@ Var vänlig och försök igen.</translation>
<translation>&amp;Nätverk</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Stänger av en del avancerade funktioner, men samtliga block kommer fortfarande verifieras. Vid avstängning av denna inställning kommer den fullständiga blockkedjan behövas laddas ned igen. Det använda hårddiskutrymmet kan öka något.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Trim- &amp; block-utrymme till</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Vid avstängning av denna inställning kommer den fullständiga blockkedjan behövas laddas ned igen.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = auto, &lt;0 = lämna så många kärnor lediga)</translation>
</message>
@@ -1062,7 +1088,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
- <translation>Om du avaktiverar betalning med obekräftad växel, kan inte växeln från en transaktion användas förrän den transaktionen har minst en bekräftelse.</translation>
+ <translation>Om du avaktiverar spendering av obekräftad växel, kan inte växeln från en transaktion användas förrän transaktionen har minst en bekräftelse. Detta påverkar också hur ditt saldo beräknas.</translation>
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
@@ -1070,13 +1096,21 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
- <translation>Öppna automatiskt Bitcoin-klientens port på routern. Detta fungerar endast om din router har UPnP aktiverat.</translation>
+ <translation>Öppna automatiskt Bitcoin-klientens port på routern. Detta fungerar endast om din router stödjer UPnP och det är är aktiverat.</translation>
</message>
<message>
<source>Map port using &amp;UPnP</source>
<translation>Tilldela port med hjälp av &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Acceptera anslutningar utifrån.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Tillåt ankommande anslutningar</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Anslut till Bitcoin-nätverket genom en SOCKS5-proxy.</translation>
</message>
@@ -1157,6 +1191,10 @@ Var vänlig och försök igen.</translation>
<translation>Om myntkontrollfunktioner skall visas eller inte</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;URL:er för tredjepartstransaktioner</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1245,11 +1283,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Mined balance that has not yet matured</source>
- <translation>Den genererade balansen som ännu inte har mognat</translation>
+ <translation>Genererat saldo som ännu inte har mognat</translation>
</message>
<message>
<source>Balances</source>
- <translation>Balanser</translation>
+ <translation>Saldon</translation>
</message>
<message>
<source>Total:</source>
@@ -1257,11 +1295,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Your current total balance</source>
- <translation>Ditt nuvarande totala saldo</translation>
+ <translation>Ditt aktuella totala saldo</translation>
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>Ditt nuvarande saldo i granska-bara adresser</translation>
+ <translation>Ditt aktuella saldo i granska-bara adresser</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1273,15 +1311,15 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
- <translation>Okonfirmerade transaktioner till granska-bara adresser</translation>
+ <translation>Obekräftade transaktioner till granska-bara adresser</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>Den genererade balansen i granska-bara adresser som ännu inte har mognat</translation>
+ <translation>Genererat saldo i granska-bara adresser som ännu inte har mognat</translation>
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation>Nuvarande total balans i granska-bara adresser</translation>
+ <translation>Aktuellt totalt saldo i granska-bara adresser</translation>
</message>
</context>
<context>
@@ -1292,15 +1330,19 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Cannot start bitcoin: click-to-pay handler</source>
- <translation>Kan inte starta bitcoin: klicka-och-betala handhavare</translation>
+ <translation>Kan inte starta bitcoin: klicka-och-betala hanteraren</translation>
</message>
<message>
<source>URI handling</source>
<translation>URI-hantering</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' är inte en accepterad URI. Använd 'bitcoin:' istället.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
- <translation>Hämtningsadressen för betalningsförfrågan är ogiltig: %1</translation>
+ <translation>Hämtningsadressen för betalningsbegäran är ogiltig: %1</translation>
</message>
<message>
<source>Invalid payment address %1</source>
@@ -1308,15 +1350,15 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>URI kan inte tolkas! Detta kan orsakas av en ogiltig Bitcoin-adress eller felaktiga URI parametrar.</translation>
+ <translation>URI kan inte parsas! Detta kan orsakas av en ogiltig Bitcoin-adress eller felaktiga URI-parametrar.</translation>
</message>
<message>
<source>Payment request file handling</source>
- <translation>Hantering av betalningsförfrågningsfil</translation>
+ <translation>Hantering av betalningsbegäransfil</translation>
</message>
<message>
<source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
- <translation>Betalningsförfrågningsfilen kan inte läsas! Detta kan orsakas av en felaktig betalningsförfrågnigsfil.</translation>
+ <translation>Betalningsbegäransfilen kan inte läsas! Detta kan orsakas av en ogiltig betalningsbegäransfil.</translation>
</message>
<message>
<source>Payment request rejected</source>
@@ -1336,7 +1378,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Unverified payment requests to custom payment scripts are unsupported.</source>
- <translation>Overifierade betalningsförfrågningar till anpassade betalningsskript stöds inte.</translation>
+ <translation>Overifierade betalningsbegäranden till anpassade betalningsskript stöds inte.</translation>
</message>
<message>
<source>Invalid payment request.</source>
@@ -1360,7 +1402,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Payment request cannot be parsed!</source>
- <translation>Betalningsbegäran kan inte behandlas!</translation>
+ <translation>Betalningsbegäran kan inte parsas!</translation>
</message>
<message>
<source>Bad response from server %1</source>
@@ -1368,7 +1410,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Network request error</source>
- <translation>Fel vid närverksbegäran</translation>
+ <translation>Fel vid nätverksbegäran</translation>
</message>
<message>
<source>Payment acknowledged</source>
@@ -1496,12 +1538,16 @@ Var vänlig och försök igen.</translation>
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Kunde inte tolka argumentet: %1.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
- <translation>Fel: Den angivna datakatalogen "%1" finns inte.</translation>
+ <translation>Fel: Angiven datakatalog "%1" finns inte.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Fel: Kan inte läsa konfigurationsfilen: %1. Använd bara nyckel=värde formatet.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Fel: Kan inte tolka konfigurationsfil: %1.</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1587,13 +1633,21 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Current number of transactions</source>
- <translation>Nuvarande antal transaktioner</translation>
+ <translation>Aktuellt antal transaktioner</translation>
</message>
<message>
<source>Memory usage</source>
<translation>Minnesåtgång</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Plånbok:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(ingen)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Återställ</translation>
</message>
@@ -1683,7 +1737,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>The duration of a currently outstanding ping.</source>
- <translation>Tidsåtgången för en nuvarande utestående ping.</translation>
+ <translation>Tidsåtgången för en aktuell utestående ping.</translation>
</message>
<message>
<source>Ping Wait</source>
@@ -1762,6 +1816,10 @@ Var vänlig och försök igen.</translation>
<translation>&amp;Ta bort blockering</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>Standardplånbok</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>Välkommen till %1 RPC-konsolen.</translation>
</message>
@@ -1770,10 +1828,30 @@ Var vänlig och försök igen.</translation>
<translation>Använd upp- och ner-pilarna för att navigera i historiken, och %1 för att rensa skärmen.</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Skriv %1 för att få en överblick över tillgängliga kommandon.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>För mer information om att använda denna konsol, skriv %1.</translation>
+ </message>
+ <message>
+ <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
+ <translation>VARNING: Bedragare är kända för att be användare skriva olika kommandon här, varpå de stjäl plånböckernas innehåll. Använd inte konsolen utan att fullt ut förstå konsekvenserna av ett visst kommando.</translation>
+ </message>
+ <message>
<source>Network activity disabled</source>
<translation>Nätverksaktivitet inaktiverad</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Utför instruktion utan plånbok</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Utför instruktion med plånbok "%1"</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(nod-id: %1)</translation>
</message>
@@ -1822,15 +1900,15 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
- <translation>Ett frivilligt meddelande att bifoga betalningsbegäran, vilket visas när begäran öppnas. NB: Meddelandet kommer inte att sändas med betalningen över Bitcoinnätverket.</translation>
+ <translation>Ett valfritt meddelande att bifoga betalningsbegäran, vilket visas när begäran öppnas. Obs: Meddelandet kommer inte att sändas med betalningen över Bitcoin-nätverket.</translation>
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
- <translation>En frivillig etikett att associera med den nya mottagningsadressen.</translation>
+ <translation>En valfri etikett att associera med den nya mottagningsadressen.</translation>
</message>
<message>
<source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation>Använd detta formulär för att begära betalningar. Alla fält är &lt;b&gt;frivilliga&lt;/b&gt;.</translation>
+ <translation>Använd detta formulär för att begära betalningar. Alla fält är &lt;b&gt;valfria&lt;/b&gt;.</translation>
</message>
<message>
<source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
@@ -1845,6 +1923,14 @@ Var vänlig och försök igen.</translation>
<translation>Rensa</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Bech32-addresser (BIP-173) är billigare att spendera från och har bättre skytt mot skrivfel mot konstnaden att äldre plånböcker inte förstår dem. När inte valet är gjort kommer en address som är kompatibel med äldre plånböcker att skapas istället.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Skapa Bech32-adress</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Historik för begärda betalningar</translation>
</message>
@@ -1932,6 +2018,10 @@ Var vänlig och försök igen.</translation>
<translation>Meddelande</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Plånbok</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI:n är för lång, försöka minska texten för etikett / meddelande.</translation>
</message>
@@ -1964,11 +2054,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>(no amount requested)</source>
- <translation>(inget belopp begärd)</translation>
+ <translation>(inget belopp begärt)</translation>
</message>
<message>
<source>Requested</source>
- <translation>Begärd</translation>
+ <translation>Begärt</translation>
</message>
</context>
<context>
@@ -2019,11 +2109,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
- <translation>Om denna är aktiverad men växeladressen är tom eller felaktig kommer växeln att sändas till en nygenererad adress.</translation>
+ <translation>Om denna är aktiverad men växeladressen är tom eller ogiltig kommer växeln att sändas till en nyss skapad adress.</translation>
</message>
<message>
<source>Custom change address</source>
- <translation>Specialväxeladress</translation>
+ <translation>Anpassad växeladress</translation>
</message>
<message>
<source>Transaction Fee:</source>
@@ -2034,6 +2124,10 @@ Var vänlig och försök igen.</translation>
<translation>Välj...</translation>
</message>
<message>
+ <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
+ <translation>Med standardavgiften riskerar en transaktion ta timmar eller dagar för att bekräftas, om den ens gör det. Överväg att själv välja avgift alternativt vänta tills du har validerat hela kedjan.</translation>
+ </message>
+ <message>
<source>Warning: Fee estimation is currently not possible.</source>
<translation>Varning: Avgiftsberäkning är för närvarande inte möjlig.</translation>
</message>
@@ -2042,12 +2136,16 @@ Var vänlig och försök igen.</translation>
<translation>Fäll ihop avgiftsinställningarna</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>per kilobyte</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Ange en egen avgift per kB (1 000 bytes) av transaktionens virtuella storlek.
+
+Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut för en transaktion på 500 bytes (en halv kB) om man valt "100 satoshi per kB" som egen avgift.</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Om den anpassad avgiften är satt till 1000 satoshi och transaktionen bara är 250 byte, betalar "per kilobyte" bara 250 satoshi i avgift, medans "totalt minst" betalar 1000 satoshi. För transaktioner större än en kilobyte betalar både per kilobyte.</translation>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
</message>
<message>
<source>Hide</source>
@@ -2055,7 +2153,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
- <translation>Att betala endast den minsta avgiften är bara bra så länge det är mindre transaktionsvolym än utrymme i blocken. Men tänk på att det kan hamna i en aldrig bekräftar transaktion när det finns mer efterfrågan på bitcoin transaktioner än nätverket kan bearbeta.</translation>
+ <translation>Att bara betala den minsta avgiften är helt ok så länge transaktionsvolymen är mindre än ledigt utrymme i blocken. Men tänk på att det kan bli en en transaktion som aldrig bekräftas om efterfrågan på bitcoin-transaktioner är större än vad nätverket kan hantera.</translation>
</message>
<message>
<source>(read the tooltip)</source>
@@ -2094,16 +2192,24 @@ Var vänlig och försök igen.</translation>
<translation>Bekräftelsestidsmål:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Möjliggör ersättande avgift</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>Med ersättande avgift (BIP-125) kan du höja transaktionsavgiften efter att transaktionen redan skickats. Om du väljer bort det kan en högre avgift rekommenderas för att kompensera för ökad risk för förhöjd transaktionstid.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Rensa &amp;alla</translation>
</message>
<message>
<source>Balance:</source>
- <translation>Balans:</translation>
+ <translation>Saldo:</translation>
</message>
<message>
<source>Confirm the send action</source>
- <translation>Bekräfta sändordern</translation>
+ <translation>Bekräfta sändåtgärden</translation>
</message>
<message>
<source>S&amp;end</source>
@@ -2150,20 +2256,36 @@ Var vänlig och försök igen.</translation>
<translation>Är du säker på att du vill skicka?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>adderad som transaktionsavgift</translation>
+ <source>or</source>
+ <translation>eller</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Du kan välja att höja avgiften senare (med ersättande avgift, BIP-125).</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Totalt belopp %1</translation>
+ <source>from wallet %1</source>
+ <translation>från plånbok: %1</translation>
</message>
<message>
- <source>or</source>
- <translation>eller</translation>
+ <source>Please, review your transaction.</source>
+ <translation>Var vänlig se över din transaktion.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaktionsavgift</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Använder inte ersättande avgift, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Totalt</translation>
</message>
<message>
<source>Confirm send coins</source>
- <translation>Bekräfta skickade mynt</translation>
+ <translation>Bekräfta att mynt ska skickas</translation>
</message>
<message>
<source>The recipient address is not valid. Please recheck.</source>
@@ -2175,15 +2297,15 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>The amount exceeds your balance.</source>
- <translation>Värdet överstiger ditt saldo.</translation>
+ <translation>Beloppet överstiger ditt saldo.</translation>
</message>
<message>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation>Totalvärdet överstiger ditt saldo när transaktionsavgiften %1 är pålagd.</translation>
+ <translation>Totalbeloppet överstiger ditt saldo när transaktionsavgiften %1 är pålagd.</translation>
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
- <translation>Duplicerad adress upptäckt: adresser skall endast användas en gång var.</translation>
+ <translation>Dubblettadress hittades: adresser skall endast användas en gång var.</translation>
</message>
<message>
<source>Transaction creation failed!</source>
@@ -2211,7 +2333,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
- <translation>Varning: Felaktig Bitcoinadress</translation>
+ <translation>Varning: Ogiltig Bitcoin-adress</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
@@ -2219,15 +2341,15 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Confirm custom change address</source>
- <translation>Bekräfta anpassad växlingsadress</translation>
+ <translation>Bekräfta anpassad växeladress</translation>
</message>
<message>
<source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
- <translation>Den adress du valt för växel ingår inte i denna plånbok. Eventuella eller alla pengar i din plånbok kan skickas till den här adressen. Är du säker?</translation>
+ <translation>Den adress du valt för växel ingår inte i denna plånbok. Eventuella eller alla pengar i din plånbok kan komma att skickas till den här adressen. Är du säker?</translation>
</message>
<message>
<source>(no label)</source>
- <translation>(Ingen etikett)</translation>
+ <translation>(ingen etikett)</translation>
</message>
</context>
<context>
@@ -2254,7 +2376,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
- <translation>Bitcoinadress att sända betalning till</translation>
+ <translation>Bitcoin-adress att sända betalning till</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2274,13 +2396,17 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
- <translation>Avgiften dras från beloppet som skickas. Mottagaren kommer att få mindre bitcoins än du angivit i belopp-fältet. Om flera mottagare valts kommer avgiften delas jämt.</translation>
+ <translation>Avgiften dras från beloppet som skickas. Mottagaren kommer att ta emot mindre bitcoin än du angivit i beloppsfältet. Om flera mottagare valts kommer avgiften att fördelas jämt.</translation>
</message>
<message>
<source>S&amp;ubtract fee from amount</source>
<translation>S&amp;ubtrahera avgiften från beloppet</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>Använd tillgängligt saldo</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Meddelande:</translation>
</message>
@@ -2294,11 +2420,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Ange en etikett för denna adress att adderas till listan över använda adresser</translation>
+ <translation>Ange en etikett för denna adress för att lägga till den i listan med använda adresser</translation>
</message>
<message>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
- <translation>Ett meddelande som bifogades bitcoin-URI, vilket lagras med transaktionen som referens. NB: Meddelandet kommer inte att sändas över Bitcoinnätverket.</translation>
+ <translation>Ett meddelande som bifogades bitcoin: -URIn och som lagras med transaktionen som referens. NB: Meddelandet kommer inte att sändas över Bitcoin-nätverket.</translation>
</message>
<message>
<source>Pay To:</source>
@@ -2310,7 +2436,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Enter a label for this address to add it to your address book</source>
- <translation>Ange en etikett för den här adressen och lägg till den i din adressbok</translation>
+ <translation>Ange en etikett för denna adress för att lägga till den i din adressbok</translation>
</message>
</context>
<context>
@@ -2343,11 +2469,11 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
- <translation>Du kan underteckna meddelanden/avtal med dina adresser för att bevisa att du kan ta emot bitcoins som skickats till dem. Var försiktig så du inte undertecknar något oklart eller konstigt, eftersom phishing-angrepp kan försöka få dig att underteckna din identitet till dem. Underteckna endast väldetaljerade meddelanden som du godkänner.</translation>
+ <translation>Du kan signera meddelanden/avtal med dina adresser för att bevisa att du kan ta emot bitcoin som skickats till dem. Var försiktig så du inte signerar något oklart eller konstigt, eftersom phishing-angrepp kan försöka få dig att signera över din identitet till dem. Signera endast väldetaljerade meddelanden som du godkänner.</translation>
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
- <translation>Bitcoinadress att signera meddelandet med</translation>
+ <translation>Bitcoin-adress att signera meddelandet med</translation>
</message>
<message>
<source>Choose previously used address</source>
@@ -2379,7 +2505,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Signera meddelandet för att bevisa att du äger denna adress</translation>
+ <translation>Signera meddelandet för att bevisa att du äger denna Bitcoin-adress</translation>
</message>
<message>
<source>Sign &amp;Message</source>
@@ -2399,15 +2525,15 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation>Ange mottagarens adress, meddelande (kopiera radbrytningar, mellanrum, flikar, etc. exakt) och signatur nedan för att verifiera meddelandet. Undvik att läsa in mera information i signaturen än vad som stod i själva undertecknade meddelandet, för att undvika ett man-in-the-middle-angrepp. Notera att detta endast bevisar att undertecknad tar emot med adressen, det bevisar inte vem som skickat transaktionen!</translation>
+ <translation>Ange mottagarens adress, meddelande (kopiera radbrytningar, mellanslag, TAB-tecken, osv. exakt) och signatur nedan, för att verifiera meddelandet. Undvik att läsa in mera information i signaturen än vad som stod i själva det signerade meddelandet, för att undvika ett man-in-the-middle-angrepp. Notera att detta endast bevisar att den signerande parten tar emot med adressen, det bevisar inte vem som skickat transaktionen!</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
- <translation>Bitcoinadressen som meddelandet signerades med</translation>
+ <translation>Bitcoin-adress som meddelandet signerades med</translation>
</message>
<message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Verifiera meddelandet för att vara säker på att den var signerad med den angivna Bitcoin-adressen</translation>
+ <translation>Verifiera meddelandet för att vara säker på att det signerades med angiven Bitcoin-adress</translation>
</message>
<message>
<source>Verify &amp;Message</source>
@@ -2419,7 +2545,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Click "Sign Message" to generate signature</source>
- <translation>Klicka "Signera Meddelande" för att generera en signatur</translation>
+ <translation>Klicka "Signera Meddelande" för att skapa en signatur</translation>
</message>
<message>
<source>The entered address is invalid.</source>
@@ -2439,7 +2565,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Private key for the entered address is not available.</source>
- <translation>Privata nyckel för den angivna adressen är inte tillgänglig.</translation>
+ <translation>Den privata nyckeln för den angivna adressen är inte tillgänglig.</translation>
</message>
<message>
<source>Message signing failed.</source>
@@ -2499,10 +2625,6 @@ Var vänlig och försök igen.</translation>
<translation>konflikt med en transaktion med %1 konfirmationer</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/nedkopplad</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/obekräftade, %1</translation>
</message>
@@ -2531,10 +2653,6 @@ Var vänlig och försök igen.</translation>
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>,har inte lyckats sända än</translation>
- </message>
- <message>
<source>Date</source>
<translation>Datum</translation>
</message>
@@ -2619,6 +2737,10 @@ Var vänlig och försök igen.</translation>
<translation>Transaktionens totala storlek</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Transaktionens virtuella storlek</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>Utmatningsindex</translation>
</message>
@@ -2628,7 +2750,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation>Genererade mynt måste vänta %1 block innan de kan användas. När du skapade detta block sändes det till nätverket för att läggas till i blockkedjan. Om blocket inte kommer in i kedjan kommer dess status att ändras till "accepteras inte" och kommer ej att gå att spendera. Detta kan ibland hända om en annan nod genererar ett block nästan samtidigt som dig.</translation>
+ <translation>Skapade mynt måste mogna i %1 block innan de kan spenderas. När du skapade detta block sändes det till nätverket för att läggas till i blockkedjan. Om blocket inte kommer in i kedjan kommer dess status att ändras till "ej accepterat" och går inte att spendera. Detta kan ibland hända om en annan nod skapar ett block nästan samtidigt som dig.</translation>
</message>
<message>
<source>Debug information</source>
@@ -2689,12 +2811,8 @@ Var vänlig och försök igen.</translation>
<translation>Öppet till %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Nerkopplad</translation>
- </message>
- <message>
<source>Unconfirmed</source>
- <translation>Obekräftade:</translation>
+ <translation>Obekräftade</translation>
</message>
<message>
<source>Abandoned</source>
@@ -2702,7 +2820,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Confirming (%1 of %2 recommended confirmations)</source>
- <translation>Bekräftar (%1 av %2 bekräftelser)</translation>
+ <translation>Bekräftar (%1 av %2 rekommenderade bekräftelser)</translation>
</message>
<message>
<source>Confirmed (%1 confirmations)</source>
@@ -2717,12 +2835,8 @@ Var vänlig och försök igen.</translation>
<translation>Omogen (%1 bekräftelser, blir tillgänglig efter %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Det här blocket togs inte emot av några andra noder och kommer antagligen inte att bli accepterad!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
- <translation>Genererad men inte accepterad</translation>
+ <translation>Skapad men inte accepterad</translation>
</message>
<message>
<source>Received with</source>
@@ -2754,7 +2868,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>(no label)</source>
- <translation>(Ingen etikett)</translation>
+ <translation>(ingen etikett)</translation>
</message>
<message>
<source>Transaction status. Hover over this field to show number of confirmations.</source>
@@ -2762,7 +2876,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Date and time that the transaction was received.</source>
- <translation>Tidpunkt då transaktionen mottogs.</translation>
+ <translation>Datum och tid då transaktionen mottogs.</translation>
</message>
<message>
<source>Type of transaction.</source>
@@ -2770,7 +2884,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>Anger om granska-bara--adresser är involverade i denna transaktion.</translation>
+ <translation>Anger om en granska-bara--adress är involverad i denna transaktion.</translation>
</message>
<message>
<source>User-defined intent/purpose of the transaction.</source>
@@ -2778,7 +2892,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Amount removed from or added to balance.</source>
- <translation>Belopp draget eller tillagt till balans.</translation>
+ <translation>Belopp draget eller tillagt till saldo.</translation>
</message>
</context>
<context>
@@ -2832,6 +2946,10 @@ Var vänlig och försök igen.</translation>
<translation>Övriga</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Ange adress, transaktions-id eller etikett för att söka</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Minsta belopp</translation>
</message>
@@ -2869,7 +2987,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Edit label</source>
- <translation>Ändra etikett</translation>
+ <translation>Redigera etikett</translation>
</message>
<message>
<source>Show transaction details</source>
@@ -2917,7 +3035,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>There was an error trying to save the transaction history to %1.</source>
- <translation>Det inträffade ett fel när transaktionshistoriken skulle sparas till %1.</translation>
+ <translation>Ett fel inträffade när transaktionshistoriken skulle sparas till %1.</translation>
</message>
<message>
<source>Exporting Successful</source>
@@ -2925,7 +3043,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>The transaction history was successfully saved to %1.</source>
- <translation>Transaktionshistoriken sparades utan problem till %1.</translation>
+ <translation>Transaktionshistoriken sparades till %1.</translation>
</message>
<message>
<source>Range:</source>
@@ -2947,7 +3065,7 @@ Var vänlig och försök igen.</translation>
<name>WalletFrame</name>
<message>
<source>No wallet has been loaded.</source>
- <translation>Ingen plånbok har laddats in.</translation>
+ <translation>Ingen plånbok har lästs in.</translation>
</message>
</context>
<context>
@@ -2957,6 +3075,10 @@ Var vänlig och försök igen.</translation>
<translation>Skicka Bitcoins</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>Avgiftsökningsfel</translation>
+ </message>
+ <message>
<source>Increasing transaction fee failed</source>
<translation>Ökning av avgiften lyckades inte</translation>
</message>
@@ -2966,7 +3088,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Current fee:</source>
- <translation>Nuvarande avgift:</translation>
+ <translation>Aktuell avgift:</translation>
</message>
<message>
<source>Increase:</source>
@@ -2977,6 +3099,10 @@ Var vänlig och försök igen.</translation>
<translation>Ny avgift:</translation>
</message>
<message>
+ <source>Confirm fee bump</source>
+ <translation>Bekräfta avgiftshöjning</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Kan ej signera transaktion.</translation>
</message>
@@ -2993,7 +3119,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>Exportera informationen i den nuvarande fliken till en fil</translation>
+ <translation>Exportera informationen i aktuell flik till en fil</translation>
</message>
<message>
<source>Backup Wallet</source>
@@ -3009,7 +3135,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>There was an error trying to save the wallet data to %1.</source>
- <translation>Det inträffade ett fel när plånbokens data skulle sparas till %1.</translation>
+ <translation>Ett fel inträffade när plånbokens data skulle sparas till %1.</translation>
</message>
<message>
<source>Backup Successful</source>
@@ -3017,40 +3143,20 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>The wallet data was successfully saved to %1.</source>
- <translation>Plånbokens data sparades utan problem till %1.</translation>
+ <translation>Plånbokens data sparades till %1.</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>Avbryt</translation>
</message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Inställningar:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Ange katalog för data</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Anslut till en nod för att hämta klientadresser, och koppla från</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Ange din egen publika adress</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Tillåt kommandon från kommandotolken och JSON-RPC-kommandon</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distribuerad under MIT mjukvarulicens, se den bifogade filen %s eller %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Om &lt;kategori&gt; inte anges eller om &lt;category&gt; = 1, visa all avlusningsinformation.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Beskärning konfigurerad under miniminivån %d MiB. Vänligen använd ett högre värde.</translation>
</message>
@@ -3067,18 +3173,10 @@ Var vänlig och försök igen.</translation>
<translation>Fel: Ett kritiskt internt fel uppstod, se debug.log för detaljer</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Avgift (i %s/kB) att lägga till på transaktioner du skickar (förvalt: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Rensar blockstore...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Kör i bakgrunden som tjänst och acceptera kommandon</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Kunde inte starta HTTP-server. Se avlusningsloggen för detaljer.</translation>
</message>
@@ -3091,44 +3189,20 @@ Var vänlig och försök igen.</translation>
<translation>%s-utvecklarna</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>En avgiftskurs (i %s/kB) som används när det inte finns tillräcklig data för att uppskatta avgiften (förvalt: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Acceptera vidarebefodrade transaktioner från vitlistade noder även när transaktioner inte vidarebefodras (förvalt: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Bind till given adress och lyssna alltid på den. Använd [värd]:port notation för IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Kan inte låsa data-mappen %s. %s körs förmodligen redan.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Ta bort alla plånbokstransaktioner och återskapa bara dom som är en del av blockkedjan genom att ange -rescan vid uppstart</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Kan inte låta addrman hitta utgående uppkopplingar samtidigt som specifika uppkopplingar skapas</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
- <translation>Fel vid läsning av %s! Alla nycklar lästes korrekt, men transaktionsdatat eller adressbokens poster kanske saknas eller är felaktiga.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Exekvera kommando när en plånbokstransaktion ändras (%s i cmd är ersatt av TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Extra transaktioner att hålla i minnet för kompakta blockrekonstruktioner (standard: %u)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Maximalt tillåten median-peer tidsoffset justering. Lokalt perspektiv av tiden kan bli påverkad av partners, framåt eller bakåt denna tidsrymd. (förvalt: %u sekunder)</translation>
+ <translation>Fel vid läsning av %s! Alla nycklar lästes korrekt, men transaktionsdata eller poster i adressboken kanske saknas eller är felaktiga.</translation>
</message>
<message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Maximal total avgift (i %s) att använda i en plånbokstransaktion eller råa transaktioner. Sätts denna för lågt kan stora transaktioner avbrytas (förvalt: %s)</translation>
+ <source>Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)</source>
+ <translation>Gruppera utgående transaktioner med adress, där samtliga eller inga används, istället för att välja vid varje utgående transaktion. Detta ökar din integritet genom att en adress enbart används en gång (om inte någon skickar till den efteråt), men kan öka dina utgifter då valet av ingående transaktioner görs suboptimalt (standardvärde: %u)</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -3139,46 +3213,34 @@ Var vänlig och försök igen.</translation>
<translation>Var snäll och bidra om du finner %s användbar. Besök %s för mer information om mjukvaran.</translation>
</message>
<message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Ange antalet skriptkontrolltrådar (%u till %d, 0 = auto, &lt;0 = lämna så många kärnor lediga, förval: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Blockdatabasen innehåller ett block som verkar vara från framtiden. Detta kan vara på grund av att din dators datum och tid är felaktiga. Bygg bara om blockdatabasen om du är säker på att datorns datum och tid är korrekt</translation>
</message>
<message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
- <translation>Detta är ett förhandstestbygge - använd på egen risk - använd inte för mining eller handels applikationer</translation>
- </message>
- <message>
- <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
- <translation>Kan inte spola tillbaka databasen till obeskärt läge. Du måste ladda ner blockkedjan igen</translation>
+ <translation>Detta är ett förhandstestbygge - använd på egen risk - använd inte för brytning eller handelsapplikationer</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Använd UPnP för att mappa den lyssnande porten (förvalt: 1 när lyssning aktiverat och utan -proxy)</translation>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>Detta är transaktionsavgiften som slängs borta om det är mindre än damm på denna nivå</translation>
</message>
<message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Användarnamn och hashat lösenord för JSON-RPC-anslutningar. Fältet &lt;userpw&gt; kommer i formatet: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Ett kanoniskt pythonskript finns inkluderat i share/rpcuser. Klienten kopplas sedan normalt med rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; par argument. Detta alternativ kan anges flera gånger</translation>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>Kunde inte spela om block. Du kommer att behöva bygga om databasen med -reindex-chainstate.</translation>
</message>
<message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Plånboken skapar inte transaktioner som bryter mot mempools kedjegränser (förval: %u)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Kan inte spola tillbaka databasen till obeskärt läge. Du måste ladda ner blockkedjan igen</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>Varning: Nätverket verkar inte vara helt överens! Några miners verkar ha problem.</translation>
+ <translation>Varning: Nätverket verkar inte vara helt överens! Några brytare verkar ha problem.</translation>
</message>
<message>
<source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
<translation>Varning: Vi verkar inte helt överens med våra peers! Du kan behöva uppgradera, eller andra noder kan behöva uppgradera.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Hurvida du vill spara mempoolen vid avstängning och ladda på omstart (förval: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d av de senaste 100 blocken har oväntad version</translation>
</message>
@@ -3191,36 +3253,12 @@ Var vänlig och försök igen.</translation>
<translation>-maxmempool måste vara minst %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; Kan vara:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Acceptera anslutningar utifrån (förvalt: 1 om ingen -proxy eller -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Lägg till kommentar till user-agent-strängen</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Försök att rädda privata nycklar från en korrupt plånbok vid uppstart</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Block skapande inställningar:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Kan inte matcha -%s adress: '%s'</translation>
</message>
<message>
<source>Change index out of range</source>
- <translation>Förändringsindexet utom räckhåll</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>Anslutningsalternativ:</translation>
+ <translation>Förändringsindexet utanför tillåtet intervall</translation>
</message>
<message>
<source>Copyright (C) %i-%i</source>
@@ -3231,36 +3269,12 @@ Var vänlig och försök igen.</translation>
<translation>Korrupt blockdatabas har upptäckts</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Avlusnings/Test-alternativ:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Ladda inte plånboken och stäng av RPC-anrop till plånboken</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Vill du bygga om blockdatabasen nu?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Aktivera publicering av hashblock i &lt;adress&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Aktivera publicering av hashtransaktion i &lt;adress&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Aktivera publicering av råa block i &lt;adress&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Aktivera publicering av råa transaktioner i &lt;adress&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Aktivera byte av transaktioner i minnespoolen (förvalt: %u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Fel vid skapande av %s: Det är inte möjligt att skapa icke-HD plånböcker med denna version.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -3275,12 +3289,16 @@ Var vänlig och försök igen.</translation>
<translation>Fel vid inläsning av %s</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Fel vid laddning av %s: Privata nycklar kan enbart bli avstängda vid skapelsen</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
- <translation>Fel vid inläsningen av %s: Plånboken är koruppt</translation>
+ <translation>Fel vid inläsning av %s: Plånboken är korrupt</translation>
</message>
<message>
<source>Error loading %s: Wallet requires newer version of %s</source>
- <translation>Fel vid inläsningen av %s: Plånboken kräver en senare version av %s</translation>
+ <translation>Fel vid inläsning av %s: Plånboken kräver en senare version av %s</translation>
</message>
<message>
<source>Error loading block database</source>
@@ -3299,6 +3317,10 @@ Var vänlig och försök igen.</translation>
<translation>Misslyckades att lyssna på någon port. Använd -listen=0 om du vill detta.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Misslyckades med att skanna om plånboken under initiering.</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importerar...</translation>
</message>
@@ -3312,7 +3334,7 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Ogiltigt belopp för -%s=&lt;belopp&gt;:'%s'</translation>
+ <translation>Ogiltigt belopp för -%s=&lt;amount&gt;:'%s'</translation>
</message>
<message>
<source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
@@ -3320,41 +3342,29 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Ogiltigt belopp för -fallbackfee=&lt;belopp&gt;: '%s'</translation>
+ <translation>Ogiltigt belopp för -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Håll minnespoolen över transaktioner under &lt;n&gt; megabyte (förvalt: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Den specificerade mappen för block "%s" existerar inte.</translation>
</message>
<message>
- <source>Loading P2P addresses...</source>
- <translation>Laddar P2P adresser...</translation>
+ <source>Upgrading txindex database</source>
+ <translation>Uppgraderar databas för txindex</translation>
</message>
<message>
- <source>Loading banlist...</source>
- <translation>Laddar svarta listan...</translation>
+ <source>Loading P2P addresses...</source>
+ <translation>Läser in P2P-adresser...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Plats för authcookie (förvalt: datamapp)</translation>
+ <source>Loading banlist...</source>
+ <translation>Läser in svarta listan...</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
<translation>Inte tillräckligt med filbeskrivningar tillgängliga.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Anslut enbart till noder i nätverket &lt;net&gt; (IPv4, IPv6 eller onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Visa denna hjälptext och avsluta</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Visa version och avsluta</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Beskärning kan inte konfigureras med ett negativt värde.</translation>
</message>
@@ -3363,34 +3373,30 @@ Var vänlig och försök igen.</translation>
<translation>Beskärningsläge är inkompatibel med -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Återskapa blockkedjans status och index från blk*.dat filer på disken</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Återskapa blockkedjans status från aktuella indexerade block</translation>
+ <source>Replaying blocks...</source>
+ <translation>Spelar om block...</translation>
</message>
<message>
<source>Rewinding blocks...</source>
<translation>Spolar tillbaka blocken...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Sätt databasens cachestorlek i megabyte (%d till %d, förvalt: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Ange plånboksfil (inom datakatalogen)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Källkoden är tillgänglig från %s.</translation>
</message>
<message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>Beräkning av transaktionsavgift och växel mislyckades</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
<translation>Det går inte att binda till %s på den här datorn. %s är förmodligen redan igång.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Lyckas inte generera nycklar</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Argumentet -benchmark stöds inte och ignoreras, använd -debug=bench.</translation>
</message>
@@ -3403,16 +3409,12 @@ Var vänlig och försök igen.</translation>
<translation>Argumentet -tor hittades men stöds inte, använd -onion.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation>Uppgraderar UTXO-databasen</translation>
- </message>
- <message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Använd UPnP för att mappa den lyssnande porten (förvalt: %u)</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Saknar stöd för loggningskategori %s=%s.</translation>
</message>
<message>
- <source>Use the test chain</source>
- <translation>Använd testkedjan</translation>
+ <source>Upgrading UTXO database</source>
+ <translation>Uppgraderar UTXO-databasen</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -3423,100 +3425,36 @@ Var vänlig och försök igen.</translation>
<translation>Verifierar block...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Plånbokens Avlusnings/Testnings optioner:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Plånboken behöver sparas om: Starta om %s för att fullfölja</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Plånboksinställningar:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Tillåt JSON-RPC-anslutningar från specifik källa. Tillåtna &lt;ip&gt; är enkel IP (t.ex 1.2.3.4), en nätverk/nätmask (t.ex. 1.2.3.4/255.255.255.0) eller ett nätverk/CIDR (t.ex. 1.2.3.4/24). Detta alternativ anges flera gånger</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Bind till given adress och vitlista klienter som ansluter till den. Använd [värd]:port notation för IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Skapa nya filer med systemets förvalda rättigheter, istället för umask 077 (bara effektivt med avaktiverad plånboks funktionalitet)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Upptäck egna IP adresser (standard: 1 vid lyssning ingen -externalip eller -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Fel: Avlyssning av inkommande anslutningar misslyckades (Avlyssningen returnerade felkod %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Exekvera kommando när ett relevant meddelande är mottagen eller när vi ser en väldigt lång förgrening (%s i cmd är utbytt med ett meddelande)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Avgifter (i %s/kB) mindre än detta betraktas som nollavgift för vidarebefordran, mining och transaktionsskapande (förvalt: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Om paytxfee inte är satt, inkludera tillräcklig avgift så att transaktionen börjar att konfirmeras inom n blocks (förvalt: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
- <translation>Otillåtet belopp för -maxtxfee=&lt;belopp&gt;: '%s' (måste åtminstånde vara minrelay avgift %s för att förhindra stoppade transkationer)</translation>
- </message>
- <message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maximal storlek på data i databärartransaktioner som vi reläar och bryter (förvalt: %u) </translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Slumpa autentiseringen för varje proxyanslutning. Detta möjliggör Tor ström-isolering (förvalt: %u)</translation>
+ <translation>Ogiltigt belopp för -maxtxfee=&lt;amount&gt;: '%s' (måste vara åtminstone minrelay avgift %s för att förhindra stoppade transaktioner)</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Transaktionen är för liten att skicka efter det att avgiften har dragits</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Vitlistade klienter kan inte bli DoS-bannade och deras transaktioner reläas alltid, även om dom redan är i mempoolen, användbart för t.ex en gateway </translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
- <translation>Du måste bygga om databasen genom att använda -reindex för att återgå till obeskärt läge. Detta kommer att ladda ner hela blockkedjan.</translation>
- </message>
- <message>
- <source>(default: %u)</source>
- <translation>(förvalt: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Acceptera publika REST förfrågningar (förvalt: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Skapa automatiskt dold tjänst i Tor (förval: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Anslut genom SOCKS5 proxy</translation>
+ <translation>Du måste bygga om databasen genom att använda -reindex för att återgå till obeskärt läge. Detta kommer att ladda ner hela blockkedjan på nytt.</translation>
</message>
<message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
- <translation>Fel vid laddning av %s: Du kan inte avaktivera HD på en redan existerande HD plånbok</translation>
+ <translation>Fel vid inläsning av %s: Du kan inte avaktivera HD på en redan existerande HD-plånbok</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
<translation>Fel vid läsning från databas, avslutar.</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Importera block från extern blk000??.dat-fil vid uppstart</translation>
+ <source>Error upgrading chainstate database</source>
+ <translation>Fel vid uppgradering av blockdatabasen</translation>
</message>
<message>
<source>Information</source>
@@ -3532,51 +3470,35 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation>Ogiltigt belopp för -paytxfee=&lt;belopp&gt;:'%s' (måste vara minst %s)</translation>
+ <translation>Ogiltigt belopp för -paytxfee=&lt;amount&gt;:'%s' (måste vara minst %s)</translation>
</message>
<message>
<source>Invalid netmask specified in -whitelist: '%s'</source>
<translation>Ogiltig nätmask angiven i -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Håll som mest &lt;n&gt; oanslutningsbara transaktioner i minnet (förvalt: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Port måste anges med -whitelist: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Nodreläalternativ:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC-serveralternativ:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Minskar -maxconnections från %d till %d, på grund av systembegränsningar.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Sök i blockkedjan efter saknade plånbokstransaktioner vid uppstart</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Skicka trace-/debuginformation till terminalen istället för till debug.log</translation>
+ <source>Signing transaction failed</source>
+ <translation>Signering av transaktion misslyckades</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Visa alla avlusningsalternativ (använd: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Angiven -walletdir "%s" finns inte</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Krymp debug.log filen vid klient start (förvalt: 1 vid ingen -debug)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Angiven -walletdir "%s" är en relativ sökväg</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>Signering av transaktion misslyckades</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Angiven -walletdir "%s" är inte en katalog</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3587,14 +3509,6 @@ Var vänlig och försök igen.</translation>
<translation>Detta är experimentmjukvara.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Lösenord för Tor-kontrollport (förval: inget)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Tor-kontrollport att använda om onion är aktiverat (förval: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Transaktions belopp för liten</translation>
</message>
@@ -3611,18 +3525,18 @@ Var vänlig och försök igen.</translation>
<translation>Det går inte att binda till %s på den här datorn (bind returnerade felmeddelande %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Uppgradera plånbok till senaste formatet vid uppstart</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Användarnamn för JSON-RPC-anslutningar</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Det gick inte att skapa ursprungliga nycklar</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Verifierar plånbok(er)...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Plånbok %s är lokaliserad utanför plånboksmappen %s</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Varning</translation>
</message>
@@ -3631,84 +3545,16 @@ Var vänlig och försök igen.</translation>
<translation>Varning: okända nya regler aktiverade (versionsbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Ska allt göras i endast block-läge (förval: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Du måste återskapa databasen med -reindex för att ändra -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Töm plånboken på alla transaktioner...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ-alternativ för notiser:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Lösenord för JSON-RPC-anslutningar</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Exekvera kommando när det bästa blocket ändras (%s i cmd är utbytt av blockhash)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Tillåt DNS-sökningar för -addnode, -seednode och -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = spara tx metadata t.ex. kontoägare och betalningsbegäransinformation, 2 = släng tx metadata)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee är väldigt högt satt! Så höga avgifter kan komma att betalas för en enstaka transaktion.</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Håll inte transaktioner i minnespoolen längre än &lt;n&gt; timmar (förvalt: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Samma antal byte per sigop i transaktioner som vi reläar och bryter (förvalt: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
- <translation>Fel vid laddning av %s: Du kan inte aktivera HD på en existerande icke-HD plånbok</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Fel vid inläsningen av plånbok %s. -wallet parametern kan bara innehålla ett filnamn (inte en sökväg).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Avgifter (i %s/kB) mindre än detta anses vara nollavgifter vid skapande av transaktion (standard: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Vidarebefordra alltid transaktioner från vitlistade noder även om de bryter mot den lokala reläpolicyn (förvalt: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Hur grundlig blockverifikationen vid -checkblocks är (0-4, förvalt: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Upprätthåll ett fullständigt transaktionsindex, som används av getrawtransaction rpc-anrop (förval: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Antal sekunder att hindra klienter som missköter sig från att ansluta (förvalt: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Skriv ut avlusningsinformation (förvalt: %u, att ange &lt;category&gt; är frivilligt)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Stöd filtrering av block och transaktioner med bloomfilter (standard: %u)</translation>
+ <translation>Fel vid inläsning av %s: Du kan inte aktivera HD på en existerande icke-HD plånbok</translation>
</message>
<message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
@@ -3723,10 +3569,6 @@ Var vänlig och försök igen.</translation>
<translation>Total längd på strängen för nätverksversion (%i) överskrider maxlängden (%i). Minska numret eller storleken på uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Försöker hålla utgående trafik under givet mål (i MiB per 24 timmar), 0 = ingen gräns (förvalt: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Argumentet -socks hittades och stöds inte. Det är inte längre möjligt att sätta SOCKS-version längre, bara SOCKS5-proxy stöds.</translation>
</message>
@@ -3735,112 +3577,24 @@ Var vänlig och försök igen.</translation>
<translation>Argumentet -whitelistalwaysrelay stöds inte utan ignoreras, använd -whitelistrelay och/eller -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Använd separat SOCKS5 proxy för att nå kollegor via dolda tjänster i Tor (förvalt: -%s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Varning: Okända blockversioner bryts! Det är möjligt att okända regler används</translation>
</message>
<message>
<source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Varning: Plånboksfilen var korrupt, datat har räddats! Den ursprungliga %s har sparas som %s i %s. Om ditt saldo eller transaktioner är felaktiga bör du återställa från en säkerhetskopia.</translation>
+ <translation>Varning: Plånboksfilen var korrupt, data har räddats! Den ursprungliga %s har sparas som %s i %s. Om ditt saldo eller transaktioner är felaktiga bör du återställa från en säkerhetskopia.</translation>
</message>
<message>
<source>%s is set very high!</source>
<translation>%s är satt väldigt högt!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(förvalt: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Sök alltid efter klientadresser med DNS sökningen (förvalt: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Fel vid inläsningen av plånbok %s. -wallet filnamn måste var en vanlig fil.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
- <translation>Fel vid inläsningen av plånbok %s. Dublett -wallet filnamn anges.</translation>
- </message>
- <message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Fel vid inläsningen av plånbok %s. Ogiltiga tecken i -wallet filnamn.</translation>
+ <translation>Fel vid inläsningen av plånbok %s. Dublett -wallet filnamn angavs.</translation>
</message>
<message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Hur många block att kontrollera vid uppstart (förvalt: %u, 0 = alla)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Inkludera IP-adresser i debugutskrift (förvalt: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Lyssna på JSON-RPC-anslutningar på &lt;port&gt; (förval: %u eller testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Lyssna efter anslutningar på &lt;port&gt; (förvalt: %u eller testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Ha som mest &lt;n&gt; anslutningar till andra klienter (förvalt: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Gör så att plånboken sänder ut transaktionerna</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximal mottagningsbuffert per anslutning, &lt;n&gt;*1000 byte (förvalt: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximal sändningsbuffert per anslutning, &lt;n&gt;*1000 byte (förvalt: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Skriv ut tidsstämpel i avlusningsinformationen (förvalt: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Reläa och bearbeta databärartransaktioner (förvalt: %u) </translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Reläa icke-P2SH multisig (förvalt: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Sätt storleken på nyckelpoolen till &lt;n&gt; (förvalt: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Sätt maximal BIP141 blockvikt (förvalt: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Ange antalet trådar för att hantera RPC anrop (förvalt: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Ange konfigurationsfil (förvalt: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Ange timeout för uppkoppling i millisekunder (minimum:1, förvalt: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Ange pid-fil (förvalt: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Spendera okonfirmerad växel när transaktioner sänds (förvalt: %u)</translation>
+ <source>Keypool ran out, please call keypoolrefill first</source>
+ <translation>Nyckelpoolen har tagit slut, var vänlig anropa keypoolrefill först.</translation>
</message>
<message>
<source>Starting network threads...</source>
@@ -3859,10 +3613,6 @@ Var vänlig och försök igen.</translation>
<translation>Det här är transaktionsavgiften du kommer betala om du skickar en transaktion. </translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Tröskelvärde för att koppla ifrån klienter som missköter sig (förvalt: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Transaktionens belopp får ej vara negativ</translation>
</message>
@@ -3876,13 +3626,33 @@ Var vänlig och försök igen.</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Okänt nätverk som anges i -onlynet: '%s'</translation>
+ <translation>Okänt nätverk angavs i -onlynet: '%s'</translation>
</message>
<message>
<source>Insufficient funds</source>
<translation>Otillräckligt med bitcoins</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Kan inte generera en nyckel för växeladress. Privata nycklar är avstängda för denna plånboken.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Kan inte uppgradera till en icke-HD delad plånbok utan att uppgradera till att stödja nyckelpoolen innan splittring. Var vänlig använd -upgradewallet=169900 eller -upgradewallet utan version specificerad.</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Avgiftsestimering misslyckades. Fallbackfee är avstänt. Var vänlig vänta några block, alternativt aktivera -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Varning: Privata nycklar upptäckta i plånbok (%s) vilken har dessa inaktiverade</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Kan inte skriva till mapp "%s", var vänlig se över filbehörigheter.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Laddar blockindex...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_szl.ts b/src/qt/locale/bitcoin_szl.ts
new file mode 100644
index 0000000000..9559df2a7d
--- /dev/null
+++ b/src/qt/locale/bitcoin_szl.ts
@@ -0,0 +1,2123 @@
+<TS language="szl" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>Kliknij prawy knefel mysze, coby edytować adresã abo etyketã</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>Zrychtuj nowõ adresã</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>&amp;Nowy</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Skopiyruj aktualnie ôbranõ adresã do skrytki</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>&amp;Kopiyruj</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>&amp;Zawrzij</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>Wychrōń zaznaczōnõ adresã z brify</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Wkludź adresã abo etyketã coby wyszukać</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Eksportuj dane z aktywnyj szkarty do zbioru</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;Eksportuj</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>&amp;Wychrōń</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Ôbier adresã, na kerõ chcesz posłać mōnety</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation>Ôbier adresã, na kerõ chcesz dostać mōnety</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>Ô&amp;bier</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Adresy posyłaniŏ</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Adresy ôdbiyraniŏ</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Tukej sōm adresy Bitcoin na kere posyłŏsz płaty. Dycki wybaduj wielość i adresã ôdbiyrŏcza przed posłaniym mōnet.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Tukej sōm adresy Bitcoin do ôdbiyraniŏ płatōw. Zalycŏ sie używaniŏ nowych adres ôdbiorczych dlŏ kożdyj transakcyje.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;Kopiyruj Adresã</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Kopiyruj &amp;Etyketã</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;Edytuj</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Eksportuj wykŏz adres</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Zbiōr *.CSV (daty rozdzielane kōmami)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Eksportowanie niy podarziło sie</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <translation>Przitrefiōł sie feler w czasie spamiyntowaniŏ brify adres do %1. Proszã sprōbować zaś.</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Etyketa</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Adresa</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(chyba etykety)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation>Ôkiynko Hasła</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>Wkludź hasło</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>Nowe hasło</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>Powtōrz nowe hasło</translation>
+ </message>
+ <message>
+ <source>Show password</source>
+ <translation>Pokŏż hasło</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Wkludź nowe hasło do portmanyja.&lt;br/&gt;Proszã używać hasła słożōnego z &lt;b&gt;10 abo wiyncyj losowych liter&lt;/b&gt; abo &lt;b&gt;8 abo wiyncyj słōw.&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Zaszyfruj portmanyj</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Ta ôperacyjŏ wymŏgŏ hasła do portmanyja coby ôdszperować portmanyj.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Ôdszperuj portmanyj.</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Ta ôperacyjŏ wymŏgŏ hasła do portmanyja coby ôdszyfrować portmanyj.</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>Ôdszyfruj portmanyj</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Pōmiyń hasło</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation>Podej stare i nowe hasło do portmanyja.</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Przituplikuj szyfrowanie portmanyja</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation>Pozōr: jeźli zaszyfrujesz swōj portmanyj i stracisz hasło &lt;b&gt;STRACISZ WSZYJSKE SWOJE BITCOINY&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Na isto chcesz zaszyfrować swōj portmanyj?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Portmanyj zaszyfrowany</translation>
+ </message>
+ <message>
+ <source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation>%1 zawrzi sie coby dokōńczyć proces szyfrowaniŏ. Pamiyntej, iże szyfrowanie portmanyja ganc niy zabezpieczŏ Twojich bitcoinów przed chabiyniym bez wirusy abo trojany mogōnce zakażać Twōj kōmputer.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation>WŎŻNE: Wszyjske wykōnane wczaśnij kopije zbioru portmanyja winny być umiyniōne na nowe, szyfrowane zbiory. Z powodōw bezpiyczyństwa, piyrwyjsze kopije niyszyfrowanych zbiorōw portmanyja stōnõ sie bezużyteczne jak ino zaczniesz używać nowego, szyfrowanego portmanyja.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Zaszyfrowanie portmanyja niy podarziło sie</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Zaszyfrowanie portmanyja niy podarziło sie bez wnyntrzny feler. Twōj portmanyj niy ôstoł zaszyfrowany.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Podane hasła niy sōm take same.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Ôdszperowanie portmanyja niy podarziło sie</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Wkludzōne hasło do ôdszyfrowaniŏ portmanyja je niynŏleżne.</translation>
+ </message>
+ <message>
+ <source>Wallet decryption failed</source>
+ <translation>Ôdszyfrowanie portmanyja niy podarziło sie</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Hasło do portmanyja ôstało sprŏwnie pōmiyniōne.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Pozōr: Caps Lock je zapuszczōny!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Maska necu</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Szpera do</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>Szkryftnij &amp;wiadōmość</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>Synchrōnizacyjŏ z necym...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>&amp;Podsumowanie</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>Pokazuje ôgōlny widok portmanyja</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>&amp;Transakcyje</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>Przeglōndej historyjõ transakcyji</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>&amp;Zakōńcz</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Zawrzij aplikacyjõ</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>&amp;Ô %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Pokŏż informacyje ô %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>Ô &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Pokŏż informacyje ô Qt</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>Ô&amp;pcyje...</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>Zmiyń ôpcyje kōnfiguracyje dlŏ %1</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;Zaszyfruj Portmanyj...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>Zrychtuj kopijõ ibrycznõ</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>Pōmiyń &amp;hasło</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses...</source>
+ <translation>&amp;Adresy posyłaniŏ</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses...</source>
+ <translation>Ad&amp;resy ôdbiyraniŏ</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Ôdewrzij &amp;URI...</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Portmanyj:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>wychodny portmanyj</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Kliknij coby zastawić aktywność necowõ.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Aktywność necowŏ ôstała zastawiōnŏ.</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Kliknij, coby zaś zapuścić aktywność necowõ.</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Synchrōnizowanie nŏgōwkōw (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Pōnowne indeksowanie blokōw na dysku...</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy je &lt;b&gt;zapuszczone&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>Poślij mōnety na adresã Bitcoin</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation>Ibryczny portmanyj w inkszyj lokalizacyje</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Pōmiyń hasło użyte do szyfrowaniŏ portmanyja</translation>
+ </message>
+ <message>
+ <source>&amp;Debug window</source>
+ <translation>Ôkno &amp;debugowaniŏ</translation>
+ </message>
+ <message>
+ <source>Open debugging and diagnostic console</source>
+ <translation>Ôdewrzij kōnsolã debugowaniŏ i diagnostyki</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Weryfikuj wiadōmość...</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Portmanyj</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>&amp;Poślij</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>Ôd&amp;bier</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>Pokŏż / &amp;Skryj</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Pokazuje abo skrywŏ bazowe ôkno</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Szyfruj klucze prywatne, kere sōm we twojim portmanyju</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Podpisz wiadōmości swojōm adresōm coby dowiyść jejich posiadanie</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Zweryfikuj wiadōmość, coby wejzdrzeć sie, iże ôstała podpisanŏ podanōm adresōm Bitcoin.</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>&amp;Zbiōr</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>&amp;Nasztalowania</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>Pō&amp;moc</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Lajsta szkart</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation>Żōndej płatu (gyneruje kod QR jak tyż URI bitcoin:)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Pokŏż wykŏz adres i etyket użytych do posyłaniŏ</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Pokŏż wykŏz adres i etyket użytych do ôdbiyraniŏ</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI or payment request</source>
+ <translation>Ôdewrzij URI bitcoin: abo żōndanie płatu</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>Ôp&amp;cyje piski kōmynd</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n aktywne połōnczynie do necu Bitcoin</numerusform><numerusform>%n aktywnych połōnczyń do necu Bitcoin</numerusform><numerusform>%n aktywnych skuplowań do necu Bitcoin</numerusform></translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Indeksowanie blokōw na dysku...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Przetwŏrzanie blokōw na dysku...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Przetworzōno %n blok historyji transakcyji.</numerusform><numerusform>Przetworzōno %n blokōw historyji transakcyji.</numerusform><numerusform>Przetworzōno %n blokōw historyji transakcyji.</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 za</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Ôstatni dostany blok ôstoł wygynerowany %1 tymu.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Transakcyje po tym mōmyncie niy bydōm jeszcze widzialne.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Feler</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Pozōr</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Informacyjŏ</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>Terŏźny</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Pokŏż pōmoc %1 coby zobŏczyć wykŏz wszyjskich ôpcyji piski nakŏzań.</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 klijynt</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>Trwŏ synchrōnizacyjŏ...</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Datōm: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Kwota: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>Portmanyj: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Zorta: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Etyketa: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Adresa: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Transakcyjŏ wysłanŏ</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Transakcyjŏ przichodzōncŏ</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>Gynerowanie kluczy HD je &lt;b&gt;zapuszczone&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Gynerowanie kluczy HD je &lt;b&gt;zastawiōne&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation>Portmanyj je &lt;b&gt;zaszyfrowany&lt;/b&gt; i terŏźnie &lt;b&gt;ôdszperowany&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation>Portmanyj je &lt;b&gt;zaszyfrowany&lt;/b&gt; i terŏźnie &lt;b&gt;zaszperowany&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation>Przitrefiōł sie krytyczny feler. Bitcoin niy poradzi kōntynuować bezpiycznie i ôstanie zawrzity.</translation>
+ </message>
+</context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation>Ôbiōr mōnet</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Wielość:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bajtōw:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Kwota:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Ôpłŏcka:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Sztaub:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Po ôpłŏcce:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Wydŏwka:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>Zaznacz/Ôdznacz wszyjsko</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Tryb strōma</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Tryb wykŏzu</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Kwota</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation>Ôdebrane z etyketōm</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Ôdebrane z adresōm</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Datōm</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>Przituplowania</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Przituplowany</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Kopiyruj adresã</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopiyruj etyketã</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopiyruj kwotã</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Kopiyruj ID transakcyje</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Zaszperuj niywydane</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Ôdszperuj niywydane</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Kopiyruj wielość</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Kopiyruj ôpłŏckã</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Kopiyruj wielość po ôpłŏcce</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Kopiyruj wielość bajtōw</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Kopiyruj sztaub</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Kopiyruj wydŏwkã</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 zaszperowane)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>ja</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>niy</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>Ta etyketa stŏwŏ sie czyrwōnŏ jeźli keryś z ôdbiyrŏczy dostŏwŏ kwotã myńszõ aniżeli terŏźny prōg sztaubu.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Chwiyrŏ sie +/- %1 satoshi na wchōd.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(chyba etykety)</translation>
+ </message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>wydŏwka z %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(wydŏwka)</translation>
+ </message>
+</context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation>Edytuj adresã</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>&amp;Etyketa</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation>Etyketa ôbwiōnzanŏ z tym wpisym na wykŏzie adres</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>Ta adresa je ôbwiōnzanŏ z wpisym na wykŏzie adres. Może być zmodyfikowany jyno dlŏ adres posyłajōncych.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>&amp;Adresa</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation>Nowŏ adresa posyłaniŏ</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Edytuj adresã ôdbiōru</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Edytuj adresã posyłaniŏ</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Wkludzōnŏ adresa "%1" niyma nŏleżnōm adresōm Bitcoin.</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adresa "%1" już je za adresã ôdbiorczõ z etyketōm "%2" i bez to niy idzie jeji przidać za adresã nadŏwcy.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Wkludzōnŏ adresa "%1" już je w ksiōnżce adres z ôpisym "%2".</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Niy idzie było ôdszperować portmanyja.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Gynerowanie nowego klucza niy podarziło sie.</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>Bydzie zrychtowany nowy folder danych.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>miano</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Katalog już je. Przidej %1 jeźli mŏsz zastrojynie zrychtować tukej nowy katalog.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>Niy idzie było tukej zrychtować folderu datōw.</translation>
+ </message>
+</context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation>wersyjŏ</translation>
+ </message>
+ <message>
+ <source>(%1-bit)</source>
+ <translation>(%1-bit)</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>Ô %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>Ôpcyje piski kōmynd</translation>
+ </message>
+</context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Welcome</source>
+ <translation>Witej</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation>Witej w %1.</translation>
+ </message>
+ <message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation>Pōniywŏż je to piyrsze sztartniyńcie programu, możesz ôbrać kaj %1 bydzie spamiyntować swoje daty.</translation>
+ </message>
+ <message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation>Kej naciśniesz OK, %1 zacznie pobiyrać i przetwŏrzać cołkõ %4 keta blokōw (%2GB) przi zaczynaniu ôd piyrszych transakcyji w %3 kej %4 ôstoł sztartniynty.</translation>
+ </message>
+ <message>
+ <source>This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
+ <translation>Wstympnŏ synchrōnizacyjŏ je barzo wymŏgajōncŏ i może wyzdradzić wczaśnij niyzaôbserwowane niyprzileżytości sprzyntowe. Za kożdym sztartniyńciym %1 pobiyranie bydzie kōntynuowane ôd placu w kerym ôstało zastawiōne.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation>Jeźli ôbrołś ôpcyjõ ukrōcyniŏ spamiyntowaniŏ kety blokōw (przicinanie) daty historyczne cołki czas bydōm musiały być pobrane i przetworzōne, jednak po tym ôstanõ wychrōniōne coby ôgraniczyć użycie dysku.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation>Użyj wychodnego folderu datōw</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>Użyj ôbranego folderu datōw</translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>Co nojmynij %1 GB datōw ôstanie spamiyntane w tym katalogu, daty te bydōm z czasym corŏz srogsze.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation>Kole %1 GB datōw ôstanie spamiyntane w tym katalogu.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>%1 sebiere i spamiyntŏ kopijõ kety blokōw Bitcoin.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>Portmanyj tyż ôstanie spamiyntany w tym katalogu.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>Feler: podany folder datōw "%1" niy mōg ôstać zrychtowany.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Feler</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>%n GB swobodnego placu dostympne</numerusform><numerusform>%n GB swobodnego placu dostympne</numerusform><numerusform>%n GB swobodnego placu dostympne</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(z %n GB przidajnego)</numerusform><numerusform>(z %n GB przidajnych)</numerusform><numerusform>(z %n GB przidajnych)</numerusform></translation>
+ </message>
+</context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation>Formular</translation>
+ </message>
+ <message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation>Świyże transakcyje mogōm niy być jeszcze widzialne, a tedyć saldo portmanyja może być niynŏleżne. Te detale bydōm nŏleżne, kej portmanyj zakōńczy synchrōnizacyjõ z necym bitcoin, zgodnie z miyniōnym ôpisym.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation>Prōba wydaniŏ bitcoinōw kere niy sōm jeszcze wyświytlōne za transakcyjŏ ôstanie ôdciepniyntŏ bez nec.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Ôstało blokōw</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Niyznōme...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Czŏs ôstatnigo bloku</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>Postymp</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>Przirost postympu na godzinã</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>ôbliczanie...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Przewidowany czŏs abszlusu synchrōnizacyje</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Skryj</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1)...</source>
+ <translation>Niyznōme. Synchrōnizowanie nŏgōwkōw (%1)...</translation>
+ </message>
+</context>
+<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <source>Open URI</source>
+ <translation>Ôdewrzij URI</translation>
+ </message>
+ <message>
+ <source>Open payment request from URI or file</source>
+ <translation>Ôdewrzij żōndanie płatu z URI abo zbioru</translation>
+ </message>
+ <message>
+ <source>URI:</source>
+ <translation>URI:</translation>
+ </message>
+ <message>
+ <source>Select payment request file</source>
+ <translation>Ôtwōrz żōndanie płatu ze zbioru</translation>
+ </message>
+ <message>
+ <source>Select payment request file to open</source>
+ <translation>Ôbier zbiōr żōndaniŏ płatu do ôdewrzyniŏ</translation>
+ </message>
+</context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>Options</source>
+ <translation>Ôpcyje</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation>&amp;Bazowe</translation>
+ </message>
+ <message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Autōmatycznie sztartnij %1 po wlogowaniu do systymu.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Sztartuj %1 w czasie logowaniŏ do systymu</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Srogość bufōra bazy datōw</translation>
+ </message>
+ <message>
+ <source>MB</source>
+ <translation>MB</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>Wielość wōntkōw &amp;weryfikacyje skryptu</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>Adresa IP proxy (bp. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ </message>
+ <message>
+ <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
+ <translation>Minimalizuje zamiast zakōńczyć fungowanie aplikacyje przi zawiyraniu ôkna. Kej ta ôpcyjŏ je zapuszczonŏ, aplikacyjŏ zakōńczy fungowanie po ôbraniu Zawrzij w myni.</translation>
+ </message>
+ <message>
+ <source>Active command-line options that override above options:</source>
+ <translation>Aktywne ôpcyje piski kōmynd, kere nadpisujōm powyższe ôpcyje:</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Ôdewrzij %1 zbiōr kōnfiguracyje z czynnego katalogu.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Ôdewrzij zbiōr kōnfiguracyje</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>Prziwrōć wszyjske wychodne ustawiyniŏ klijynta.</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;Resetuj Ôpcyje</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>&amp;Nec</translation>
+ </message>
+ <message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Zastawiŏ niykere moderne funkcyje, ale wszyjske bloki durch bydōm w połni wybadowane. Cŏfniyńcie tego nasztalowaniŏ fołdruje pōnownego sebraniŏ cołkij kety blokōw. Istne spotrzebowanie dysku może być cosikej wyższe.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Przitnij skłŏd &amp;blokōw do</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Cŏfniyńcie tego ustawiyniŏ wymŏgŏ pōnownego sebraniŏ cołkij kety blokōw.</translation>
+ </message>
+ <message>
+ <source>(0 = auto, &lt;0 = leave that many cores free)</source>
+ <translation>(0 = autōmatycznie, &lt;0 = ôstŏw tela swobodnych drzyni)</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>Portm&amp;anyj</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation>Ekspert</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Zapuść funkcyje kōntroli mōnet</translation>
+ </message>
+ <message>
+ <source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
+ <translation>Jeźli zastawisz możebność wydaniŏ niyprzituplikowanyj wydanej wydŏwki, wydŏwka z transakcyje niy bydzie mogła ôstać użytŏ, podwiela ta transakcyjŏ niy bydzie miała nojmynij jednego przituplowaniŏ. To tyż mŏ wpływ na porachowanie Twojigo salda.</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation>&amp;Wydej niyprzituplowanõ wydŏwkã</translation>
+ </message>
+ <message>
+ <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
+ <translation>Autōmatycznie ôdewrzij port klijynta Bitcoin na routerze. Ta ôpcyjŏ funguje ino jeźli twōj router podpiyrŏ UPnP i je ôno zapuszczone.</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation>Mapuj port przi używaniu &amp;UPnP</translation>
+ </message>
+ <message>
+ <source>Accept connections from outside.</source>
+ <translation>Akceptuj skuplowania ôd zewnōntrz.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Zwōl na skuplowania przichodzōnce</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>Skupluj sie z necym Bitcoin bez SOCKS5 proxy.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;Skupluj bez proxy SOCKS5 (wychodne proxy):</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>Proxy &amp;IP:</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation>&amp;Port:</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation>Port ôd proxy (bp. 9050)</translation>
+ </message>
+ <message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Tor</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>Skupluj sie z necym Bitcoin ze pōmocōm ôsobnego proxy SOCKS5 dlŏ necu TOR</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>Ô&amp;kno</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation>Gŏdka &amp;używŏcza:</translation>
+ </message>
+ <message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation>Idzie sam nasztalować gŏdka interfejsu używŏcza. Nasztalowanie prziniesie skutki po resztarcie %1.</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>&amp;OK</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>&amp;Pociep</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>wychodny</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation>żŏdyn</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Ôpcyje kōnfiguracyje</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Feler</translation>
+ </message>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation>Formular</translation>
+ </message>
+ <message>
+ <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
+ <translation>Wyświytlanŏ informacyjŏ może być niyterŏźnŏ. Twōj portmanyj synchrōnizuje sie autōmatycznie z necym bitcoin zarŏz po tym, jak zrychtowane je skuplowanie, ale proces tyn niy ôstoł jeszcze skōńczōny.</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Dostympne:</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>Czekajōnce:</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>Salda</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Cuzamyn:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation>Twoje terŏźne saldo</translation>
+ </message>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ <message>
+ <source>URI handling</source>
+ <translation>Bedynōng URI</translation>
+ </message>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' to niyma nŏleżne URI. Użyj 'bitcoin:'.</translation>
+ </message>
+ <message>
+ <source>Payment request network doesn't match client network.</source>
+ <translation>Nec żōndaniŏ płatu niy ôdpadŏ necu klijynta.</translation>
+ </message>
+ <message>
+ <source>Unverified payment requests to custom payment scripts are unsupported.</source>
+ <translation>Niyzweryfikowane żōndaniŏ płatu do włŏsnych skryptōw płatu sōm niypodpiyrane.</translation>
+ </message>
+ <message>
+ <source>Network request error</source>
+ <translation>Feler żōndaniŏ necu</translation>
+ </message>
+ <message>
+ <source>Payment acknowledged</source>
+ <translation>Płat przituplowany</translation>
+ </message>
+</context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>User Agent</source>
+ <translation>Agynt Używŏcza</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>Ping</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Ôdebrane</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Kwota</translation>
+ </message>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Wkludź adresã Bitcoin (bp. %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 d</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 h</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 m</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 s</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>N/A</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation>%1 ms</translation>
+ </message>
+ <message>
+ <source>%1 B</source>
+ <translation>%1 B</translation>
+ </message>
+ <message>
+ <source>%1 KB</source>
+ <translation>%1 KB</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 MB</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 GB</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>niyznōme</translation>
+ </message>
+</context>
+<context>
+ <name>QObject::QObject</name>
+ <message>
+ <source>Error: %1</source>
+ <translation>Feler: %1</translation>
+ </message>
+</context>
+<context>
+ <name>QRImageWidget</name>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Spamiyntej Ôbrŏzek</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Kopiyruj Ôbrŏzek</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Spamiyntej kod QR</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>Ôbrŏzek PNG (*.png)</translation>
+ </message>
+</context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>N/A</source>
+ <translation>N/A</translation>
+ </message>
+ <message>
+ <source>Client version</source>
+ <translation>Wersyjŏ klijynta</translation>
+ </message>
+ <message>
+ <source>Debug window</source>
+ <translation>Ôkno debugowaniŏ</translation>
+ </message>
+ <message>
+ <source>Using BerkeleyDB version</source>
+ <translation>Używanie wersyje BerkeleyDB</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>Katalog datōw</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation>Czŏs sztartniyńciŏ</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>Nec</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>Miano</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation>Wielość skuplowań</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation>Keta blokōw</translation>
+ </message>
+ <message>
+ <source>Current number of blocks</source>
+ <translation>Terŏźniŏ wielość blokōw</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>Terŏźniŏ wielość transakcyji</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation>Portmanyj: </translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Ôdebrane</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Richtōng</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>Wersyjŏ</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>Agynt Używŏcza</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>Usugi</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>Czŏs Skuplowaniŏ</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Czas ôstatnigo bloku</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>Ô&amp;dewrzij</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;Ruch necowy</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>Wchōd:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Wychōd:</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;dziyń</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>Ô&amp;dkupluj</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>wychodny portmanyj</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Witej w %1 kōnsoli RPC.</translation>
+ </message>
+ <message>
+ <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
+ <translation>POZŌR: Machlyrze namŏwiajōm do wpisowaniŏ tukej roztōmajtych nakŏzań coby porwać portmanyj. Niy używej tyj kōnsole bez połnego zrozumiyniŏ wpisowanych nakŏzań.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Aktywność necowŏ zastawiōnŏ</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>nikej</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>Wchodowy</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>Wychodowy</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation>Ja</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation>Niy</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etyketa:</translation>
+ </message>
+ <message>
+ <source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
+ <translation>Ôpcyjōnalnŏ wiadōmość do prziwstōniŏ do żōndaniŏ płatu, kerŏ bydzie wyświytlanŏ, kej żōndanie ôstanie ôdewrzōne. Napōmniynie: wiadōmość ta niy ôstanie wysłanŏ z płatym w nec Bitcoin.</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>Wypucuj</translation>
+ </message>
+ <message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Natywne adresy segwit (aka Bech32 abo BIP-173) zmyńszajōm niyskorzij twoje ôpłŏcki za transakcyje i dadzōm lepsze zabezpieczynie przed chybami, ale stare portmanyje jejich niy podpiyrajōm. Jeźli ôdznaczōne, zrychtowanŏ ôstanie adresa kōmpatybilnŏ ze starszymi portmanyjami.</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>Pokŏż</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Wychrōń</translation>
+ </message>
+ <message>
+ <source>Copy URI</source>
+ <translation>Kopiyruj URI</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopiyruj etyketã</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Kopiyruj wiadōmość</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopiyruj kwotã</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>QR Code</source>
+ <translation>Kod QR</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation>Kopiyruj &amp;URI</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Address</source>
+ <translation>Kopiyruj &amp;Adresã</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Spamiyntej Ôbrozek</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>Informacyje ô płacie</translation>
+ </message>
+ <message>
+ <source>URI</source>
+ <translation>URI</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Adresa</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Kwota</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etyketa</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Wiadōmość</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Portmanyj</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Datōm</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etyketa</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Wiadōmość</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(chyba etykety)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Poślij mōnety</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Wielość:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bajtōw:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Kwota:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Ôpłŏcka:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Po ôpłŏcce:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Wydŏwka:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>Ôbier...</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Pozōr: Ôszacowanie ôpłŏcki za transakcyje je aktualnie niymożebne.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>na kilobajt</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Skryj</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>Doradzane:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>Włŏsne:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Sztaub:</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation>Saldo:</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Kopiyruj wielość</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopiyruj kwotã</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Kopiyruj ôpłŏckã</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Kopiyruj wielość po ôpłŏcce</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Kopiyruj wielość bajtōw</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Kopiyruj sztaub</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Kopiyruj wydŏwkã</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blokōw)</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>abo</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Utworzynie transakcyje niy podarziło sie!</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Pozōr: niynŏleżnŏ adresa Bitcoin</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Pozōr: Niyznōmŏ adresa wydŏwki</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(chyba etykety)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etyketa:</translation>
+ </message>
+ <message>
+ <source>This is a normal payment.</source>
+ <translation>To je normalny płat.</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Użyj dostympnego salda</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Wiadōmość:</translation>
+ </message>
+ <message>
+ <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
+ <translation>Wiadōmość, kerŏ ôstała prziwstōnŏ do URI bitcoin:, kerŏ bydzie przechowowanŏ z transakcyjōm w cylach informacyjnych. Napōmniynie: Ta wiadōmość niy bydzie rozszyrzowanŏ w necu Bitcoin.</translation>
+ </message>
+ </context>
+<context>
+ <name>SendConfirmationDialog</name>
+ <message>
+ <source>Yes</source>
+ <translation>Ja</translation>
+ </message>
+</context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>Szkryfki - Podpisz / Zweryfikuj Wiadōmość</translation>
+ </message>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;Szkryftnij Wiadōmość</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>Szkryftnij &amp;Wiadōmość</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation>&amp;Weryfikuj Wiadōmość</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Szkryftniyńcie wiadōmości niy podarziło sie.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Wiadōmość szkryftniyntŏ.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Weryfikacyjŏ wiadōmości niy podarziła sie.</translation>
+ </message>
+ </context>
+<context>
+ <name>SplashScreen</name>
+ <message>
+ <source>[testnet]</source>
+ <translation>[testnet]</translation>
+ </message>
+</context>
+<context>
+ <name>TrafficGraphWidget</name>
+ <message>
+ <source>KB/s</source>
+ <translation>KB/s</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Status</source>
+ <translation>Sztatus</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Datōm</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>Źrōdło</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>Z</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>niyznōme</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>Do</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>etyketa</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Wiadōmość</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Kōmyntŏrz</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transakcyjŏ</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Kwota</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Datōm</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Zorta</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etyketa</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Ôdebrane z</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Ôdebrane ôd</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Płat do siebie</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(chyba etykety)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>All</source>
+ <translation>Wszyjske</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Dzisiej</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Ôdebrane z</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Inksze</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Wkludź adresa, idyntyfikatōr transakcyje abo etyketã coby wyszukać</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Kopiyruj adresã</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Kopiyruj etyketã</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Kopiyruj kwotã</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Kopiyruj ID transakcyje</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Edytuj etyketa</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Zbiōr *.CSV (dane rozdzielane kōmami)</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Przituplowany</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Datōm</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Zorta</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etyketa</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>Adresa</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Eksportowanie niy podarziło sie</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>do</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ </context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Poślij mōnety</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>Nowŏ ôpłŏcka:</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Eksportuj dane z aktywnyj szkarty do zbioru</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Backup niy podarził sie</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>Pociep</translation>
+ </message>
+</context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Bitcoin Core</source>
+ <translation>Bitcoin Core</translation>
+ </message>
+ <message>
+ <source>The %s developers</source>
+ <translation>Twōrcy %s</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Pozōr: Nec niy wydŏwŏ sie w połni zgodliwy! Niykerzi grubiŏrze wydajōm sie doświadczać niyprzileżytości.</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Copyright (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>Feler wgrŏwaniŏ %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Feler wgrŏwaniŏ %s: Klucze prywatne mogōm być zastawiōne ino w czasie tworzyniŏ</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Feler wgrŏwaniŏ %s: Portmanyj poprzniōny</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Feler wgrŏwaniŏ %s: Portmanyj wymŏgŏ nowszyj wersyje %s</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>Feler wgrŏwaniŏ bazy blokōw</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low!</source>
+ <translation>Feler: Za mało wolnego placu na dysku!</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>Wgrŏwanie adres P2P...</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>Wgrŏwanie wykŏzu zaszperowanych...</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
+ <translation>Niypodpiyrany argumynt -benchmark zignorowany, użyj -debug=bench.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
+ <translation>Niypodpiyrany argumynt -debugnet zignorowany, użyj -debug=net.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -tor found, use -onion.</source>
+ <translation>Znŏdniynto było niypodpiyrany argumynt -tor, użyj -onion.</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Niypodpiyranŏ kategoryjŏ registrowaniŏ %s=%s.</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>Weryfikacyjŏ blokōw...</translation>
+ </message>
+ <message>
+ <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
+ <translation>Feler w czasie wgrŏwaniŏ %s: Niy idzie zastawić HD w już bydōncym portmanyju HD</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Informacyjŏ</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation>Szkryftniyńcie transakcyji niy podarziło sie</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>To je eksperymyntalny softwer.</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>Transakcyjŏ za srogŏ</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>Weryfikacyjŏ portmanyja(ōw)...</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Pozōr</translation>
+ </message>
+ <message>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <translation>Pozōr: aktywowano było niyznōme nowe prawidła (versionbit %i)</translation>
+ </message>
+ <message>
+ <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
+ <translation>Feler w czasie wgrŏwaniŏ %s: Niy idzie zapuścić HD w już bydōncym portmanyju niy-HD</translation>
+ </message>
+ <message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation>Imyntnŏ dugość kety wersyje (%i) przekrŏczŏ maksymalnõ dopuszczalnõ dugość (%i). Zmyńsz wielość abo miara parametra uacomment.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
+ <translation>Znŏdniynto było niypodpiyrany argumynt -socks. Ôbiyranie wersyje SOCKS je już niymożebne, podpiyrane sōm ino proxy SOCKS5.</translation>
+ </message>
+ <message>
+ <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
+ <translation>Niypodpiyrany argumynt -whitelistalwaysrelay zignorowany, użyj -whitelistrelay i/abo -whitelistforcerelay.</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
+ <translation>Pozōr: wydobywane sōm niyznōme wersyje blokōw! Możliwe, iże ôbowiōnzujōm niyznōme prawidła.</translation>
+ </message>
+ <message>
+ <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
+ <translation>Pozōr: Ôdtworzōno było dane z poprzniōnego zbioru portmanyja! Ôryginalny %s ôstoł zapisany za %s w %s; jeźli twoje saldo abo transakcyje sōm niynŏleżne winiyn żeś prziwrōcić kopijõ ibrycznõ.</translation>
+ </message>
+ <message>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>Feler w czasie wgrŏwaniŏ portmanyja %s. Podanŏ tuplowane miano zbioru w -wallet.</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>Sztartowanie wōntkōw necowych...</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation>Niyznōmy nec ôkryślōny w -onlynet: '%s'</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Pozōr: Wykryto było klucze prywatne w portmanyju {%s} kery mŏ zastawiōne klucze prywatne</translation>
+ </message>
+ <message>
+ <source>Loading block index...</source>
+ <translation>Wgrŏwanie indeksu blokōw...</translation>
+ </message>
+ <message>
+ <source>Loading wallet...</source>
+ <translation>Wgrŏwanie portmanyja...</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>Pōnowne skanowanie</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation>Wgrŏwanie zakōńczōne</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Feler</translation>
+ </message>
+</context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts
index e43fa04e27..9e598c0483 100644
--- a/src/qt/locale/bitcoin_ta.ts
+++ b/src/qt/locale/bitcoin_ta.ts
@@ -580,6 +580,10 @@
<source>Address</source>
<translation>முகவரி</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>பணப்பை</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -712,10 +716,6 @@
<translation>Bitcoin மையம்</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(default: %u)</translation>
- </message>
- <message>
<source>Information</source>
<translation>தகவல்</translation>
</message>
@@ -724,10 +724,6 @@
<translation>எச்சரிக்கை</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(default: %s)</translation>
- </message>
- <message>
<source>Error</source>
<translation>தவறு</translation>
</message>
diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts
index 8ee52ffca4..81491c8ddc 100644
--- a/src/qt/locale/bitcoin_th_TH.ts
+++ b/src/qt/locale/bitcoin_th_TH.ts
@@ -511,42 +511,6 @@
<source>Command-line options</source>
<translation>ตัวเลือก Command-line</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>วิธีใช้งาน:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>ตัวเลือก command-line</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>ตัวเลือก UI:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>เลือกไดเร็กทอรี่ข้อมูลตั้งแต่เริ่มต้นสตาร์ทอัพ (ค่าเริ่มต้น: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>ตั้งค่าภาษา ยกตัวอย่าง "de_DE" (ค่าเริ่มต้น: ภาษาท้องถิ่นของระบบ)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>เริ่มต้นมินิไมซ์</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>ตั้งค่า SSL root certificates สำหรับเรียกการชำระเงิน (ค่าเริ่มต้น: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>แสดง splash screen ตอนเริ่มต้น (ค่าเริ่มต้น: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>รีเซตการเปลี่ยนการตั้งค่าทั้งหมดใน GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -802,6 +766,10 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
+ <message>
+ <source>Wallet</source>
+ <translation>กระเป๋าเงิน</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -894,10 +862,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>ตัวเลือก:</translation>
- </message>
- <message>
<source>Information</source>
<translation>ข้อมูล</translation>
</message>
diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts
index a5623c0173..db30aa04c2 100644
--- a/src/qt/locale/bitcoin_tr.ts
+++ b/src/qt/locale/bitcoin_tr.ts
@@ -30,6 +30,10 @@
<translation>Seçili adresi listeden sil</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Aranacak adres ya da etiket giriniz</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Açık olan sekmedeki verileri bir dosyaya aktar</translation>
</message>
@@ -322,6 +326,14 @@
<translation>&amp;URI Aç...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Cüzdan:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>varsayılan cüzdan</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Ağ etkinliğini devre dışı bırakmak için tıklayın.</translation>
</message>
@@ -342,6 +354,10 @@
<translation>Diskteki bloklar yeniden indeksleniyor...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Tünelleme &lt;b&gt;etkin&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Bir bitcoin adresine bitcoin gönder</translation>
</message>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Cüzdan: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Tür: %1
@@ -730,10 +752,6 @@
<translation>&amp;Adres</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Yeni alım adresi</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Yeni gönderi adresi</translation>
</message>
@@ -750,8 +768,8 @@
<translation>Girilen "%1" adresi geçerli bir Bitcoin adresi değildir.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Girilen "%1" adresi zaten adres defterinde mevcuttur.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Adres "%1" adres "%2" etiketiyle alım adresiniz olarak mevcut ve bu sebepten gönderen adres olarak eklenemiyor.</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +821,6 @@
<source>Command-line options</source>
<translation>Komut satırı seçenekleri</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Kullanım:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>komut satırı seçenekleri</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Arayüz Seçenekleri:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Başlangıçta veri klasörü seç (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Lisan belirt, mesela "de_De" (varsayılan: sistem dili)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Küçültülmüş olarak başlat</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Ödeme talebi için SSL kök sertifikalarını belirle (varsayılan: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Başlatıldığında başlangıç ekranını göster (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Grafik arayüzde yapılan tüm seçenek değişikliklerini sıfırla</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1519,8 +1501,8 @@
<translation>Hata: Belirtilen "%1" veri klasörü yoktur.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Hata: %1 yapılandırma dosyası ayrıştırılamadı. Sadece anahtar=değer dizimini kullanınız.</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Hata: %1 yapılandırma dosyası ayrıştırılamadı. </translation>
</message>
<message>
<source>Error: %1</source>
@@ -1613,6 +1595,14 @@
<translation>Bellek kullanımı</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Cüzdan:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(boş)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;Sıfırla</translation>
</message>
@@ -1781,6 +1771,10 @@
<translation>&amp;Yasaklamayı Kaldır</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>varsayılan cüzdan</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>%1 RPC konsoluna hoş geldiniz.</translation>
</message>
@@ -1805,6 +1799,14 @@
<translation>Ağ etkinliği devre dışı bırakıldı</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Komut bir cüzdan olmadan çalıştırılıyor</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Komut "%1" cüzdanı kullanılarak çalıştırılıyor</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(düğüm kimliği: %1)</translation>
</message>
@@ -1876,6 +1878,10 @@
<translation>Temizle</translation>
</message>
<message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Yerli segwit (Bech32) adresi oluştur</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Talep edilen ödemelerin tarihçesi</translation>
</message>
@@ -1884,10 +1890,6 @@
<translation>Ödeme &amp;talep et</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>Bech32 adresi oluştur</translation>
- </message>
- <message>
<source>Show the selected request (does the same as double clicking an entry)</source>
<translation>Seçilen talebi göster (bir unsura çift tıklamakla aynı anlama gelir)</translation>
</message>
@@ -1967,6 +1969,10 @@
<translation>İleti</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Cüzdan</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Sonuç URI çok uzun, etiket ya da ileti metnini kısaltmayı deneyiniz.</translation>
</message>
@@ -2081,10 +2087,6 @@
<translation>kilobayt başı</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Eğer özel ücret 1000 satoşi olarak ayarlandıysa ve işlem sadece 250 baytsa, "kilobayt başı" ücret olarak sadece 250 satoşi öder ve "toplam asgari" 1000 satoşi öder. Bir kilobayttan yüksek işlemler için ikisi de kilobayt başı ödeme yapar.</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Gizle</translation>
</message>
@@ -2185,16 +2187,24 @@
<translation>Göndermek istediğinizden emin misiniz?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>işlem ücreti olarak eklendi</translation>
+ <source>or</source>
+ <translation>veya</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Toplam Tutar %1</translation>
+ <source>from wallet %1</source>
+ <translation>cüzdan %1'den</translation>
</message>
<message>
- <source>or</source>
- <translation>veya</translation>
+ <source>Please, review your transaction.</source>
+ <translation>Lütfen, işleminizi gözden geçirin.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>İşlem ücreti</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Toplam Tutar</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2534,10 +2544,6 @@
<translation>%1 doğrulamalı bir işlem ile çelişti</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/çevrim dışı</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/doğrulanmamış, %1</translation>
</message>
@@ -2566,14 +2572,6 @@
<translation>Durum</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, henüz başarılı bir şekilde yayınlanmadı</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, %n düğüm aracılığıyla yayınlandı</numerusform><numerusform>, %n düğüm aracılığıyla yayınlandı</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Tarih</translation>
</message>
@@ -2728,10 +2726,6 @@
<translation>%1 değerine dek açık</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Çevrim dışı</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Doğrulanmamış</translation>
</message>
@@ -2756,10 +2750,6 @@
<translation>Olgunlaşmamış (%1 doğrulama, %2 doğrulama sonra kullanılabilir olacaktır)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Bu blok başka hiçbir düğüm tarafından alınmamıştır ve muhtemelen kabul edilmeyecektir!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Oluşturuldu ama kabul edilmedi</translation>
</message>
@@ -2871,6 +2861,10 @@
<translation>Diğer</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Aramak için adres, gönderim numarası ya da etiket yazınız</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>En düşük tutar</translation>
</message>
@@ -3058,38 +3052,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Cüzdan verileri %1 konumuna başarıyla kaydedildi.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>İptal</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Seçenekler:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Veri dizinini belirt</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Eş adresleri elde etmek için bir düğüme bağlan ve ardından bağlantıyı kes</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Kendi genel adresinizi tanımlayın</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Komut satırı ve JSON-RPC komutlarını kabul et</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>MIT yazılım lisansı altında dağıtılmıştır, beraberindeki %s ya da %s dosyasına bakınız.</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Eğer &lt;category&gt; belirtilmemişse ya da &lt;category&gt; = 1 ise, tüm hata ayıklama verilerini çıktı al.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Budama, en düşük değer olan %d MiB'den düşük olarak ayarlanmıştır. Lütfen daha yüksek bir sayı kullanınız.</translation>
</message>
@@ -3106,18 +3080,10 @@
<translation>Hata: Ölümcül dahili bir hata meydana geldi, ayrıntılar için debug.log dosyasına bakınız</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Yolladığınız işlemlere eklenecek ücret (%s/kB olarak) (varsayılan: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Blockstore budanıyor...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Arka planda daemon (servis) olarak çalış ve komutları kabul et</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>HTTP sunucusu başlatılamadı. Ayrıntılar için debug.log dosyasına bakınız.</translation>
</message>
@@ -3130,50 +3096,14 @@
<translation>%s geliştiricileri</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>Ücret tahmini için yetersiz veri bulunduğunda kullanılacak ücret oranı (%s/kB olarak) (varsayılan: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>İşlemler aktarılmadığında dahi beyaz listedeki eşlerden aktarılan işlemleri kabul et (varsayılan: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Belirtilen adrese bağlan ve daima ondan dinle. IPv6 için [makine]:port yazımını kullanınız</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>%s veri dizininde kilit elde edilemedi. %s muhtemelen hâlihazırda çalışmaktadır.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Tüm cüzdan işlemlerini sil ve başlangıçta -rescan ile sadece blok zincirinin parçası olanları geri getir</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>%s dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak işlem verileri ya da adres defteri ögeleri hatalı veya eksik olabilir.</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Bir cüzdan işlemi değiştiğinde komutu çalıştır (komuttaki %s işlem kimliği ile değiştirilecektir)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Daha küçük boyutlu blok yeniden yapılandırması için fazladan işlemleri bellekte tut. (varsayılan: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>Eğer bu blok zincirde yer alıyorsa onun ve atalarının geçerli olduğunu varsay ve potansiyel olarak onların betik doğrulamasını atla. (Tümünü doğrulamak için 0, varsayılan %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>İzin verilen edilen en yüksek medyan eş zamanı değişiklik sınırının ayarlaması. Zamanın yerel perspektifi bu miktar kadar ileri ya da geri eşler tarafından etkilenebilir. (Varsayılan %u saniye)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Tek bir cüzdan işleminde ya da ham işlemde kullanılacak en yüksek toplam ücret (%s olarak); bunu çok düşük olarak ayarlamak büyük işlemleri iptal edebilir (varsayılan: %s)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>Lütfen bilgisayarınızın saat ve tarihinin doğru olduğunu kontrol ediniz! Saatinizde gecikme varsa %s doğru şekilde çalışamaz.</translation>
</message>
@@ -3182,18 +3112,6 @@
<translation>%s programını faydalı buluyorsanız lütfen katkıda bulununuz. Yazılım hakkında daha fazla bilgi için %s adresini ziyaret ediniz.</translation>
</message>
<message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Eski blokları budamayı (silme) etkinleştirerek depolama gereksinimlerini azaltın. Bu belirli blokları silmek için pruneblockchain uzak yordam çağrısına (RPC) izin verir. Eğer bloklar hedef mebibyte boyutuna ulaşırsa eski blokların otomatik olarak budanmasını sağlar. Bu kip, -txindex ve -rescan ile uyumsuzdur. Uyarı: Bu ayarı geri almak, blok zincirinin tamamını yeniden yüklemeyi gerektirir. (varsayılan: 0 = blok budaması devre dışı, 1 = RPC üzerinden manuel budamaya izin verir, &gt;%u = mebibyte olarak belirtilen hedef boyutun altında kalması için blok dosyalarını otomatik olarak budar)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Blok oluşturmaya dahil olan işlemler için en düşük ücret oranını (%s/kB olarak) ayarla. (varsayılan: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Betik kontrolü iş parçacıklarının sayısını belirler (%u ilâ %d, 0 = otomatik, &lt;0 = bu sayıda çekirdeği kullanma, varsayılan: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Blok veritabanı gelecekten gibi görünen bir blok içermektedir. Bu, bilgisayarınızın saat ve tarihinin yanlış ayarlanmış olmasından kaynaklanabilir. Blok veritabanını sadece bilgisayarınızın tarih ve saatinin doğru olduğundan eminseniz yeniden derleyin.</translation>
</message>
@@ -3206,18 +3124,6 @@
<translation>Veritabanını çatallama öncesi duruma geri sarmak mümkün değil. Blok zincirini tekrar indirmeniz gerekmektedir</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde ve -proxy olmadığında 1)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>JSON-RPC bağlantıları için kullanıcı adı ve karmalanmış parola. &lt;userpw&gt; alanı şu biçimdedir: &lt;KULLANICI ADI&gt;:&lt;SALT&gt;$&lt;HASH&gt;. Kanonik bir Python betiği share/rpcuser klasöründe bulunabilir. Ardından istemci normal şekilde rpcuser=&lt;KULLANICI ADI&gt;/rpcpassword=&lt;PAROLA&gt; argüman çiftini kullanarak bağlanabilir. Bu seçenek birden çok kez belirtilebilir.</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Cüzdan, zincir bellek alanı limitlerini ihlal eden işlem oluşturmayacak. (varsayılan: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Uyarı: Ağ üyeleri aralarında tamamen anlaşmış gibi gözükmüyor! Bazı madenciler sorun yaşıyor gibi görünmektedir.</translation>
</message>
@@ -3238,42 +3144,14 @@
<translation>-maxmempool en az %d MB olmalıdır</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;kategori&gt; şunlar olabilir:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Dışarıdan gelen bağlantıları kabul et (varsayılan: -proxy veya -connect yoksa 1)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Kullanıcı aracı zincirine yorumu ekle</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Başlangıçta bozuk bir cüzdandan özel anahtarları geri kazanmayı dene</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Blok oluşturma seçenekleri:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Çözümlenemedi - %s adres: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Blok zinciri seçim ayarları:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Aralık dışında değişiklik indeksi</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Bağlantı seçenekleri:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Telif hakkı (C) %i-%i</translation>
</message>
@@ -3282,38 +3160,10 @@
<translation>Bozuk blok veritabanı tespit edildi</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Hata ayıklama/deneme seçenekleri:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Cüzdanı yükleme ve cüzdan RPC çağrılarını devre dışı bırak</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Blok veritabanını şimdi yeniden inşa etmek istiyor musunuz?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Blok karma değerinin &lt;adres&gt;te yayınlanmasını etkinleştir</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Karma değer işleminin &lt;adres&gt;te yayınlanmasını etkinleştir</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Ham blokun &lt;adres&gt;te yayınlanmasını etkinleştir</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Ham işlemin &lt;adres&gt;te yayınlanmasını etkinleştir</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Bellek alanında işlem değiştirmeyi etkinleştir (varsayılan: %u)</translation>
- </message>
- <message>
<source>Error initializing block database</source>
<translation>Blok veritabanını başlatılırken bir hata meydana geldi</translation>
</message>
@@ -3378,8 +3228,8 @@
<translation> -fallbackfee=&lt;tutar&gt; için geçersiz tutar: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>İşlem bellek alanını &lt;n&gt; megabayttan düşük tut (varsayılan: %u)</translation>
+ <source>Upgrading txindex database</source>
+ <translation>txindex veritabanı yükseltiliyor</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3390,26 +3240,10 @@
<translation>Yasaklama listesi yükleniyor...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>auth çerezinin konumu (varsayılan: veri klasörü)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Kafi derecede dosya tanımlayıcıları mevcut değil.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Sadece &lt;net&gt; ağındaki düğümlere bağlan (ipv4, ipv6 veya onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Bu yardım mesajını yaz ve çık</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Sürümü yaz ve çık</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Budama negatif bir değerle yapılandırılamaz.</translation>
</message>
@@ -3418,14 +3252,6 @@
<translation>Budama kipi -txindex ile uyumsuzdur.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Zincir durumu ve blok indeksini diskteki blk*.dat dosyalarından yeniden derle</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Zincir durumunu güncel olarak indekslenen bloklardan yeniden derle</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Bloklar tekrar işleniyor...</translation>
</message>
@@ -3434,14 +3260,6 @@
<translation>Bloklar geri sarılıyor...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Veritabanı önbellek boyutunu megabayt olarak belirt (%d ilâ %d, varsayılan: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Cüzdan dosyası belirtiniz (veri klasörünün içinde)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>Kaynak kod şuradan elde edilebilir: %s.</translation>
</message>
@@ -3454,6 +3272,10 @@
<translation>Bu bilgisayarda %s unsuruna bağlanılamadı. %s muhtemelen hâlihazırda çalışmaktadır.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Anahtar üretilemiyor</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Desteklenmeyen -benchmark argümanı görmezden gelindi, -debug=bench kullanınız.</translation>
</message>
@@ -3474,14 +3296,6 @@
<translation>UTXO veritabanı yükseltiliyor</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Dinleme portunu haritalamak için UPnP kullan (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Test blok zincirini kullan</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>Kullanıcı Aracı açıklaması (%s) güvensiz karakterler içermektedir.</translation>
</message>
@@ -3490,90 +3304,26 @@
<translation>Bloklar kontrol ediliyor...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Cüzdan hata ayıklama/test etme seçenekleri:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Cüzdanın tekrar yazılması gerekiyordu: işlemi tamamlamak için %s programını yeniden başlatınız</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Cüzdan seçenekleri:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Belirtilen kaynaktan JSON-RPC bağlantılarını kabul et. Bir &lt;ip&gt; için geçerli olanlar şunlardır: IP adresi (mesela 1.2.3.4), bir ağ/ağ maskesi (örneğin 1.2.3.4/255.255.255.0) ya da bir ağ/CIDR (mesela 1.2.3.4/24). Bu seçenek birden fazla kez belirtilebilir</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Belirtilen adrese bağlan ve ona bağlanan eşleri beyaz listeye al. IPv6 için [makine]:port imlasını kullanınız</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Yeni dosyaları umask 077 yerine varsayılan izinlerle oluştur (sadece devre dışı cüzdan işlevselliği ile etkilidir)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Kendi IP adreslerini keşfet (varsayılan: dinlenildiğinde ve -externalip ya da -proxy yoksa 1)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Hata: İçeri gelen bağlantıların dinlenmesi başarısız oldu (dinleme %s hatasını verdi)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>İlgili bir uyarı alındığında ya da gerçekten uzun bir çatallama gördüğümüzde komutu çalıştır (komuttaki %s mesaj ile değiştirilir)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Bundan düşük ücretler (%s/kB olarak) aktarma, oluşturma ve işlem yaratma için sıfır değerinde ücret olarak kabul edilir (varsayılan: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Eğer paytxfee ayarlanmadıysa kafi derecede ücret ekleyin ki işlemler teyite vasati n blok içinde başlasın (varsayılan: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>-maxtxfee=&lt;tutar&gt; için geçersiz tutar: '%s' (Sıkışmış işlemleri önlemek için en az %s değerinde en düşük aktarım ücretine eşit olmalıdır)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Aktardığımız ve oluşturduğumuz veri taşıyıcı işlemlerindeki en yüksek veri boyutu (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Her vekil bağlantısı için kimlik verilerini rastgele yap. Bu, Tor akış izolasyonunu etkinleştirir (varsayılan: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Bu işlem, tutar düşüldükten sonra göndermek için çok düşük</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Beyaz listeye alınan eşler DoS yasaklamasına uğramazlar ve işlemleri zaten mempool'da olsalar da daima aktarılır, bu mesela bir geçit için kullanışlıdır</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Budama olmayan kipe dönmek için veritabanını -reindex ile tekrar derlemeniz gerekir. Bu, tüm blok zincirini tekrar indirecektir</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(varsayılan: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Herkese açık REST taleplerini kabul et (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Otomatik olarak gizli Tor servisi oluştur (varsayılan: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>SOCKS5 vekil sunucusu vasıtasıyla bağlan</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>%s yüklemesinde hata: Zaten HD olan bir cüzdanda HD devre dışı bırakılamaz </translation>
</message>
@@ -3586,10 +3336,6 @@
<translation>Zincirdurumu veritabanı yükseltme hatası</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Başlangıçta harici blk000??.dat dosyasından blokları içe aktarır</translation>
- </message>
- <message>
<source>Information</source>
<translation>Bilgi</translation>
</message>
@@ -3610,44 +3356,28 @@
<translation>-whitelist: '%s' unsurunda geçersiz bir ağ maskesi belirtildi</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Hafızada en çok &lt;n&gt; bağlanılamaz işlem tut (varsayılan: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>-whitebind: '%s' ile bir port belirtilmesi lazımdır</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Düğüm aktarma seçenekleri:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC sunucu seçenekleri:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Sistem sınırlamaları sebebiyle -maxconnections %d değerinden %d değerine düşürülmüştür.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Başlangıçta blok zincirini eksik cüzdan işlemleri için tekrar tara</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>İzleme/hata ayıklama verilerini debug.log dosyası yerine konsola gönder</translation>
+ <source>Signing transaction failed</source>
+ <translation>İşlemin imzalanması başarısız oldu</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Tüm hata ayıklama seçeneklerini göster (kullanımı: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Belirtilen -walletdir "%s" mevcut değil</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>İstemci başlatıldığında debug.log dosyasını küçült (varsayılan: -debug bulunmadığında 1)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Belirtilen -walletdir "%s" göreceli bir yoldur</translation>
</message>
<message>
- <source>Signing transaction failed</source>
- <translation>İşlemin imzalanması başarısız oldu</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Belirtilen -walletdir "%s" bir dizin değildir</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3658,14 +3388,6 @@
<translation>Bu, deneysel bir yazılımdır.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor kontrol portu parolası (varsayılan: boş)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Eğer onion dinlemesi etkinse kullanılacak Tor kontrol portu (varsayılan: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>İşlem tutarı çok düşük</translation>
</message>
@@ -3682,18 +3404,18 @@
<translation>Bu bilgisayarda %s ögesine bağlanılamadı (bağlanma %s hatasını verdi)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Başlangıçta cüzdanı en yeni biçime güncelle</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC bağlantıları için kullanıcı ismi</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Başlangıç anahtarları üretilemiyor</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Cüzdan(lar) kontrol ediliyor...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Cüzdan %s, %s cüzdan klasörünün dışında bulunuyor</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Uyarı</translation>
</message>
@@ -3702,94 +3424,18 @@
<translation>Uyarı: bilinmeyen yeni kurallar etkinleştirilmiştir (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Sadece blok kipinde çalışılıp çalışılmayacağı (varsayılan: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>Veritabanını -txindex değerini değiştirmek için -reindex kullanarak tekrar oluşturmanız gerekiyor</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Cüzdandaki tüm işlemler kaldırılıyor...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ bildirim seçenekleri:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC bağlantıları için parola</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>En iyi blok değiştiğinde komutu çalıştır (komut için %s parametresi blok hash değeri ile değiştirilecektir)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>-addnode, -seednode ve -connect için DNS aramalarına izin ver</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = tx meta verilerini tut mesela hesap sahibi ve ödeme talebi bilgileri, 2 = tx meta verilerini at)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee çok yüksek bir değere ayarlanmış! Bu denli yüksek ücretler tek bir işlemde ödenebilir.</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>İşlemleri bellek alanında &lt;n&gt; saatten fazla tutma (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Oluşturma ve aktarma işlemlerinde sigop başına eşdeğer bayt (varsayılan: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>%s yüklenmesinde hata: zaten var olan ve HD olmayan bir cüzdanda HD etkinleştirilemez.</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>%s cüzdanı yüklenirken hata oluştu. -wallet değişkeni sadece belirli bir dosya adını belirtmelidir (bir dizini değil).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Bundan düşük ücretler (%s/kB olarak) işlem oluşturulması için sıfır değerinde ücret olarak kabul edilir (varsayılan: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Yerel aktarma politikasını ihlal etseler bile beyaz listedeki eşlerden gelen işlemlerin aktarılmasını zorla (varsayılan: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>-checkblocks'un blok kontrolünün ne kadar kapsamlı olacağı (0 ilâ 4, varsayılan: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>İşlemlerin tamamının indeksini tut, getrawtransaction rpc çağrısı tarafından kullanılır (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Aksaklık gösteren eşlerle terkar bağlantıyı engelleme süresi, saniye olarak (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Hata ayıklama bilgisini dök (varsayılan: %u, &lt;category&gt; sağlanması seçime dayalıdır)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Ham işlemin serileştirilmesini ayarlar veya blok non-verbose, non-segwit(0) veya segwit(1) kipinde onaltılık değeri döndürür (default: %d)</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>Cüzdanları tutmak için bir dizin belirtin (eğer varsa varsayılan: &lt;datadir&gt;/wallets, yoksa &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Blokların ve işlemlerin bloom filtreleri ile süzülmesini destekle (varsayılan: %u)</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>İşlem ücret tahminleri mevcut olmadığında ödeyebileceğiniz işlem ücreti budur.</translation>
</message>
@@ -3802,10 +3448,6 @@
<translation>Ağ sürümü zincirinin toplam boyutu (%i) en yüksek boyutu geçmektedir (%i). Kullanıcı aracı açıklamasının sayısı veya boyutunu azaltınız.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Giden trafiği belirtilen hedefin altında tutmaya çalışır (24 saat başı MiB olarak), 0 = sınırsız (varsayılan: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Desteklenmeyen -socks argümanı bulundu. SOCKS sürümünün ayarlanması artık mümkün değildir, sadece SOCKS5 vekilleri desteklenmektedir.</translation>
</message>
@@ -3814,10 +3456,6 @@
<translation>Desteklenmeyen argüman -whitelistalwaysrelay görmezden gelindi, -whitelistrelay ve/veya -whitelistforcerelay kullanın.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Eşlere gizli Tor servisleri ile ulaşmak için ayrı SOCKS5 vekil sunucusu kullan (varsayılan: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Uyarı: Bilinmeyen blok sürümü oluşturulmaya çalışılıyor. Bilinmeyen kuralların işlemesi mümkündür.</translation>
</message>
@@ -3826,110 +3464,18 @@
<translation>Uyarı: wallet.dat bozuk, veriler geri kazanıldı! Özgün %s, %s olarak %s klasörüne kaydedildi; bakiyeniz ya da işlemleriniz yanlışsa bir yedeklemeden tekrar yüklemeniz gerekir.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Beyaz listeye eklenen eşler verilen IP adresinden (ör. 1.2.3.4) veya CIDR ağından (ör. 1.2.3.0/24) bağlanabilir. Değerler birden çok kez kullanılabilir.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s çok yüksek ayarlanmış!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(varsayılan: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Eş adresleri sorgulaması için daima DNS aramasını kullan (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>%s cüzdanı yüklenirken hata oluştu. -wallet dosya adı normal bir dosya adı olmalıdır.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>%s cüzdanı yüklenirken hata oluştu. Belirtilen -wallet dosya adında başka bir kopya daha var.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>%s cüzdanı yüklenirken hata oluştu. -wallet dosya adında geçersiz karakterler var.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Başlangıçta kontrol edilecek blok sayısı (varsayılan: %u, 0 = hepsi)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Hata ayıklama çıktısına IP adreslerini dahil et (varsayılan: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Keypool tükendi, lütfen önce keypoolrefill'i çağırın</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>JSON-RPC bağlantılarını &lt;port&gt; üzerinde dinle (varsayılan: %u veya tesnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Bağlantılar için dinlenecek &lt;port&gt; (varsayılan: %u ya da testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Eşler ile en çok &lt;n&gt; adet bağlantı kur (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Cüzdanın işlemleri yayınlamasını sağla</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Her bağlantı için en yüksek alım tamponu, &lt;n&gt;*1000 bayt (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Her bağlantı için çok gönderme tamponu, &lt;n&gt;*1000 bayt (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Hata ayıklama verilerinin önüne zaman damgası ekle (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Veri taşıyıcı işlemleri oluştur ve aktar (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>P2SH olmayan çoklu imzaları aktar (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Anahtar alan boyutunu &lt;n&gt; değerine ayarla (varsayılan: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>En yüksek BIP141 blok ağırlığını ayarla (varsayılan: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Hizmet RCP aramaları iş parçacığı sayısını belirle (varsayılan: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Yapılandırma dosyası belirtiniz (varsayılan: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Bağlantı zaman aşım süresini milisaniye olarak belirt (en düşüki: 1, varsayılan: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Pid dosyası belirtiniz (varsayılan: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Gönderme işlemlerinde doğrulanmamış para üstünü harca (varsayılan: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Ağ iş parçacıkları başlatılıyor...</translation>
</message>
@@ -3946,10 +3492,6 @@
<translation>Eğer bir gönderme işlemi yaparsanız bu ödeyeceğiniz işlem ücretidir.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Aksaklık gösteren eşlerle bağlantıyı kesme sınırı (varsayılan: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>İşlem tutarı negatif olmamalıdır</translation>
</message>
@@ -3970,6 +3512,14 @@
<translation>Yetersiz bakiye</translation>
</message>
<message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>İşlem ücreti hesaplama başarısız. Fallbackfee özelliği devre dışı. Lütfen bir kaç blok için bekleyiniz yada -fallbackfee özelliğini aktif ediniz.</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Veriler klasöre yazılamıyor '%s'; yetkilendirmeyi kontrol edin.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Blok indeksi yükleniyor...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_tr_TR.ts b/src/qt/locale/bitcoin_tr_TR.ts
index efaca68e01..bf2dae99dc 100644
--- a/src/qt/locale/bitcoin_tr_TR.ts
+++ b/src/qt/locale/bitcoin_tr_TR.ts
@@ -30,6 +30,10 @@
<translation>Seçili adresi listeden sil</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Aramak için adres veya etiket girin</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Seçili sekmedeki veriyi dosya olarak dışa aktar</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Yeni parolayı tekrarla</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Şifreyi göster</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Yeni parolayı cüzdana girin.&lt;br/&gt;Lütfen &lt;b&gt;on yada daha fazla karakter&lt;/b&gt; veya &lt;b&gt;sekiz yada daha fazla kelime&lt;/b&gt;içeren bir parola kullanın. </translation>
</message>
@@ -192,6 +200,10 @@
<translation>Cüzdan şifreleme başarısız oldu</translation>
</message>
<message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Cüzdan şifreleme dahili bir hata nedeniyle başarısız oldu. Cüzdanınız şifrelenemedi.</translation>
+ </message>
+ <message>
<source>The supplied passphrases do not match.</source>
<translation>Girilen parolalar eşleşmiyor.</translation>
</message>
@@ -210,6 +222,10 @@
<context>
<name>BitcoinGUI</name>
<message>
+ <source>Sign &amp;message...</source>
+ <translation>İmza &amp;mesaj</translation>
+ </message>
+ <message>
<source>Synchronizing with network...</source>
<translation>Ağ ile bağlantı kuruluyor...</translation>
</message>
@@ -234,6 +250,18 @@
<translation>Hakkında%1</translation>
</message>
<message>
+ <source>Show information about %1</source>
+ <translation>%1 hakkındaki bilgileri görüntüle</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>Qt Hakkında</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Qt hakkındaki bilgileri görüntüleyin</translation>
+ </message>
+ <message>
<source>&amp;Options...</source>
<translation>&amp;Seçenekler</translation>
</message>
@@ -246,18 +274,46 @@
<translation>&amp;Cüzdan Yedekleme</translation>
</message>
<message>
+ <source>&amp;Sending addresses...</source>
+ <translation>Gönderme adresleri</translation>
+ </message>
+ <message>
<source>&amp;Receiving addresses...</source>
<translation>Alış adresleri</translation>
</message>
<message>
+ <source>Open &amp;URI...</source>
+ <translation>URI'yi aç</translation>
+ </message>
+ <message>
<source>Network activity disabled.</source>
<translation>Ağ etkinliği devre dışı.</translation>
</message>
<message>
+ <source>Click to enable network activity again.</source>
+ <translation>Ağ aktivitesini tekrar başlatmak için tıklayın.</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Bloklar disk üzerinde yeniden indeksleniyor...</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Bitcoin adresine madeni para gönderin</translation>
</message>
<message>
+ <source>Backup wallet to another location</source>
+ <translation>Cüzdanınızı başka bir lokasyona yedekleyin</translation>
+ </message>
+ <message>
+ <source>Open debugging and diagnostic console</source>
+ <translation>Hata giderme konsolunu aç</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>Onay mesajı...</translation>
+ </message>
+ <message>
<source>Bitcoin</source>
<translation>Bitcoin
</translation>
@@ -267,10 +323,38 @@
<translation>Cüzdan</translation>
</message>
<message>
+ <source>&amp;Send</source>
+ <translation>Gönder</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>Al</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>Göster / Gizle</translation>
+ </message>
+ <message>
<source>&amp;Settings</source>
<translation>&amp;Ayarlar</translation>
</message>
<message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation>Kullanılan gönderim adreslerinin ve etiketlerinin listesini göster</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Kullanılan alış adreslerinin ve etiketlerinin listesini göster</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>Komut satırı ayarları</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Bloklar disk üzerinde indeksleniyor...</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Hata</translation>
</message>
@@ -282,10 +366,79 @@
<source>Information</source>
<translation>Bilgi</translation>
</message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Tarih %1</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>HD anahtar üretimi&lt;b&gt;aktif&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>HD anahtar üretimi &lt;b&gt;pasif&lt;/b&gt;</translation>
+ </message>
</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Bytes:</source>
+ <translation>Bayt</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Ücret:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Ücretten sonra kalan:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Değişen:</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>Listeleme modu</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>Onaylamalar</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Kabul edilen</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Adresi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Etiketi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Ücreti kopyala</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 kilitli)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>Evet</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>Hayır</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(etiket yok)</translation>
</message>
@@ -293,6 +446,10 @@
<context>
<name>EditAddressDialog</name>
<message>
+ <source>Edit Address</source>
+ <translation>Adresi Düzenle</translation>
+ </message>
+ <message>
<source>&amp;Label</source>
<translation>Etiket</translation>
</message>
@@ -300,16 +457,56 @@
<source>&amp;Address</source>
<translation>Adres</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>Yeni gönderim adresi</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Alış adresini düzenleyin</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Gönderim adresini düzenleyin</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>Girilen adres "%1" Bitcoin adresiyle eşleşmiyor.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>Yeni anahtar üretimi başarısız.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
+ <message>
+ <source>name</source>
+ <translation>isim</translation>
+ </message>
</context>
<context>
<name>HelpMessageDialog</name>
- </context>
+ <message>
+ <source>version</source>
+ <translation>versiyon</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>Hakkında %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>Komut satırı ayarları</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
<message>
+ <source>Welcome</source>
+ <translation>Hoş geldiniz</translation>
+ </message>
+ <message>
<source>Bitcoin</source>
<translation>Bitcoin
</translation>
@@ -321,6 +518,30 @@
</context>
<context>
<name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation>Form</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Kalan blokların sayısı</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Bilinmiyor...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Son blok zamanı</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>hesaplanıyor...</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Gizle</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -328,41 +549,445 @@
<context>
<name>OptionsDialog</name>
<message>
+ <source>Options</source>
+ <translation>Ayarlar</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation>&amp;Ana Menü</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Veritabanı önbelleğinin boyutu</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>Proxy bağlantısı IP adresleri (örneğin IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Konfigürasyon dosyasını aç</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>Bütün ayarları varsayılana çevir</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>Ağ</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>Cüzdan</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation>Proxy portu (örneğin 9050)</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>Pencere</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation>Kullanıcı arayüzü dili</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>Tamam</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>İptal</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>Varsayılan</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Değişikliklerin aktif edilebilmesi için yeniden başlatma gerekiyor.</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Konfigürasyon ayarları</translation>
+ </message>
+ <message>
+ <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
+ <translation>Konfigürasyon dosyası GUI ayarlarını geçersiz kılmak için gelişmiş kullanıcı ayarlarını değiştirir. Ek olarak, herhangi bir komut satırı seçeneği konfigürasyon dosyasını geçersiz kılar.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Hata</translation>
</message>
- </context>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation>Konfigürasyon dosyası açılamadı.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>Bu değişiklik istemcinin yeniden başlatılmasını gerektirir.</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>Sağlanan proxy adresi geçerli değil.</translation>
+ </message>
+</context>
<context>
<name>OverviewPage</name>
- </context>
+ <message>
+ <source>Form</source>
+ <translation>Form</translation>
+ </message>
+ <message>
+ <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
+ <translation>Gösterilen bilgi geçerli olmayabilir. Bağlantı tekrar sağlandıktan sonra cüzdanınız otomatik olarak senkronize olacaktır. Henüz senkronize olma işlemi tamamlanmadı.</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>Sadece görüntülenebilir:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Kullanılabilir:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>Mevcut harcanabilir tutarınız</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>Bekleyen:</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Toplam:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation>Toplam mevcut miktarınız</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>Sadece görüntülenebilir adreslerdeki mevcut miktarınız</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Harcanabilir:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Yakın zamanda yapılmış işlemler</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>Sadece görüntülenebilir adreslerdeki doğrulanmamış işlemler</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>Sadece görüntülenebilir adreslerdeki mevcut toplam miktar</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Ödeme isteği hatası</translation>
+ </message>
+ <message>
+ <source>Payment request fetch URL is invalid: %1</source>
+ <translation>Ödeme isteği URL'si hatalı: %1</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Hatalı ödeme adresi %1</translation>
+ </message>
+ <message>
+ <source>Network request error</source>
+ <translation>Ağ hatası</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
- </context>
+ <message>
+ <source>Sent</source>
+ <translation>Gönder</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Alındı</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
- </context>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Bitcoin adresinizi girin (örneğin %1)</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>Yok</translation>
+ </message>
+ <message>
+ <source>%1 and %2</source>
+ <translation>%1 ve %2</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>bilinmiyor</translation>
+ </message>
+</context>
<context>
<name>QObject::QObject</name>
- </context>
+ <message>
+ <source>Error: %1</source>
+ <translation>Hata: %1</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Görüntüyü kaydet</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Görüntüyü kopyala</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>QR kodu kaydet</translation>
+ </message>
</context>
<context>
<name>RPCConsole</name>
- </context>
+ <message>
+ <source>N/A</source>
+ <translation>Yok</translation>
+ </message>
+ <message>
+ <source>Client version</source>
+ <translation>Arayüz versiyonu</translation>
+ </message>
+ <message>
+ <source>&amp;Information</source>
+ <translation>&amp;Bilgi</translation>
+ </message>
+ <message>
+ <source>Debug window</source>
+ <translation>Hata giderme penceresi</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>Genel</translation>
+ </message>
+ <message>
+ <source>Using BerkeleyDB version</source>
+ <translation>Kullanılan BerkeleyDB versiyonu</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation>Başlangıç zamanı</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>Ağ</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>İsim</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation>Bağlantı sayısı</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation>Blok zinciri</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>Bellek kullanımı</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Yeniden başlat</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Alındı</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Gönder</translation>
+ </message>
+ <message>
+ <source>Whitelisted</source>
+ <translation>Beyaz listede</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>Versiyon</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>Servisler</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>Bağlantı süresi</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation>Son gönderim</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>Son alış</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>Ping süresi</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>Ping bekliyor</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Son blok zamanı</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>&amp;Aç</translation>
+ </message>
+ <message>
+ <source>&amp;Console</source>
+ <translation>&amp;Konsol</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;Ağ trafiği</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation>Toplam</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation>Konsolu temizle</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;saat</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;gün</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;hafta</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;yıl</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Bağlantı kesildi</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Ağ aktivitesi pasif</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>asla</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>Gelen</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>Giden</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation>Evet</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation>Hayır</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>Bilinmiyor</translation>
+ </message>
+</context>
<context>
<name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etiket</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>&amp;Mesaj</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>Temizle</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>Göster</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Sil</translation>
+ </message>
+ <message>
+ <source>Copy URI</source>
+ <translation>URI'yi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Etiketi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Mesajı kopyala</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>QR Code</source>
+ <translation>QR kod</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation>URI'yi kopyala</translation>
+ </message>
+ <message>
<source>Copy &amp;Address</source>
<translation>&amp;Adresi Kopyala</translation>
</message>
<message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Görüntüyü kaydet</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>Ödeme bilgisi</translation>
+ </message>
+ <message>
+ <source>URI</source>
+ <translation>URI</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>adres</translation>
</message>
@@ -370,37 +995,189 @@
<source>Label</source>
<translation>etiket</translation>
</message>
+ <message>
+ <source>Message</source>
+ <translation>Mesaj</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation>Cüzdan</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>etiket</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Mesaj</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(etiket yok)</translation>
</message>
+ <message>
+ <source>(no message)</source>
+ <translation>(mesaj yok)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
<message>
+ <source>Send Coins</source>
+ <translation>Coin gönder</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>Otomatik seçildi</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bayt</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Ücret:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>Ücretten sonra kalan:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Değişen:</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>Gönderim ücreti:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>Seçiniz...</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>kilobyte başına</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Gizle</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>Önerilen:</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Hepsini sil</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Ücreti kopyala</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blok)</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1'den %2'e</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Göndermek istediğinize emin misiniz?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ya da</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Gönderim ücreti</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Coin gönderimini onaylayın</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Uyarı: Hatalı Bitcoin adresi</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(etiket yok)</translation>
</message>
</context>
<context>
<name>SendCoinsEntry</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Etiket</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Panodaki adresi yapıştırın</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Mesaj:</translation>
+ </message>
</context>
<context>
<name>SendConfirmationDialog</name>
- </context>
+ <message>
+ <source>Yes</source>
+ <translation>Evet</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
</context>
<context>
<name>SignVerifyMessageDialog</name>
- </context>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Panodaki adresi yapıştırın</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation>İmza</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>İmza &amp;Mesaj</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Hepsini sil</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>Girilen adres hatalı.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Adresi kontrol ettikten sonra lütfen tekrar deneyin.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>İmzanızı kontrol ettikten sonra lütfen tekrar deneyin.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Mesaj onayı hatalı.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Mesaj onaylandı.</translation>
+ </message>
+</context>
<context>
<name>SplashScreen</name>
</context>
@@ -409,17 +1186,101 @@
</context>
<context>
<name>TransactionDesc</name>
- </context>
+ <message>
+ <source>Status</source>
+ <translation>Durum</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>Kaynak</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Oluşturuldu</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>bilinmiyor</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>etiket</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>kabul edilmedi</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Gönderim ücreti</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Mesaj</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Yorum</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>Gönderimin toplam boyutu</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Hata giderme bilgisi</translation>
+ </message>
+ <message>
+ <source>true</source>
+ <translation>doğru</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>anlış</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Tip</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>etiket</translation>
</message>
<message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Onaylandı (%1 onaylanan)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Oluşturuldu fakat kabul edilmedi</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>ile alındı</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Kazıldı</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(yok)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(etiket yok)</translation>
</message>
@@ -427,10 +1288,66 @@
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>Hepsi</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Bugün</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>Bu hafta</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>Bu Ay</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Son ay</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>Bu yıl</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>ile alındı</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Kazıldı</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Diğerleri</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Adresi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Etiketi kopyala</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Virgül ile ayrılmış dosya (*.csv)</translation>
</message>
<message>
+ <source>Confirmed</source>
+ <translation>Kabul edilen</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Tip</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>etiket</translation>
</message>
@@ -451,59 +1368,91 @@
</context>
<context>
<name>WalletModel</name>
+ <message>
+ <source>Send Coins</source>
+ <translation>Coin gönder</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>Yeni ücret:</translation>
+ </message>
</context>
<context>
<name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>&amp;Çıkar</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Cüzdanı yedekle</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Yedekleme başarısız</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Yedekleme tamamlandı</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Print this help message and exit</source>
- <translation>Bu yardım mesajını yazdır ve çıkış yap</translation>
+ <source>Bitcoin Core</source>
+ <translation>Bitcoin Çekirdeği</translation>
</message>
<message>
- <source>Print version and exit</source>
- <translation>Versiyonu yazdır ve çıkış yap</translation>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Copyright (C) %i-%i</translation>
</message>
<message>
- <source>Verifying blocks...</source>
- <translation>Bloklar Onaylanıyor...</translation>
+ <source>Error: Disk space is low!</source>
+ <translation>Hata: Disk boyutu düşük!</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Cüzdan Ayarları</translation>
+ <source>Loading P2P addresses...</source>
+ <translation>P2P adresleri yükleniyor...</translation>
</message>
<message>
- <source>Information</source>
- <translation>Bilgi</translation>
+ <source>Loading banlist...</source>
+ <translation>Ban listesi yükleniyor...</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>Bloklar Onaylanıyor...</translation>
</message>
<message>
- <source>RPC server options:</source>
- <translation>RPC sunucu ayarları</translation>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>%s tamamlanması için cüzdanın yeniden başlatılması gerekiyor</translation>
</message>
<message>
- <source>Transaction too large</source>
- <translation>İşlem çok büyük</translation>
+ <source>Error reading from database, shutting down.</source>
+ <translation>Veritabanı okuma hatası, kapatıldı.</translation>
</message>
<message>
- <source>Warning</source>
- <translation>Uyarı</translation>
+ <source>Information</source>
+ <translation>Bilgi</translation>
</message>
<message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Yapılandırma dosyasını belirle (varsayılan: %s)</translation>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Hatalı -onion adresi ya da host adı: '%s'</translation>
</message>
<message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Milisaniyelik zaman aşımına uğramış bağlantıyı belirle (minimum: 1, varsayılan: %d)</translation>
+ <source>This is experimental software.</source>
+ <translation>Bu deneysel bir yazılımdır.</translation>
</message>
<message>
- <source>Specify pid file (default: %s)</source>
- <translation>Pid dosyasını belirle (Varsayılan: %s)</translation>
+ <source>Transaction too large</source>
+ <translation>İşlem çok büyük</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>Cüzdan(lar) onaylanıyor...</translation>
</message>
<message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>İşlem gönderiminde onaylanmamış değişimi öde (Varsayılan: %u)</translation>
+ <source>Warning</source>
+ <translation>Uyarı</translation>
</message>
<message>
<source>Starting network threads...</source>
@@ -522,10 +1471,6 @@
<translation>Bir işlem göndermeniz durumunda işlem ücretiniz budur</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Sorunlu emsalleri koparma eşiği (Varsayılan: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>İşlem miktarı negatif olmamalı</translation>
</message>
diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts
index 6ea28b3141..1865a84834 100644
--- a/src/qt/locale/bitcoin_uk.ts
+++ b/src/qt/locale/bitcoin_uk.ts
@@ -30,6 +30,10 @@
<translation>Вилучити вибрані адреси з переліку</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Введіть адресу чи мітку для пошуку</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Експортувати дані з поточної вкладки в файл</translation>
</message>
@@ -132,6 +136,10 @@
<translation>Повторіть пароль</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Показати пароль</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Введіть нову кодову фразу для гаманця.&lt;br/&gt;Будь ласка, використовуйте кодові фрази що містять &lt;b&gt; щонайменше десять випадкових символів &lt;/b&gt; або &lt;b&gt; щонайменше вісім слів &lt;/b&gt;.</translation>
</message>
@@ -318,6 +326,14 @@
<translation>Відкрити &amp;URI</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Гаманець:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>типовий гаманець</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Натисніть, щоб вимкнути активність мережі.</translation>
</message>
@@ -338,6 +354,10 @@
<translation>Переіндексація блоків на диску ...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Проксі &lt;b&gt;увімкнено&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Відправити монети на вказану адресу</translation>
</message>
@@ -435,7 +455,7 @@
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n активне з'єднання з мережею Bitcoin</numerusform><numerusform>%n активні з'єднання з мережею Bitcoin</numerusform><numerusform>%n активних з'єднань з мережею Bitcoin</numerusform></translation>
+ <translation><numerusform>%n активне з'єднання з мережею Bitcoin</numerusform><numerusform>%n активні з'єднання з мережею Bitcoin</numerusform><numerusform>%n активних з'єднань з мережею Bitcoin</numerusform><numerusform>%n активних з'єднань з мережею Bitcoin</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
@@ -447,7 +467,7 @@
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
- <translation><numerusform>Оброблено %n блок історії транзакцій.</numerusform><numerusform>Оброблено %n блоки історії транзакцій.</numerusform><numerusform>Оброблено %n блоків історії транзакцій.</numerusform></translation>
+ <translation><numerusform>Оброблено %n блок історії транзакцій.</numerusform><numerusform>Оброблено %n блоки історії транзакцій.</numerusform><numerusform>Оброблено %n блоків історії транзакцій.</numerusform><numerusform>Оброблено %n блоків історії транзакцій.</numerusform></translation>
</message>
<message>
<source>%1 behind</source>
@@ -506,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>Гаманець: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>Тип: %1
@@ -722,10 +748,6 @@
<translation>&amp;Адреса</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Нова адреса для отримання</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Нова адреса для відправлення</translation>
</message>
@@ -742,8 +764,12 @@
<translation>Введена адреса "%1" не є адресою в мережі Bitcoin.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Введена адреса "%1" вже присутня в адресній книзі.</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>Адреса "%1" вже існує як отримувач з міткою "%2" і не може бути додана як відправник.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>Введена адреса "%1" вже присутня в адресній книзі з міткою "%2".</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -795,42 +821,6 @@
<source>Command-line options</source>
<translation>Параметри командного рядка</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Використання:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>параметри командного рядка</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Параметри інтерфейсу:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Обирати каталог даних під час запуску (типово: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Встановити мову (наприклад: "de_DE") (типово: системна)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Запускати згорнутим</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Вказати кореневі SSL-сертифікати для запиту платежу (типово: -системні-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Показувати заставку під час запуску (типово: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Скинути налаштування, які було змінено через графічний інтерфейс користувача</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -892,11 +882,11 @@
</message>
<message numerus="yes">
<source>%n GB of free space available</source>
- <translation><numerusform>Доступно %n ГБ вільного простору</numerusform><numerusform>Доступно %n ГБ вільного простору</numerusform><numerusform>Доступно %n ГБ вільного простору</numerusform></translation>
+ <translation><numerusform>Доступно %n ГБ вільного простору</numerusform><numerusform>Доступно %n ГБ вільного простору</numerusform><numerusform>Доступно %n ГБ вільного простору</numerusform><numerusform>Доступно %n ГБ вільного простору</numerusform></translation>
</message>
<message numerus="yes">
<source>(of %n GB needed)</source>
- <translation><numerusform>(в той час, як необхідно %n ГБ)</numerusform><numerusform>(в той час, як необхідно %n ГБ)</numerusform><numerusform>(в той час, як необхідно %n ГБ)</numerusform></translation>
+ <translation><numerusform>(в той час, як необхідно %n ГБ)</numerusform><numerusform>(в той час, як необхідно %n ГБ)</numerusform><numerusform>(в той час, як необхідно %n ГБ)</numerusform><numerusform>(в той час, як необхідно %n ГБ)</numerusform></translation>
</message>
</context>
<context>
@@ -1004,6 +994,18 @@
<translation>Показує, чи типово використовується проксі SOCKS5 для досягнення рівної участі для цього типу мережі.</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>Використовуйте окремі проксі-сервери SOCKS&amp;5 для підключення до вузлів через приховані сервіси Tor:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Приховати значок із системного лотка.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Приховати піктограму з лотка</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<translation>Згортати замість закриття. Якщо ця опція включена, програма закриється лише після вибору відповідного пункту в меню.</translation>
</message>
@@ -1036,6 +1038,22 @@
<translation>&amp;Мережа</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Вимикає деякі нові властивості але всі блоки будуть повністю перевірені. Повернення цієї опції вимагає перезавантаження вього ланцюжка блоків. Фактичний розмір бази може бути дещо більший.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Скоротити місце під блоки...</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>ГБ</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Повернення цієї опції вимагає перезавантаження вього ланцюжка блоків.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = автоматично, &lt;0 = вказує кількість вільних ядер)</translation>
</message>
@@ -1068,6 +1086,14 @@
<translation>Відображення порту через &amp;UPnP</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>Приймати з'єднання ззовні.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Дозволити вхідні з'єднання</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>Підключення до мережі Bitcoin через SOCKS5 проксі.</translation>
</message>
@@ -1148,6 +1174,10 @@
<translation>Показати або сховати керування входами.</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;URL-адреси транзакцій сторонніх розробників</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;Гаразд</translation>
</message>
@@ -1180,6 +1210,10 @@
<translation>Редагувати параметри</translation>
</message>
<message>
+ <source>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
+ <translation>Файл конфігурації використовується для вказування додаткових параметрів користувача, що перекривають настройки графічного інтерфейсу користувача. Крім того, будь-які параметри командного рядка замінять цей конфігураційний файл.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Помилка</translation>
</message>
@@ -1278,10 +1312,18 @@
<translation>Помилка запиту платежу</translation>
</message>
<message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Не вдається запустити біткойн: обробник клацни-плати</translation>
+ </message>
+ <message>
<source>URI handling</source>
<translation>Обробка URI</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' не вірний URI. Використовуйте 'bitcoin:'.</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>URL запиту платежу є некоректним: %1</translation>
</message>
@@ -1290,6 +1332,10 @@
<translation>Помилка в адресі платежу %1</translation>
</message>
<message>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation>Неможливо обробити URI! Причиною цього може бути некоректна Біткойн-адреса або неправильні параметри URI.</translation>
+ </message>
+ <message>
<source>Payment request file handling</source>
<translation>Обробка файлу запиту платежу</translation>
</message>
@@ -1314,6 +1360,12 @@
<translation>Запит платежу не ініціалізовано.</translation>
</message>
<message>
+ <source>Unverified payment requests to custom payment scripts are unsupported.</source>
+ <translation>
+70/5000
+Неперевірені запити на оплату до індивідуальних платіжних скриптів не підтримуються.</translation>
+ </message>
+ <message>
<source>Invalid payment request.</source>
<translation>Помилка в запиті платежу.</translation>
</message>
@@ -1361,6 +1413,10 @@
<translation>Вузол/Сервіс</translation>
</message>
<message>
+ <source>NodeId</source>
+ <translation>Ідентифікатор вузла</translation>
+ </message>
+ <message>
<source>Ping</source>
<translation>Затримка</translation>
</message>
@@ -1411,10 +1467,34 @@
<source>%1 ms</source>
<translation>%1 мс</translation>
</message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation><numerusform>%n секунда</numerusform><numerusform>%n секунд</numerusform><numerusform>%n секунд</numerusform><numerusform>%n секунд</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation><numerusform>%n хвилина</numerusform><numerusform>%n хвилин</numerusform><numerusform>%n хвилин</numerusform><numerusform>%n хвилин</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation><numerusform>%n година</numerusform><numerusform>%n годин</numerusform><numerusform>%n годин</numerusform><numerusform>%n годин</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation><numerusform>%n день</numerusform><numerusform>%n днів</numerusform><numerusform>%n днів</numerusform><numerusform>%n днів</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation><numerusform>%n тиждень</numerusform><numerusform>%n тижнів</numerusform><numerusform>%n тижнів</numerusform><numerusform>%n тижнів</numerusform></translation>
+ </message>
<message>
<source>%1 and %2</source>
<translation>%1 та %2</translation>
</message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation><numerusform>%n рік</numerusform><numerusform>%n років</numerusform><numerusform>%n років</numerusform><numerusform>%n років</numerusform></translation>
+ </message>
<message>
<source>%1 B</source>
<translation>%1 Б</translation>
@@ -1432,6 +1512,10 @@
<translation>%1 ГБ</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation>%1 безпечний вихід ще не виконано...</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>невідомо</translation>
</message>
@@ -1439,6 +1523,18 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>Помилка розбору параметрів команди: %1</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>Помилка: Вказаного каталогу даних «%1» не існує.</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Помилка: Неможливо розібрати файл конфігурації: %1.</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>Помилка: %1</translation>
</message>
@@ -1489,6 +1585,10 @@
<translation>Використовується BerkeleyDB версії</translation>
</message>
<message>
+ <source>Datadir</source>
+ <translation>Каталог даних</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>Час запуску</translation>
</message>
@@ -1525,6 +1625,18 @@
<translation>Використання пам'яті</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>Гаманець:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(відсутні)</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Скинути</translation>
+ </message>
+ <message>
<source>Received</source>
<translation>Отримано</translation>
</message>
@@ -1573,6 +1685,10 @@
<translation>Клієнт користувача</translation>
</message>
<message>
+ <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation>Відкрийте файл журналу налагодження %1 з поточного каталогу даних. Це може зайняти кілька секунд для файлів великого розміру.</translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation>Зменшити розмір шрифту</translation>
</message>
@@ -1613,6 +1729,10 @@
<translation>Поточна Затримка</translation>
</message>
<message>
+ <source>Min Ping</source>
+ <translation>Мін Пінг</translation>
+ </message>
+ <message>
<source>Time Offset</source>
<translation>Різниця часу</translation>
</message>
@@ -1669,10 +1789,54 @@
<translation>1 &amp;рік</translation>
</message>
<message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Від'єднати</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>Заблокувати на</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;Розблокувати</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>гаманець за змовчуванням</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Ласкаво просимо до консолі RPC %1.</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>Використовуйте стрілки вгору та вниз для навігації історії та %1 для очищення екрана.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Введіть %1 для перегляду доступних команд.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>Щоб отримати додаткові відомості про використання консолі введіть %1.</translation>
+ </message>
+ <message>
+ <source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
+ <translation>ПОПЕРЕДЖЕННЯ. Шахраї активно вказували вводити тут команди і отримували доступ до вмісту гаманця користувачів. Не використовуйте цю консоль без повного розуміння наслідків виконання команд.</translation>
+ </message>
+ <message>
<source>Network activity disabled</source>
<translation>Мережева активність вимкнена.</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>Виконати команду без гаманця</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Виконати команду для "%1" гаманця</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(ІД вузла: %1)</translation>
</message>
@@ -1744,6 +1908,14 @@
<translation>Очистити</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Чиста сегвіт адреса (segwit, Bech32, BIP-173) знижує комісію та пропонує кращий захист від помилок, але старі гаманці її не підтримують. Якщо позначка знята, буде створено адресу, сумісну зі старими гаманцями.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Згенерувати чисту SegWit (Bech32) адресу</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Історія запитів платежу</translation>
</message>
@@ -1803,10 +1975,18 @@
<translation>&amp;Зберегти зображення...</translation>
</message>
<message>
+ <source>Request payment to %1</source>
+ <translation>Запит платежу на %1</translation>
+ </message>
+ <message>
<source>Payment information</source>
<translation>Інформація про платіж</translation>
</message>
<message>
+ <source>URI</source>
+ <translation>URI</translation>
+ </message>
+ <message>
<source>Address</source>
<translation>Адреса</translation>
</message>
@@ -1822,7 +2002,19 @@
<source>Message</source>
<translation>Повідомлення</translation>
</message>
- </context>
+ <message>
+ <source>Wallet</source>
+ <translation>Гаманець</translation>
+ </message>
+ <message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>Кінцевий URI занадто довгий, спробуйте зменшити текст для мітки / повідомлення.</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Помилка кодування URI в QR-код.</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1917,16 +2109,28 @@
<translation>Виберіть...</translation>
</message>
<message>
+ <source>Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
+ <translation>Використання зарезервованої комісії може призвести до виконання транзакції, підтвердження котрої займе години, або дні, або ніколи не буде підтверджено. Обміркуйте можливість вибору комісії вручну, або зачекайте завершення валідації повного ланцюгу.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Попередження: оцінка розміру комісії наразі неможлива.</translation>
+ </message>
+ <message>
<source>collapse fee-settings</source>
<translation>згорнути налаштування оплат</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>за кілобайт</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Вкажіть комісію за кБ (1,000 байт) віртуального розміру транзакції.
+
+Примітка: Так як комісія нараховується за байт, комісія "100 сатоші за кБ" для транзакції розміром 500 байт (пів 1 кБ) буде приблизно 50 сатоші. </translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Якщо комісія встановлюється в 1000 сатоші і розмір транзакції лише 250 байтів, то опція "за кілобайт" встановлює комісію в 250 сатоші, в той час, як "всього щонайменше" - в 1000 сатоші. Для транзакцій більших за кілобайт в обох випадках буде знято комісію за кілобайт.</translation>
+ <source>per kilobyte</source>
+ <translation>за кілобайт</translation>
</message>
<message>
<source>Hide</source>
@@ -1973,6 +2177,14 @@
<translation>Час підтвердження:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Увімкнути Заміна-Через-Комісію</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>З опцією Заміна-Через-Комісію (BIP-125) ви можете збільшити комісію за транзакцію після її надсилання. Інакше може бути рекомендоване збільшення розміру комісії для компенсації підвищеного ризику затримки транзакції.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Очистити &amp;все</translation>
</message>
@@ -2017,10 +2229,110 @@
<translation>Скопіювати решту</translation>
</message>
<message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 блоків)</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 до %2</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Ви впевнені, що хочете відправити?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>або</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>Ви можете збільшити комісію пізніше (сигналізує Заміна-Через-Комісію, BIP-125).</translation>
+ </message>
+ <message>
+ <source>from wallet %1</source>
+ <translation>з гаманця %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Будь-ласка, перевірте вашу транзакцію.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Комісія за транзакцію</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Не сигналізує Заміна-Через-Комісію, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Всього</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Підтвердьте надсилання монет</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>Неприпустима адреса отримувача. Будь ласка, перевірте.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>Сума платні повинна бути більше 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>Сума перевищує ваш баланс.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>Після додавання комісії %1, сума перевищить ваш баланс.</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>Знайдено адресу, що дублюється: кожна адреса має бути вказана тільки один раз.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Транзакцію не виконано!</translation>
+ </message>
+ <message>
+ <source>The transaction was rejected with the following reason: %1</source>
+ <translation>Транзакцію відхилено з наступної причини: %1</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>Комісія більша, ніж %1, вважається абсурдно високою.</translation>
+ </message>
+ <message>
<source>Payment request expired.</source>
<translation>Запит платежу прострочено.</translation>
</message>
<message>
+ <source>Pay only the required fee of %1</source>
+ <translation>Сплатіть лише обов'язкову комісію у розмірі %1</translation>
+ </message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>Очікуваний початок підтвердження через %n блок.</numerusform><numerusform>Очікуваний початок підтвердження протягом %n блоків.</numerusform><numerusform>Очікуваний початок підтвердження протягом %n блоків.</numerusform><numerusform>Очікуваний початок підтвердження протягом %n блоків.</numerusform></translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Увага: Неприпустима Біткойн-адреса.</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Увага: Невідома адреса для решти</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>Підтвердити індивідуальну адресу для решти</translation>
+ </message>
+ <message>
+ <source>The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
+ <translation>Адреса, яку ви обрали для решти, не є частиною цього гаманця. Будь-які або всі кошти з вашого гаманця можуть бути надіслані на цю адресу. Ви впевнені?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>немає мітки</translation>
</message>
@@ -2076,6 +2388,10 @@
<translation>В&amp;ідняти комісію від суми</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>Використати наявний баланс</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>Повідомлення:</translation>
</message>
@@ -2118,6 +2434,10 @@
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 припиняє роботу...</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation>Не вимикайте комп’ютер до зникнення цього вікна.</translation>
</message>
@@ -2277,11 +2597,43 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Відкрито на %n блок</numerusform><numerusform>Відкрито на %n блоків</numerusform><numerusform>Відкрито на %n блоків</numerusform><numerusform>Відкрито на %n блоків</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Відкрито до %1</translation>
</message>
<message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>конфліктує з транзакцією із %1 підтвердженнями</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, %1</source>
+ <translation>0/не підтверджено, %1</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>в пулі пам'яті</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>не в пулі пам'яті</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>відкинуто</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/не підтверджено</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 підтверджень</translation>
+ </message>
+ <message>
<source>Status</source>
<translation>Статут</translation>
</message>
@@ -2314,6 +2666,10 @@
<translation>Власна адреса</translation>
</message>
<message>
+ <source>watch-only</source>
+ <translation>тільки спостереження</translation>
+ </message>
+ <message>
<source>label</source>
<translation>мітка</translation>
</message>
@@ -2321,6 +2677,10 @@
<source>Credit</source>
<translation>Кредит</translation>
</message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>дозріє через %n блок</numerusform><numerusform>дозріє через %n блоків</numerusform><numerusform>дозріє через %n блоків</numerusform><numerusform>дозріє через %n блоків</numerusform></translation>
+ </message>
<message>
<source>not accepted</source>
<translation>не прийнято</translation>
@@ -2362,10 +2722,26 @@
<translation>Розмір транзакції</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>Віртуальний розмір транзакції</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>Вихідний індекс</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>Продавець</translation>
</message>
<message>
+ <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation>Згенеровані монети стануть доступні для використання після %1 підтверджень. Коли ви згенерували цей блок, його було відправлено в мережу для внесення до ланцюжку блоків. Якщо блок не буде додано до ланцюжку блоків, його статус зміниться на «не підтверджено», і згенеровані монети неможливо буде витратити. Таке часом трапляється, якщо хтось згенерував інший блок на декілька секунд раніше.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Налагоджувальна інформація</translation>
+ </message>
+ <message>
<source>Transaction</source>
<translation>Транзакція</translation>
</message>
@@ -2411,15 +2787,15 @@
<source>Label</source>
<translation>Мітка</translation>
</message>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Відкрито на %n блок</numerusform><numerusform>Відкрито на %n блоків</numerusform><numerusform>Відкрито на %n блоків</numerusform><numerusform>Відкрито на %n блоків</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Відкрито до %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Поза мережею</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Не підтверджено</translation>
</message>
@@ -2444,10 +2820,6 @@
<translation>Повністтю не підтверджено (%1 підтверджень, будуть доступні після %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>Цей блок не був отриманий жодними іншими вузлами і, ймовірно, не буде прийнятий!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Згенеровано (не підтверджено)</translation>
</message>
@@ -2472,6 +2844,14 @@
<translation>Добуто</translation>
</message>
<message>
+ <source>watch-only</source>
+ <translation>тільки спостереження</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(н/д)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>немає мітки</translation>
</message>
@@ -2488,6 +2868,10 @@
<translation>Тип транзакції.</translation>
</message>
<message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>Чи було залучено адресу для спостереження в цій транзакції.</translation>
+ </message>
+ <message>
<source>User-defined intent/purpose of the transaction.</source>
<translation>Визначений користувачем намір чи мета транзакції.</translation>
</message>
@@ -2547,6 +2931,10 @@
<translation>Інше</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Введіть адресу, ідентифікатор транзакції або мітку для пошуку</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Мінімальна сума</translation>
</message>
@@ -2630,7 +3018,27 @@
<source>Exporting Failed</source>
<translation>Експортування пройшло не успішно</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>Виникла помилка при спробі зберегти історію транзакцій до %1.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Експортовано успішно</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>Історію транзакцій було успішно збережено до %1.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Діапазон:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>до</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
<message>
@@ -2640,18 +3048,54 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>No wallet has been loaded.</source>
+ <translation>Жоден гаманець не завантажено.</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
+ <source>Send Coins</source>
+ <translation>Відправити Монети</translation>
+ </message>
+ <message>
+ <source>Fee bump error</source>
+ <translation>Помилка штурхання комісії</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Підвищення комісії за транзакцію не виконано</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>Ви бажаєте збільшити комісію?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Поточна комісія:</translation>
</message>
<message>
+ <source>Increase:</source>
+ <translation>Збільшити:</translation>
+ </message>
+ <message>
<source>New fee:</source>
<translation>Нова комісія:</translation>
</message>
- </context>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>Підтвердити штурхання комісії</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>Не можливо підписати транзакцію.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>Не вдалось виконати транзакцію</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -2675,6 +3119,10 @@
<translation>Помилка резервного копіювання</translation>
</message>
<message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>Виникла помилка при спробі зберегти дані гаманця до %1.</translation>
+ </message>
+ <message>
<source>Backup Successful</source>
<translation>Резервну копію створено успішно</translation>
</message>
@@ -2682,32 +3130,16 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Дані гаманця успішно збережено в %1.</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>Скасувати</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Параметри:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Вкажіть робочий каталог</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Підключитись до вузла, щоб отримати список адрес інших учасників та від'єднатись</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Вкажіть вашу власну публічну адресу</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Приймати команди із командного рядка та команди JSON-RPC</translation>
- </message>
- <message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>Якщо &lt;category&gt; не задано, або ж якщо &lt;category&gt; = 1, виводить всю налагоджувальну інформацію.</translation>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation>Розповсюджується за ліцензією на програмне забезпечення MIT, дивіться супровідний файл %s або %s</translation>
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
@@ -2726,18 +3158,10 @@
<translation>Помилка: Сталася фатальна помилка (детальніший опис наведено в debug.log)</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Комісія (в %s/КБ), що додаватиметься до вихідних транзакцій (типово: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Скорочення кількості блоків...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Запустити в фоновому режимі (як демон) та приймати команди</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Неможливо запустити HTTP-сервер. Детальніший опис наведено в журналі зневадження.</translation>
</message>
@@ -2746,84 +3170,92 @@
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Прив'язатися до даної адреси та прослуховувати її. Використовуйте запис виду [хост]:порт для IPv6</translation>
+ <source>The %s developers</source>
+ <translation>Розробники %s</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Видалити всі транзакції гаманця та відновити ті, що будуть знайдені під час запуску за допомогою -rescan</translation>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>Неможливо блокувати каталог даних %s. %s, ймовірно, вже працює.</translation>
</message>
<message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Виконати команду, коли транзакція гаманця зміниться (замість %s в команді буде підставлено ідентифікатор транзакції)</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Неможливо встановити визначені з'єднання і одночасно використовувати addrman для встановлення вихідних з'єднань.</translation>
</message>
<message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Встановити кількість потоків скрипту перевірки (від %u до %d, 0 = автоматично, &lt;0 = вказує кількість вільних ядер, типово: %d)</translation>
+ <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation>Помилка читання %s! Всі ключі зчитано правильно, але записи в адресній книзі, або дані транзакцій можуть бути відсутніми чи невірними.</translation>
+ </message>
+ <message>
+ <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
+ <translation>Перевірте правильність дати та часу комп'ютера. Якщо ваш годинник налаштовано невірно, %s не буде працювати належним чином.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Будь ласка, зробіть внесок, якщо ви знаходите %s корисним. Відвідайте %s для отримання додаткової інформації про програмне забезпечення.</translation>
</message>
<message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>Схоже, що база даних блоків містить блок з майбутнього. Це може статися із-за некоректно встановленої дати та/або часу. Перебудовуйте базу даних блоків лише тоді, коли ви переконані, що встановлено правильну дату і час</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Використовувати UPnP для відображення порту, що прослуховується (типово: 1 при прослуховуванні та за відсутності -proxy)</translation>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation>Це перед-релізна тестова збірка - використовуйте на свій власний ризик - не використовуйте для майнінгу або в торговельних додатках</translation>
</message>
<message>
- <source>-maxmempool must be at least %d MB</source>
- <translation>-maxmempool має бути не менше %d МБ</translation>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>Це комісія за транзакцію, яку ви можете відкинути, якщо решта менша, ніж пил на цьому рівні</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; може бути:</translation>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>Неможливо відтворити блоки. Вам потрібно буде перебудувати базу даних, використовуючи -reindex-chainstate.</translation>
</message>
<message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Приймати підключення ззовні (типово: 1 за відсутності -proxy чи -connect)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Неможливо повернути базу даних в стан до розвилки. Вам потрібно буде перезавантажити ланцюжок блоків</translation>
</message>
<message>
- <source>Block creation options:</source>
- <translation>Опції створення блоку:</translation>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Увага: Мережа, здається, не повністю погоджується! Деякі добувачі напевно зазнають проблем.</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Параметри з'єднання:</translation>
+ <source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
+ <translation>Попередження: неможливо досягти консенсусу з підключеними вузлами! Вам, або іншим вузлам необхідно оновити програмне забезпечення.</translation>
</message>
<message>
- <source>Copyright (C) %i-%i</source>
- <translation>Всі права збережено. %i-%i</translation>
+ <source>%d of last 100 blocks have unexpected version</source>
+ <translation>%d з останніх 100 блоків мають неочікувану версію</translation>
</message>
<message>
- <source>Corrupted block database detected</source>
- <translation>Виявлено пошкоджений блок бази даних</translation>
+ <source>%s corrupt, salvage failed</source>
+ <translation>%s пошкоджено, відновлення невдале</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Параметри тестування/налагодження:</translation>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation>-maxmempool має бути не менше %d МБ</translation>
</message>
<message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Не завантажувати гаманець та вимкнути звернення до нього через RPC</translation>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>Не можу вирішити -%s адресу: '%s'</translation>
</message>
<message>
- <source>Do you want to rebuild the block database now?</source>
- <translation>Ви хочете перебудувати базу даних блоків зараз?</translation>
+ <source>Change index out of range</source>
+ <translation>Індекс решти за межами діапазону</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Дозволено введення хеш блоку в рядок &lt;address&gt;</translation>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Всі права збережено. %i-%i</translation>
</message>
<message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Дозволено введення хеш транзакції в рядок &lt;address&gt;</translation>
+ <source>Corrupted block database detected</source>
+ <translation>Виявлено пошкоджений блок бази даних</translation>
</message>
<message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Дозволено введення RAW блоку в рядок &lt;address&gt;</translation>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>Ви хочете перебудувати базу даних блоків зараз?</translation>
</message>
<message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Дозволено введення RAW транзакції в рядок &lt;address&gt;</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>Помилка створення %s: Ви не можете створювати не-HD гаманці з цією версією.</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -2834,6 +3266,22 @@
<translation>Помилка ініціалізації середовища бази даних гаманця %s!</translation>
</message>
<message>
+ <source>Error loading %s</source>
+ <translation>Помилка завантаження %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Помилка завантаження %s: Власні ключі можуть бути тільки вимкнені при створенні</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Помилка завантаження %s: Гаманець пошкоджено</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Помилка завантаження %s: Гаманець потребує новішої версії %s</translation>
+ </message>
+ <message>
<source>Error loading block database</source>
<translation>Помилка завантаження бази даних блоків</translation>
</message>
@@ -2850,6 +3298,10 @@
<translation>Не вдалося слухати на жодному порту. Використовуйте -listen=0, якщо ви хочете цього.</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Помилка пересканування гаманця під час ініціалізації</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Імпорт...</translation>
</message>
@@ -2858,24 +3310,36 @@
<translation>Початковий блок некоректний/відсутній. Чи правильно вказано каталог даних для обраної мережі?</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Утримувати розмір пам'яті для пулу транзакцій меншим за &lt;n&gt; мегабайтів (типово: %u)</translation>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>Невдала перевірка правильності ініціалізації. %s закривається.</translation>
</message>
<message>
- <source>Not enough file descriptors available.</source>
- <translation>Бракує доступних дескрипторів файлів.</translation>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>Невірна сума -%s=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>Невірна сума для -discardfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>Невірна сума для зарезервованої комісії -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Оновлення txindex бази</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Підключатися тільки до вузлів в мережі &lt;net&gt; (ipv4, ipv6 або onion)</translation>
+ <source>Loading P2P addresses...</source>
+ <translation>Завантаження P2P адрес...</translation>
</message>
<message>
- <source>Print this help message and exit</source>
- <translation>Надрукувати це довідкове повідомлення та вийти</translation>
+ <source>Loading banlist...</source>
+ <translation>Завантаження бан-списку...</translation>
</message>
<message>
- <source>Print version and exit</source>
- <translation>Версія для друку і виходу</translation>
+ <source>Not enough file descriptors available.</source>
+ <translation>Бракує доступних дескрипторів файлів.</translation>
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
@@ -2894,12 +3358,20 @@
<translation>Перетворювання блоків...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Встановити розмір кешу бази даних в мегабайтах (від %d до %d, типово: %d)</translation>
+ <source>The source code is available from %s.</source>
+ <translation>Вихідний код доступний з %s.</translation>
+ </message>
+ <message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>Не вдалось розрахувати обсяг комісії за транзакцію та решти</translation>
</message>
<message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Вкажіть файл гаманця (в межах каталогу даних)</translation>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>Неможливо прив'язати %s на цьому комп'ютері. %s, ймовірно, вже працює.</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation>Не вдається створити ключі</translation>
</message>
<message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
@@ -2914,8 +3386,12 @@
<translation>Параметр -tor не підтримується; використовуйте -onion.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Використовувати UPnP для відображення порту, що прослуховується (типово: %u)</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Непідтримувана категорія ведення журналу %s=%s.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>Оновлення бази даних UTXO</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -2926,94 +3402,50 @@
<translation>Перевірка блоків...</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Параметри гаманця:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Дозволити підключення по протоколу JSON-RPC зі вказаного джерела. Правильною для &lt;ip&gt; є окрема IP-адреса (наприклад, 1.2.3.4), IP-адреса та маска підмережі (наприклад, 1.2.3.4/255.255.255.0) або CIDR-адреса (наприклад, 1.2.3.4/24). Цей параметр можна вказувати декілька разів.</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Прив'язатися до даної адреси та вносити до білого списку учасників, що під'єднуються до неї. Використовуйте запис виду [хост]:порт для IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Створювати нові файли з типовими для системи атрибутами доступу замість маски 077 (діє тільки при вимкненому гаманці)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Визначити власні IP-адреси (типово: 1 при прослуховуванні та за відсутності -externalip або -proxy)</translation>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>Гаманець вимагав перезапису: перезавантажте %s для завершення</translation>
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Помилка: Не вдалося налаштувати прослуховування вхідних підключень (listen повернув помилку: %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Виконати команду при надходженні важливого сповіщення або при спостереженні тривалого розгалуження ланцюжка (замість %s буде підставлено повідомлення)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Комісії (в %s/kB), що менші за вказану, вважатимуться нульовими для зміни, аналізу та створення транзакцій (типово: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>Якщо параметр paytxfee не встановлено, включити комісію для отримання перших підтверджень транзакцій протягом n блоків (типово: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Неприпустима сума для -maxtxfee = &lt;amount&gt;: «%s» ( плата повинна бути, принаймні %s, щоб запобігти зависанню транзакцій)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Максимальний розмір даних в транзакціях носіїв даних, що ми передаємо і добуваємо (за замовчуванням: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Надавати випадкові дані доступу для кожного проксі-з'єднання. Це дозволяє ввімкнути ізоляцію потоків Tor'у (типово: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>Залишок від суми транзакції зі сплатою комісії занадто малий </translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Учасники, що знаходяться в білому списку, не можуть бути заблоковані за DoS та їхні транзакції завжди ретранслюватимуться (навіть якщо вони є в пам'яті), що може бути корисним, наприклад, для шлюзу</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>Вам необхідно перебудувати базу даних з використанням -reindex для завантаження повного ланцюжка блоків.</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(типово: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Приймати публічні REST-запити (типово: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Автоматичне з'єднання з прихованим сервісом Tor (типово: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Підключитись через SOCKS5-проксі</translation>
+ <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
+ <translation>Помилка завантаження %s: Ви не можете відключити режим HD в існуючому HD-гаманці</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
<translation>Помилка читання бази даних, припиняю роботу.</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Спочатку імпортує блоки з зовнішнього файлу blk000??.dat </translation>
+ <source>Error upgrading chainstate database</source>
+ <translation>Помилка оновлення бази даних стану ланцюжка</translation>
</message>
<message>
<source>Information</source>
<translation>Інформація</translation>
</message>
<message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Невірна -onion адреса або ім'я хоста: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Невірна -proxy адреса або ім'я хоста: '%s'</translation>
+ </message>
+ <message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
<translation>Вказано некоректну суму для параметру -paytxfee: «%s» (повинно бути щонайменше %s)</translation>
</message>
@@ -3022,44 +3454,28 @@
<translation>Вказано неправильну маску підмережі для -whitelist: «%s»</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Утримувати в пам'яті щонайбільше &lt;n&gt; транзакцій, що споживають невідомі входи (типово: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Необхідно вказати порт для -whitebind: «%s»</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Параметри вузла ретрансляції:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>Параметри сервера RPC:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Зменшення значення -maxconnections з %d до %d із-за обмежень системи.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Спочатку переглянте ланцюжок блоків на наявність втрачених транзакцій гаманця</translation>
+ <source>Signing transaction failed</source>
+ <translation>Підписання транзакції не вдалося</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Відсилати налагоджувальну інформацію на консоль, а не у файл debug.log</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Вказаний каталог гаманця -walletdir "%s" не існує</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Показати всі налагоджувальні параметри (використання: --help -help-debug)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Вказаний каталог гаманця -walletdir "%s" є відносним шляхом</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Стискати файл debug.log під час старту клієнта (типово: 1 коли відсутній параметр -debug)</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>Підписання транзакції не вдалося</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Вказаний шлях -walletdir "%s" не є каталогом</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3070,14 +3486,6 @@
<translation>Це програмне забезпечення є експериментальним.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Пароль управління порт протоколом Tor (типово: empty)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Скористайтесь управлінням порт протоколом Tor, в разі перехоплення обміну цибулевої маршрутизації (типово: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Сума транзакції занадто мала</translation>
</message>
@@ -3094,180 +3502,76 @@
<translation>Неможливо прив'язатися до %s на цьому комп'ютері (bind повернув помилку: %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Спочатку оновіть гаманець до останньої версії</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Ім'я користувача для JSON-RPC-з'єднань</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>Не вдається створити початкові ключі</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>Перевірка гаманця(ців)... </translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>Гаманець %s знаходиться поза каталогом гаманця %s</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>Попередження</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Чи слід працювати в режимі тільки блоки (типово: %u)</translation>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <translation>Попередження: активовано невідомі нові правила (versionbit %i)</translation>
</message>
<message>
<source>Zapping all transactions from wallet...</source>
<translation>Видалення всіх транзакцій з гаманця...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>Параметри сповіщень ZeroMQ:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Пароль для JSON-RPC-з'єднань</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Виконати команду, коли з'явиться новий блок (%s в команді змінюється на хеш блоку)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Дозволити пошук в DNS для команд -addnode, -seednode та -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = утримувати метадані транзакцій (до яких відноситься інформація про власника рахунку та запити платежів), 2 - відкинути)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>Встановлено дуже велике значення -maxtxfee! Такі великі комісії можуть бути сплачені окремою транзакцією.</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Не тримати транзакції в пам'яті довше &lt;n&gt; годин (типово: %u)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Комісії (в %s/kB), що менші за вказану, вважатимуться нульовими для створення транзакцій (типово: %s)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>Рівень ретельності перевірки блоків (0-4, типово: %u)</translation>
+ <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
+ <translation>Помилка завантаження %s: Ви не можете ввімкнути режим HD в існуючому не-HD гаманці</translation>
</message>
<message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Утримувати повний індекс транзакцій (використовується RPC-викликом getrawtransaction) (типово: %u)</translation>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>Це комісія за транзакцію, яку ви можете сплатити, коли кошторисна вартість недоступна.</translation>
</message>
<message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Час в секундах, протягом якого відключені учасники з поганою поведінкою не зможуть підключитися (типово: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Виводити налагоджувальну інформацію (типово: %u, вказання &lt;category&gt; необов'язкове)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Фільтрація блоків та транзакцій з допомогою фільтрів Блума (типово: %u)</translation>
+ <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
+ <translation>Цей продукт включає в себе програмне забезпечення, розроблене проектом OpenSSL для використання в OpenSSL Toolkit %s та криптографічне програмне забезпечення, написане Еріком Янгом та програмне забезпечення UPnP, написане Томасом Бернардом.</translation>
</message>
<message>
<source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
<translation>Загальна довжина рядку мережевої версії (%i) перевищує максимально допустиму (%i). Зменшіть число чи розмір коментарів клієнта користувача.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Намагається зберегти вихідний трафік відповідно до зданого значення (в MIB за 24 години), 0 = без обмежень (типово: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Параметр -socks не підтримується. Можливість вказувати версію SOCKS було видалено, так як підтримується лише SOCKS5.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Використовувати окремий SOCKS5-проксі для з'єднання з учасниками через приховані сервіси Tor (типово: %s)</translation>
- </message>
- <message>
- <source>(default: %s)</source>
- <translation>(типово: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Завжди дізнаватися адреси учасників через DNS (типово: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Помилка завантаження гаманця %s. Недійсні символи в імені файлу -wallet.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>Скільки блоків перевіряти під час запуску (типово: %u, 0 = всі)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Включити IP-адреси до налагоджувального виводу (типово: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Прослуховувати &lt;port&gt; для JSON-RPC з'єднань (типово: %u, для тестової мережі: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Чекати на з'єднання на &lt;port&gt; (типово: %u, для тестової мережі: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Підтримувати щонайбільше &lt;n&gt; з'єднань з учасниками (типово: %u)</translation>
+ <source>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</source>
+ <translation>Непідтримуваний аргумент -whitelistalwaysrelay ігнорується, використовуйте -whitelistrelay та/або -whitelistforcerelay.</translation>
</message>
<message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Дозволити гаманцю розповсюджувати транзакції</translation>
+ <source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
+ <translation>Попередження: видобуваються невідомі версії блоків! Можливо активовано невідомі правила</translation>
</message>
<message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Максимальний розмір вхідного буферу на одне з'єднання, &lt;n&gt;*1000 байтів (типово: %u)</translation>
+ <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
+ <translation>Попередження: файл гаманця пошкоджено, дані врятовано! Оригінальний %s збережено як %s в %s; якщо ваш баланс або транзакції некорректно відображаються, ви повинні відновити його з резервної копії.</translation>
</message>
<message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Максимальний розмір вихідного буферу на одне з'єднання, &lt;n&gt;*1000 байтів (типово: %u)</translation>
+ <source>%s is set very high!</source>
+ <translation>%s встановлено дуже високо!</translation>
</message>
<message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Доповнювати налагоджувальний вивід відміткою часу (типово: %u)</translation>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>Помилка завантаження гаманця %s. Значення параметра -wallet дублюється.</translation>
</message>
<message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Ретранслювати та створювати транзакції носіїв даних (типово: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Ретранслювати не-P2SH транзакції з мультипідписом (типово: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Встановити розмір пулу ключів &lt;n&gt; (типово: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Встановити максимальний розмір блоку BIP141 (за замовчуванням: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Встановити число потоків для обслуговування викликів RPC (типово: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Вказати файл конфігурації (типово: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Вказати тайм-аут підключення в мілісекундах (щонайменше: 1, типово: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Вказати pid-файл (типово: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Витрачати непідтверджену решту при відправленні транзакцій (типово: %u)</translation>
+ <source>Keypool ran out, please call keypoolrefill first</source>
+ <translation>Пул ключів скінчився, потрібно викликати keypoolrefill</translation>
</message>
<message>
<source>Starting network threads...</source>
@@ -3286,10 +3590,6 @@
<translation>Це транзакційна комісія, яку ви сплатите, якщо будете надсилати транзакцію.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Поріг відключення учасників з поганою поведінкою (типово: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Сума транзакції занадто мала (зменьшіть комісію, якщо можливо)</translation>
</message>
@@ -3310,6 +3610,26 @@
<translation>Недостатньо коштів</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>Неможливо створити ключ зміни адреси. Власні ключі вимкнено для цього гаманця.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>Неможливо оновити не-HD гаманець без оновлення підтримки пулу ключів. Будь-ласка використовуйте -upgradewallet=169900 чи -upgradewallet без вказівки версії. </translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Оцінка комісії не вдалася. Fallbackfee вимкнено. Зачекайте кілька блоків або ввімкніть -fallbackfee. </translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Попередження: Власні ключі виявлено в гаманці {%s} з забороненими власними ключами</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Неможливо записати до каталог даних '%s'; перевірте дозвіл.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Завантаження індексу блоків...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ur_PK.ts b/src/qt/locale/bitcoin_ur_PK.ts
index eadd059f7d..03502be8a8 100644
--- a/src/qt/locale/bitcoin_ur_PK.ts
+++ b/src/qt/locale/bitcoin_ur_PK.ts
@@ -53,10 +53,46 @@
<source>C&amp;hoose</source>
<translation>چننا</translation>
</message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>پتے ارسال کیے جارہے ہیں</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>پتے موصول ہورہے ہیں</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>&amp;پتا نقل کریں</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>&amp;لیبل نقل کریں</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>&amp;تدوین</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>پتا فہرست ایکسپورٹ کریں</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>کاما سے جدا فائلیں (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>ایکسپورٹ ناکام ہوا</translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
<message>
+ <source>Label</source>
+ <translation>لیبل</translation>
+ </message>
+ <message>
<source>Address</source>
<translation> پتہ</translation>
</message>
@@ -176,9 +212,17 @@
<source>Address</source>
<translation> پتہ</translation>
</message>
+ <message>
+ <source>Label</source>
+ <translation>لیبل</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>لیبل</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -221,13 +265,29 @@
</context>
<context>
<name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>لیبل</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
<message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>کاما سے جدا فائلیں (*.csv)</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>لیبل</translation>
+ </message>
+ <message>
<source>Address</source>
<translation> پتہ</translation>
</message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>ایکسپورٹ ناکام ہوا</translation>
+ </message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts
index ad70b3309a..d369d4f16a 100644
--- a/src/qt/locale/bitcoin_uz@Cyrl.ts
+++ b/src/qt/locale/bitcoin_uz@Cyrl.ts
@@ -30,6 +30,10 @@
<translation>Жорий танланган манзилни рўйхатдан ўчириш</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Излаш учун манзил ёки ёрлиқни киритинг</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Жорий ички ойна ичидаги маълумотларни файлга экспорт қилиш</translation>
</message>
@@ -413,15 +417,7 @@
<source>Command-line options</source>
<translation>Буйруқлар сатри мосламалари</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Фойдаланиш:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>буйруқлар қатори орқали мослаш</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -952,6 +948,10 @@
<source>&amp;Save Image...</source>
<translation>Расмни &amp;сақлаш</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>Ҳамён</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1050,6 +1050,10 @@
<source>S&amp;end</source>
<translation>Жў&amp;натиш</translation>
</message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Ўтказма тўлови</translation>
+ </message>
</context>
<context>
<name>SendCoinsEntry</name>
@@ -1168,46 +1172,18 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Танламалар:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Маълумотлар директориясини кўрсатинг</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Буйруқлар сатри ва JSON-RPC буйруқларига рози бўлинг</translation>
- </message>
- <message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Демон сифатида орқа фонда ишга туширинг ва буйруқларга рози бўлинг</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Уланиш кўрсаткичлари:</translation>
- </message>
- <message>
<source>Information</source>
<translation>Маълумот</translation>
</message>
<message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC уланишлари учун фойдаланувчи номи</translation>
- </message>
- <message>
<source>Warning</source>
<translation>Диққат</translation>
</message>
<message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC уланишлари учун парол</translation>
- </message>
- <message>
<source>Insufficient funds</source>
<translation>Кам миқдор</translation>
</message>
diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts
index 5e1e13ba8e..768ad38912 100644
--- a/src/qt/locale/bitcoin_vi.ts
+++ b/src/qt/locale/bitcoin_vi.ts
@@ -3,15 +3,15 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Phải chuột để edit address hoặc label</translation>
+ <translation>Phải chuột để sửa địa chỉ hoặc nhãn</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>Create một address mới</translation>
+ <translation>Tạo một địa chỉ mới</translation>
</message>
<message>
<source>&amp;New</source>
- <translation>&amp;Tạo mới</translation>
+ <translation>&amp;Mới</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
@@ -30,6 +30,10 @@
<translation>Xóa địa chỉ đang chọn từ danh sách</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Enter address or label to search</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Xuất dữ liệu trong thẻ hiện tại ra file</translation>
</message>
@@ -314,6 +318,10 @@
<translation>Mở &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Ví tiền</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>Click để vô hiệu hoạt động mạng.</translation>
</message>
@@ -722,10 +730,6 @@
<translation>Địa chỉ</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>Address đang nhận mới</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>Address đang gửi mới</translation>
</message>
@@ -742,10 +746,6 @@
<translation>Address đã nhập "%1" không valid Bitcoin address.</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>Address đã nhập "%1" đã có trong address book.</translation>
- </message>
- <message>
<source>Could not unlock wallet.</source>
<translation>Không thể unlock wallet.</translation>
</message>
@@ -795,42 +795,6 @@
<source>Command-line options</source>
<translation>Command-line options</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Usage:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>command-line options</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>Tùy chỉnh UI:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>Chọn dữ liệu danh mục trên startup (default: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Cài đặt ngôn ngữ, ví dụ "de_DE" (default: system locale)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>Khởi tạo tối thiểu</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Đặt chứng chỉ SSL root certificates cho payment request (default: -system-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>Hiển thị splash screen trên startup (default: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>Reset tất cả cài đặt thay đổi trong GUI</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -1503,10 +1467,6 @@
<translation>Error: Xác định data directory "%1" không tồn tại.</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>Error: Không thể parse configuration file: %1. Chỉ dùng key=value syntax.</translation>
- </message>
- <message>
<source>Error: %1</source>
<translation>Error: %1</translation>
</message>
@@ -1939,6 +1899,10 @@
<translation>Tin nhắn</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Ví</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>Đang tính toán URI quá dài, cố gắng giảm text cho label / message.</translation>
</message>
@@ -2057,10 +2021,6 @@
<translation>trên mỗi kilobyte</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>Nếu the custom fee được đặt 1000 satoshis và the transaction chỉ 250 bytes, nên "per kilobyte" chỉ trả 250 satoshis trong fee, trong khi "total at least" trả 1000 satoshis. Để các giao dịch lớn hơn a kilobyte both pay by kilobyte.</translation>
- </message>
- <message>
<source>Hide</source>
<translation>Ẩn</translation>
</message>
@@ -2161,18 +2121,14 @@
<translation>Bạn chắc chắn muốn gửi chứ?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>đã thêm transaction fee</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>Tổng Số lượng %1</translation>
- </message>
- <message>
<source>or</source>
<translation>hoặc</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation>Transaction fee</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Confirm gửi coins</translation>
</message>
@@ -2510,10 +2466,6 @@
<translation>conflicted with a transaction with %1 confirmations</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1/offline</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/unconfirmed, %1</translation>
</message>
@@ -2542,14 +2494,6 @@
<translation>Status</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>, has not been successfully broadcast yet</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>, broadcast qua %n nodes</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>Ngày</translation>
</message>
@@ -2704,10 +2648,6 @@
<translation>Open until %1</translation>
</message>
<message>
- <source>Offline</source>
- <translation>Offline</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>Unconfirmed</translation>
</message>
@@ -2732,10 +2672,6 @@
<translation>Immature (%1 confirmations, will be available after %2)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>This block was not received by any other nodes and will probably not be accepted!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>Generated but not accepted</translation>
</message>
@@ -3042,38 +2978,14 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>The wallet data was successfully saved to %1.</translation>
</message>
-</context>
+ </context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Options:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>Specify data directory</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>Specify your own public address</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>Accept command line and JSON-RPC commands</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>Distributed under the MIT software license, see the accompanying file %s or %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>Prune configured below the minimum of %d MiB. Please use a higher number.</translation>
</message>
@@ -3090,18 +3002,10 @@
<translation>Error: A fatal internal error occurred, see debug.log for details</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>Fee (in %s/kB) to add to transactions you send (default: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning blockstore...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>Run in the background as a daemon and accept commands</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>Unable to start HTTP server. See debug log for details.</translation>
</message>
@@ -3114,54 +3018,14 @@
<translation>The %s developers</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>Bind to given address and always listen on it. Use [host]:port notation for IPv6</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>Extra transactions to keep in memory for compact block reconstructions (default: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</translation>
</message>
@@ -3170,22 +3034,6 @@
<translation>Please contribute if you find %s useful. Visit %s for further information about the software.</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</translation>
</message>
@@ -3206,18 +3054,6 @@
<translation>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>Wallet will not create transactions that violate mempool chain limits (default: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</translation>
</message>
@@ -3226,10 +3062,6 @@
<translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>Whether to save the mempool on shutdown and load on restart (default: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>%d of last 100 blocks have unexpected version</translation>
</message>
@@ -3242,42 +3074,14 @@
<translation>-maxmempool must be at least %d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; can be:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>Append comment to the user agent string</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>Attempt to recover private keys from a corrupt wallet on startup</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>Block creation options:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>Cannot resolve -%s address: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>Chain selection options:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>Change index out of range</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>Connection options:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>Copyright (C) %i-%i</translation>
</message>
@@ -3286,38 +3090,10 @@
<translation>Corrupted block database detected</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>Debugging/Testing options:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>Do not load the wallet and disable wallet RPC calls</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Do you want to rebuild the block database now?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>Enable publish hash block in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>Enable publish hash transaction in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>Enable publish raw block in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>Enable publish raw transaction in &lt;address&gt;</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>Enable transaction replacement in the memory pool (default: %u)</translation>
- </message>
- <message>
<source>Error initializing block database</source>
<translation>Error initializing block database</translation>
</message>
@@ -3378,10 +3154,6 @@
<translation>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</translation>
- </message>
- <message>
<source>Loading P2P addresses...</source>
<translation>Loading P2P addresses...</translation>
</message>
@@ -3390,26 +3162,10 @@
<translation>Loading banlist...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>Location of the auth cookie (default: data dir)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>Not enough file descriptors available.</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>Print this help message and exit</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>Print version and exit</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>Prune cannot be configured with a negative value.</translation>
</message>
@@ -3418,14 +3174,6 @@
<translation>Prune mode is incompatible with -txindex.</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>Rebuild chain state and block index from the blk*.dat files on disk</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>Rebuild chain state from the currently indexed blocks</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>Replaying blocks...</translation>
</message>
@@ -3434,14 +3182,6 @@
<translation>Rewinding blocks...</translation>
</message>
<message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>Set database cache size in megabytes (%d to %d, default: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>Specify wallet file (within data directory)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>The source code is available from %s.</translation>
</message>
@@ -3474,14 +3214,6 @@
<translation>Upgrading UTXO database</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>Use UPnP to map the listening port (default: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>Use the test chain</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>User Agent comment (%s) contains unsafe characters.</translation>
</message>
@@ -3490,90 +3222,26 @@
<translation>Verifying blocks...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>Wallet debugging/testing options:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>Wallet needed to be rewritten: restart %s to complete</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>Wallet options:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>Error: Listening for incoming connections failed (listen returned error %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maximum size of data in data carrier transactions we relay and mine (default: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>The transaction amount is too small to send after the fee has been deducted</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(default: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>Accept public REST requests (default: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>Automatically create Tor hidden service (default: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>Connect through SOCKS5 proxy</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>Error loading %s: You can't disable HD on an already existing HD wallet</translation>
</message>
@@ -3586,10 +3254,6 @@
<translation>Error upgrading chainstate database</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>Imports blocks from external blk000??.dat file on startup</translation>
- </message>
- <message>
<source>Information</source>
<translation>Thông tin</translation>
</message>
@@ -3610,42 +3274,14 @@
<translation>Invalid netmask specified in -whitelist: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Need to specify a port with -whitebind: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>Node relay options:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC server options:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>Reducing -maxconnections from %d to %d, because of system limitations.</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>Rescan the block chain for missing wallet transactions on startup</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>Send trace/debug info to console instead of debug.log file</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>Show all debugging options (usage: --help -help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>Shrink debug.log file on client startup (default: 1 when no -debug)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>Signing transaction failed</translation>
</message>
@@ -3658,14 +3294,6 @@
<translation>This is experimental software.</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor control port password (default: empty)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>Tor control port to use if onion listening enabled (default: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>Transaction amount too small</translation>
</message>
@@ -3682,14 +3310,6 @@
<translation>Unable to bind to %s on this computer (bind returned error %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>Upgrade wallet to latest format on startup</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>Username for JSON-RPC connections</translation>
- </message>
- <message>
<source>Verifying wallet(s)...</source>
<translation>Verifying wallet(s)...</translation>
</message>
@@ -3702,98 +3322,18 @@
<translation>Warning: unknown new rules activated (versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>Whether to operate in a blocks only mode (default: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>You need to rebuild the database using -reindex to change -txindex</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>Zapping all transactions from wallet...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ notification options:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>Password for JSON-RPC connections</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>Allow DNS lookups for -addnode, -seednode and -connect</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>Error loading %s: You can't enable HD on an already existing non-HD wallet</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>How thorough the block verification of -checkblocks is (0-4, default: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>Support filtering of blocks and transaction with bloom filters (default: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>This is the transaction fee you may pay when fee estimates are not available.</translation>
</message>
@@ -3806,10 +3346,6 @@
<translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</translation>
</message>
@@ -3818,10 +3354,6 @@
<translation>Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</translation>
</message>
@@ -3830,110 +3362,18 @@
<translation>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is set very high!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(default: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>Always query for peer addresses via DNS lookup (default: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>Error loading wallet %s. -wallet filename must be a regular file.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Error loading wallet %s. Duplicate -wallet filename specified.</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>Error loading wallet %s. Invalid characters in -wallet filename.</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>How many blocks to check at startup (default: %u, 0 = all)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>Include IP addresses in debug output (default: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>Keypool ran out, please call keypoolrefill first</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>Maintain at most &lt;n&gt; connections to peers (default: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>Make the wallet broadcast transactions</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>Prepend debug output with timestamp (default: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Relay and mine data carrier transactions (default: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>Relay non-P2SH multisig (default: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>Set key pool size to &lt;n&gt; (default: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>Set maximum BIP141 block weight (default: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>Set the number of threads to service RPC calls (default: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>Specify configuration file (default: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>Specify connection timeout in milliseconds (minimum: 1, default: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>Specify pid file (default: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>Spend unconfirmed change khi đang gửi transactions (default: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>Starting network threads...</translation>
</message>
@@ -3950,10 +3390,6 @@
<translation>Đây là transaction fee bạn sẽ pay nếu gửi transaction.</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>Ngường ngắt kết nối không hoạt động peers (default: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>Transaction amounts phải không âm</translation>
</message>
diff --git a/src/qt/locale/bitcoin_vi_VN.ts b/src/qt/locale/bitcoin_vi_VN.ts
index 50aa1889eb..c9f9ca2add 100644
--- a/src/qt/locale/bitcoin_vi_VN.ts
+++ b/src/qt/locale/bitcoin_vi_VN.ts
@@ -11,7 +11,7 @@
</message>
<message>
<source>&amp;New</source>
- <translation>&amp;Mới</translation>
+ <translation>&amp;Tạo mới</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
@@ -62,6 +62,14 @@
<translation>Địa chỉ nhận</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation>Đây là các địa chỉ Bitcoin để gửi bạn gửi tiền. Trước khi gửi bạn nên kiểm tra lại số tiền bạn muốn gửi và địa chỉ bitcoin của người nhận.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
+ <translation>Đây là các địa chỉ Bitcoin để bạn nhận tiền. Với mỗi giao dịch, bạn nên dùng một địa chỉ Bitcoin mới để nhận tiền.</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;Chép Địa chỉ</translation>
</message>
@@ -120,6 +128,14 @@
<translation>Điền lại passphrase</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>Hiện mật khẩu</translation>
+ </message>
+ <message>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Nhập passphrase mới cho Ví của bạn.&lt;br/&gt;Vui long dùng passphrase gồm&lt;b&gt;ít nhất 10 ký tự bất kỳ &lt;/b&gt;, hoặc &lt;b&gt;ít nhất 8 chữ&lt;/b&gt;.</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Mã hóa ví</translation>
</message>
@@ -608,23 +624,7 @@ Ví của bạn chưa được mã hóa.</translation>
<source>Command-line options</source>
<translation>&amp;Tùy chọn dòng lệnh</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>Mức sử dụng</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>tùy chọn dòng lệnh</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>Chọn ngôn ngữ, ví dụ "de_DE" (mặc định: Vị trí hệ thống)</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>Đặt chứng nhận SSL gốc cho yêu cầu giao dịch (mặc định: -hệ thống-)</translation>
- </message>
- </context>
+</context>
<context>
<name>Intro</name>
<message>
@@ -964,6 +964,10 @@ Ví của bạn chưa được mã hóa.</translation>
<translation>Tin nhắn</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>Ví</translation>
+ </message>
+ <message>
<source>Error encoding URI into QR Code.</source>
<translation>Lỗi khi encode từ URI thành QR Code</translation>
</message>
@@ -1086,10 +1090,6 @@ Ví của bạn chưa được mã hóa.</translation>
<translation>%1 đến %2</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>Tổng cộng %1</translation>
- </message>
- <message>
<source>or</source>
<translation>hoặc</translation>
</message>
@@ -1203,18 +1203,10 @@ Ví của bạn chưa được mã hóa.</translation>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>Lựa chọn:</translation>
- </message>
- <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(mặc định: %u)</translation>
- </message>
- <message>
<source>Information</source>
<translation>Thông tin</translation>
</message>
@@ -1227,10 +1219,6 @@ Ví của bạn chưa được mã hóa.</translation>
<translation>Chú ý</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(mặc định: %s)</translation>
- </message>
- <message>
<source>Insufficient funds</source>
<translation>Không đủ tiền</translation>
</message>
diff --git a/src/qt/locale/bitcoin_zh.ts b/src/qt/locale/bitcoin_zh.ts
index f1d9be62a2..7edb8e038d 100644
--- a/src/qt/locale/bitcoin_zh.ts
+++ b/src/qt/locale/bitcoin_zh.ts
@@ -1,6 +1,30 @@
<TS language="zh" version="2.1">
<context>
<name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>右键单击来编辑地址或者标签</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>创建一个新地址</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>复制当前已选地址到系统剪切板</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>从列表中删除当前已选地址</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>将当前选项卡中的数据导出到文件</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>选择想要发送币的地址</translation>
+ </message>
</context>
<context>
<name>AddressTableModel</name>
@@ -168,6 +192,10 @@
</context>
<context>
<name>WalletView</name>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>将当前选项卡中的数据导出到文件</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts
index 9c19fac0c8..ed9f6c2d7d 100644
--- a/src/qt/locale/bitcoin_zh_CN.ts
+++ b/src/qt/locale/bitcoin_zh_CN.ts
@@ -30,6 +30,10 @@
<translation>从列表中删除选中的地址</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>输入地址或标签来搜索</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>将当前标签页数据导出到文件</translation>
</message>
@@ -43,15 +47,15 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>选择要付钱过去的地址</translation>
+ <translation>选择要发币给哪些地址</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>选择要收钱进来的地址</translation>
+ <translation>选择要用哪些地址收币</translation>
</message>
<message>
<source>C&amp;hoose</source>
- <translation>选择</translation>
+ <translation>选择(&amp;C)</translation>
</message>
<message>
<source>Sending addresses</source>
@@ -63,23 +67,23 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation>这些是你要付款过去的比特币地址。在付钱之前,务必要检查金额和收款地址是否正确。</translation>
+ <translation>您可以给这些比特币地址付款。在付款之前,务必要检查金额和收款地址是否正确。</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
- <translation>这些是你用来收款的比特币地址。建议在每次交易时,都使用一个新的收款地址。</translation>
+ <translation>您可以用这些比特币地址收款。建议在每次交易时,都使用一个新的收款地址。</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>复制地址</translation>
+ <translation>复制地址(&amp;C)</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>复制标签</translation>
+ <translation>复制标签(&amp;L)</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation>编辑</translation>
+ <translation>编辑(&amp;E)</translation>
</message>
<message>
<source>Export Address List</source>
@@ -132,6 +136,10 @@
<translation>重复新密码</translation>
</message>
<message>
+ <source>Show password</source>
+ <translation>显示密码</translation>
+ </message>
+ <message>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>输入钱包的新密码。&lt;br/&gt;密码请用&lt;b&gt;10 个以上的随机字符&lt;/b&gt;,或是&lt;b&gt;8 个以上的字词&lt;/b&gt;。</translation>
</message>
@@ -181,7 +189,7 @@
</message>
<message>
<source>%1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>%1 现在要关闭,以完成加密过程。请注意,加密钱包不能完全防止入侵你的电脑的恶意程序偷取钱币。</translation>
+ <translation>%1 现在要关闭,以完成加密过程。请注意,加密钱包不能完全防止入侵您电脑的恶意程序偷取您的比特币。</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
@@ -307,17 +315,25 @@
</message>
<message>
<source>&amp;Sending addresses...</source>
- <translation>正在发送地址(&amp;S)...</translation>
+ <translation>付款地址(&amp;S)...</translation>
</message>
<message>
<source>&amp;Receiving addresses...</source>
- <translation>正在接收地址(&amp;R)...</translation>
+ <translation>收款地址(&amp;R)...</translation>
</message>
<message>
<source>Open &amp;URI...</source>
<translation>打开 &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>钱包:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>默认钱包</translation>
+ </message>
+ <message>
<source>Click to disable network activity.</source>
<translation>点击禁用网络活动。</translation>
</message>
@@ -335,7 +351,11 @@
</message>
<message>
<source>Reindexing blocks on disk...</source>
- <translation>正在为数据块重建索引...</translation>
+ <translation>正在为区块数据重建索引...</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>代理已被&lt;b&gt;启用&lt;/b&gt;:%1</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
@@ -433,13 +453,21 @@
<source>&amp;Command-line options</source>
<translation>命令行选项(&amp;C)</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n 个有效连接至比特币网络</numerusform></translation>
+ </message>
<message>
<source>Indexing blocks on disk...</source>
- <translation>正在为数据块建立索引...</translation>
+ <translation>正在为区块数据建立索引...</translation>
</message>
<message>
<source>Processing blocks on disk...</source>
- <translation>正在处理数据块...</translation>
+ <translation>正在处理区块数据...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>已处理 %n 个区块的交易历史</numerusform></translation>
</message>
<message>
<source>%1 behind</source>
@@ -498,6 +526,11 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>钱包:%1</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>类型: %1
@@ -548,7 +581,7 @@
<name>CoinControlDialog</name>
<message>
<source>Coin Selection</source>
- <translation>选择钱币</translation>
+ <translation>币源选择(Coin Selection)</translation>
</message>
<message>
<source>Quantity:</source>
@@ -568,7 +601,7 @@
</message>
<message>
<source>Dust:</source>
- <translation>小额:</translation>
+ <translation>粉尘:</translation>
</message>
<message>
<source>After Fee:</source>
@@ -576,11 +609,11 @@
</message>
<message>
<source>Change:</source>
- <translation>变更 : </translation>
+ <translation>找零 : </translation>
</message>
<message>
<source>(un)select all</source>
- <translation>(不)全选</translation>
+ <translation>全(不)选</translation>
</message>
<message>
<source>Tree mode</source>
@@ -656,7 +689,7 @@
</message>
<message>
<source>Copy dust</source>
- <translation>复制零散金额</translation>
+ <translation>复制粉尘金额</translation>
</message>
<message>
<source>Copy change</source>
@@ -676,7 +709,7 @@
</message>
<message>
<source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>当任何一个收款金额小于目前的零散金额上限时,文字会变红色。</translation>
+ <translation>当任何一个收款金额小于目前的粉尘金额上限时,文字会变红色。</translation>
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
@@ -718,10 +751,6 @@
<translation>地址(&amp;A)</translation>
</message>
<message>
- <source>New receiving address</source>
- <translation>新建收款地址</translation>
- </message>
- <message>
<source>New sending address</source>
<translation>新建付款地址</translation>
</message>
@@ -738,8 +767,12 @@
<translation>输入的地址 %1 并不是有效的比特币地址。</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>输入的地址 %1 已经存在地址簿。</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>地址“%1”已经存在,它是一个接受地址,标签为“%2”,所以它不能被添加为一个发送地址。</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>输入地址“%1”已经存在于地址簿中,标签为“%2”。</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -747,7 +780,7 @@
</message>
<message>
<source>New key generation failed.</source>
- <translation>产生新的密钥失败了。</translation>
+ <translation>生成新密钥失败。</translation>
</message>
</context>
<context>
@@ -785,48 +818,12 @@
</message>
<message>
<source>About %1</source>
- <translation>關於 %1</translation>
+ <translation>关于 %1</translation>
</message>
<message>
<source>Command-line options</source>
<translation>命令行选项</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>使用:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>命令行选项</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>界面选项:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>在启动时选择目录(默认%u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>设置语言, 例如“zh-CN”(默认:系统语言)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>启动时最小化</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>设置付款请求的SSL根证书(默认:-系统-)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>显示启动画面(默认:%u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>重置图形界面所有的变更设置</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -886,7 +883,15 @@
<source>Error</source>
<translation>错误</translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>%n GB 可用空闲空间</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(%n GB 需要)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -911,7 +916,7 @@
</message>
<message>
<source>Last block time</source>
- <translation>上一数据块时间</translation>
+ <translation>上一区块时间</translation>
</message>
<message>
<source>Progress</source>
@@ -1000,12 +1005,24 @@
<translation>显示默认的SOCKS5代理是否被用于在该类型的网络下连接同伴</translation>
</message>
<message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
+ <translation>通过Tor隐藏服务连接节点时使用不同的SOCKS&amp;5代理:</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>隐藏系统通知区图标</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>隐藏通知区图标(&amp;H)</translation>
+ </message>
+ <message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
- <translation>窗口被关闭时最小化而不是退出应用程序。当此选项启用时,应用程序只会在菜单中选择退出时退出。</translation>
+ <translation>窗口被关闭时最小化而不是退出应用程序。当此选项启用时,应用程序只会在菜单中选择“退出”时退出。</translation>
</message>
<message>
<source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
- <translation>出现在交易的选项卡的上下文菜单项的第三方网址 (例如:区块链接查询) 。 %s的URL被替换为交易哈希。多个的URL需要竖线 | 分隔。</translation>
+ <translation>出现在交易的选项卡的上下文菜单项的第三方网址 (例如:区块浏览器) 。 %s的URL被替换为交易哈希。多个的URL需要竖线 | 分隔。</translation>
</message>
<message>
<source>Active command-line options that override above options:</source>
@@ -1032,6 +1049,22 @@
<translation>网络(&amp;N)</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>禁用一些高级特性,但是仍然会对所有区块数据进行完整验证。必须重新下载整个区块链数据才能撤销此设置。实际的磁盘空间占用可能会略高。</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>将区块存储修剪至(&amp;B)</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>警告:还原此设置需要重新下载整个区块链。</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation>(0 = 自动, &lt;0 = 保持指定数量的CPU核心空闲)</translation>
</message>
@@ -1049,11 +1082,11 @@
</message>
<message>
<source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
- <translation>如果禁用未确认的零钱,则零钱至少需要1个确认才能使用。同时账户余额计算会受到影响。</translation>
+ <translation>如果您禁止动用尚未确认的找零资金,则一笔交易的找零资金至少需要有1个确认后才能动用。这同时也会影响账户余额的计算。</translation>
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
- <translation>使用未经确认的零钱(&amp;S)</translation>
+ <translation>动用尚未确认的找零资金(&amp;S)</translation>
</message>
<message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
@@ -1064,6 +1097,14 @@
<translation>使用 &amp;UPnP 映射端口</translation>
</message>
<message>
+ <source>Accept connections from outside.</source>
+ <translation>接收外部连接。</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>允许流入连接(&amp;G)</translation>
+ </message>
+ <message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<translation>通过 SOCKS5 代理连接比特币网络。</translation>
</message>
@@ -1117,7 +1158,7 @@
</message>
<message>
<source>M&amp;inimize on close</source>
- <translation>单击关闭按钮最小化(&amp;I)</translation>
+ <translation>单击关闭按钮时最小化(&amp;I)</translation>
</message>
<message>
<source>&amp;Display</source>
@@ -1144,6 +1185,10 @@
<translation>是否需要交易源地址控制功能。</translation>
</message>
<message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>第三方交易网址(&amp;T)</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>确定(&amp;O)</translation>
</message>
@@ -1287,6 +1332,10 @@
<translation>URI 处理</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>‘bitcoin://’不是合法的URI。请使用'bitcoin:'作为替代。</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>取得付款请求的 URL 无效: %1</translation>
</message>
@@ -1424,10 +1473,34 @@
<source>%1 ms</source>
<translation>%1 毫秒</translation>
</message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation><numerusform>%n 秒</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation><numerusform>%n 分</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation><numerusform>%n 时</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation><numerusform>%n 天</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation><numerusform>%n 周</numerusform></translation>
+ </message>
<message>
<source>%1 and %2</source>
<translation>%1 和 %2</translation>
</message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation><numerusform>%n 年</numerusform></translation>
+ </message>
<message>
<source>%1 B</source>
<translation>%1 字节</translation>
@@ -1456,12 +1529,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>解析命令行参数错误:%1</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>错误:指定的数据目录“%1”不存在。</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>错误:无法解析配置文件:%1。只接受 key=value语法。</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>错误:无法解析配置文件:%1</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1535,15 +1612,15 @@
</message>
<message>
<source>Block chain</source>
- <translation>数据链</translation>
+ <translation>区块链</translation>
</message>
<message>
<source>Current number of blocks</source>
- <translation>当前数据块数量</translation>
+ <translation>当前区块数量</translation>
</message>
<message>
<source>Memory Pool</source>
- <translation>资金池</translation>
+ <translation>内存池</translation>
</message>
<message>
<source>Current number of transactions</source>
@@ -1554,6 +1631,14 @@
<translation>内存使用</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>钱包:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(无)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>&amp;重启</translation>
</message>
@@ -1591,7 +1676,7 @@
</message>
<message>
<source>Starting Block</source>
- <translation>正在启动数据块</translation>
+ <translation>起步区块</translation>
</message>
<message>
<source>Synced Headers</source>
@@ -1599,7 +1684,7 @@
</message>
<message>
<source>Synced Blocks</source>
- <translation>同步区块链</translation>
+ <translation>已同步区块</translation>
</message>
<message>
<source>User Agent</source>
@@ -1655,7 +1740,7 @@
</message>
<message>
<source>Last block time</source>
- <translation>上一数据块时间</translation>
+ <translation>上一区块时间</translation>
</message>
<message>
<source>&amp;Open</source>
@@ -1718,6 +1803,10 @@
<translation>重新允许</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>默认钱包</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.</source>
<translation>欢迎使用 %1 的 RPC 控制台。</translation>
</message>
@@ -1726,6 +1815,14 @@
<translation>使用上下方向键浏览历史, 以及 %1 清除屏幕。</translation>
</message>
<message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>输入%1命令显示可用命令信息。</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>输入%1来取得使用这个控制台的更多信息。</translation>
+ </message>
+ <message>
<source>WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.</source>
<translation>警告: 已有骗子通过要求用户在此输入指令以盗取钱包。不要在没有完全理解命令规范时使用控制台。</translation>
</message>
@@ -1734,6 +1831,14 @@
<translation>网络活动已禁用</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>不使用任何钱包执行命令</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>使用“%1”钱包执行命令</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(节点ID: %1)</translation>
</message>
@@ -1805,6 +1910,14 @@
<translation>清除</translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>原生隔离见证地址(又称为Bech32或者BIP-173)可减少您日后的交易费用,并且可以更好的防范打字错误,但旧版本的钱包不能识别这种地址。如果取消勾选,则会生成一个与旧版本钱包兼容的地址。</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>生成原生隔离见证 (Bech32)地址</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>请求付款的历史</translation>
</message>
@@ -1892,6 +2005,10 @@
<translation>消息</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>钱包</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>URI 太长,请试着精简标签或消息文本。</translation>
</message>
@@ -1975,15 +2092,15 @@
</message>
<message>
<source>Change:</source>
- <translation>变更 : </translation>
+ <translation>找零 : </translation>
</message>
<message>
<source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
- <translation>如果激活该选项,但是零钱地址用光或者非法,将会新生成零钱地址,转入零钱。</translation>
+ <translation>如果该选项已被激活,但是找零地址却被用光了,或者是非法的,找零资金将会被转入新生成的地址。</translation>
</message>
<message>
<source>Custom change address</source>
- <translation>自定义零钱地址</translation>
+ <translation>自定义找零地址</translation>
</message>
<message>
<source>Transaction Fee:</source>
@@ -2006,12 +2123,16 @@
<translation>收起 费用设置 </translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>每kb</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>按照交易的虚拟大小自定义每kB ( 1,000 字节 )要交多少手续费。
+
+注意:手续费是按照字节数计算的,对于一笔大小为500字节(1kB的一半)的交易来说,"每kB付100聪手续费"就意味着手续费一共只付了50聪。</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>如果自定义交易费设置为 1000聪而交易大小只有250字节,则“每千字节" 模式只支付250聪交易费, 而"最少"模式则支付1000聪。 大于1000字节的交易按每千字节付费。</translation>
+ <source>per kilobyte</source>
+ <translation>每kb</translation>
</message>
<message>
<source>Hide</source>
@@ -2035,7 +2156,7 @@
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
- <translation>(智能交易费用 尚未初始化。 需要再下载一些数据块...)</translation>
+ <translation>(智能交易费用 尚未初始化。 需要再下载一些区块数据...)</translation>
</message>
<message>
<source>Send to multiple recipients at once</source>
@@ -2058,6 +2179,14 @@
<translation>确认时间目标:</translation>
</message>
<message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>启用手续费追加</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation>手续费追加(Replace-By-Fee,BIP-125)可以让你在送出交易后才来提高手续费。不用这个功能的话,建议付比较高的手续费来降低交易延迟的风险。</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>清除所有(&amp;A)</translation>
</message>
@@ -2114,16 +2243,32 @@
<translation>您确定要发出吗?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>已添加交易费</translation>
+ <source>or</source>
+ <translation>或</translation>
</message>
<message>
- <source>Total Amount %1</source>
- <translation>总金额 %1</translation>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>你可以之后再提高手续费(有BIP-125手续费追加的标记)</translation>
</message>
<message>
- <source>or</source>
- <translation>或</translation>
+ <source>from wallet %1</source>
+ <translation>从钱包%1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>请检查您的交易。</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>交易费用</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>没有BIP-125手续费追加的标记。</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>总额</translation>
</message>
<message>
<source>Confirm send coins</source>
@@ -2169,13 +2314,17 @@
<source>Pay only the required fee of %1</source>
<translation>只支付必要费用 %1</translation>
</message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>预计 %n 个区块后开始被确认。</numerusform></translation>
+ </message>
<message>
<source>Warning: Invalid Bitcoin address</source>
<translation>警告: 比特币地址无效</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
- <translation>警告:未知的更改地址</translation>
+ <translation>警告:未知的找零地址</translation>
</message>
<message>
<source>Confirm custom change address</source>
@@ -2241,6 +2390,10 @@
<translation>从金额中减去交易费(&amp;U)</translation>
</message>
<message>
+ <source>Use available balance</source>
+ <translation>使用全部可用余额</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>消息:</translation>
</message>
@@ -2446,6 +2599,10 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>在进一步同步完%n个区块前状态待定</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>至 %1 个数据块时开启</translation>
@@ -2455,10 +2612,6 @@
<translation>与一个有 %1 个确认的交易冲突</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1 / 离线</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0/未确认,%1</translation>
</message>
@@ -2487,10 +2640,6 @@
<translation>状态</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>,未被成功广播</translation>
- </message>
- <message>
<source>Date</source>
<translation>日期</translation>
</message>
@@ -2530,6 +2679,10 @@
<source>Credit</source>
<translation>收入</translation>
</message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>还差 %n 个区块成熟</numerusform></translation>
+ </message>
<message>
<source>not accepted</source>
<translation>未被接受</translation>
@@ -2571,6 +2724,10 @@
<translation>交易总大小</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>交易虚拟大小</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>输出索引</translation>
</message>
@@ -2580,7 +2737,7 @@
</message>
<message>
<source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation>生成的比特币在可以使用前必须有 %1 个成熟的区块。当您生成了此区块后,它将被广播到网络中以加入区块链。如果它未成功进入区块链,其状态将变更为“不接受”并且不可使用。这可能偶尔会发生,如果另一个节点比你早几秒钟成功生成一个区块。</translation>
+ <translation>新挖出的比特币在可以使用前必须经过 %1 个区块确认的成熟过程。当您挖出此区块后,它将被广播到网络中以加入区块链。如果它未成功进入区块链,其状态将变更为“不接受”并且不可使用。这可能偶尔会发生,在另一个节点比你早几秒钟成功挖出一个区块时就会这样。</translation>
</message>
<message>
<source>Debug information</source>
@@ -2632,15 +2789,15 @@
<source>Label</source>
<translation>标签</translation>
</message>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>在进一步同步完%n个区块前状态待定</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>至 %1 个数据块时开启</translation>
</message>
<message>
- <source>Offline</source>
- <translation>离线</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>未确认</translation>
</message>
@@ -2665,10 +2822,6 @@
<translation>未成熟 (%1 个确认,将在 %2 个后可用)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>此数据块未被任何其他节点接收,可能不被接受!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>已生成但未被接受</translation>
</message>
@@ -2780,6 +2933,10 @@
<translation>其它</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>输入地址、交易识别码或标签进行搜索</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>最小金额</translation>
</message>
@@ -2905,6 +3062,10 @@
<translation>发送</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>手续费提升失败</translation>
+ </message>
+ <message>
<source>Increasing transaction fee failed</source>
<translation>增加交易费失败</translation>
</message>
@@ -2925,6 +3086,10 @@
<translation>新交易费:</translation>
</message>
<message>
+ <source>Confirm fee bump</source>
+ <translation>确认手续费提升</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>无法签署交易。</translation>
</message>
@@ -2967,41 +3132,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>钱包数据成功保存至 %1。</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>取消</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>选项:
-</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>指定数据目录
-</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>连接一个节点并获取对端地址,然后断开连接</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>指定您的公共地址</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>接受命令行和 JSON-RPC 命令
-</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>在MIT协议下分发,参见附带的 %s 文件或 %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>如果&lt;category&gt;未提供或&lt;category&gt; = 1,输出所有调试信息。</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>修剪值被设置为低于最小值%d MiB,请使用更大的数值。</translation>
</message>
@@ -3011,27 +3153,17 @@
</message>
<message>
<source>Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.</source>
- <translation>无法在开启修剪的状态下重扫描,请使用 -reindex重新下载完整的区块链。</translation>
+ <translation>无法在开启修剪的状态下进行重扫描,请使用 -reindex重新下载完整的区块链。</translation>
</message>
<message>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation>错误:发生了致命的内部错误,详情见 debug.log 文件</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>为付款交易添加交易费 (%s/kB) (默认: %s) </translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>正在修剪区块存储...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>在后台运行并接受命令
-
-</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>无法启动HTTP服务,查看日志获取更多信息</translation>
</message>
@@ -3044,42 +3176,18 @@
<translation>%s 开发人员</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>当费用估计数据(default: %s)不足时将会启用的费率 (in %s/kB) </translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>即使在无关联交易(默认: %d)时也接受来自白名单同行的关联交易</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>绑定指定的IP地址开始监听。IPv6地址请使用[host]:port 格式</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>无法锁定数据目录 %s。%s 可能已经在运行。</translation>
</message>
<message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>删除钱包的所有交易记录,且只有用 -rescan参数启动客户端才能重新取回交易记录 </translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>无法同时指定特定连接地址以及自动寻找连接。</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>读取 %s 时发生错误!所有的密钥都可以正确读取,但是交易记录或地址簿数据可能已经丢失或出错。</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>排除某一类Debug信息。可以与 -debug=1 一起使用,以输出除了指定类别以外的Debug日志。</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>当最佳区块变化时执行命令 (命令行中的 %s 会被替换成区块哈希值)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>最大的单次钱包或原始转账费用(%s),设置太低可能导致大尺寸交易失败(默认:%s)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>请检查电脑的日期时间设置是否正确!时间错误可能会导致 %s 运行异常。</translation>
</message>
@@ -3088,10 +3196,6 @@
<translation>如果你认为%s对你比较有用的话,请对我们进行一些捐赠支持。请访问%s网站来获取有关这个软件的更多信息。</translation>
</message>
<message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>设置脚本验证的程序 (%u 到 %d, 0 = 自动, &lt;0 = 保留自由的核心, 默认值: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>区块数据库包含未来的交易,这可能是由本机错误的日期时间引起。若确认本机日期时间正确,请重新建立区块数据库。</translation>
</message>
@@ -3101,11 +3205,15 @@
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <translation>如果对你的交易量来说,消耗的手续费微乎其微,那么这笔手续费你或许可以忽略它。</translation>
+ <translation>如果找零金额低于粉尘水平,你或许可以忽略这笔手续费。</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>使用UPnP暴露本机监听端口(默认:1 当正在监听且不使用代理)</translation>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>没办法重算区块。你需要先用-reindex-chainstate参数来重建数据库。</translation>
+ </message>
+ <message>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>没办法将数据库倒转回分叉前的状态。必须要重新下载区块链。</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -3116,10 +3224,6 @@
<translation>警告:我们的同行似乎不完全同意!您可能需要升级,或者其他节点可能需要升级。</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>是否在退出时保存内存池,并在启动时重新载入(默认值: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>最后100个区块中的%d个包含未知的版本号</translation>
</message>
@@ -3132,40 +3236,12 @@
<translation>-maxmempool 最小为%d MB</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; 可能是:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>接受来自外部的连接 (缺省: 如果不带 -proxy or -connect 参数设置为1)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>为用户代理字符串附加说明</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>启动时尝试从已损坏的钱包文件中恢复私钥</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>数据块创建选项:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>无法解析 - %s 地址: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>区块链选择选项:</translation>
- </message>
- <message>
<source>Change index out of range</source>
- <translation>修改索引超过范围</translation>
- </message>
- <message>
- <source>Connection options:</source>
- <translation>连接选项:</translation>
+ <translation>找零超过索引范围</translation>
</message>
<message>
<source>Copyright (C) %i-%i</source>
@@ -3173,43 +3249,19 @@
</message>
<message>
<source>Corrupted block database detected</source>
- <translation>检测发现数据块数据库损坏。请使用 -reindex参数重启客户端。</translation>
- </message>
- <message>
- <source>Debugging/Testing options:</source>
- <translation>调试/测试选项:</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>不要加载钱包和禁用钱包的 RPC 调用</translation>
+ <translation>检测到区块数据库损坏</translation>
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
- <translation>你想现在就重建块数据库吗?</translation>
- </message>
- <message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>允许在&lt;address&gt;广播哈希区块</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>允许在&lt;address&gt;广播哈希交易</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>允许在&lt;address&gt;广播原始区块</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>允许在&lt;address&gt;广播原始交易</translation>
+ <translation>你想现在就重建区块数据库吗?</translation>
</message>
<message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>保证内存池中的交易更换(默认:%u)</translation>
+ <source>Error creating %s: You can't create non-HD wallets with this version.</source>
+ <translation>生成%s发生错误:这个版本不能用来产生非HD钱包。</translation>
</message>
<message>
<source>Error initializing block database</source>
- <translation>初始化数据块数据库出错</translation>
+ <translation>初始化区块数据库出错</translation>
</message>
<message>
<source>Error initializing wallet database environment %s!</source>
@@ -3229,11 +3281,11 @@
</message>
<message>
<source>Error loading block database</source>
- <translation>导入数据块数据库出错</translation>
+ <translation>导入区块数据库出错</translation>
</message>
<message>
<source>Error opening block database</source>
- <translation>导入数据块数据库出错</translation>
+ <translation>导入区块数据库出错</translation>
</message>
<message>
<source>Error: Disk space is low!</source>
@@ -3244,6 +3296,10 @@
<translation>监听端口失败。请使用 -listen=0 参数。</translation>
</message>
<message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>初始化时重新扫描钱包失败了</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>导入中...</translation>
</message>
@@ -3264,8 +3320,12 @@
<translation>-fallbackfee 的无效数额=&lt;amount&gt;: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>保持交易内存池大小低于&lt;n&gt;MB(默认:%u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>指定的区块目录"%s"不存在。</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>正在升级交易索引数据库</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3276,26 +3336,10 @@
<translation>正在加载黑名单...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>认证Cookie的位置 (默认: data目录)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>没有足够的文件描述符可用。</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>只连接 &lt;net&gt;网络中的节点 (ipv4, ipv6 或 onion) </translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>打印出这段帮助信息并退出</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>打印版本信息并退出</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>修剪不能配置一个负数。</translation>
</message>
@@ -3304,30 +3348,30 @@
<translation>修剪模式与 -txindex 不兼容。</translation>
</message>
<message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>从当前索引的区块中重建链状态</translation>
+ <source>Replaying blocks...</source>
+ <translation>正在对区块进行重算…</translation>
</message>
<message>
<source>Rewinding blocks...</source>
- <translation>回退区块</translation>
- </message>
- <message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>设置以MB为单位的数据库缓存大小(%d 到 %d, 默认值: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>指定钱包文件(数据目录内)</translation>
+ <translation>回退区块...</translation>
</message>
<message>
<source>The source code is available from %s.</source>
<translation>源代码可以在 %s 获得。</translation>
</message>
<message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>计算交易手续费和找零失败</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
<translation>无法在本机绑定 %s 端口。%s 可能已经在运行。</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>无法生成密钥</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>忽略不支持的选项 -benchmark,使用 -debug=bench</translation>
</message>
@@ -3348,14 +3392,6 @@
<translation>升级UTXO数据库</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>使用UPnp映射监听端口 (默认: %u) </translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>使用测试链</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>用户代理评论(%s)包含不安全的字符。</translation>
</message>
@@ -3364,84 +3400,28 @@
<translation>正在验证区块...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>钱包调试/测试选项:</translation>
- </message>
- <message>
- <source>Wallet options:</source>
- <translation>钱包选项:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>允许来自指定地址的 JSON-RPC 连接。 &lt;ip&gt;为单一IP (如: 1.2.3.4), 网络/掩码 (如: 1.2.3.4/255.255.255.0), 网络/CIDR (如: 1.2.3.4/24)。该选项可多次指定。</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>绑定到指定地址和连接的白名单节点。 IPv6使用 [主机]:端口 格式 </translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>创建系统默认权限的文件,而不是 umask 077 (只在关闭钱包功能时有效) </translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>发现自己的 IP 地址(默认: 监听并且无 -externalip 或 -proxy 时为 1)</translation>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>钱包需要被重写:请重新启动%s来完成</translation>
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>错误:监听外部连接失败 (监听返回错误 %s) </translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>当收到相关提醒或者我们看到一个长分叉时执行命令(%s 将替换为消息)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>交易费(in %s/kB)比这更小的在关联、挖掘和生成交易时将被视为零费交易 (默认: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>如果未设置交易费用,自动添加足够的交易费以确保交易在平均n个数据块内被确认 (默认: %u) </translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>-maxtxfee=&lt;amount&gt;: '%s' 的金额无效(交易费至少为 %s,以免交易滞留过久)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>Maximum size of data in data carrier transactions we relay and mine (default: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>为每个代理连接随机化凭据。这将启用 Tor 流隔离 (默认: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>在交易费被扣除后发送的交易金额太小</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>白名单节点不能被DoS banned ,且转发所有来自他们的交易(即便这些交易已经存在于mempool中),常用于网关 </translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>您需要使用 -reindex 重新构建数据库以返回未修剪的模式。这将重新下载整个区块链</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(默认: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>接受公共 REST 请求 (默认: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>自动建立Tor隐藏服务 (默认:%d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>通过 SOCKS5 代理连接</translation>
+ <source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
+ <translation>加载%s发生错误:不能对已存在的HD钱包停用HD功能。</translation>
</message>
<message>
<source>Error reading from database, shutting down.</source>
@@ -3452,10 +3432,6 @@
<translation>升级链状态数据库出错</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>启动时从其他来源的 blk000??.dat 文件导入区块</translation>
- </message>
- <message>
<source>Information</source>
<translation>信息</translation>
</message>
@@ -3476,44 +3452,28 @@
<translation>-whitelist: '%s' 指定的网络掩码无效</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>内存中最多保留 &lt;n&gt; 笔孤立的交易 (默认: %u) </translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>-whitebind: '%s' 需要指定一个端口</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>节点中继选项:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC 服务器选项:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>因为系统的限制,将 -maxconnections 参数从 %d 降到了 %d</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>重新扫描区块链以查找遗漏的钱包交易</translation>
+ <source>Signing transaction failed</source>
+ <translation>签署交易失败</translation>
</message>
<message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>跟踪/调试信息输出到控制台,不输出到 debug.log 文件</translation>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>以-walletdir指定的路径“%s”不存在</translation>
</message>
<message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>显示所有调试选项 (用法: --帮助 -帮助调试)</translation>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>以-walletdir指定的路径“%s”是相对路径</translation>
</message>
<message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>客户端启动时压缩debug.log文件(缺省:no-debug模式时为1)</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation>签署交易失败</translation>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>以-walletdir指定的路径“%s”不是个目录</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -3524,14 +3484,6 @@
<translation>这是实验性的软件。</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor 控制端口密码 (默认值: 空白)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>开启监听 onion 连接时的 Tor 控制端口号 (默认值: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>交易量太小</translation>
</message>
@@ -3548,18 +3500,18 @@
<translation>无法在此计算机上绑定 %s (绑定返回错误 %s)</translation>
</message>
<message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>程序启动时升级钱包到最新格式</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC 连接用户名</translation>
+ <source>Unable to generate initial keys</source>
+ <translation>无法产生初始的密钥</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
<translation>正在检测钱包的完整性...</translation>
</message>
<message>
+ <source>Wallet %s resides outside wallet directory %s</source>
+ <translation>钱包文件%s没有在钱包目录%s里面</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation>警告</translation>
</message>
@@ -3568,85 +3520,28 @@
<translation>警告: 不明的交易规则被启用了(versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>是否用块方进行 (%u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>您需要用 -reindex 重建数据库,从而令 -txindex 的变动生效</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>正在消除錢包中的所有交易...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ 通知选项:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC 连接密码
-</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>当最佳数据块变化时执行命令 (命令行中的 %s 会被替换成数据块哈希值)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>使用 -addnode, -seednode 和 -connect 选项时允许查询DNS</translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 = 保留 tx meta data , 如 account owner 和 payment request information, 2 = 不保留 tx meta data) </translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>参数 -maxtxfee 设定了很高的金额!这是你一次交易就有可能付出的最高手续费。</translation>
</message>
<message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>不要让交易留在内存池中超过 &lt;n&gt; 个小时 (默认值: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>加载钱包出错 %s. -wallet参数必需指定为文件名(而不是目录路径)。</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>当产生交易时,如果每千字节 (kB) 的手续费比这个值 (单位是 %s) 低,就视为没支付手续费 (默认值: %s)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>数据块验证 严密级别 -checkblocks (0-4, 默认: %u) </translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>维护一份完整的交易索引, 用于 getrawtransaction RPC调用 (默认: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>限制 非礼节点 若干秒内不能连接 (默认: %u) </translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>输出调试信息 (默认: %u, 提供 &lt;category&gt; 是可选项)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>支持用 Bloom 过滤器来过滤区块和交易(默认值: %u)</translation>
+ <source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
+ <translation>加载%s发生错误:不能对已存在的非HD钱包启用HD功能</translation>
</message>
<message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>这是在费用估计不可用时你可能会支付的交易费。</translation>
</message>
<message>
- <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <translation>网络版本字符串的总长度 (%i) 超过最大长度 (%i) 了。请减少 uacomment 参数的数目或长度。</translation>
+ <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
+ <translation>此产品包含了由OpenSSL Project所开发的OpenSSL Toolkit软件%s,由Eric Young撰写的加解密软件,以及由Thomas Bernard所撰写的UPnP软件。</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>尝试保持上传带宽低于(MiB/24h),0=无限制(默认:%d)</translation>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation>网络版本字符串的总长度 (%i) 超过最大长度 (%i) 了。请减少 uacomment 参数的数目或长度。</translation>
</message>
<message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
@@ -3657,108 +3552,24 @@
<translation>一个不被支持的参数 -whitelistalwaysrelay 被忽略了。请使用 -whitelistrelay 或者 -whitelistforcerelay.</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>通过 Tor 隐藏服务连接节点时使用不同的 SOCKS5 代理 (默认: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>警告: 未知的区块版本被挖掘!未知规则可能已生效</translation>
</message>
<message>
- <source>%s is set very high!</source>
- <translation>%s非常高!</translation>
+ <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
+ <translation>警告:钱包文件损坏,但数据被救回!原始的钱包文件%s已经重命名为%s并存储到%s目录下 。如果您的账户余额或者交易记录不正确,请使用您的钱包备份文件恢复。</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(默认: %s) </translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>始终通过 DNS 查询节点地址 (默认: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>加载钱包 %s 出错。 -wallet 必须是正规文件名。</translation>
+ <source>%s is set very high!</source>
+ <translation>%s非常高!</translation>
</message>
<message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>加载钱包 %s 出错。 重复的 -wallet 文件名。</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>加载钱包 %s 出错。 -wallet 文件名中包含无效字符。</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>启动时检测多少个数据块(默认: %u, 0=所有)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>在调试输出中包含IP地址 (默认: %u)</translation>
- </message>
- <message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>使用 &lt;port&gt;端口监听 JSON-RPC 连接 (默认: %u ; testnet: %u) </translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>使用端口 &lt;port&gt; 监听连接 (默认: %u ; testnet: %u) </translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>保留最多 &lt;n&gt; 条节点连接 (默认: %u) </translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>钱包广播事务处理</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>每个连接的最大接收缓存,&lt;n&gt;*1000 字节 (默认: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>每个连接的最大发送缓存,&lt;n&gt;*1000 字节 (默认: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>输出调试信息时,前面加上时间戳 (默认: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>Relay and mine data carrier transactions (default: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>是否转发 非P2SH格式的多签名交易 (默认: %u) </translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>设置私钥池大小为 &lt;n&gt; (默认:%u) </translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>设置BIP141最大区块权重 (默认: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>设置RPC服务线程数 (默认: %d) </translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>指定配置文件 (默认: %s) </translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>指定连接超时毫秒数 (最小: 1, 默认: %d) </translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>指定 pid 文件 (默认: %s) </translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>付款时允许使用未确认的零钱 (默认: %u) </translation>
+ <source>Keypool ran out, please call keypoolrefill first</source>
+ <translation>密钥池已经耗尽,请先执行keypoolrefill</translation>
</message>
<message>
<source>Starting network threads...</source>
@@ -3769,18 +3580,22 @@
<translation>钱包避免低于最小交易费的支付</translation>
</message>
<message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation>如果发送交易,这将是你要支付的交易费。</translation>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>这是你每次交易付款时最少要付的手续费。</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>断开 非礼节点的阀值 (默认: %u) </translation>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>如果发送交易,这将是你要支付的交易费。</translation>
</message>
<message>
<source>Transaction amounts must not be negative</source>
<translation>交易金额不不可为负数</translation>
</message>
<message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>此交易在内存池中的交易链太长</translation>
+ </message>
+ <message>
<source>Transaction must have at least one recipient</source>
<translation>交易必须包含至少一个接收人</translation>
</message>
@@ -3793,6 +3608,14 @@
<translation>金额不足</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>无法生成一个找零地址密钥。对于此钱包,私钥已被禁用。</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>不能写入到数据目录'%s';请检查文件权限。</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>正在加载区块索引...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts
index 7d2cc69360..df77762c6c 100644
--- a/src/qt/locale/bitcoin_zh_HK.ts
+++ b/src/qt/locale/bitcoin_zh_HK.ts
@@ -586,6 +586,10 @@
<source>Label</source>
<translation>標記</translation>
</message>
+ <message>
+ <source>Wallet</source>
+ <translation>錢包</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts
index 63658b7d84..635151bcc9 100644
--- a/src/qt/locale/bitcoin_zh_TW.ts
+++ b/src/qt/locale/bitcoin_zh_TW.ts
@@ -11,7 +11,7 @@
</message>
<message>
<source>&amp;New</source>
- <translation>新增</translation>
+ <translation>新增(&amp;N)</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
@@ -19,27 +19,31 @@
</message>
<message>
<source>&amp;Copy</source>
- <translation>複製</translation>
+ <translation>複製(&amp;C)</translation>
</message>
<message>
<source>C&amp;lose</source>
- <translation>關閉</translation>
+ <translation>關閉(&amp;L)</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
<translation>把目前選擇的位址從列表中刪掉</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>請輸入要搜尋的位址或標記</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>把目前分頁的資料匯出存成檔案</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation>匯出</translation>
+ <translation>匯出(&amp;E)</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation>刪掉</translation>
+ <translation>刪掉(&amp;D)</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
@@ -51,7 +55,7 @@
</message>
<message>
<source>C&amp;hoose</source>
- <translation>選取</translation>
+ <translation>選取(&amp;H)</translation>
</message>
<message>
<source>Sending addresses</source>
@@ -71,15 +75,15 @@
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>複製位址</translation>
+ <translation>複製位址(&amp;C)</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>複製標記</translation>
+ <translation>複製標記(&amp;L)</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation>編輯</translation>
+ <translation>編輯(&amp;E)</translation>
</message>
<message>
<source>Export Address List</source>
@@ -189,7 +193,7 @@
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation>重要: 請改用新產生有加密的錢包檔,來取代舊錢包檔的備份。為了安全性的理由,當你開始使用新的有加密的錢包後,舊錢包檔的備份就不能再使用了。</translation>
+ <translation>重要須知: 請改用新造出來、有加密的錢包檔,來取代舊錢包檔的備份。為了安全起見,當你開始使用新的有加密的錢包後,舊錢包檔的備份就沒有用了。</translation>
</message>
<message>
<source>Wallet encryption failed</source>
@@ -239,7 +243,7 @@
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>簽署訊息...</translation>
+ <translation>簽署訊息(&amp;M)...</translation>
</message>
<message>
<source>Synchronizing with network...</source>
@@ -247,7 +251,7 @@
</message>
<message>
<source>&amp;Overview</source>
- <translation>總覽</translation>
+ <translation>總覽(&amp;O)</translation>
</message>
<message>
<source>Node</source>
@@ -259,7 +263,7 @@
</message>
<message>
<source>&amp;Transactions</source>
- <translation>交易</translation>
+ <translation>交易(&amp;T)</translation>
</message>
<message>
<source>Browse transaction history</source>
@@ -267,7 +271,7 @@
</message>
<message>
<source>E&amp;xit</source>
- <translation>結束</translation>
+ <translation>結束(&amp;X)</translation>
</message>
<message>
<source>Quit application</source>
@@ -275,7 +279,7 @@
</message>
<message>
<source>&amp;About %1</source>
- <translation>關於%1</translation>
+ <translation>關於%1(&amp;A)</translation>
</message>
<message>
<source>Show information about %1</source>
@@ -291,7 +295,7 @@
</message>
<message>
<source>&amp;Options...</source>
- <translation>選項...</translation>
+ <translation>選項(&amp;O)...</translation>
</message>
<message>
<source>Modify configuration options for %1</source>
@@ -299,27 +303,35 @@
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>加密錢包...</translation>
+ <translation>加密錢包(&amp;E)...</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>備份錢包...</translation>
+ <translation>備份錢包(&amp;B)...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
- <translation>改變密碼...</translation>
+ <translation>改變密碼(&amp;C)...</translation>
</message>
<message>
<source>&amp;Sending addresses...</source>
- <translation>付款位址...</translation>
+ <translation>付款位址(&amp;S)...</translation>
</message>
<message>
<source>&amp;Receiving addresses...</source>
- <translation>收款位址...</translation>
+ <translation>收款位址(&amp;R)...</translation>
</message>
<message>
<source>Open &amp;URI...</source>
- <translation>開啓 URI...</translation>
+ <translation>開啓 &amp;URI...</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>錢包:</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>預設錢包</translation>
</message>
<message>
<source>Click to disable network activity.</source>
@@ -342,6 +354,10 @@
<translation>正在為磁碟裡的區塊重建索引...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>代理伺服器&lt;b&gt;已經啟用&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>付錢給一個 Bitcoin 位址</translation>
</message>
@@ -355,7 +371,7 @@
</message>
<message>
<source>&amp;Debug window</source>
- <translation>除錯視窗</translation>
+ <translation>除錯視窗(&amp;D)</translation>
</message>
<message>
<source>Open debugging and diagnostic console</source>
@@ -363,7 +379,7 @@
</message>
<message>
<source>&amp;Verify message...</source>
- <translation>驗證訊息...</translation>
+ <translation>驗證訊息(&amp;V)...</translation>
</message>
<message>
<source>Bitcoin</source>
@@ -375,15 +391,15 @@
</message>
<message>
<source>&amp;Send</source>
- <translation>付款</translation>
+ <translation>付款(&amp;S)</translation>
</message>
<message>
<source>&amp;Receive</source>
- <translation>收款</translation>
+ <translation>收款(&amp;R)</translation>
</message>
<message>
<source>&amp;Show / Hide</source>
- <translation>顯示或隱藏</translation>
+ <translation>顯示或隱藏(&amp;S)</translation>
</message>
<message>
<source>Show or hide the main Window</source>
@@ -403,15 +419,15 @@
</message>
<message>
<source>&amp;File</source>
- <translation>檔案</translation>
+ <translation>檔案(&amp;F)</translation>
</message>
<message>
<source>&amp;Settings</source>
- <translation>設定</translation>
+ <translation>設定(&amp;S)</translation>
</message>
<message>
<source>&amp;Help</source>
- <translation>說明</translation>
+ <translation>說明(&amp;H)</translation>
</message>
<message>
<source>Tabs toolbar</source>
@@ -435,7 +451,7 @@
</message>
<message>
<source>&amp;Command-line options</source>
- <translation>命令列選項</translation>
+ <translation>命令列選項(&amp;C)</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
@@ -510,6 +526,12 @@
</translation>
</message>
<message>
+ <source>Wallet: %1
+</source>
+ <translation>錢包: %1
+</translation>
+ </message>
+ <message>
<source>Type: %1
</source>
<translation>種類: %1
@@ -715,7 +737,7 @@
</message>
<message>
<source>&amp;Label</source>
- <translation>標記</translation>
+ <translation>標記(&amp;L)</translation>
</message>
<message>
<source>The label associated with this address list entry</source>
@@ -727,11 +749,7 @@
</message>
<message>
<source>&amp;Address</source>
- <translation>位址</translation>
- </message>
- <message>
- <source>New receiving address</source>
- <translation>造新的收款位址</translation>
+ <translation>位址(&amp;A)</translation>
</message>
<message>
<source>New sending address</source>
@@ -750,8 +768,12 @@
<translation>輸入的位址 %1 並不是有效的 Bitcoin 位址。</translation>
</message>
<message>
- <source>The entered address "%1" is already in the address book.</source>
- <translation>輸入的位址 %1 在位址簿中已經有了。</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation>%1 已經是標記為 %2 的收款位址了,不可以又是付款位址。</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>輸入的位址 %1 本來就在位址簿中了,標記為 %2。</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -803,42 +825,6 @@
<source>Command-line options</source>
<translation>命令列選項</translation>
</message>
- <message>
- <source>Usage:</source>
- <translation>用法:</translation>
- </message>
- <message>
- <source>command-line options</source>
- <translation>命令列選項</translation>
- </message>
- <message>
- <source>UI Options:</source>
- <translation>使用介面選項:</translation>
- </message>
- <message>
- <source>Choose data directory on startup (default: %u)</source>
- <translation>啓動時選擇資料目錄(預設值: %u)</translation>
- </message>
- <message>
- <source>Set language, for example "de_DE" (default: system locale)</source>
- <translation>設定語言,比如說 de_DE (預設值: 系統語系)</translation>
- </message>
- <message>
- <source>Start minimized</source>
- <translation>啓動時縮到最小</translation>
- </message>
- <message>
- <source>Set SSL root certificates for payment request (default: -system-)</source>
- <translation>設定付款請求時所使用的 SSL 根憑證(預設值: 系統憑證庫)</translation>
- </message>
- <message>
- <source>Show splash screen on startup (default: %u)</source>
- <translation>顯示啓動畫面(預設值: %u)</translation>
- </message>
- <message>
- <source>Reset all settings changed in the GUI</source>
- <translation>重置所有在使用界面更改的設定</translation>
- </message>
</context>
<context>
<name>Intro</name>
@@ -993,7 +979,7 @@
</message>
<message>
<source>&amp;Main</source>
- <translation>主要</translation>
+ <translation>主要(&amp;M)</translation>
</message>
<message>
<source>Automatically start %1 after logging in to the system.</source>
@@ -1001,11 +987,11 @@
</message>
<message>
<source>&amp;Start %1 on system login</source>
- <translation>系統登入時啟動 %1</translation>
+ <translation>系統登入時啟動 %1 (&amp;S)</translation>
</message>
<message>
<source>Size of &amp;database cache</source>
- <translation>資料庫快取大小</translation>
+ <translation>資料庫快取大小(&amp;D)</translation>
</message>
<message>
<source>MB</source>
@@ -1013,7 +999,7 @@
</message>
<message>
<source>Number of script &amp;verification threads</source>
- <translation>指令碼驗證執行緒數目</translation>
+ <translation>指令碼驗證執行緒數目(&amp;V)</translation>
</message>
<message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
@@ -1025,7 +1011,7 @@
</message>
<message>
<source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>透過另外的 SOCKS5 代理伺服器來連線到 Bitcoin 網路中的 Tor 隱藏服務。</translation>
+ <translation>透過另外的 SOCKS&amp;5 代理伺服器來連線到 Bitcoin 網路中的 Tor 隱藏服務:</translation>
</message>
<message>
<source>Hide the icon from the system tray.</source>
@@ -1033,7 +1019,7 @@
</message>
<message>
<source>&amp;Hide tray icon</source>
- <translation>隱藏通知區圖示</translation>
+ <translation>隱藏通知區圖示(&amp;H)</translation>
</message>
<message>
<source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
@@ -1061,11 +1047,27 @@
</message>
<message>
<source>&amp;Reset Options</source>
- <translation>重設選項</translation>
+ <translation>重設選項(&amp;R)</translation>
</message>
<message>
<source>&amp;Network</source>
- <translation>網路</translation>
+ <translation>網路(&amp;N)</translation>
+ </message>
+ <message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>啟用時有些進階功能會不能使用,不過區塊資料還是會被完全驗證。如果把這個設定改回來,會需要重新下載整個區塊鏈。區塊資料實際使用的磁碟空間會比設定值稍微大一點。</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>修剪區塊資料大小到</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB (十億位元組)</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>把這個設定改回來會需要重新下載整個區塊鏈。</translation>
</message>
<message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
@@ -1073,7 +1075,7 @@
</message>
<message>
<source>W&amp;allet</source>
- <translation>錢包</translation>
+ <translation>錢包(&amp;A)</translation>
</message>
<message>
<source>Expert</source>
@@ -1081,7 +1083,7 @@
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation>開啟錢幣控制功能</translation>
+ <translation>開啟錢幣控制功能(&amp;C)</translation>
</message>
<message>
<source>If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
@@ -1089,7 +1091,7 @@
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
- <translation>可以花還沒確認的零錢</translation>
+ <translation>可以花還沒確認的零錢(&amp;S)</translation>
</message>
<message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
@@ -1105,7 +1107,7 @@
</message>
<message>
<source>Allow incomin&amp;g connections</source>
- <translation>接受外來連線</translation>
+ <translation>接受外來連線(&amp;G)</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
@@ -1113,15 +1115,15 @@
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation>透過 SOCKS5 代理伺服器連線(預設代理伺服器):</translation>
+ <translation>透過 SOCKS5 代理伺服器連線(預設代理伺服器 &amp;C):</translation>
</message>
<message>
<source>Proxy &amp;IP:</source>
- <translation>代理位址:</translation>
+ <translation>代理位址(&amp;I):</translation>
</message>
<message>
<source>&amp;Port:</source>
- <translation>埠號:</translation>
+ <translation>埠號(&amp;P):</translation>
</message>
<message>
<source>Port of the proxy (e.g. 9050)</source>
@@ -1149,7 +1151,7 @@
</message>
<message>
<source>&amp;Window</source>
- <translation>視窗</translation>
+ <translation>視窗(&amp;W)</translation>
</message>
<message>
<source>Show only a tray icon after minimizing the window.</source>
@@ -1157,19 +1159,19 @@
</message>
<message>
<source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation>縮到最小到通知區而不是工作列</translation>
+ <translation>縮到最小到通知區而不是工作列(&amp;M)</translation>
</message>
<message>
<source>M&amp;inimize on close</source>
- <translation>關閉時縮到最小</translation>
+ <translation>關閉時縮到最小(&amp;I)</translation>
</message>
<message>
<source>&amp;Display</source>
- <translation>顯示</translation>
+ <translation>顯示(&amp;D)</translation>
</message>
<message>
<source>User Interface &amp;language:</source>
- <translation>使用界面語言:</translation>
+ <translation>使用界面語言(&amp;L):</translation>
</message>
<message>
<source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
@@ -1177,7 +1179,7 @@
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
- <translation>金額顯示單位:</translation>
+ <translation>金額顯示單位(&amp;U):</translation>
</message>
<message>
<source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
@@ -1189,15 +1191,15 @@
</message>
<message>
<source>&amp;Third party transaction URLs</source>
- <translation>第三方交易網址連結</translation>
+ <translation>第三方交易網址連結(&amp;T)</translation>
</message>
<message>
<source>&amp;OK</source>
- <translation>好</translation>
+ <translation>好(&amp;O)</translation>
</message>
<message>
<source>&amp;Cancel</source>
- <translation>取消</translation>
+ <translation>取消(&amp;C)</translation>
</message>
<message>
<source>default</source>
@@ -1334,6 +1336,10 @@
<translation>URI 處理</translation>
</message>
<message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>字首為 bitcoin:// 不是有效的 URI,請改用 bitcoin: 開頭。</translation>
+ </message>
+ <message>
<source>Payment request fetch URL is invalid: %1</source>
<translation>取得付款要求的 URL 無效: %1</translation>
</message>
@@ -1531,12 +1537,16 @@
<context>
<name>QObject::QObject</name>
<message>
+ <source>Error parsing command line arguments: %1.</source>
+ <translation>解析命令列參數 %1 時發生錯誤。</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation>錯誤: 不存在指定的資料目錄 "%1" 。</translation>
</message>
<message>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
- <translation>錯誤: 沒辦法解析設定檔: %1。只能用「名稱=設定值」這種語法。</translation>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>錯誤: 沒辦法解析設定檔: %1。</translation>
</message>
<message>
<source>Error: %1</source>
@@ -1547,11 +1557,11 @@
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image...</source>
- <translation>儲存圖片...</translation>
+ <translation>儲存圖片(&amp;S)...</translation>
</message>
<message>
<source>&amp;Copy Image</source>
- <translation>複製圖片</translation>
+ <translation>複製圖片(&amp;C)</translation>
</message>
<message>
<source>Save QR Code</source>
@@ -1574,7 +1584,7 @@
</message>
<message>
<source>&amp;Information</source>
- <translation>資訊</translation>
+ <translation>資訊(&amp;I)</translation>
</message>
<message>
<source>Debug window</source>
@@ -1629,8 +1639,16 @@
<translation>記憶體使用量</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>錢包:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(無)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
- <translation>重置</translation>
+ <translation>重置(&amp;R)</translation>
</message>
<message>
<source>Received</source>
@@ -1642,7 +1660,7 @@
</message>
<message>
<source>&amp;Peers</source>
- <translation>節點</translation>
+ <translation>節點(&amp;P)</translation>
</message>
<message>
<source>Banned peers</source>
@@ -1738,15 +1756,15 @@
</message>
<message>
<source>&amp;Open</source>
- <translation>開啓</translation>
+ <translation>開啓(&amp;O)</translation>
</message>
<message>
<source>&amp;Console</source>
- <translation>主控台</translation>
+ <translation>主控台(&amp;C)</translation>
</message>
<message>
<source>&amp;Network Traffic</source>
- <translation>網路流量</translation>
+ <translation>網路流量(&amp;N)</translation>
</message>
<message>
<source>Totals</source>
@@ -1770,23 +1788,23 @@
</message>
<message>
<source>1 &amp;hour</source>
- <translation>1 小時</translation>
+ <translation>1 小時(&amp;H)</translation>
</message>
<message>
<source>1 &amp;day</source>
- <translation>1 天</translation>
+ <translation>1 天(&amp;D)</translation>
</message>
<message>
<source>1 &amp;week</source>
- <translation>1 星期</translation>
+ <translation>1 星期(&amp;W)</translation>
</message>
<message>
<source>1 &amp;year</source>
- <translation>1 年</translation>
+ <translation>1 年(&amp;Y)</translation>
</message>
<message>
<source>&amp;Disconnect</source>
- <translation>斷線</translation>
+ <translation>斷線(&amp;D)</translation>
</message>
<message>
<source>Ban for</source>
@@ -1794,7 +1812,11 @@
</message>
<message>
<source>&amp;Unban</source>
- <translation>連線解禁</translation>
+ <translation>連線解禁(&amp;U)</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>預設錢包</translation>
</message>
<message>
<source>Welcome to the %1 RPC console.</source>
@@ -1821,6 +1843,14 @@
<translation>網路活動已關閉</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>不使用任何錢包來執行指令</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>使用 %1 錢包來執行指令</translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(節點識別碼: %1)</translation>
</message>
@@ -1857,15 +1887,15 @@
<name>ReceiveCoinsDialog</name>
<message>
<source>&amp;Amount:</source>
- <translation>金額:</translation>
+ <translation>金額(&amp;A):</translation>
</message>
<message>
<source>&amp;Label:</source>
- <translation>標記:</translation>
+ <translation>標記(&amp;L):</translation>
</message>
<message>
<source>&amp;Message:</source>
- <translation>訊息:</translation>
+ <translation>訊息(&amp;M):</translation>
</message>
<message>
<source>An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
@@ -1892,20 +1922,20 @@
<translation>清空</translation>
</message>
<message>
- <source>Requested payments history</source>
- <translation>先前要求付款的記錄</translation>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>使用 segwit 原生位址(也叫做 Bech32 或 BIP-173)可以減少日後的交易手續費,也比較不容易打錯字,不過會跟舊版的錢包軟體不相容。如果沒有勾選的話,會改產生與舊版錢包軟體相容的位址。</translation>
</message>
<message>
- <source>&amp;Request payment</source>
- <translation>要求付款</translation>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>產生 segwit 原生位址(Bech32)</translation>
</message>
<message>
- <source>Bech32 addresses (BIP-173) are cheaper to spend from and offer better protection against typos. When unchecked a P2SH wrapped SegWit address will be created, compatible with older wallets.</source>
- <translation>Bech32 位址(BIP-173)是一種花費成本較小,且較不容易打錯的位址類型。如果沒有勾選的話,會使用以 P2SH 包裝的 SegWit 位址,這種位址類型跟舊版錢包相容。</translation>
+ <source>Requested payments history</source>
+ <translation>先前要求付款的記錄</translation>
</message>
<message>
- <source>Generate Bech32 address</source>
- <translation>產生 Bech32 位址</translation>
+ <source>&amp;Request payment</source>
+ <translation>要求付款(&amp;R)</translation>
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
@@ -1948,15 +1978,15 @@
</message>
<message>
<source>Copy &amp;URI</source>
- <translation>複製 URI</translation>
+ <translation>複製 &amp;URI</translation>
</message>
<message>
<source>Copy &amp;Address</source>
- <translation>複製位址</translation>
+ <translation>複製位址(&amp;A)</translation>
</message>
<message>
<source>&amp;Save Image...</source>
- <translation>儲存圖片...</translation>
+ <translation>儲存圖片(&amp;S)...</translation>
</message>
<message>
<source>Request payment to %1</source>
@@ -1987,6 +2017,10 @@
<translation>訊息</translation>
</message>
<message>
+ <source>Wallet</source>
+ <translation>錢包</translation>
+ </message>
+ <message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
<translation>產生的 URI 過長,請試著縮短標記或訊息的文字內容。</translation>
</message>
@@ -2074,7 +2108,7 @@
</message>
<message>
<source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
- <translation>如果這項有打開,但是找零位址是空的或無效,那麼找零的錢會送到一個新產生的位址去。</translation>
+ <translation>如果這項有打開,但是找零位址是空的或無效,那麼找零的錢會送到一個新造出來的位址去。</translation>
</message>
<message>
<source>Custom change address</source>
@@ -2101,12 +2135,16 @@
<translation>展開手續費設定</translation>
</message>
<message>
- <source>per kilobyte</source>
- <translation>每千位元組</translation>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>指定每一千位元祖(kB)擬真大小的交易所要付出的手續費。
+
+注意: 交易手續費是以位元組為單位來計算。因此當指定手續費為每千位元組 100 個 satoshi 時,對於一筆大小為 500 位元組(一千位元組的一半)的交易,其手續費會只有 50 個 satoshi。</translation>
</message>
<message>
- <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source>
- <translation>如果自訂手續費設定為 1000 satoshi, 而交易資料大小只有 250 個位元組的話,那麽選擇「每千位元組」就只會付 250 satoshi 的手續費,換做選「總共至少」就會付 1000 satoshi. 但是如果交易資料大小超過一千個位元組,那麽兩者都是每千位元組的費用。</translation>
+ <source>per kilobyte</source>
+ <translation>每千位元組</translation>
</message>
<message>
<source>Hide</source>
@@ -2138,7 +2176,7 @@
</message>
<message>
<source>Add &amp;Recipient</source>
- <translation>增加收款人</translation>
+ <translation>增加收款人(&amp;R)</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -2162,7 +2200,7 @@
</message>
<message>
<source>Clear &amp;All</source>
- <translation>全部清掉</translation>
+ <translation>全部清掉(&amp;A)</translation>
</message>
<message>
<source>Balance:</source>
@@ -2174,7 +2212,7 @@
</message>
<message>
<source>S&amp;end</source>
- <translation>付款</translation>
+ <translation>付款(&amp;E)</translation>
</message>
<message>
<source>Copy quantity</source>
@@ -2217,14 +2255,6 @@
<translation>你確定要付錢出去嗎?</translation>
</message>
<message>
- <source>added as transaction fee</source>
- <translation>加做交易手續費</translation>
- </message>
- <message>
- <source>Total Amount %1</source>
- <translation>總金額 %1</translation>
- </message>
- <message>
<source>or</source>
<translation>或</translation>
</message>
@@ -2233,10 +2263,26 @@
<translation>你可以之後再提高手續費(有 BIP-125 手續費追加的標記)</translation>
</message>
<message>
+ <source>from wallet %1</source>
+ <translation>從錢包 %1</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>請再次確認交易內容。</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>交易手續費</translation>
+ </message>
+ <message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation>沒有 BIP-125 手續費追加的標記。</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>總金額</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>確認付款金額</translation>
</message>
@@ -2305,15 +2351,15 @@
<name>SendCoinsEntry</name>
<message>
<source>A&amp;mount:</source>
- <translation>金額:</translation>
+ <translation>金額(&amp;M):</translation>
</message>
<message>
<source>Pay &amp;To:</source>
- <translation>付給:</translation>
+ <translation>付給(&amp;T):</translation>
</message>
<message>
<source>&amp;Label:</source>
- <translation>標記:</translation>
+ <translation>標記(&amp;L):</translation>
</message>
<message>
<source>Choose previously used address</source>
@@ -2349,7 +2395,7 @@
</message>
<message>
<source>S&amp;ubtract fee from amount</source>
- <translation>從付款金額減去手續費</translation>
+ <translation>從付款金額減去手續費(&amp;U)</translation>
</message>
<message>
<source>Use available balance</source>
@@ -2414,7 +2460,7 @@
</message>
<message>
<source>&amp;Sign Message</source>
- <translation>簽署訊息</translation>
+ <translation>簽署訊息(&amp;S)</translation>
</message>
<message>
<source>You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
@@ -2458,7 +2504,7 @@
</message>
<message>
<source>Sign &amp;Message</source>
- <translation>簽署訊息</translation>
+ <translation>簽署訊息(&amp;M)</translation>
</message>
<message>
<source>Reset all sign message fields</source>
@@ -2466,11 +2512,11 @@
</message>
<message>
<source>Clear &amp;All</source>
- <translation>全部清掉</translation>
+ <translation>全部清掉(&amp;A)</translation>
</message>
<message>
<source>&amp;Verify Message</source>
- <translation>驗證訊息</translation>
+ <translation>驗證訊息(&amp;V)</translation>
</message>
<message>
<source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
@@ -2486,7 +2532,7 @@
</message>
<message>
<source>Verify &amp;Message</source>
- <translation>驗證訊息</translation>
+ <translation>驗證訊息(&amp;M)</translation>
</message>
<message>
<source>Reset all verify message fields</source>
@@ -2574,10 +2620,6 @@
<translation>跟一個目前確認 %1 次的交易互相衝突</translation>
</message>
<message>
- <source>%1/offline</source>
- <translation>%1 次/離線中</translation>
- </message>
- <message>
<source>0/unconfirmed, %1</source>
<translation>0 次/未確認,%1</translation>
</message>
@@ -2606,14 +2648,6 @@
<translation>狀態</translation>
</message>
<message>
- <source>, has not been successfully broadcast yet</source>
- <translation>,還沒成功公告出去</translation>
- </message>
- <message numerus="yes">
- <source>, broadcast through %n node(s)</source>
- <translation><numerusform>,已公告給 %n 個節點</numerusform></translation>
- </message>
- <message>
<source>Date</source>
<translation>日期</translation>
</message>
@@ -2698,6 +2732,10 @@
<translation>交易總大小</translation>
</message>
<message>
+ <source>Transaction virtual size</source>
+ <translation>交易擬真大小</translation>
+ </message>
+ <message>
<source>Output index</source>
<translation>輸出索引</translation>
</message>
@@ -2768,10 +2806,6 @@
<translation>到 %1 前可修改</translation>
</message>
<message>
- <source>Offline</source>
- <translation>離線中</translation>
- </message>
- <message>
<source>Unconfirmed</source>
<translation>未確認</translation>
</message>
@@ -2796,10 +2830,6 @@
<translation>未成熟(確認 %1 次,會在 %2 次後可用)</translation>
</message>
<message>
- <source>This block was not received by any other nodes and will probably not be accepted!</source>
- <translation>沒有其他節點收到這個區塊,也許它不會被接受!</translation>
- </message>
- <message>
<source>Generated but not accepted</source>
<translation>生產出來但是不被接受</translation>
</message>
@@ -3080,7 +3110,7 @@
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation>匯出</translation>
+ <translation>匯出(&amp;E)</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
@@ -3110,39 +3140,18 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>錢包的資料已經成功儲存到 %1 了。</translation>
</message>
+ <message>
+ <source>Cancel</source>
+ <translation>取消</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <source>Options:</source>
- <translation>選項:</translation>
- </message>
- <message>
- <source>Specify data directory</source>
- <translation>指定資料目錄</translation>
- </message>
- <message>
- <source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation>連線到某個節點來取得其它節點的位址,然後斷線</translation>
- </message>
- <message>
- <source>Specify your own public address</source>
- <translation>指定自己的公開位址</translation>
- </message>
- <message>
- <source>Accept command line and JSON-RPC commands</source>
- <translation>接受指令列和 JSON-RPC 指令
-</translation>
- </message>
- <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation>依據 MIT 軟體授權條款散布,詳情請見附帶的 %s 檔案或是 %s</translation>
</message>
<message>
- <source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
- <translation>如果沒有提供 &lt;category&gt; 或是值為 1 就會輸出所有的除錯資訊。</translation>
- </message>
- <message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation>設定的修剪值小於最小需求的 %d 百萬位元組(MiB)。請指定大一點的數字。</translation>
</message>
@@ -3159,18 +3168,10 @@
<translation>錯誤: 發生了致命的內部錯誤,詳情請看 debug.log</translation>
</message>
<message>
- <source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
- <translation>交易付款時每千位元組(kB)的交易手續費(單位是 %s,預設值: %s)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>正在修剪區塊資料庫中...</translation>
</message>
<message>
- <source>Run in the background as a daemon and accept commands</source>
- <translation>用護靈模式在背景執行並接受指令</translation>
- </message>
- <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation>無法啟動 HTTP 伺服器。詳情請看除錯紀錄。</translation>
</message>
@@ -3183,22 +3184,6 @@
<translation>%s 開發人員</translation>
</message>
<message>
- <source>A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)</source>
- <translation>當沒有足夠的資料計算預估手續費時,所使用的手續費費率(單位是 %s/kB, 預設值: %s)</translation>
- </message>
- <message>
- <source>Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)</source>
- <translation>接受從白名點節點收到的轉發交易,即使沒有(符合準則)轉發出去(預設值: %d)</translation>
- </message>
- <message>
- <source>Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)</source>
- <translation>增加一個要連線的節線,並試著保持對它的連線不斷(詳情請見 RPC 指令 addnode 的說明)</translation>
- </message>
- <message>
- <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation>和指定的位址繫結,並且一直在指定位址聽候連線。IPv6 請用 [主機]:通訊埠 這種格式</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>沒辦法鎖定資料目錄 %s。%s 可能已經在執行了。</translation>
</message>
@@ -3207,42 +3192,10 @@
<translation>無法同時指定特定連線位址以及自動尋找連線。</translation>
</message>
<message>
- <source>Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)</source>
- <translation>只連線到指定的節點。用 -connect=0 可以關閉自動連線。(套用於這個節點的規則與 -addnode 相同)</translation>
- </message>
- <message>
- <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
- <translation>清掉錢包裡的所有交易,並且在下次啟動時,使用 -rescan 來從區塊鏈中復原回來。</translation>
- </message>
- <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>讀取錢包檔 %s 時發生錯誤!所有的密鑰都正確讀取了,但是交易資料或位址簿資料可能會缺少或不正確。</translation>
</message>
<message>
- <source>Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.</source>
- <translation>不要對一種類別紀錄除錯資訊。可以和 -debug=1 配合,用來輸入除了指定的一種或多種類別外的所有除錯紀錄。</translation>
- </message>
- <message>
- <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation>當錢包有交易改變時要執行的指令(指令中的 %s 會被取代成交易識別碼)</translation>
- </message>
- <message>
- <source>Extra transactions to keep in memory for compact block reconstructions (default: %u)</source>
- <translation>為了將摘要區塊完整回組而額外保留在記憶體中的交易數量(預設值: %u)</translation>
- </message>
- <message>
- <source>If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)</source>
- <translation>假設已經在區塊鏈中的區塊以及其先前的區塊都合法,因此對它們略過指令碼驗證(0 表示一律要驗證,預設值: %s, 測試網路: %s)</translation>
- </message>
- <message>
- <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
- <translation>跟其他節點的時間差最高可接受的中位數值。本機所認為的時間可能會被其他節點影響,往前或往後在這個值之內。(預設值: %u 秒)</translation>
- </message>
- <message>
- <source>Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)</source>
- <translation>允許一次錢包交易或未加工交易付出的最高總手續費(單位是 %s);設定太低的話,可能會無法進行資料量大的交易(預設值: %s)</translation>
- </message>
- <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation>請檢查電腦日期和時間是否正確!%s 沒辦法在時鐘不準的情況下正常運作。</translation>
</message>
@@ -3251,22 +3204,6 @@
<translation>如果你覺得 %s 有用,可以幫助我們。關於這個軟體的更多資訊請見 %s。</translation>
</message>
<message>
- <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)</source>
- <translation>是否允許在節點位址數目不足時,使用域名查詢來搜尋節點 (預設值: 當沒用 -connect 時為 1)</translation>
- </message>
- <message>
- <source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
- <translation>修剪(刪除)掉老舊區塊以降低需要的儲存空間。這樣會增加一個 RPC 指令 pruneblockchain,可以使用它來刪除指定的區塊;也可以指定目標儲存空間大小,以啟用對老舊區塊的自動修剪功能。這個模式跟 -txindex 和 -rescan 參數不相容。警告: 還原回不修剪模式會需要重新下載一整個區塊鏈。(預設值: 0 表示不修剪區塊,1 表示允許使用 RPC 指令做修剪,&gt;%u 的值表示為區塊資料的目標大小,單位是百萬位元組,MiB)</translation>
- </message>
- <message>
- <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
- <translation>設定製造區塊時,所要包含交易每千位元組的最低手續費(單位是 %s)。(預設值: %s)</translation>
- </message>
- <message>
- <source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
- <translation>設定指令碼驗證的執行緒數目 (%u 到 %d,0 表示程式自動決定,小於 0 表示保留處理器核心不用的數目,預設值: %d)</translation>
- </message>
- <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation>區塊資料庫中有來自未來的區塊。可能是你電腦的日期時間不對。如果確定電腦日期時間沒錯的話,就重建區塊資料庫看看。</translation>
</message>
@@ -3287,18 +3224,6 @@
<translation>沒辦法將資料庫倒轉回分岔前的狀態。必須要重新下載區塊鍊。</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>是否要使用「通用即插即用」協定(UPnP),來設定聽候連線的通訊埠的對應(預設值: 當有聽候連線且沒有指定 -proxy 參數時為 1)</translation>
- </message>
- <message>
- <source>Username and hashed password for JSON-RPC connections. The field &lt;userpw&gt; comes in the format: &lt;USERNAME&gt;:&lt;SALT&gt;$&lt;HASH&gt;. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=&lt;USERNAME&gt;/rpcpassword=&lt;PASSWORD&gt; pair of arguments. This option can be specified multiple times</source>
- <translation>JSON-RPC 連線要用的使用者名稱和雜湊密碼。&lt;userpw&gt; 的格式是:&lt;使用者名稱&gt;:&lt;調味值&gt;$&lt;雜湊值&gt;。在 share/rpcuser 目錄下有一個示範的 python 程式。之後客戶端程式就可以用這對參數正常連線:rpcuser=&lt;使用者名稱&gt; 和 rpcpassword=&lt;密碼&gt;。這個選項可以給很多次。</translation>
- </message>
- <message>
- <source>Wallet will not create transactions that violate mempool chain limits (default: %u)</source>
- <translation>錢包軟體不會產生違反記憶池交易鏈限制的交易(預設值: %u)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>警告: 位元幣網路對於區塊鏈結的決定目前有分歧!有些礦工看來會有問題。</translation>
</message>
@@ -3307,10 +3232,6 @@
<translation>警告: 我們和某些連線的節點對於區塊鏈結的決定不同!你可能需要升級,或是需要等其它的節點升級。</translation>
</message>
<message>
- <source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
- <translation>是否要在結束時儲存記憶池,並在下次重起時載入(預設值: %u)</translation>
- </message>
- <message>
<source>%d of last 100 blocks have unexpected version</source>
<translation>最近的 100 個區塊中有 %d 個意料之外的區塊版本</translation>
</message>
@@ -3323,42 +3244,14 @@
<translation>參數 -maxmempool 至少要給 %d 百萬位元組(MB)</translation>
</message>
<message>
- <source>&lt;category&gt; can be:</source>
- <translation>&lt;category&gt; 可以是:</translation>
- </message>
- <message>
- <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation>是否接受外來連線(預設值: 當沒有 -proxy 或 -connect 時為 1)</translation>
- </message>
- <message>
- <source>Append comment to the user agent string</source>
- <translation>對使用者代理字串添加註解</translation>
- </message>
- <message>
- <source>Attempt to recover private keys from a corrupt wallet on startup</source>
- <translation>啟動時嘗試從壞掉的錢包檔復原密鑰</translation>
- </message>
- <message>
- <source>Block creation options:</source>
- <translation>區塊製造選項:</translation>
- </message>
- <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation>沒辦法解析 -%s 參數指定的位址: '%s'</translation>
</message>
<message>
- <source>Chain selection options:</source>
- <translation>區塊鏈選項:</translation>
- </message>
- <message>
<source>Change index out of range</source>
<translation>找零的索引值超出範圍</translation>
</message>
<message>
- <source>Connection options:</source>
- <translation>連線選項:</translation>
- </message>
- <message>
<source>Copyright (C) %i-%i</source>
<translation>版權所有 (C) %i-%i</translation>
</message>
@@ -3367,38 +3260,10 @@
<translation>發現區塊資料庫壞掉了</translation>
</message>
<message>
- <source>Debugging/Testing options:</source>
- <translation>除錯與測試選項</translation>
- </message>
- <message>
- <source>Do not load the wallet and disable wallet RPC calls</source>
- <translation>不要載入錢包,並且拿掉錢包相關的 RPC 功能請求。</translation>
- </message>
- <message>
<source>Do you want to rebuild the block database now?</source>
<translation>你想要現在重建區塊資料庫嗎?</translation>
</message>
<message>
- <source>Enable publish hash block in &lt;address&gt;</source>
- <translation>開啟傳送區塊雜湊值到目標 ZeroMQ 位址 &lt;address&gt; 去</translation>
- </message>
- <message>
- <source>Enable publish hash transaction in &lt;address&gt;</source>
- <translation>開啟傳送交易雜湊值到目標 ZeroMQ 位址 &lt;address&gt; 去</translation>
- </message>
- <message>
- <source>Enable publish raw block in &lt;address&gt;</source>
- <translation>開啟傳送區塊原始資料到目標 ZeroMQ 位址 &lt;address&gt; 去</translation>
- </message>
- <message>
- <source>Enable publish raw transaction in &lt;address&gt;</source>
- <translation>開啟傳送交易原始資料到目標 ZeroMQ 位址 &lt;address&gt; 去</translation>
- </message>
- <message>
- <source>Enable transaction replacement in the memory pool (default: %u)</source>
- <translation>對交易暫存池啟用替代交易(預設值: %u)</translation>
- </message>
- <message>
<source>Error creating %s: You can't create non-HD wallets with this version.</source>
<translation>產生 %s 發生錯誤:這個版本不能用來產生非 HD 錢包。</translation>
</message>
@@ -3415,6 +3280,10 @@
<translation>載入檔案 %s 時發生錯誤</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>載入 %s 時發生錯誤: 只有在造新錢包時能夠指定不允許私鑰</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>載入檔案 %s 時發生錯誤: 錢包損毀了</translation>
</message>
@@ -3467,8 +3336,12 @@
<translation>設定 -fallbackfee=&lt;金額&gt; 的金額無效: '%s'</translation>
</message>
<message>
- <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
- <translation>在記憶體暫存池中保持最多 &lt;n&gt; 個百萬位元組的交易(預設值: %u)</translation>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>指定的區塊目錄 "%s" 不存在。</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>正在升級 txindex 資料庫</translation>
</message>
<message>
<source>Loading P2P addresses...</source>
@@ -3479,26 +3352,10 @@
<translation>正在載入禁止連線名單中...</translation>
</message>
<message>
- <source>Location of the auth cookie (default: data dir)</source>
- <translation>認證 cookie 資料的位置(預設值: 同資料目錄)</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation>檔案描述元不足。</translation>
</message>
<message>
- <source>Only connect to nodes in network &lt;net&gt; (ipv4, ipv6 or onion)</source>
- <translation>只和 &lt;net&gt; 網路上的節點連線(ipv4, ipv6, 或 onion)</translation>
- </message>
- <message>
- <source>Print this help message and exit</source>
- <translation>顯示說明訊息後結束</translation>
- </message>
- <message>
- <source>Print version and exit</source>
- <translation>顯示版本後結束</translation>
- </message>
- <message>
<source>Prune cannot be configured with a negative value.</source>
<translation>修剪值不能設定為負的。</translation>
</message>
@@ -3507,14 +3364,6 @@
<translation>修剪模式和 -txindex 參數不相容。</translation>
</message>
<message>
- <source>Rebuild chain state and block index from the blk*.dat files on disk</source>
- <translation>從磁碟裡的區塊檔 blk*.dat 重建區塊鏈狀態和區塊索引</translation>
- </message>
- <message>
- <source>Rebuild chain state from the currently indexed blocks</source>
- <translation>從目前已編索引的區塊資料重建區塊鏈狀態</translation>
- </message>
- <message>
<source>Replaying blocks...</source>
<translation>正在對區塊進行重算...</translation>
</message>
@@ -3523,18 +3372,6 @@
<translation>正在倒轉回區塊鏈之前的狀態...</translation>
</message>
<message>
- <source>Send transactions with full-RBF opt-in enabled (RPC only, default: %u)</source>
- <translation>送出允許提高手續費(full-RBF)的交易(僅適用於 RPC 指令,預設值: %u)</translation>
- </message>
- <message>
- <source>Set database cache size in megabytes (%d to %d, default: %d)</source>
- <translation>設定資料庫快取大小是多少百萬位元組(MB,範圍: %d 到 %d,預設值: %d)</translation>
- </message>
- <message>
- <source>Specify wallet file (within data directory)</source>
- <translation>指定錢包檔(會在資料目錄中)</translation>
- </message>
- <message>
<source>The source code is available from %s.</source>
<translation>原始碼可以在 %s 取得。</translation>
</message>
@@ -3547,6 +3384,10 @@
<translation>沒辦法繫結在這台電腦上的 %s 。%s 可能已經在執行了。</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>沒辦法產生密鑰</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>忽略了不再支援的 -benchmark 參數,請改用 -debug=bench</translation>
</message>
@@ -3567,14 +3408,6 @@
<translation>正在升級 UTXO 資料庫</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: %u)</source>
- <translation>使用通用隨插即用 (UPnP) 協定來設定對應的服務連接埠(預設值: %u)</translation>
- </message>
- <message>
- <source>Use the test chain</source>
- <translation>使用測試區塊鏈</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation>使用者代理註解(%s)中含有不安全的字元。</translation>
</message>
@@ -3583,90 +3416,26 @@
<translation>正在驗證區塊資料...</translation>
</message>
<message>
- <source>Wallet debugging/testing options:</source>
- <translation>錢包除錯與測試選項:</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation>錢包需要重寫: 請重新啓動 %s 來完成</translation>
</message>
<message>
- <source>Wallet options:</source>
- <translation>錢包選項:</translation>
- </message>
- <message>
- <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; 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</source>
- <translation>允許指定的來源建立 JSON-RPC 連線。&lt;ip&gt; 的有效值可以是一個單獨位址(像是 1.2.3.4),一個網段/網段罩遮值(像是 1.2.3.4/255.255.255.0),或是網段/CIDR值(像是 1.2.3.4/24)。這個選項可以設定多次。</translation>
- </message>
- <message>
- <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
- <translation>和指定的位址繫結,並且把連線過來的節點放進白名單。IPv6 請用 [主機]:通訊埠 這種格式</translation>
- </message>
- <message>
- <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
- <translation>用系統預設權限來造出新的檔案,而不是用使用者權限罩遮(umask)值 077 (只有在關掉錢包功能時才有作用)。</translation>
- </message>
- <message>
- <source>Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)</source>
- <translation>找出自己的網際網路位址(預設值: 當有聽候連線且沒有指定 -externalip 或 -proxy 時為 1)</translation>
- </message>
- <message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation>錯誤: 聽候外來連線失敗(回傳錯誤 %s)</translation>
</message>
<message>
- <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
- <translation>當收到相關警示,或發現相當長的分支時,所要執行的指令(指令中的 %s 會被取代成警示訊息)</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)</source>
- <translation>當處理轉發的交易、挖礦、或製造交易時,如果每千位元組(kB)的手續費比這個值(單位是 %s)低,就視為沒付手續費(預設值: %s)</translation>
- </message>
- <message>
- <source>If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)</source>
- <translation>當沒有設定 paytxfee 時,自動包含可以讓交易能在平均 n 個區塊內開始確認的手續費(預設值: %u)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation>-maxtxfee=&lt;amount&gt;: '%s' 的金額無效 (必須大於最低轉發手續費 %s 以避免交易無法確認)</translation>
</message>
<message>
- <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source>
- <translation>轉發和開採時,對只帶資料的交易的大小上限(預設值: %u)</translation>
- </message>
- <message>
- <source>Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)</source>
- <translation>對每個代理連線使用隨機產生的憑證。這個選項會開啟 Tor 的串流隔離(預設值: %u)</translation>
- </message>
- <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>扣除手續費後的交易金額太少而不能傳送</translation>
</message>
<message>
- <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
- <translation>在白名單中的節點不會因為偵測到阻斷服務攻擊(DoS)而被停用。來自這些節點的交易也一定會被轉發,即使說交易本來就在記憶池裡了也一樣。適用於像是閘道伺服器。</translation>
- </message>
- <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation>回到非修剪的模式需要用 -reindex 參數來重建資料庫。這會導致重新下載整個區塊鏈。</translation>
</message>
<message>
- <source>(default: %u)</source>
- <translation>(預設值: %u)</translation>
- </message>
- <message>
- <source>Accept public REST requests (default: %u)</source>
- <translation>接受公開的REST請求 (預設值: %u)</translation>
- </message>
- <message>
- <source>Automatically create Tor hidden service (default: %d)</source>
- <translation>自動產生 Tor 隱藏服務(預設值: %d)</translation>
- </message>
- <message>
- <source>Connect through SOCKS5 proxy</source>
- <translation>透過 SOCKS5 代理伺服器連線</translation>
- </message>
- <message>
<source>Error loading %s: You can't disable HD on an already existing HD wallet</source>
<translation>載入 %s 發生錯誤:不能對已存在的 HD 錢包停用 HD 功能。</translation>
</message>
@@ -3679,10 +3448,6 @@
<translation>升級區塊鏈狀態資料庫時發生錯誤</translation>
</message>
<message>
- <source>Imports blocks from external blk000??.dat file on startup</source>
- <translation>啟動時從其它來源的 blk000??.dat 檔匯入區塊</translation>
- </message>
- <message>
<source>Information</source>
<translation>資訊</translation>
</message>
@@ -3703,42 +3468,14 @@
<translation>指定在 -whitelist 的網段無效: '%s'</translation>
</message>
<message>
- <source>Keep at most &lt;n&gt; unconnectable transactions in memory (default: %u)</source>
- <translation>保持最多 &lt;n&gt; 無法連結的交易在記憶體 (預設: %u)</translation>
- </message>
- <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>指定 -whitebind 時必須包含通訊埠: '%s'</translation>
</message>
<message>
- <source>Node relay options:</source>
- <translation>節點轉發選項:</translation>
- </message>
- <message>
- <source>RPC server options:</source>
- <translation>RPC 伺服器選項:</translation>
- </message>
- <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation>因為系統的限制,將 -maxconnections 參數從 %d 降到了 %d</translation>
</message>
<message>
- <source>Rescan the block chain for missing wallet transactions on startup</source>
- <translation>啟動時重新掃描區塊鏈,來尋找錢包可能漏掉的交易。</translation>
- </message>
- <message>
- <source>Send trace/debug info to console instead of debug.log file</source>
- <translation>在終端機顯示追蹤或除錯資訊,而不是寫到檔案 debug.log 中</translation>
- </message>
- <message>
- <source>Show all debugging options (usage: --help -help-debug)</source>
- <translation>顯示所有的除錯選項 (用法: --help --help-debug)</translation>
- </message>
- <message>
- <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation>客戶端軟體啓動時把 debug.log 檔縮小(預設值: 當沒有 -debug 時為 1)</translation>
- </message>
- <message>
<source>Signing transaction failed</source>
<translation>簽署交易失敗</translation>
</message>
@@ -3763,14 +3500,6 @@
<translation>這套軟體屬於實驗性質。</translation>
</message>
<message>
- <source>Tor control port password (default: empty)</source>
- <translation>Tor 控制埠密碼(預設值: 空白)</translation>
- </message>
- <message>
- <source>Tor control port to use if onion listening enabled (default: %s)</source>
- <translation>開啟聽候 onion 連線時的 Tor 控制埠號碼(預設值: %s)</translation>
- </message>
- <message>
<source>Transaction amount too small</source>
<translation>交易金額太小</translation>
</message>
@@ -3788,15 +3517,7 @@
</message>
<message>
<source>Unable to generate initial keys</source>
- <translation>無法產生初始的金鑰</translation>
- </message>
- <message>
- <source>Upgrade wallet to latest format on startup</source>
- <translation>啟動時把錢包檔案升級成最新的格式</translation>
- </message>
- <message>
- <source>Username for JSON-RPC connections</source>
- <translation>JSON-RPC 連線使用者名稱</translation>
+ <translation>無法產生初始的密鑰</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
@@ -3815,110 +3536,18 @@
<translation>警告: 不明的交易規則被啟用了(versionbit %i)</translation>
</message>
<message>
- <source>Whether to operate in a blocks only mode (default: %u)</source>
- <translation>是否要用只要區塊模式運作(預設值: %u)</translation>
- </message>
- <message>
- <source>You need to rebuild the database using -reindex to change -txindex</source>
- <translation>改變 -txindex 參數後,必須要用 -reindex 參數來重建資料庫</translation>
- </message>
- <message>
<source>Zapping all transactions from wallet...</source>
<translation>正在砍掉錢包中的所有交易...</translation>
</message>
<message>
- <source>ZeroMQ notification options:</source>
- <translation>ZeroMQ 通知選項:</translation>
- </message>
- <message>
- <source>Password for JSON-RPC connections</source>
- <translation>JSON-RPC 連線密碼</translation>
- </message>
- <message>
- <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation>當最新區塊改變時要執行的指令(指令中的 %s 會被取代成區塊雜湊值)</translation>
- </message>
- <message>
- <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation>允許對 -addnode, -seednode, -connect 的參數使用域名查詢 </translation>
- </message>
- <message>
- <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
- <translation>(1 表示保留交易描述資料,像是帳戶使用者和付款請求資訊;2 表示丟掉交易描述資料)</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>參數 -maxtxfee 設定了很高的金額!這可是你一次交易就有可能付出的最高手續費。</translation>
</message>
<message>
- <source>Bind to given address to listen for JSON-RPC connections. 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, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)</source>
- <translation>和指定的位址繫結以聽候 JSON-RPC 連線。必須同時指定 -rpcallowip 這項設定才有作用。不一定要指定埠號,指定的話會覆蓋掉 -rpcport 設定。IPv6 請用 [主機]:通訊埠 這種格式。這個選項可以設定多次。(預設值: 127.0.0.1 和 ::1,也就是 localhost。當有指定 -rpcallowip 時,預設值為 0.0.0.0 和 ::,也就是所有位址)</translation>
- </message>
- <message>
- <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
- <translation>不要讓交易留在記憶池中超過 &lt;n&gt; 個小時(預設值: %u)</translation>
- </message>
- <message>
- <source>Equivalent bytes per sigop in transactions for relay and mining (default: %u)</source>
- <translation>轉發和開採時,交易資料中每個 sigop 的等同位元組數(預設值: %u)</translation>
- </message>
- <message>
<source>Error loading %s: You can't enable HD on an already existing non-HD wallet</source>
<translation>載入 %s 發生錯誤:不能對已存在的非 HD 錢包啟用 HD 功能。</translation>
</message>
<message>
- <source>Error loading wallet %s. -wallet parameter must only specify a filename (not a path).</source>
- <translation>載入錢包檔 %s 失敗。-wallet 參數只能指定檔案名稱(不包含路徑)。</translation>
- </message>
- <message>
- <source>Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)</source>
- <translation>當製造交易時,如果每千位元組(kB)的手續費比這個值(單位是 %s)低,就視為沒付手續費(預設值: %s)</translation>
- </message>
- <message>
- <source>Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)</source>
- <translation>強制轉發從白名點節點收到的交易,即使它們違反了本機的轉發準則(預設值: %d)</translation>
- </message>
- <message>
- <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
- <translation>使用 -checkblocks 檢查區塊的仔細程度(0 到 4,預設值: %u)</translation>
- </message>
- <message>
- <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source>
- <translation>維護全部交易的索引,用在 getrawtransaction 這個 RPC 請求(預設值: %u)</translation>
- </message>
- <message>
- <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source>
- <translation>避免與亂搞的節點連線的秒數(預設: %u)</translation>
- </message>
- <message>
- <source>Output debugging information (default: %u, supplying &lt;category&gt; is optional)</source>
- <translation>輸出除錯資訊(預設值: %u, 不一定要指定 &lt;category&gt;)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight to this * 4. Deprecated, use blockmaxweight</source>
- <translation>設定 BIP141 區塊重量的最大值為指定值乘以 4。此設定即將淘汰,請改用 blockmaxweight</translation>
- </message>
- <message>
- <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
- <translation>設定非冗長模式時,回傳的交易原始資料或區塊位元值的序列化形式:無 segwit 為 0,或是有 segwit 為 1 (預設值: %d)</translation>
- </message>
- <message>
- <source>Specify directory to hold wallets (default: &lt;datadir&gt;/wallets if it exists, otherwise &lt;datadir&gt;)</source>
- <translation>指定用來放錢包檔的目錄(預設值: 如果存在的話就用 &lt;datadir&gt;/wallets, 否則為 &lt;datadir&gt;)</translation>
- </message>
- <message>
- <source>Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)</source>
- <translation>指定除錯紀錄檔的位址: 可以用絕對路徑,也可以用相對於資料路徑的相對路徑(預設值: %s)</translation>
- </message>
- <message>
- <source>Support filtering of blocks and transaction with bloom filters (default: %u)</source>
- <translation>支援用布倫過濾器來過濾區塊和交易(預設值: %u)</translation>
- </message>
- <message>
- <source>The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target</source>
- <translation>容許自動免找零成為手續費的交易手續費率(單位: %s/kB, 預設值: %s)。注意: 如果在該費率下,找零的零錢會成為零散錢,則自動棄掉成為手續費。但棄掉的零錢費率永遠不會大於零散錢的轉發費率,金額也不會大於最長預估確認時間所需的手續費</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>這是當預估手續費還沒計算出來時,付款交易預設會付的手續費。</translation>
</message>
@@ -3931,10 +3560,6 @@
<translation>網路版本字串的總長度(%i)超過最大長度(%i)了。請減少 uacomment 參數的數目或長度。</translation>
</message>
<message>
- <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
- <translation>試著保持輸出流量在目標值以下,單位是每 24 小時的百萬位元組(MiB)數,0 表示沒有限制(預設值: %d)</translation>
- </message>
- <message>
<source>Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source>
<translation>找到不再支援的 -socks 參數。現在只支援 SOCKS5 協定的代理伺服器,因此不可以指定 SOCKS 協定版本了。</translation>
</message>
@@ -3943,10 +3568,6 @@
<translation>忽略不支援的參數 -whitelistalwaysrelay,請改用 -whitelistrelay 和 -whitelistforcerelay​ 的組合。</translation>
</message>
<message>
- <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
- <translation>使用另外的 SOCK5 代理伺服器,來透過 Tor 隱藏服務跟其他節點聯絡(預設值: %s)</translation>
- </message>
- <message>
<source>Warning: Unknown block versions being mined! It's possible unknown rules are in effect</source>
<translation>警告: 有礦工正在開採不明版本的區塊!這表示有不明的交易規則正在作用中</translation>
</message>
@@ -3955,110 +3576,18 @@
<translation>警告: 錢包檔壞掉,但資料被救回來了!原來的檔案 %s 改儲存為 %s,在目錄 %s 下。 如果餘額或交易資料有誤的話,你應該要從備份資料復原回來。</translation>
</message>
<message>
- <source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
- <translation>把來自指定位址(例如:1.2.3.4)或 CIDR 格式網段(例如:1.2.3.0/24)的節點放進白名單。這個選項可以設定多次。</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s 的設定值異常大!</translation>
</message>
<message>
- <source>(default: %s)</source>
- <translation>(預設值: %s)</translation>
- </message>
- <message>
- <source>Always query for peer addresses via DNS lookup (default: %u)</source>
- <translation>是否一定要用域名查詢來搜尋節點(預設值: %u)</translation>
- </message>
- <message>
- <source>Error loading wallet %s. -wallet filename must be a regular file.</source>
- <translation>載入錢包檔 %s 失敗。-wallet 參數檔名的檔案必須是一般檔案。</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>載入錢包檔 %s 失敗。-wallet 參數指定了重複的檔名。</translation>
</message>
<message>
- <source>Error loading wallet %s. Invalid characters in -wallet filename.</source>
- <translation>載入錢包檔 %s 失敗。-wallet 參數檔名含有無效的字元。</translation>
- </message>
- <message>
- <source>How many blocks to check at startup (default: %u, 0 = all)</source>
- <translation>啓動時檢查的區塊數(預設值: %u, 指定 0 表示全部)</translation>
- </message>
- <message>
- <source>Include IP addresses in debug output (default: %u)</source>
- <translation>在除錯輸出內容中包含網際網路位址(預設值: %u)</translation>
- </message>
- <message>
<source>Keypool ran out, please call keypoolrefill first</source>
<translation>密鑰池已經乾了,請先執行 keypoolrefill</translation>
</message>
<message>
- <source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>在通訊埠 &lt;port&gt; 聽候 JSON-RPC 連線(預設值: %u, 或若為測試網路: %u)</translation>
- </message>
- <message>
- <source>Listen for connections on &lt;port&gt; (default: %u or testnet: %u)</source>
- <translation>在通訊埠 &lt;port&gt; 聽候連線(預設值: %u, 或若為測試網路: %u)</translation>
- </message>
- <message>
- <source>Maintain at most &lt;n&gt; connections to peers (default: %u)</source>
- <translation>維持與節點連線數的上限為 &lt;n&gt; 個(預設值: %u)</translation>
- </message>
- <message>
- <source>Make the wallet broadcast transactions</source>
- <translation>讓錢包能公告交易</translation>
- </message>
- <message>
- <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>每個連線的接收緩衝區大小上限為 &lt;n&gt;*1000 個位元組(預設值: %u)</translation>
- </message>
- <message>
- <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: %u)</source>
- <translation>每個連線的傳送緩衝區大小上限為 &lt;n&gt;*1000 個位元組(預設值: %u)</translation>
- </message>
- <message>
- <source>Prepend debug output with timestamp (default: %u)</source>
- <translation>在除錯輸出內容前附加時間(預設值: %u)</translation>
- </message>
- <message>
- <source>Relay and mine data carrier transactions (default: %u)</source>
- <translation>允許轉發和開採只帶資料的交易(預設值: %u)</translation>
- </message>
- <message>
- <source>Relay non-P2SH multisig (default: %u)</source>
- <translation>允許轉發非 P2SH 的多簽章交易(預設值: %u)</translation>
- </message>
- <message>
- <source>Set key pool size to &lt;n&gt; (default: %u)</source>
- <translation>設定密鑰池大小為 &lt;n&gt; (預設值: %u)</translation>
- </message>
- <message>
- <source>Set maximum BIP141 block weight (default: %d)</source>
- <translation>設定 BIP141 區塊重量的最大值(預設值: %d)</translation>
- </message>
- <message>
- <source>Set the number of threads to service RPC calls (default: %d)</source>
- <translation>設定處理 RPC 服務請求的執行緒數目(預設值: %d)</translation>
- </message>
- <message>
- <source>Specify configuration file (default: %s)</source>
- <translation>指定設定檔(預設值: %s)</translation>
- </message>
- <message>
- <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source>
- <translation>指定連線在幾毫秒後逾時 (最少值: 1, 預設值: %d)</translation>
- </message>
- <message>
- <source>Specify pid file (default: %s)</source>
- <translation>指定行程識別碼檔案(預設值: %s)</translation>
- </message>
- <message>
- <source>Spend unconfirmed change when sending transactions (default: %u)</source>
- <translation>傳送交易時可以花還沒確認的零錢(預設值: %u)</translation>
- </message>
- <message>
<source>Starting network threads...</source>
<translation>正在啟動網路執行緒...</translation>
</message>
@@ -4075,10 +3604,6 @@
<translation>這是你交易付款時所要付的手續費。</translation>
</message>
<message>
- <source>Threshold for disconnecting misbehaving peers (default: %u)</source>
- <translation>與亂搞的節點斷線的臨界值 (預設: %u)</translation>
- </message>
- <message>
<source>Transaction amounts must not be negative</source>
<translation>交易金額不能是負的</translation>
</message>
@@ -4099,6 +3624,26 @@
<translation>累積金額不足</translation>
</message>
<message>
+ <source>Can't generate a change-address key. Private keys are disabled for this wallet.</source>
+ <translation>沒辦法造出密鑰給找零位址使用,因為目前這個錢包不允許有私鑰。</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
+ <translation>無法將一個非 HD 分支錢包升級成不支援預先分支密鑰池的 HD 分支錢包版本。請用 -upgradewallet=169900 參數或是不指定版本的 -upgradewallet 參數來升級錢包。</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>計算預估手續費失敗了,也沒有備用手續費(fallbackfee)可用。請再多等待幾個區塊,或是啟用 -fallbackfee 參數。</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>警告: 在不允許私鑰的錢包 {%s} 中發現有私鑰</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>沒辦法寫入資料目錄 '%s',請檢查是否有權限。</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>正在載入區塊索引...</translation>
</message>
diff --git a/src/qt/macdockiconhandler.h b/src/qt/macdockiconhandler.h
index 1c28593d4a..ff867e21a7 100644
--- a/src/qt/macdockiconhandler.h
+++ b/src/qt/macdockiconhandler.h
@@ -1,44 +1,27 @@
-// Copyright (c) 2011-2015 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_QT_MACDOCKICONHANDLER_H
#define BITCOIN_QT_MACDOCKICONHANDLER_H
-#include <QMainWindow>
#include <QObject>
-QT_BEGIN_NAMESPACE
-class QIcon;
-class QMenu;
-class QWidget;
-QT_END_NAMESPACE
-
-/** Macintosh-specific dock icon handler.
+/** macOS-specific Dock icon handler.
*/
class MacDockIconHandler : public QObject
{
Q_OBJECT
public:
- ~MacDockIconHandler();
-
- QMenu *dockMenu();
- void setIcon(const QIcon &icon);
- void setMainWindow(QMainWindow *window);
static MacDockIconHandler *instance();
static void cleanup();
- void handleDockIconClickEvent();
Q_SIGNALS:
void dockIconClicked();
private:
MacDockIconHandler();
-
- QWidget *m_dummyWidget;
- QMenu *m_dockMenu;
- QMainWindow *mainWindow;
};
#endif // BITCOIN_QT_MACDOCKICONHANDLER_H
diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm
index b9ad191da7..102adce6c5 100644
--- a/src/qt/macdockiconhandler.mm
+++ b/src/qt/macdockiconhandler.mm
@@ -1,107 +1,36 @@
-// Copyright (c) 2011-2013 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "macdockiconhandler.h"
-#include <QImageWriter>
-#include <QMenu>
-#include <QBuffer>
-#include <QWidget>
-
#undef slots
-#include <Cocoa/Cocoa.h>
#include <objc/objc.h>
#include <objc/message.h>
static MacDockIconHandler *s_instance = nullptr;
-bool dockClickHandler(id self,SEL _cmd,...) {
+bool dockClickHandler(id self, SEL _cmd, ...) {
Q_UNUSED(self)
Q_UNUSED(_cmd)
- s_instance->handleDockIconClickEvent();
+ Q_EMIT s_instance->dockIconClicked();
- // Return NO (false) to suppress the default OS X actions
+ // Return NO (false) to suppress the default macOS actions
return false;
}
void setupDockClickHandler() {
- Class cls = objc_getClass("NSApplication");
- id appInst = objc_msgSend((id)cls, sel_registerName("sharedApplication"));
-
- if (appInst != nullptr) {
- id delegate = objc_msgSend(appInst, sel_registerName("delegate"));
- Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class"));
- SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
- if (class_getInstanceMethod(delClass, shouldHandle))
- class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:");
- else
- class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler,"B@:");
- }
+ id app = objc_msgSend((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
+ id delegate = objc_msgSend(app, sel_registerName("delegate"));
+ Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class"));
+ SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
+ class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "B@:");
}
-
MacDockIconHandler::MacDockIconHandler() : QObject()
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
setupDockClickHandler();
- this->m_dummyWidget = new QWidget();
- this->m_dockMenu = new QMenu(this->m_dummyWidget);
- this->setMainWindow(nullptr);
-#if QT_VERSION >= 0x050200
- this->m_dockMenu->setAsDockMenu();
-#endif
- [pool release];
-}
-
-void MacDockIconHandler::setMainWindow(QMainWindow *window) {
- this->mainWindow = window;
-}
-
-MacDockIconHandler::~MacDockIconHandler()
-{
- delete this->m_dummyWidget;
- this->setMainWindow(nullptr);
-}
-
-QMenu *MacDockIconHandler::dockMenu()
-{
- return this->m_dockMenu;
-}
-
-void MacDockIconHandler::setIcon(const QIcon &icon)
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSImage *image = nil;
- if (icon.isNull())
- image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
- else {
- // generate NSImage from QIcon and use this as dock icon.
- QSize size = icon.actualSize(QSize(128, 128));
- QPixmap pixmap = icon.pixmap(size);
-
- // Write image into a R/W buffer from raw pixmap, then save the image.
- QBuffer notificationBuffer;
- if (!pixmap.isNull() && notificationBuffer.open(QIODevice::ReadWrite)) {
- QImageWriter writer(&notificationBuffer, "PNG");
- if (writer.write(pixmap.toImage())) {
- NSData* macImgData = [NSData dataWithBytes:notificationBuffer.buffer().data()
- length:notificationBuffer.buffer().size()];
- image = [[NSImage alloc] initWithData:macImgData];
- }
- }
-
- if(!image) {
- // if testnet image could not be created, load std. app icon
- image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
- }
- }
-
- [NSApp setApplicationIconImage:image];
- [image release];
- [pool release];
}
MacDockIconHandler *MacDockIconHandler::instance()
@@ -115,14 +44,3 @@ void MacDockIconHandler::cleanup()
{
delete s_instance;
}
-
-void MacDockIconHandler::handleDockIconClickEvent()
-{
- if (this->mainWindow)
- {
- this->mainWindow->activateWindow();
- this->mainWindow->show();
- }
-
- Q_EMIT this->dockIconClicked();
-}
diff --git a/src/qt/macnotificationhandler.h b/src/qt/macnotificationhandler.h
index 1e25d3e7a4..03c744c12e 100644
--- a/src/qt/macnotificationhandler.h
+++ b/src/qt/macnotificationhandler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,7 +19,7 @@ public:
void showNotification(const QString &title, const QString &text);
/** check if OS can handle UserNotifications */
- bool hasUserNotificationCenterSupport(void);
+ bool hasUserNotificationCenterSupport();
static MacNotificationHandler *instance();
};
diff --git a/src/qt/macnotificationhandler.mm b/src/qt/macnotificationhandler.mm
index 0e04d50baa..a07079eece 100644
--- a/src/qt/macnotificationhandler.mm
+++ b/src/qt/macnotificationhandler.mm
@@ -24,25 +24,10 @@ void MacNotificationHandler::showNotification(const QString &title, const QStrin
{
// check if users OS has support for NSUserNotification
if(this->hasUserNotificationCenterSupport()) {
- // okay, seems like 10.8+
- QByteArray utf8 = title.toUtf8();
- char* cString = (char *)utf8.constData();
- NSString *titleMac = [[NSString alloc] initWithUTF8String:cString];
-
- utf8 = text.toUtf8();
- cString = (char *)utf8.constData();
- NSString *textMac = [[NSString alloc] initWithUTF8String:cString];
-
- // do everything weak linked (because we will keep <10.8 compatibility)
- id userNotification = [[NSClassFromString(@"NSUserNotification") alloc] init];
- [userNotification performSelector:@selector(setTitle:) withObject:titleMac];
- [userNotification performSelector:@selector(setInformativeText:) withObject:textMac];
-
- id notificationCenterInstance = [NSClassFromString(@"NSUserNotificationCenter") performSelector:@selector(defaultUserNotificationCenter)];
- [notificationCenterInstance performSelector:@selector(deliverNotification:) withObject:userNotification];
-
- [titleMac release];
- [textMac release];
+ NSUserNotification* userNotification = [[NSUserNotification alloc] init];
+ userNotification.title = title.toNSString();
+ userNotification.informativeText = text.toNSString();
+ [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification: userNotification];
[userNotification release];
}
}
diff --git a/src/qt/macos_appnap.h b/src/qt/macos_appnap.h
new file mode 100644
index 0000000000..8c2cd840b0
--- /dev/null
+++ b/src/qt/macos_appnap.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_QT_MACOS_APPNAP_H
+#define BITCOIN_QT_MACOS_APPNAP_H
+
+#include <memory>
+
+class CAppNapInhibitor final
+{
+public:
+ explicit CAppNapInhibitor();
+ ~CAppNapInhibitor();
+
+ void disableAppNap();
+ void enableAppNap();
+
+private:
+ class CAppNapImpl;
+ std::unique_ptr<CAppNapImpl> impl;
+};
+
+#endif // BITCOIN_QT_MACOS_APPNAP_H
diff --git a/src/qt/macos_appnap.mm b/src/qt/macos_appnap.mm
new file mode 100644
index 0000000000..22a88782ab
--- /dev/null
+++ b/src/qt/macos_appnap.mm
@@ -0,0 +1,71 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "macos_appnap.h"
+
+#include <AvailabilityMacros.h>
+#include <Foundation/NSProcessInfo.h>
+#include <Foundation/Foundation.h>
+
+class CAppNapInhibitor::CAppNapImpl
+{
+public:
+ ~CAppNapImpl()
+ {
+ if(activityId)
+ enableAppNap();
+ }
+
+ void disableAppNap()
+ {
+ if (!activityId)
+ {
+ @autoreleasepool {
+ const NSActivityOptions activityOptions =
+ NSActivityUserInitiatedAllowingIdleSystemSleep &
+ ~(NSActivitySuddenTerminationDisabled |
+ NSActivityAutomaticTerminationDisabled);
+
+ id processInfo = [NSProcessInfo processInfo];
+ if ([processInfo respondsToSelector:@selector(beginActivityWithOptions:reason:)])
+ {
+ activityId = [processInfo beginActivityWithOptions: activityOptions reason:@"Temporarily disable App Nap for bitcoin-qt."];
+ [activityId retain];
+ }
+ }
+ }
+ }
+
+ void enableAppNap()
+ {
+ if(activityId)
+ {
+ @autoreleasepool {
+ id processInfo = [NSProcessInfo processInfo];
+ if ([processInfo respondsToSelector:@selector(endActivity:)])
+ [processInfo endActivity:activityId];
+
+ [activityId release];
+ activityId = nil;
+ }
+ }
+ }
+
+private:
+ NSObject* activityId;
+};
+
+CAppNapInhibitor::CAppNapInhibitor() : impl(new CAppNapImpl()) {}
+
+CAppNapInhibitor::~CAppNapInhibitor() = default;
+
+void CAppNapInhibitor::disableAppNap()
+{
+ impl->disableAppNap();
+}
+
+void CAppNapInhibitor::enableAppNap()
+{
+ impl->enableAppNap();
+}
diff --git a/src/qt/main.cpp b/src/qt/main.cpp
new file mode 100644
index 0000000000..6a3c2249d1
--- /dev/null
+++ b/src/qt/main.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <qt/bitcoin.h>
+
+#include <QCoreApplication>
+
+#include <functional>
+#include <string>
+
+/** Translate string to current locale using Qt. */
+extern const std::function<std::string(const char*)> G_TRANSLATION_FUN = [](const char* psz) {
+ return QCoreApplication::translate("bitcoin-core", psz).toStdString();
+};
+
+int main(int argc, char* argv[]) { return GuiMain(argc, argv); }
diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp
index e9d03c5828..8ecc33da84 100644
--- a/src/qt/modaloverlay.cpp
+++ b/src/qt/modaloverlay.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -21,7 +21,7 @@ layerIsVisible(false),
userClosed(false)
{
ui->setupUi(this);
- connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
+ connect(ui->closeButton, &QPushButton::clicked, this, &ModalOverlay::closeClicked);
if (parent) {
parent->installEventFilter(this);
raise();
@@ -71,6 +71,7 @@ void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
if (count > bestHeaderHeight) {
bestHeaderHeight = count;
bestHeaderDate = blockDate;
+ UpdateHeaderSyncLabel();
}
}
@@ -136,11 +137,16 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri
if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
} else {
- ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
+ UpdateHeaderSyncLabel();
ui->expectedTimeLeft->setText(tr("Unknown..."));
}
}
+void ModalOverlay::UpdateHeaderSyncLabel() {
+ int est_headers_left = bestHeaderDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
+ ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1, %2%)...").arg(bestHeaderHeight).arg(QString::number(100.0 / (bestHeaderHeight + est_headers_left) * bestHeaderHeight, 'f', 1)));
+}
+
void ModalOverlay::toggleVisibility()
{
showHide(layerIsVisible, true);
diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h
index 63465ab66e..cf8b53f2b3 100644
--- a/src/qt/modaloverlay.h
+++ b/src/qt/modaloverlay.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -45,6 +45,7 @@ private:
QVector<QPair<qint64, double> > blockProcessTime;
bool layerIsVisible;
bool userClosed;
+ void UpdateHeaderSyncLabel();
};
#endif // BITCOIN_QT_MODALOVERLAY_H
diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp
index c4b732e3e0..f0c860e669 100644
--- a/src/qt/networkstyle.cpp
+++ b/src/qt/networkstyle.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -17,7 +17,7 @@ static const struct {
} network_styles[] = {
{"main", QAPP_APP_NAME_DEFAULT, 0, 0, ""},
{"test", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")},
- {"regtest", QAPP_APP_NAME_TESTNET, 160, 30, "[regtest]"}
+ {"regtest", QAPP_APP_NAME_REGTEST, 160, 30, "[regtest]"}
};
static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles);
@@ -88,5 +88,5 @@ const NetworkStyle *NetworkStyle::instantiate(const QString &networkId)
network_styles[x].titleAddText);
}
}
- return 0;
+ return nullptr;
}
diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp
index 64a8e5d989..4b91c19761 100644
--- a/src/qt/notificator.cpp
+++ b/src/qt/notificator.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -39,7 +39,7 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon
mode(None),
trayIcon(_trayIcon)
#ifdef USE_DBUS
- ,interface(0)
+ ,interface(nullptr)
#endif
{
if(_trayIcon && _trayIcon->supportsMessages())
@@ -154,14 +154,14 @@ QVariant FreedesktopImage::toVariant(const QImage &img)
void Notificator::notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
{
- Q_UNUSED(cls);
- // Arguments for DBus call:
+ // https://developer.gnome.org/notification-spec/
+ // Arguments for DBus "Notify" call:
QList<QVariant> args;
// Program Name:
args.append(programName);
- // Unique ID of this notification type:
+ // Replaces ID; A value of 0 means that this notification won't replace any existing notifications:
args.append(0U);
// Application Icon, empty string
@@ -209,9 +209,8 @@ void Notificator::notifyDBus(Class cls, const QString &title, const QString &tex
}
#endif
-void Notificator::notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
+void Notificator::notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout)
{
- Q_UNUSED(icon);
QSystemTrayIcon::MessageIcon sicon = QSystemTrayIcon::NoIcon;
switch(cls) // Set icon based on class
{
@@ -222,13 +221,12 @@ void Notificator::notifySystray(Class cls, const QString &title, const QString &
trayIcon->showMessage(title, text, sicon, millisTimeout);
}
-// Based on Qt's tray icon implementation
#ifdef Q_OS_MAC
-void Notificator::notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon) {
+void Notificator::notifyMacUserNotificationCenter(const QString &title, const QString &text)
+{
// icon is not supported by the user notification center yet. OSX will use the app icon.
MacNotificationHandler::instance()->showNotification(title, text);
}
-
#endif
void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
@@ -241,11 +239,11 @@ void Notificator::notify(Class cls, const QString &title, const QString &text, c
break;
#endif
case QSystemTray:
- notifySystray(cls, title, text, icon, millisTimeout);
+ notifySystray(cls, title, text, millisTimeout);
break;
#ifdef Q_OS_MAC
case UserNotificationCenter:
- notifyMacUserNotificationCenter(cls, title, text, icon);
+ notifyMacUserNotificationCenter(title, text);
break;
#endif
default:
diff --git a/src/qt/notificator.h b/src/qt/notificator.h
index 3da24cd1a1..7d80b43e43 100644
--- a/src/qt/notificator.h
+++ b/src/qt/notificator.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -57,7 +57,7 @@ private:
enum Mode {
None, /**< Ignore informational notifications, and show a modal pop-up dialog for Critical notifications. */
Freedesktop, /**< Use DBus org.freedesktop.Notifications */
- QSystemTray, /**< Use QSystemTray::showMessage */
+ QSystemTray, /**< Use QSystemTrayIcon::showMessage() */
UserNotificationCenter /**< Use the 10.8+ User Notification Center (Mac only) */
};
QString programName;
@@ -68,9 +68,9 @@ private:
void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
#endif
- void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
+ void notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout);
#ifdef Q_OS_MAC
- void notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon);
+ void notifyMacUserNotificationCenter(const QString &title, const QString &text);
#endif
};
diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp
index d211f908c8..48db95679f 100644
--- a/src/qt/openuridialog.cpp
+++ b/src/qt/openuridialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index a57343f036..40dc7bf400 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,6 +10,7 @@
#include <qt/forms/ui_optionsdialog.h>
#include <qt/bitcoinunits.h>
+#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
@@ -23,30 +24,27 @@
#include <QIntValidator>
#include <QLocale>
#include <QMessageBox>
+#include <QSystemTrayIcon>
#include <QTimer>
OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
QDialog(parent),
ui(new Ui::OptionsDialog),
- model(0),
- mapper(0)
+ model(nullptr),
+ mapper(nullptr)
{
ui->setupUi(this);
/* Main elements init */
ui->databaseCache->setMinimum(nMinDbCache);
ui->databaseCache->setMaximum(nMaxDbCache);
- static const uint64_t GiB = 1024 * 1024 * 1024;
- static const uint64_t nMinDiskSpace = MIN_DISK_SPACE_FOR_BLOCK_FILES / GiB +
- (MIN_DISK_SPACE_FOR_BLOCK_FILES % GiB) ? 1 : 0;
- ui->pruneSize->setMinimum(nMinDiskSpace);
ui->threadsScriptVerif->setMinimum(-GetNumCores());
ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS);
ui->pruneWarning->setVisible(false);
ui->pruneWarning->setStyleSheet("QLabel { color: red; }");
ui->pruneSize->setEnabled(false);
- connect(ui->prune, SIGNAL(toggled(bool)), ui->pruneSize, SLOT(setEnabled(bool)));
+ connect(ui->prune, &QPushButton::toggled, ui->pruneSize, &QWidget::setEnabled);
/* Network elements init */
#ifndef USE_UPNP
@@ -61,18 +59,24 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
ui->proxyPortTor->setEnabled(false);
ui->proxyPortTor->setValidator(new QIntValidator(1, 65535, this));
- connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool)));
- connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool)));
- connect(ui->connectSocks, SIGNAL(toggled(bool)), this, SLOT(updateProxyValidationState()));
+ connect(ui->connectSocks, &QPushButton::toggled, ui->proxyIp, &QWidget::setEnabled);
+ connect(ui->connectSocks, &QPushButton::toggled, ui->proxyPort, &QWidget::setEnabled);
+ connect(ui->connectSocks, &QPushButton::toggled, this, &OptionsDialog::updateProxyValidationState);
- connect(ui->connectSocksTor, SIGNAL(toggled(bool)), ui->proxyIpTor, SLOT(setEnabled(bool)));
- connect(ui->connectSocksTor, SIGNAL(toggled(bool)), ui->proxyPortTor, SLOT(setEnabled(bool)));
- connect(ui->connectSocksTor, SIGNAL(toggled(bool)), this, SLOT(updateProxyValidationState()));
+ connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyIpTor, &QWidget::setEnabled);
+ connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyPortTor, &QWidget::setEnabled);
+ connect(ui->connectSocksTor, &QPushButton::toggled, this, &OptionsDialog::updateProxyValidationState);
/* Window elements init */
#ifdef Q_OS_MAC
/* remove Window tab on Mac */
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow));
+#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED > 101100
+ /* hide launch at startup option if compiled against macOS > 10.11 (removed API) */
+ ui->bitcoinAtStartup->setVisible(false);
+ ui->verticalLayout_Main->removeWidget(ui->bitcoinAtStartup);
+ ui->verticalLayout_Main->removeItem(ui->horizontalSpacer_0_Main);
+#endif
#endif
/* remove Wallet tab in case of -disablewallet */
@@ -115,13 +119,24 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
mapper->setOrientation(Qt::Vertical);
+ GUIUtil::ItemDelegate* delegate = new GUIUtil::ItemDelegate(mapper);
+ connect(delegate, &GUIUtil::ItemDelegate::keyEscapePressed, this, &OptionsDialog::reject);
+ mapper->setItemDelegate(delegate);
+
/* setup/change UI elements when proxy IPs are invalid/valid */
ui->proxyIp->setCheckValidator(new ProxyAddressValidator(parent));
ui->proxyIpTor->setCheckValidator(new ProxyAddressValidator(parent));
- connect(ui->proxyIp, SIGNAL(validationDidChange(QValidatedLineEdit *)), this, SLOT(updateProxyValidationState()));
- connect(ui->proxyIpTor, SIGNAL(validationDidChange(QValidatedLineEdit *)), this, SLOT(updateProxyValidationState()));
- connect(ui->proxyPort, SIGNAL(textChanged(const QString&)), this, SLOT(updateProxyValidationState()));
- connect(ui->proxyPortTor, SIGNAL(textChanged(const QString&)), this, SLOT(updateProxyValidationState()));
+ connect(ui->proxyIp, &QValidatedLineEdit::validationDidChange, this, &OptionsDialog::updateProxyValidationState);
+ connect(ui->proxyIpTor, &QValidatedLineEdit::validationDidChange, this, &OptionsDialog::updateProxyValidationState);
+ connect(ui->proxyPort, &QLineEdit::textChanged, this, &OptionsDialog::updateProxyValidationState);
+ connect(ui->proxyPortTor, &QLineEdit::textChanged, this, &OptionsDialog::updateProxyValidationState);
+
+ if (!QSystemTrayIcon::isSystemTrayAvailable()) {
+ ui->hideTrayIcon->setChecked(true);
+ ui->hideTrayIcon->setEnabled(false);
+ ui->minimizeToTray->setChecked(false);
+ ui->minimizeToTray->setEnabled(false);
+ }
}
OptionsDialog::~OptionsDialog()
@@ -139,6 +154,10 @@ void OptionsDialog::setModel(OptionsModel *_model)
if (_model->isRestartRequired())
showRestartWarning(true);
+ // Prune values are in GB to be consistent with intro.cpp
+ static constexpr uint64_t nMinDiskSpace = (MIN_DISK_SPACE_FOR_BLOCK_FILES / GB_BYTES) + (MIN_DISK_SPACE_FOR_BLOCK_FILES % GB_BYTES) ? 1 : 0;
+ ui->pruneSize->setRange(nMinDiskSpace, std::numeric_limits<int>::max());
+
QString strLabel = _model->getOverriddenByCommandLine();
if (strLabel.isEmpty())
strLabel = tr("none");
@@ -154,20 +173,30 @@ void OptionsDialog::setModel(OptionsModel *_model)
/* warn when one of the following settings changes by user action (placed here so init via mapper doesn't trigger them) */
/* Main */
- connect(ui->prune, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning()));
- connect(ui->prune, SIGNAL(clicked(bool)), this, SLOT(togglePruneWarning(bool)));
- connect(ui->pruneSize, SIGNAL(valueChanged(int)), this, SLOT(showRestartWarning()));
- connect(ui->databaseCache, SIGNAL(valueChanged(int)), this, SLOT(showRestartWarning()));
- connect(ui->threadsScriptVerif, SIGNAL(valueChanged(int)), this, SLOT(showRestartWarning()));
+ connect(ui->prune, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
+ connect(ui->prune, &QCheckBox::clicked, this, &OptionsDialog::togglePruneWarning);
+ connect(ui->pruneSize, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning);
+ connect(ui->databaseCache, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning);
+ connect(ui->threadsScriptVerif, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning);
/* Wallet */
- connect(ui->spendZeroConfChange, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning()));
+ connect(ui->spendZeroConfChange, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
/* Network */
- connect(ui->allowIncoming, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning()));
- connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning()));
- connect(ui->connectSocksTor, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning()));
+ connect(ui->allowIncoming, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
+ connect(ui->connectSocks, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
+ connect(ui->connectSocksTor, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning);
/* Display */
- connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning()));
- connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning()));
+ connect(ui->lang, static_cast<void (QValueComboBox::*)()>(&QValueComboBox::valueChanged), [this]{ showRestartWarning(); });
+ connect(ui->thirdPartyTxUrls, &QLineEdit::textChanged, [this]{ showRestartWarning(); });
+}
+
+void OptionsDialog::setCurrentTab(OptionsDialog::Tab tab)
+{
+ QWidget *tab_widget = nullptr;
+ if (tab == OptionsDialog::Tab::TAB_NETWORK) tab_widget = ui->tabNetwork;
+ if (tab == OptionsDialog::Tab::TAB_MAIN) tab_widget = ui->tabMain;
+ if (tab_widget && ui->tabWidget->currentWidget() != tab_widget) {
+ ui->tabWidget->setCurrentWidget(tab_widget);
+ }
}
void OptionsDialog::setMapper()
@@ -197,8 +226,10 @@ void OptionsDialog::setMapper()
/* Window */
#ifndef Q_OS_MAC
- mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon);
- mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
+ if (QSystemTrayIcon::isSystemTrayAvailable()) {
+ mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon);
+ mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
+ }
mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
#endif
@@ -286,7 +317,7 @@ void OptionsDialog::showRestartWarning(bool fPersistent)
ui->statusLabel->setText(tr("This change would require a client restart."));
// clear non-persistent status label after 10 seconds
// Todo: should perhaps be a class attribute, if we extend the use of statusLabel
- QTimer::singleShot(10000, this, SLOT(clearStatusLabel()));
+ QTimer::singleShot(10000, this, &OptionsDialog::clearStatusLabel);
}
}
diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h
index 54e1a8a9b1..9bc1c8ae4f 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -40,8 +40,14 @@ public:
explicit OptionsDialog(QWidget *parent, bool enableWallet);
~OptionsDialog();
+ enum Tab {
+ TAB_MAIN,
+ TAB_NETWORK,
+ };
+
void setModel(OptionsModel *model);
void setMapper();
+ void setCurrentTab(OptionsDialog::Tab tab);
private Q_SLOTS:
/* set OK button state (enabled / disabled) */
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 834ff7633c..5b4fb4cc18 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,6 +9,7 @@
#include <qt/optionsmodel.h>
#include <qt/bitcoinunits.h>
+#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <interfaces/node.h>
@@ -16,7 +17,6 @@
#include <net.h>
#include <netbase.h>
#include <txdb.h> // for -dbcache defaults
-#include <qt/intro.h>
#include <QNetworkProxy>
#include <QSettings>
@@ -92,10 +92,10 @@ void OptionsModel::Init(bool resetSettings)
settings.setValue("bPrune", false);
if (!settings.contains("nPruneSize"))
settings.setValue("nPruneSize", 2);
- // Convert prune size to MB:
- const uint64_t nPruneSizeMB = settings.value("nPruneSize").toInt() * 1000;
- if (!m_node.softSetArg("-prune", settings.value("bPrune").toBool() ? std::to_string(nPruneSizeMB) : "0")) {
- addOverriddenOption("-prune");
+ // Convert prune size from GB to MiB:
+ const uint64_t nPruneSizeMiB = (settings.value("nPruneSize").toInt() * GB_BYTES) >> 20;
+ if (!m_node.softSetArg("-prune", settings.value("bPrune").toBool() ? std::to_string(nPruneSizeMiB) : "0")) {
+ addOverriddenOption("-prune");
}
if (!settings.contains("nDatabaseCache"))
@@ -109,7 +109,7 @@ void OptionsModel::Init(bool resetSettings)
addOverriddenOption("-par");
if (!settings.contains("strDataDir"))
- settings.setValue("strDataDir", Intro::getDefaultDataDirectory());
+ settings.setValue("strDataDir", GUIUtil::getDefaultDataDirectory());
// Wallet
#ifdef ENABLE_WALLET
@@ -186,7 +186,7 @@ void OptionsModel::Reset()
BackupSettings(GetDataDir(true) / "guisettings.ini.bak", settings);
// Save the strDataDir setting
- QString dataDir = Intro::getDefaultDataDirectory();
+ QString dataDir = GUIUtil::getDefaultDataDirectory();
dataDir = settings.value("strDataDir", dataDir).toString();
// Remove all entries from our QSettings object
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 2777cbeaf2..1af3a72b92 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -31,7 +31,7 @@ class OptionsModel : public QAbstractListModel
Q_OBJECT
public:
- explicit OptionsModel(interfaces::Node& node, QObject *parent = 0, bool resetSettings = false);
+ explicit OptionsModel(interfaces::Node& node, QObject *parent = nullptr, bool resetSettings = false);
enum OptionID {
StartAtStartup, // bool
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index 8e8788dad3..d8e48f350a 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -113,8 +113,8 @@ public:
OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent),
ui(new Ui::OverviewPage),
- clientModel(0),
- walletModel(0),
+ clientModel(nullptr),
+ walletModel(nullptr),
txdelegate(new TxViewDelegate(platformStyle, this))
{
ui->setupUi(this);
@@ -133,12 +133,12 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent)
ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
- connect(ui->listTransactions, SIGNAL(clicked(QModelIndex)), this, SLOT(handleTransactionClicked(QModelIndex)));
+ connect(ui->listTransactions, &QListView::clicked, this, &OverviewPage::handleTransactionClicked);
// start with displaying the "out of sync" warnings
showOutOfSyncWarning(true);
- connect(ui->labelWalletStatus, SIGNAL(clicked()), this, SLOT(handleOutOfSyncWarningClicks()));
- connect(ui->labelTransactionsStatus, SIGNAL(clicked()), this, SLOT(handleOutOfSyncWarningClicks()));
+ connect(ui->labelWalletStatus, &QPushButton::clicked, this, &OverviewPage::handleOutOfSyncWarningClicks);
+ connect(ui->labelTransactionsStatus, &QPushButton::clicked, this, &OverviewPage::handleOutOfSyncWarningClicks);
}
void OverviewPage::handleTransactionClicked(const QModelIndex &index)
@@ -161,15 +161,21 @@ void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
{
int unit = walletModel->getOptionsModel()->getDisplayUnit();
m_balances = balances;
- ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.balance, false, BitcoinUnits::separatorAlways));
- ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_balance, false, BitcoinUnits::separatorAlways));
- ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_balance, false, BitcoinUnits::separatorAlways));
- ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, false, BitcoinUnits::separatorAlways));
- ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
- ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
-
+ if (walletModel->privateKeysDisabled()) {
+ ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ } else {
+ ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.balance, false, BitcoinUnits::separatorAlways));
+ ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
+ }
// only show immature (newly mined) balance if it's non-zero, so as not to complicate things
// for the non-mining users
bool showImmature = balances.immature_balance != 0;
@@ -178,7 +184,7 @@ void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
// for symmetry reasons also show immature label when the watch-only one is shown
ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
- ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watch-only immature balance
+ ui->labelWatchImmature->setVisible(!walletModel->privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
}
// show/hide watch-only labels
@@ -201,7 +207,7 @@ void OverviewPage::setClientModel(ClientModel *model)
if(model)
{
// Show warning if this is a prerelease version
- connect(model, SIGNAL(alertsChanged(QString)), this, SLOT(updateAlerts(QString)));
+ connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts);
updateAlerts(model->getStatusBarWarnings());
}
}
@@ -227,12 +233,14 @@ void OverviewPage::setWalletModel(WalletModel *model)
interfaces::Wallet& wallet = model->wallet();
interfaces::WalletBalances balances = wallet.getBalances();
setBalance(balances);
- connect(model, SIGNAL(balanceChanged(interfaces::WalletBalances)), this, SLOT(setBalance(interfaces::WalletBalances)));
+ connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
- connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
+ connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit);
- updateWatchOnlyLabels(wallet.haveWatchOnly());
- connect(model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyLabels(bool)));
+ updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->privateKeysDisabled());
+ connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
+ updateWatchOnlyLabels(showWatchOnly && !walletModel->privateKeysDisabled());
+ });
}
// update the display unit, to not use the default ("BTC")
diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h
index d519eca43a..00ba7ad4ce 100644
--- a/src/qt/overviewpage.h
+++ b/src/qt/overviewpage.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -30,7 +30,7 @@ class OverviewPage : public QWidget
Q_OBJECT
public:
- explicit OverviewPage(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit OverviewPage(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~OverviewPage();
void setClientModel(ClientModel *clientModel);
diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp
index dfeb70d669..b962ab1ef2 100644
--- a/src/qt/paymentrequestplus.cpp
+++ b/src/qt/paymentrequestplus.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <qt/paymentrequestplus.h>
-#include <util.h>
+#include <util/system.h>
#include <stdexcept>
@@ -142,7 +142,6 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
if (result != 1) {
int error = X509_STORE_CTX_get_error(store_ctx);
// For testing payment requests, we allow self signed root certs!
- // This option is just shown in the UI options, if -help-debug is enabled.
if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && gArgs.GetBoolArg("-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) {
throw SSLVerifyError(X509_verify_cert_error_string(error));
} else {
diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h
index b1b60cf582..3014628807 100644
--- a/src/qt/paymentrequestplus.h
+++ b/src/qt/paymentrequestplus.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index e5e6430959..43dccec4ea 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -1,7 +1,11 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/paymentserver.h>
#include <qt/bitcoinunits.h>
@@ -13,7 +17,7 @@
#include <policy/policy.h>
#include <key_io.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <wallet/wallet.h>
#include <cstdlib>
@@ -45,6 +49,7 @@
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
const QString BITCOIN_IPC_PREFIX("bitcoin:");
+#ifdef ENABLE_BIP70
// BIP70 payment protocol messages
const char* BIP70_MESSAGE_PAYMENTACK = "PaymentACK";
const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
@@ -52,21 +57,7 @@ const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
const char* BIP71_MIMETYPE_PAYMENT = "application/bitcoin-payment";
const char* BIP71_MIMETYPE_PAYMENTACK = "application/bitcoin-paymentack";
const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/bitcoin-paymentrequest";
-
-struct X509StoreDeleter {
- void operator()(X509_STORE* b) {
- X509_STORE_free(b);
- }
-};
-
-struct X509Deleter {
- void operator()(X509* b) { X509_free(b); }
-};
-
-namespace // Anon namespace
-{
- std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;
-}
+#endif
//
// Create a name that is unique for:
@@ -93,94 +84,6 @@ static QString ipcServerName()
static QList<QString> savedPaymentRequests;
-static void ReportInvalidCertificate(const QSslCertificate& cert)
-{
- qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
-}
-
-//
-// Load OpenSSL's list of root certificate authorities
-//
-void PaymentServer::LoadRootCAs(X509_STORE* _store)
-{
- // Unit tests mostly use this, to pass in fake root CAs:
- if (_store)
- {
- certStore.reset(_store);
- return;
- }
-
- // Normal execution, use either -rootcertificates or system certs:
- certStore.reset(X509_STORE_new());
-
- // Note: use "-system-" default here so that users can pass -rootcertificates=""
- // and get 'I don't like X.509 certificates, don't trust anybody' behavior:
- QString certFile = QString::fromStdString(gArgs.GetArg("-rootcertificates", "-system-"));
-
- // Empty store
- if (certFile.isEmpty()) {
- qDebug() << QString("PaymentServer::%1: Payment request authentication via X.509 certificates disabled.").arg(__func__);
- return;
- }
-
- QList<QSslCertificate> certList;
-
- if (certFile != "-system-") {
- qDebug() << QString("PaymentServer::%1: Using \"%2\" as trusted root certificate.").arg(__func__).arg(certFile);
-
- certList = QSslCertificate::fromPath(certFile);
- // Use those certificates when fetching payment requests, too:
- QSslSocket::setDefaultCaCertificates(certList);
- } else
- certList = QSslSocket::systemCaCertificates();
-
- int nRootCerts = 0;
- const QDateTime currentTime = QDateTime::currentDateTime();
-
- for (const QSslCertificate& cert : certList) {
- // Don't log NULL certificates
- if (cert.isNull())
- continue;
-
- // Not yet active/valid, or expired certificate
- if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) {
- ReportInvalidCertificate(cert);
- continue;
- }
-
- // Blacklisted certificate
- if (cert.isBlacklisted()) {
- ReportInvalidCertificate(cert);
- continue;
- }
- QByteArray certData = cert.toDer();
- const unsigned char *data = (const unsigned char *)certData.data();
-
- std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size()));
- if (x509 && X509_STORE_add_cert(certStore.get(), x509.get()))
- {
- // Note: X509_STORE increases the reference count to the X509 object,
- // we still have to release our reference to it.
- ++nRootCerts;
- }
- else
- {
- ReportInvalidCertificate(cert);
- continue;
- }
- }
- qWarning() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates";
-
- // Project for another day:
- // Fetch certificate revocation lists, and add them to certStore.
- // Issues to consider:
- // performance (start a thread to fetch in background?)
- // privacy (fetch through tor/proxy so IP address isn't revealed)
- // would it be easier to just use a compiled-in blacklist?
- // or use Qt's blacklist?
- // "certificate stapling" with server-side caching is more efficient
-}
-
//
// Sending to the server is done synchronously, at startup.
// If the server isn't already running, startup continues,
@@ -221,6 +124,7 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
}
}
}
+#ifdef ENABLE_BIP70
else if (QFile::exists(arg)) // Filename
{
savedPaymentRequests.append(arg);
@@ -244,6 +148,7 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
// GUI hasn't started yet so we can't pop up a message box.
qWarning() << "PaymentServer::ipcSendCommandLine: Payment request file does not exist: " << arg;
}
+#endif
}
}
@@ -289,13 +194,17 @@ bool PaymentServer::ipcSendCommandLine()
PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
QObject(parent),
saveURIs(true),
- uriServer(0),
- netManager(0),
- optionsModel(0)
+ uriServer(nullptr),
+ optionsModel(nullptr)
+#ifdef ENABLE_BIP70
+ ,netManager(nullptr)
+#endif
{
+#ifdef ENABLE_BIP70
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
+#endif
// Install global event filter to catch QFileOpenEvents
// on Mac: sent when you click bitcoin: links
@@ -314,19 +223,23 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
if (!uriServer->listen(name)) {
// constructor is called early in init, so don't use "Q_EMIT message()" here
- QMessageBox::critical(0, tr("Payment request error"),
+ QMessageBox::critical(nullptr, tr("Payment request error"),
tr("Cannot start bitcoin: click-to-pay handler"));
}
else {
- connect(uriServer, SIGNAL(newConnection()), this, SLOT(handleURIConnection()));
- connect(this, SIGNAL(receivedPaymentACK(QString)), this, SLOT(handlePaymentACK(QString)));
+ connect(uriServer, &QLocalServer::newConnection, this, &PaymentServer::handleURIConnection);
+#ifdef ENABLE_BIP70
+ connect(this, &PaymentServer::receivedPaymentACK, this, &PaymentServer::handlePaymentACK);
+#endif
}
}
}
PaymentServer::~PaymentServer()
{
+#ifdef ENABLE_BIP70
google::protobuf::ShutdownProtobufLibrary();
+#endif
}
//
@@ -349,35 +262,11 @@ bool PaymentServer::eventFilter(QObject *object, QEvent *event)
return QObject::eventFilter(object, event);
}
-void PaymentServer::initNetManager()
-{
- if (!optionsModel)
- return;
- delete netManager;
-
- // netManager is used to fetch paymentrequests given in bitcoin: URIs
- netManager = new QNetworkAccessManager(this);
-
- QNetworkProxy proxy;
-
- // Query active SOCKS5 proxy
- if (optionsModel->getProxySettings(proxy)) {
- netManager->setProxy(proxy);
-
- qDebug() << "PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
- }
- else
- qDebug() << "PaymentServer::initNetManager: No active proxy server found.";
-
- connect(netManager, SIGNAL(finished(QNetworkReply*)),
- this, SLOT(netRequestFinished(QNetworkReply*)));
- connect(netManager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError> &)),
- this, SLOT(reportSslErrors(QNetworkReply*, const QList<QSslError> &)));
-}
-
void PaymentServer::uiReady()
{
+#ifdef ENABLE_BIP70
initNetManager();
+#endif
saveURIs = false;
for (const QString& s : savedPaymentRequests)
@@ -403,8 +292,12 @@ void PaymentServer::handleURIOrFile(const QString& s)
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
{
QUrlQuery uri((QUrl(s)));
+#ifdef ENABLE_BIP70
if (uri.hasQueryItem("r")) // payment request URI
{
+ Q_EMIT message(tr("URI handling"),
+ tr("You are using a BIP70 URL which will be unsupported in the future."),
+ CClientUIInterface::ICON_WARNING);
QByteArray temp;
temp.append(uri.queryItemValue("r"));
QString decoded = QUrl::fromPercentEncoding(temp);
@@ -422,15 +315,23 @@ void PaymentServer::handleURIOrFile(const QString& s)
tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
CClientUIInterface::ICON_WARNING);
}
-
return;
}
- else // normal URI
+ else
+#endif
+ // normal URI
{
SendCoinsRecipient recipient;
if (GUIUtil::parseBitcoinURI(s, &recipient))
{
if (!IsValidDestinationString(recipient.address.toStdString())) {
+#ifndef ENABLE_BIP70
+ if (uri.hasQueryItem("r")) { // payment request
+ Q_EMIT message(tr("URI handling"),
+ tr("Cannot process payment request because BIP70 support was not compiled in."),
+ CClientUIInterface::ICON_WARNING);
+ }
+#endif
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
CClientUIInterface::MSG_ERROR);
}
@@ -448,6 +349,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (QFile::exists(s)) // payment request file
{
+#ifdef ENABLE_BIP70
PaymentRequestPlus request;
SendCoinsRecipient recipient;
if (!readPaymentRequestFromFile(s, request))
@@ -460,6 +362,11 @@ void PaymentServer::handleURIOrFile(const QString& s)
Q_EMIT receivedPaymentRequest(recipient);
return;
+#else
+ Q_EMIT message(tr("Payment request file handling"),
+ tr("Cannot process payment request because BIP70 support was not compiled in."),
+ CClientUIInterface::ICON_WARNING);
+#endif
}
}
@@ -470,8 +377,7 @@ void PaymentServer::handleURIConnection()
while (clientConnection->bytesAvailable() < (int)sizeof(quint32))
clientConnection->waitForReadyRead();
- connect(clientConnection, SIGNAL(disconnected()),
- clientConnection, SLOT(deleteLater()));
+ connect(clientConnection, &QLocalSocket::disconnected, clientConnection, &QLocalSocket::deleteLater);
QDataStream in(clientConnection);
in.setVersion(QDataStream::Qt_4_0);
@@ -484,6 +390,140 @@ void PaymentServer::handleURIConnection()
handleURIOrFile(msg);
}
+void PaymentServer::setOptionsModel(OptionsModel *_optionsModel)
+{
+ this->optionsModel = _optionsModel;
+}
+
+#ifdef ENABLE_BIP70
+struct X509StoreDeleter {
+ void operator()(X509_STORE* b) {
+ X509_STORE_free(b);
+ }
+};
+
+struct X509Deleter {
+ void operator()(X509* b) { X509_free(b); }
+};
+
+namespace // Anon namespace
+{
+ std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;
+}
+
+static void ReportInvalidCertificate(const QSslCertificate& cert)
+{
+ qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
+}
+
+//
+// Load OpenSSL's list of root certificate authorities
+//
+void PaymentServer::LoadRootCAs(X509_STORE* _store)
+{
+ // Unit tests mostly use this, to pass in fake root CAs:
+ if (_store)
+ {
+ certStore.reset(_store);
+ return;
+ }
+
+ // Normal execution, use either -rootcertificates or system certs:
+ certStore.reset(X509_STORE_new());
+
+ // Note: use "-system-" default here so that users can pass -rootcertificates=""
+ // and get 'I don't like X.509 certificates, don't trust anybody' behavior:
+ QString certFile = QString::fromStdString(gArgs.GetArg("-rootcertificates", "-system-"));
+
+ // Empty store
+ if (certFile.isEmpty()) {
+ qDebug() << QString("PaymentServer::%1: Payment request authentication via X.509 certificates disabled.").arg(__func__);
+ return;
+ }
+
+ QList<QSslCertificate> certList;
+
+ if (certFile != "-system-") {
+ qDebug() << QString("PaymentServer::%1: Using \"%2\" as trusted root certificate.").arg(__func__).arg(certFile);
+
+ certList = QSslCertificate::fromPath(certFile);
+ // Use those certificates when fetching payment requests, too:
+ QSslSocket::setDefaultCaCertificates(certList);
+ } else
+ certList = QSslSocket::systemCaCertificates();
+
+ int nRootCerts = 0;
+ const QDateTime currentTime = QDateTime::currentDateTime();
+
+ for (const QSslCertificate& cert : certList) {
+ // Don't log NULL certificates
+ if (cert.isNull())
+ continue;
+
+ // Not yet active/valid, or expired certificate
+ if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) {
+ ReportInvalidCertificate(cert);
+ continue;
+ }
+
+ // Blacklisted certificate
+ if (cert.isBlacklisted()) {
+ ReportInvalidCertificate(cert);
+ continue;
+ }
+
+ QByteArray certData = cert.toDer();
+ const unsigned char *data = (const unsigned char *)certData.data();
+
+ std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size()));
+ if (x509 && X509_STORE_add_cert(certStore.get(), x509.get()))
+ {
+ // Note: X509_STORE increases the reference count to the X509 object,
+ // we still have to release our reference to it.
+ ++nRootCerts;
+ }
+ else
+ {
+ ReportInvalidCertificate(cert);
+ continue;
+ }
+ }
+ qWarning() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates";
+
+ // Project for another day:
+ // Fetch certificate revocation lists, and add them to certStore.
+ // Issues to consider:
+ // performance (start a thread to fetch in background?)
+ // privacy (fetch through tor/proxy so IP address isn't revealed)
+ // would it be easier to just use a compiled-in blacklist?
+ // or use Qt's blacklist?
+ // "certificate stapling" with server-side caching is more efficient
+}
+
+void PaymentServer::initNetManager()
+{
+ if (!optionsModel)
+ return;
+ delete netManager;
+
+ // netManager is used to fetch paymentrequests given in bitcoin: URIs
+ netManager = new QNetworkAccessManager(this);
+
+ QNetworkProxy proxy;
+
+ // Query active SOCKS5 proxy
+ if (optionsModel->getProxySettings(proxy)) {
+ netManager->setProxy(proxy);
+
+ qDebug() << "PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
+ }
+ else
+ qDebug() << "PaymentServer::initNetManager: No active proxy server found.";
+
+ connect(netManager, &QNetworkAccessManager::finished, this, &PaymentServer::netRequestFinished);
+ connect(netManager, &QNetworkAccessManager::sslErrors, this, &PaymentServer::reportSslErrors);
+}
+
//
// Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine()
// so don't use "Q_EMIT message()", but "QMessageBox::"!
@@ -734,11 +774,6 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
}
-void PaymentServer::setOptionsModel(OptionsModel *_optionsModel)
-{
- this->optionsModel = _optionsModel;
-}
-
void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
{
// currently we don't further process or store the paymentACK message
@@ -797,3 +832,4 @@ X509_STORE* PaymentServer::getCertStore()
{
return certStore.get();
}
+#endif
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index 511fc5bd6e..30b5bc3b6d 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -32,7 +32,13 @@
// sends them to the server.
//
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#ifdef ENABLE_BIP70
#include <qt/paymentrequestplus.h>
+#endif
#include <qt/walletmodel.h>
#include <QObject>
@@ -73,6 +79,10 @@ public:
explicit PaymentServer(QObject* parent, bool startLocalServer = true);
~PaymentServer();
+ // OptionsModel is used for getting proxy settings and display unit
+ void setOptionsModel(OptionsModel *optionsModel);
+
+#ifdef ENABLE_BIP70
// Load root certificate authorities. Pass nullptr (default)
// to read from the file specified in the -rootcertificates setting,
// or, if that's not set, to use the system default root certificates.
@@ -83,9 +93,6 @@ public:
// Return certificate store
static X509_STORE* getCertStore();
- // OptionsModel is used for getting proxy settings and display unit
- void setOptionsModel(OptionsModel *optionsModel);
-
// Verify that the payment request network matches the client network
static bool verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails);
// Verify if the payment request is expired
@@ -94,33 +101,40 @@ public:
static bool verifySize(qint64 requestSize);
// Verify the payment request amount is valid
static bool verifyAmount(const CAmount& requestAmount);
+#endif
Q_SIGNALS:
// Fired when a valid payment request is received
void receivedPaymentRequest(SendCoinsRecipient);
- // Fired when a valid PaymentACK is received
- void receivedPaymentACK(const QString &paymentACKMsg);
-
// Fired when a message should be reported to the user
void message(const QString &title, const QString &message, unsigned int style);
+#ifdef ENABLE_BIP70
+ // Fired when a valid PaymentACK is received
+ void receivedPaymentACK(const QString &paymentACKMsg);
+#endif
+
public Q_SLOTS:
// Signal this when the main window's UI is ready
// to display payment requests to the user
void uiReady();
- // Submit Payment message to a merchant, get back PaymentACK:
- void fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction);
-
// Handle an incoming URI, URI with local file scheme or file
void handleURIOrFile(const QString& s);
+#ifdef ENABLE_BIP70
+ // Submit Payment message to a merchant, get back PaymentACK:
+ void fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction);
+#endif
+
private Q_SLOTS:
void handleURIConnection();
+#ifdef ENABLE_BIP70
void netRequestFinished(QNetworkReply*);
void reportSslErrors(QNetworkReply*, const QList<QSslError> &);
void handlePaymentACK(const QString& paymentACKMsg);
+#endif
protected:
// Constructor registers this on the parent QApplication to
@@ -128,19 +142,19 @@ protected:
bool eventFilter(QObject *object, QEvent *event);
private:
+ bool saveURIs; // true during startup
+ QLocalServer* uriServer;
+ OptionsModel *optionsModel;
+
+#ifdef ENABLE_BIP70
static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request);
bool processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient);
void fetchRequest(const QUrl& url);
// Setup networking
void initNetManager();
-
- bool saveURIs; // true during startup
- QLocalServer* uriServer;
-
QNetworkAccessManager* netManager; // Used to fetch payment requests
-
- OptionsModel *optionsModel;
+#endif
};
#endif // BITCOIN_QT_PAYMENTSERVER_H
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 1c90504e9e..496aeebf7d 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -49,8 +49,8 @@ class PeerTablePriv
public:
/** Local cache of peer information */
QList<CNodeCombinedStats> cachedNodeStats;
- /** Column to sort nodes by */
- int sortColumn;
+ /** Column to sort nodes by (default to unsorted) */
+ int sortColumn{-1};
/** Order (ascending or descending) to sort nodes by */
Qt::SortOrder sortOrder;
/** Index of rows by node ID */
@@ -65,7 +65,7 @@ public:
interfaces::Node::NodesStats nodes_stats;
node.getNodesStats(nodes_stats);
cachedNodeStats.reserve(nodes_stats.size());
- for (auto& node_stats : nodes_stats)
+ for (const auto& node_stats : nodes_stats)
{
CNodeCombinedStats stats;
stats.nodeStats = std::get<0>(node_stats);
@@ -96,7 +96,7 @@ public:
if (idx >= 0 && idx < cachedNodeStats.size())
return &cachedNodeStats[idx];
- return 0;
+ return nullptr;
}
};
@@ -104,16 +104,14 @@ PeerTableModel::PeerTableModel(interfaces::Node& node, ClientModel *parent) :
QAbstractTableModel(parent),
m_node(node),
clientModel(parent),
- timer(0)
+ timer(nullptr)
{
columns << tr("NodeId") << tr("Node/Service") << tr("Ping") << tr("Sent") << tr("Received") << tr("User Agent");
priv.reset(new PeerTablePriv());
- // default to unsorted
- priv->sortColumn = -1;
// set up timer for auto refresh
timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), SLOT(refresh()));
+ connect(timer, &QTimer::timeout, this, &PeerTableModel::refresh);
timer->setInterval(MODEL_UPDATE_DELAY);
// load initial data
@@ -199,8 +197,7 @@ QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, in
Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
{
- if(!index.isValid())
- return 0;
+ if (!index.isValid()) return Qt::NoItemFlags;
Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return retval;
diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h
index 69c9744c8f..b3f5dd7dbe 100644
--- a/src/qt/peertablemodel.h
+++ b/src/qt/peertablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -51,7 +51,7 @@ class PeerTableModel : public QAbstractTableModel
Q_OBJECT
public:
- explicit PeerTableModel(interfaces::Node& node, ClientModel *parent = 0);
+ explicit PeerTableModel(interfaces::Node& node, ClientModel *parent = nullptr);
~PeerTableModel();
const CNodeCombinedStats *getNodeStats(int idx);
int getRowByNodeId(NodeId nodeid);
diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp
index a3a10aac18..d537d759de 100644
--- a/src/qt/platformstyle.cpp
+++ b/src/qt/platformstyle.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -139,6 +139,6 @@ const PlatformStyle *PlatformStyle::instantiate(const QString &platformId)
platform_styles[x].useExtraSpacing);
}
}
- return 0;
+ return nullptr;
}
diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp
new file mode 100644
index 0000000000..bf1baf5470
--- /dev/null
+++ b/src/qt/qrimagewidget.cpp
@@ -0,0 +1,141 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <qt/qrimagewidget.h>
+
+#include <qt/guiutil.h>
+
+#include <QApplication>
+#include <QClipboard>
+#include <QDrag>
+#include <QMenu>
+#include <QMimeData>
+#include <QMouseEvent>
+#include <QPainter>
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h> /* for USE_QRCODE */
+#endif
+
+#ifdef USE_QRCODE
+#include <qrencode.h>
+#endif
+
+QRImageWidget::QRImageWidget(QWidget *parent):
+ QLabel(parent), contextMenu(nullptr)
+{
+ contextMenu = new QMenu(this);
+ QAction *saveImageAction = new QAction(tr("&Save Image..."), this);
+ connect(saveImageAction, &QAction::triggered, this, &QRImageWidget::saveImage);
+ contextMenu->addAction(saveImageAction);
+ QAction *copyImageAction = new QAction(tr("&Copy Image"), this);
+ connect(copyImageAction, &QAction::triggered, this, &QRImageWidget::copyImage);
+ contextMenu->addAction(copyImageAction);
+}
+
+bool QRImageWidget::setQR(const QString& data, const QString& text)
+{
+#ifdef USE_QRCODE
+ setText("");
+ if (data.isEmpty()) return false;
+
+ // limit length
+ if (data.length() > MAX_URI_LENGTH) {
+ setText(tr("Resulting URI too long, try to reduce the text for label / message."));
+ return false;
+ }
+
+ QRcode *code = QRcode_encodeString(data.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
+
+ if (!code) {
+ setText(tr("Error encoding URI into QR Code."));
+ return false;
+ }
+
+ QImage qrImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
+ qrImage.fill(0xffffff);
+ unsigned char *p = code->data;
+ for (int y = 0; y < code->width; ++y) {
+ for (int x = 0; x < code->width; ++x) {
+ qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
+ ++p;
+ }
+ }
+ QRcode_free(code);
+
+ QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE + (text.isEmpty() ? 0 : 20), QImage::Format_RGB32);
+ qrAddrImage.fill(0xffffff);
+ QPainter painter(&qrAddrImage);
+ painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));
+
+ if (!text.isEmpty()) {
+ QFont font = GUIUtil::fixedPitchFont();
+ QRect paddedRect = qrAddrImage.rect();
+
+ // calculate ideal font size
+ qreal font_size = GUIUtil::calculateIdealFontSize(paddedRect.width() - 20, text, font);
+ font.setPointSizeF(font_size);
+
+ painter.setFont(font);
+ paddedRect.setHeight(QR_IMAGE_SIZE+12);
+ painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, text);
+ }
+
+ painter.end();
+ setPixmap(QPixmap::fromImage(qrAddrImage));
+
+ return true;
+#else
+ setText(tr("QR code support not available."));
+ return false;
+#endif
+}
+
+QImage QRImageWidget::exportImage()
+{
+ if(!pixmap())
+ return QImage();
+ return pixmap()->toImage();
+}
+
+void QRImageWidget::mousePressEvent(QMouseEvent *event)
+{
+ if(event->button() == Qt::LeftButton && pixmap())
+ {
+ event->accept();
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setImageData(exportImage());
+
+ QDrag *drag = new QDrag(this);
+ drag->setMimeData(mimeData);
+ drag->exec();
+ } else {
+ QLabel::mousePressEvent(event);
+ }
+}
+
+void QRImageWidget::saveImage()
+{
+ if(!pixmap())
+ return;
+ QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr);
+ if (!fn.isEmpty())
+ {
+ exportImage().save(fn);
+ }
+}
+
+void QRImageWidget::copyImage()
+{
+ if(!pixmap())
+ return;
+ QApplication::clipboard()->setImage(exportImage());
+}
+
+void QRImageWidget::contextMenuEvent(QContextMenuEvent *event)
+{
+ if(!pixmap())
+ return;
+ contextMenu->exec(event->globalPos());
+}
diff --git a/src/qt/qrimagewidget.h b/src/qt/qrimagewidget.h
new file mode 100644
index 0000000000..2a219ac101
--- /dev/null
+++ b/src/qt/qrimagewidget.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_QT_QRIMAGEWIDGET_H
+#define BITCOIN_QT_QRIMAGEWIDGET_H
+
+#include <QImage>
+#include <QLabel>
+
+/* Maximum allowed URI length */
+static const int MAX_URI_LENGTH = 255;
+
+/* Size of exported QR Code image */
+static const int QR_IMAGE_SIZE = 300;
+
+QT_BEGIN_NAMESPACE
+class QMenu;
+QT_END_NAMESPACE
+
+/* Label widget for QR code. This image can be dragged, dropped, copied and saved
+ * to disk.
+ */
+class QRImageWidget : public QLabel
+{
+ Q_OBJECT
+
+public:
+ explicit QRImageWidget(QWidget *parent = nullptr);
+ bool setQR(const QString& data, const QString& text = "");
+ QImage exportImage();
+
+public Q_SLOTS:
+ void saveImage();
+ void copyImage();
+
+protected:
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void contextMenuEvent(QContextMenuEvent *event);
+
+private:
+ QMenu *contextMenu;
+};
+
+#endif // BITCOIN_QT_QRIMAGEWIDGET_H
diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp
index 8a13cd340f..aa936d6b7c 100644
--- a/src/qt/qvalidatedlineedit.cpp
+++ b/src/qt/qvalidatedlineedit.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,9 +10,9 @@
QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) :
QLineEdit(parent),
valid(true),
- checkValidator(0)
+ checkValidator(nullptr)
{
- connect(this, SIGNAL(textChanged(QString)), this, SLOT(markValid()));
+ connect(this, &QValidatedLineEdit::textChanged, this, &QValidatedLineEdit::markValid);
}
void QValidatedLineEdit::setValid(bool _valid)
diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h
index 9ad9e66ae2..815d5e0040 100644
--- a/src/qt/qvalidatedlineedit.h
+++ b/src/qt/qvalidatedlineedit.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2015 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp
index 72c3a9d835..76f94ecf85 100644
--- a/src/qt/qvaluecombobox.cpp
+++ b/src/qt/qvaluecombobox.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,7 +7,7 @@
QValueComboBox::QValueComboBox(QWidget *parent) :
QComboBox(parent), role(Qt::UserRole)
{
- connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(handleSelectionChanged(int)));
+ connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &QValueComboBox::handleSelectionChanged);
}
QVariant QValueComboBox::value() const
diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h
index f266302310..8892071fba 100644
--- a/src/qt/qvaluecombobox.h
+++ b/src/qt/qvaluecombobox.h
@@ -16,7 +16,7 @@ class QValueComboBox : public QComboBox
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged USER true)
public:
- explicit QValueComboBox(QWidget *parent = 0);
+ explicit QValueComboBox(QWidget *parent = nullptr);
QVariant value() const;
void setValue(const QVariant &value);
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index 8c430e0af1..fc58090dcd 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -25,8 +25,8 @@
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::ReceiveCoinsDialog),
- columnResizingFixer(0),
- model(0),
+ columnResizingFixer(nullptr),
+ model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
@@ -57,13 +57,13 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWid
contextMenu->addAction(copyAmountAction);
// context menu signals
- connect(ui->recentRequestsView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint)));
- connect(copyURIAction, SIGNAL(triggered()), this, SLOT(copyURI()));
- connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
- connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
- connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
+ connect(ui->recentRequestsView, &QWidget::customContextMenuRequested, this, &ReceiveCoinsDialog::showMenu);
+ connect(copyURIAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyURI);
+ connect(copyLabelAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyLabel);
+ connect(copyMessageAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyMessage);
+ connect(copyAmountAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyAmount);
- connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
+ connect(ui->clearButton, &QPushButton::clicked, this, &ReceiveCoinsDialog::clear);
}
void ReceiveCoinsDialog::setModel(WalletModel *_model)
@@ -73,7 +73,7 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
if(_model && _model->getOptionsModel())
{
_model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
- connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
+ connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &ReceiveCoinsDialog::updateDisplayUnit);
updateDisplayUnit();
QTableView* tableView = ui->recentRequestsView;
@@ -89,19 +89,24 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
tableView->setColumnWidth(RecentRequestsTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
connect(tableView->selectionModel(),
- SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
- SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection)));
+ &QItemSelectionModel::selectionChanged, this,
+ &ReceiveCoinsDialog::recentRequestsView_selectionChanged);
// Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this);
if (model->wallet().getDefaultAddressType() == OutputType::BECH32) {
- ui->useBech32->setCheckState(Qt::Checked);
+ ui->useLegacyAddress->setCheckState(Qt::Unchecked);
} else {
- ui->useBech32->setCheckState(Qt::Unchecked);
+ ui->useLegacyAddress->setCheckState(Qt::Checked);
}
- // eventually disable the main receive button if private key operations are disabled
- ui->receiveButton->setEnabled(!model->privateKeysDisabled());
+ // Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
+ ui->receiveButton->setEnabled(model->canGetAddresses());
+
+ // Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
+ connect(model, &WalletModel::canGetAddressesChanged, [this] {
+ ui->receiveButton->setEnabled(model->canGetAddresses());
+ });
}
}
@@ -145,7 +150,7 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
QString label = ui->reqLabel->text();
/* Generate new receiving address */
OutputType address_type;
- if (ui->useBech32->isChecked()) {
+ if (!ui->useLegacyAddress->isChecked()) {
address_type = OutputType::BECH32;
} else {
address_type = model->wallet().getDefaultAddressType();
diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h
index 931f5aa101..5bca2f46e2 100644
--- a/src/qt/receivecoinsdialog.h
+++ b/src/qt/receivecoinsdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -39,7 +39,7 @@ public:
MINIMUM_COLUMN_WIDTH = 130
};
- explicit ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~ReceiveCoinsDialog();
void setModel(WalletModel *model);
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index f9610f2d3b..20b29145a0 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,89 +6,21 @@
#include <qt/forms/ui_receiverequestdialog.h>
#include <qt/bitcoinunits.h>
-#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
+#include <qt/qrimagewidget.h>
#include <QClipboard>
-#include <QDrag>
-#include <QMenu>
-#include <QMimeData>
-#include <QMouseEvent>
#include <QPixmap>
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h> /* for USE_QRCODE */
#endif
-#ifdef USE_QRCODE
-#include <qrencode.h>
-#endif
-
-QRImageWidget::QRImageWidget(QWidget *parent):
- QLabel(parent), contextMenu(0)
-{
- contextMenu = new QMenu(this);
- QAction *saveImageAction = new QAction(tr("&Save Image..."), this);
- connect(saveImageAction, SIGNAL(triggered()), this, SLOT(saveImage()));
- contextMenu->addAction(saveImageAction);
- QAction *copyImageAction = new QAction(tr("&Copy Image"), this);
- connect(copyImageAction, SIGNAL(triggered()), this, SLOT(copyImage()));
- contextMenu->addAction(copyImageAction);
-}
-
-QImage QRImageWidget::exportImage()
-{
- if(!pixmap())
- return QImage();
- return pixmap()->toImage();
-}
-
-void QRImageWidget::mousePressEvent(QMouseEvent *event)
-{
- if(event->button() == Qt::LeftButton && pixmap())
- {
- event->accept();
- QMimeData *mimeData = new QMimeData;
- mimeData->setImageData(exportImage());
-
- QDrag *drag = new QDrag(this);
- drag->setMimeData(mimeData);
- drag->exec();
- } else {
- QLabel::mousePressEvent(event);
- }
-}
-
-void QRImageWidget::saveImage()
-{
- if(!pixmap())
- return;
- QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr);
- if (!fn.isEmpty())
- {
- exportImage().save(fn);
- }
-}
-
-void QRImageWidget::copyImage()
-{
- if(!pixmap())
- return;
- QApplication::clipboard()->setImage(exportImage());
-}
-
-void QRImageWidget::contextMenuEvent(QContextMenuEvent *event)
-{
- if(!pixmap())
- return;
- contextMenu->exec(event->globalPos());
-}
-
ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ReceiveRequestDialog),
- model(0)
+ model(nullptr)
{
ui->setupUi(this);
@@ -97,7 +29,7 @@ ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) :
ui->lblQRCode->setVisible(false);
#endif
- connect(ui->btnSaveAs, SIGNAL(clicked()), ui->lblQRCode, SLOT(saveImage()));
+ connect(ui->btnSaveAs, &QPushButton::clicked, ui->lblQRCode, &QRImageWidget::saveImage);
}
ReceiveRequestDialog::~ReceiveRequestDialog()
@@ -110,7 +42,7 @@ void ReceiveRequestDialog::setModel(WalletModel *_model)
this->model = _model;
if (_model)
- connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(update()));
+ connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &ReceiveRequestDialog::update);
// update the display unit if necessary
update();
@@ -150,55 +82,9 @@ void ReceiveRequestDialog::update()
}
ui->outUri->setText(html);
-#ifdef USE_QRCODE
- ui->lblQRCode->setText("");
- if(!uri.isEmpty())
- {
- // limit URI length
- if (uri.length() > MAX_URI_LENGTH)
- {
- ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message."));
- } else {
- QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
- if (!code)
- {
- ui->lblQRCode->setText(tr("Error encoding URI into QR Code."));
- return;
- }
- QImage qrImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
- qrImage.fill(0xffffff);
- unsigned char *p = code->data;
- for (int y = 0; y < code->width; y++)
- {
- for (int x = 0; x < code->width; x++)
- {
- qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
- p++;
- }
- }
- QRcode_free(code);
-
- QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE+20, QImage::Format_RGB32);
- qrAddrImage.fill(0xffffff);
- QPainter painter(&qrAddrImage);
- painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));
- QFont font = GUIUtil::fixedPitchFont();
- QRect paddedRect = qrAddrImage.rect();
-
- // calculate ideal font size
- qreal font_size = GUIUtil::calculateIdealFontSize(paddedRect.width() - 20, info.address, font);
- font.setPointSizeF(font_size);
-
- painter.setFont(font);
- paddedRect.setHeight(QR_IMAGE_SIZE+12);
- painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, info.address);
- painter.end();
-
- ui->lblQRCode->setPixmap(QPixmap::fromImage(qrAddrImage));
- ui->btnSaveAs->setEnabled(true);
- }
+ if (ui->lblQRCode->setQR(uri, info.address)) {
+ ui->btnSaveAs->setEnabled(true);
}
-#endif
}
void ReceiveRequestDialog::on_btnCopyURI_clicked()
diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h
index 23c5529535..a6e1a2af16 100644
--- a/src/qt/receiverequestdialog.h
+++ b/src/qt/receiverequestdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,47 +8,17 @@
#include <qt/walletmodel.h>
#include <QDialog>
-#include <QImage>
-#include <QLabel>
-#include <QPainter>
namespace Ui {
class ReceiveRequestDialog;
}
-QT_BEGIN_NAMESPACE
-class QMenu;
-QT_END_NAMESPACE
-
-/* Label widget for QR code. This image can be dragged, dropped, copied and saved
- * to disk.
- */
-class QRImageWidget : public QLabel
-{
- Q_OBJECT
-
-public:
- explicit QRImageWidget(QWidget *parent = 0);
- QImage exportImage();
-
-public Q_SLOTS:
- void saveImage();
- void copyImage();
-
-protected:
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void contextMenuEvent(QContextMenuEvent *event);
-
-private:
- QMenu *contextMenu;
-};
-
class ReceiveRequestDialog : public QDialog
{
Q_OBJECT
public:
- explicit ReceiveRequestDialog(QWidget *parent = 0);
+ explicit ReceiveRequestDialog(QWidget *parent = nullptr);
~ReceiveRequestDialog();
void setModel(WalletModel *model);
diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp
index 1c910926d4..aa746017f3 100644
--- a/src/qt/recentrequeststablemodel.cpp
+++ b/src/qt/recentrequeststablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,8 +15,6 @@
RecentRequestsTableModel::RecentRequestsTableModel(WalletModel *parent) :
QAbstractTableModel(parent), walletModel(parent)
{
- nReceiveRequestsMaxId = 0;
-
// Load entries from wallet
std::vector<std::string> vReceiveRequests;
parent->loadReceiveRequests(vReceiveRequests);
@@ -26,7 +24,7 @@ RecentRequestsTableModel::RecentRequestsTableModel(WalletModel *parent) :
/* These columns must match the indices in the ColumnIndex enumeration */
columns << tr("Date") << tr("Label") << tr("Message") << getAmountTitle();
- connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
+ connect(walletModel->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &RecentRequestsTableModel::updateDisplayUnit);
}
RecentRequestsTableModel::~RecentRequestsTableModel()
diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h
index 80c7834a19..8a1140e952 100644
--- a/src/qt/recentrequeststablemodel.h
+++ b/src/qt/recentrequeststablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -94,7 +94,7 @@ private:
WalletModel *walletModel;
QStringList columns;
QList<RecentRequestEntry> list;
- int64_t nReceiveRequestsMaxId;
+ int64_t nReceiveRequestsMaxId{0};
/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */
void updateAmountColumnTitle();
diff --git a/src/qt/res/movies/makespinner.sh b/src/qt/res/movies/makespinner.sh
index 76e36e4f31..f47c66e02c 100755
--- a/src/qt/res/movies/makespinner.sh
+++ b/src/qt/res/movies/makespinner.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+#
# Copyright (c) 2014-2015 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index f222357f27..8b6dcf0445 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -18,9 +18,8 @@
#include <netbase.h>
#include <rpc/server.h>
#include <rpc/client.h>
-#include <util.h>
-
-#include <openssl/crypto.h>
+#include <util/strencodings.h>
+#include <util/system.h>
#include <univalue.h>
@@ -68,7 +67,6 @@ const QStringList historyFilter = QStringList()
<< "importmulti"
<< "sethdseed"
<< "signmessagewithprivkey"
- << "signrawtransaction"
<< "signrawtransactionwithkey"
<< "walletpassphrase"
<< "walletpassphrasechange"
@@ -82,10 +80,10 @@ class RPCExecutor : public QObject
{
Q_OBJECT
public:
- RPCExecutor(interfaces::Node& node) : m_node(node) {}
+ explicit RPCExecutor(interfaces::Node& node) : m_node(node) {}
public Q_SLOTS:
- void request(const QString &command, const QString &walletID);
+ void request(const QString &command, const WalletModel* wallet_model);
Q_SIGNALS:
void reply(int category, const QString &command);
@@ -101,19 +99,17 @@ class QtRPCTimerBase: public QObject, public RPCTimerBase
{
Q_OBJECT
public:
- QtRPCTimerBase(std::function<void(void)>& _func, int64_t millis):
+ QtRPCTimerBase(std::function<void()>& _func, int64_t millis):
func(_func)
{
timer.setSingleShot(true);
- connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
+ connect(&timer, &QTimer::timeout, [this]{ func(); });
timer.start(millis);
}
~QtRPCTimerBase() {}
-private Q_SLOTS:
- void timeout() { func(); }
private:
QTimer timer;
- std::function<void(void)> func;
+ std::function<void()> func;
};
class QtRPCTimerInterface: public RPCTimerInterface
@@ -121,7 +117,7 @@ class QtRPCTimerInterface: public RPCTimerInterface
public:
~QtRPCTimerInterface() {}
const char *Name() { return "Qt"; }
- RPCTimerBase* NewTimer(std::function<void(void)>& func, int64_t millis)
+ RPCTimerBase* NewTimer(std::function<void()>& func, int64_t millis)
{
return new QtRPCTimerBase(func, millis);
}
@@ -144,13 +140,13 @@ public:
* - Within single quotes, no escaping is possible and no special interpretation takes place
*
* @param[in] node optional node to execute command on
- * @param[out] result stringified Result from the executed command(chain)
+ * @param[out] strResult stringified result from the executed command(chain)
* @param[in] strCommand Command line to split
* @param[in] fExecute set true if you want the command to be executed
* @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data
*/
-bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const std::string *walletID)
+bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const WalletModel* wallet_model)
{
std::vector< std::vector<std::string> > stack;
stack.push_back(std::vector<std::string>());
@@ -228,7 +224,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
if (lastResult.isArray())
{
for(char argch: curarg)
- if (!std::isdigit(argch))
+ if (!IsDigit(argch))
throw std::runtime_error("Invalid result query");
subelement = lastResult[atoi(curarg.c_str())];
}
@@ -308,8 +304,8 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
std::string method = stack.back()[0];
std::string uri;
#ifdef ENABLE_WALLET
- if (walletID) {
- QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID));
+ if (wallet_model) {
+ QByteArray encodedName = QUrl::toPercentEncoding(wallet_model->getWalletName());
uri = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
}
#endif
@@ -389,7 +385,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
}
}
-void RPCExecutor::request(const QString &command, const QString &walletID)
+void RPCExecutor::request(const QString &command, const WalletModel* wallet_model)
{
try
{
@@ -397,13 +393,12 @@ void RPCExecutor::request(const QString &command, const QString &walletID)
std::string executableCommand = command.toStdString() + "\n";
// Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.
- if(executableCommand == "help-console\n")
- {
+ if(executableCommand == "help-console\n") {
Q_EMIT reply(RPCConsole::CMD_REPLY, QString(("\n"
"This console accepts RPC commands using the standard syntax.\n"
" example: getblockhash 0\n\n"
- "This console can also accept RPC commands using parenthesized syntax.\n"
+ "This console can also accept RPC commands using the parenthesized syntax.\n"
" example: getblockhash(0)\n\n"
"Commands may be nested when specified with the parenthesized syntax.\n"
@@ -413,16 +408,14 @@ void RPCExecutor::request(const QString &command, const QString &walletID)
" example: getblockhash 0\n"
" getblockhash,0\n\n"
- "Named results can be queried with a non-quoted key string in brackets.\n"
- " example: getblock(getblockhash(0) true)[tx]\n\n"
+ "Named results can be queried with a non-quoted key string in brackets using the parenthesized syntax.\n"
+ " example: getblock(getblockhash(0) 1)[tx]\n\n"
- "Results without keys can be queried using an integer in brackets.\n"
- " example: getblock(getblockhash(0),true)[tx][0]\n\n")));
+ "Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n"
+ " example: getblock(getblockhash(0),1)[tx][0]\n\n")));
return;
}
- std::string wallet_id = walletID.toStdString();
- if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, walletID.isNull() ? nullptr : &wallet_id))
- {
+ if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, wallet_model)) {
Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
return;
}
@@ -461,6 +454,9 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
}
+ QChar nonbreaking_hyphen(8209);
+ ui->dataDir->setToolTip(ui->dataDir->toolTip().arg(QString(nonbreaking_hyphen) + "datadir"));
+ ui->blocksDir->setToolTip(ui->blocksDir->toolTip().arg(QString(nonbreaking_hyphen) + "blocksdir"));
ui->openDebugLogfileButton->setToolTip(ui->openDebugLogfileButton->toolTip().arg(tr(PACKAGE_NAME)));
if (platformStyle->getImagesOnButtons()) {
@@ -474,10 +470,10 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
ui->lineEdit->installEventFilter(this);
ui->messagesWidget->installEventFilter(this);
- connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
- connect(ui->fontBiggerButton, SIGNAL(clicked()), this, SLOT(fontBigger()));
- connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller()));
- connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear()));
+ connect(ui->clearButton, &QPushButton::clicked, this, &RPCConsole::clear);
+ connect(ui->fontBiggerButton, &QPushButton::clicked, this, &RPCConsole::fontBigger);
+ connect(ui->fontSmallerButton, &QPushButton::clicked, this, &RPCConsole::fontSmaller);
+ connect(ui->btnClearTrafficGraph, &QPushButton::clicked, ui->trafficGraph, &TrafficGraphWidget::clear);
// disable the wallet selector by default
ui->WalletSelector->setVisible(false);
@@ -485,7 +481,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
// set library version labels
#ifdef ENABLE_WALLET
- ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
+ ui->berkeleyDBVersion->setText(DbEnv::version(nullptr, nullptr, nullptr));
#else
ui->label_berkeleyDBVersion->hide();
ui->berkeleyDBVersion->hide();
@@ -538,6 +534,7 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
// forward these events to lineEdit
if(obj == autoCompleter->popup()) {
QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
+ autoCompleter->popup()->hide();
return true;
}
break;
@@ -565,19 +562,19 @@ void RPCConsole::setClientModel(ClientModel *model)
if (model && clientModel->getPeerTableModel() && clientModel->getBanTableModel()) {
// Keep up to date with client
setNumConnections(model->getNumConnections());
- connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
+ connect(model, &ClientModel::numConnectionsChanged, this, &RPCConsole::setNumConnections);
interfaces::Node& node = clientModel->node();
setNumBlocks(node.getNumBlocks(), QDateTime::fromTime_t(node.getLastBlockTime()), node.getVerificationProgress(), false);
- connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
+ connect(model, &ClientModel::numBlocksChanged, this, &RPCConsole::setNumBlocks);
updateNetworkState();
- connect(model, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
+ connect(model, &ClientModel::networkActiveChanged, this, &RPCConsole::setNetworkActive);
updateTrafficStats(node.getTotalBytesRecv(), node.getTotalBytesSent());
- connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
+ connect(model, &ClientModel::bytesChanged, this, &RPCConsole::updateTrafficStats);
- connect(model, SIGNAL(mempoolSizeChanged(long,size_t)), this, SLOT(setMempoolSize(long,size_t)));
+ connect(model, &ClientModel::mempoolSizeChanged, this, &RPCConsole::setMempoolSize);
// set up peer table
ui->peerWidget->setModel(model->getPeerTableModel());
@@ -614,23 +611,22 @@ void RPCConsole::setClientModel(ClientModel *model)
signalMapper->setMapping(banAction24h, 60*60*24);
signalMapper->setMapping(banAction7d, 60*60*24*7);
signalMapper->setMapping(banAction365d, 60*60*24*365);
- connect(banAction1h, SIGNAL(triggered()), signalMapper, SLOT(map()));
- connect(banAction24h, SIGNAL(triggered()), signalMapper, SLOT(map()));
- connect(banAction7d, SIGNAL(triggered()), signalMapper, SLOT(map()));
- connect(banAction365d, SIGNAL(triggered()), signalMapper, SLOT(map()));
- connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(banSelectedNode(int)));
+ connect(banAction1h, &QAction::triggered, signalMapper, static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map));
+ connect(banAction24h, &QAction::triggered, signalMapper, static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map));
+ connect(banAction7d, &QAction::triggered, signalMapper, static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map));
+ connect(banAction365d, &QAction::triggered, signalMapper, static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map));
+ connect(signalMapper, static_cast<void (QSignalMapper::*)(int)>(&QSignalMapper::mapped), this, &RPCConsole::banSelectedNode);
// peer table context menu signals
- connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&)));
- connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode()));
+ connect(ui->peerWidget, &QTableView::customContextMenuRequested, this, &RPCConsole::showPeersTableContextMenu);
+ connect(disconnectAction, &QAction::triggered, this, &RPCConsole::disconnectSelectedNode);
// peer table signal handling - update peer details when selecting new node
- connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
- this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &)));
+ connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::peerSelected);
// peer table signal handling - update peer details when new nodes are added to the model
- connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged()));
+ connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged, this, &RPCConsole::peerLayoutChanged);
// peer table signal handling - cache selected node ids
- connect(model->getPeerTableModel(), SIGNAL(layoutAboutToBeChanged()), this, SLOT(peerLayoutAboutToChange()));
+ connect(model->getPeerTableModel(), &PeerTableModel::layoutAboutToBeChanged, this, &RPCConsole::peerLayoutAboutToChange);
// set up ban table
ui->banlistWidget->setModel(model->getBanTableModel());
@@ -651,19 +647,20 @@ void RPCConsole::setClientModel(ClientModel *model)
banTableContextMenu->addAction(unbanAction);
// ban table context menu signals
- connect(ui->banlistWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showBanTableContextMenu(const QPoint&)));
- connect(unbanAction, SIGNAL(triggered()), this, SLOT(unbanSelectedNode()));
+ connect(ui->banlistWidget, &QTableView::customContextMenuRequested, this, &RPCConsole::showBanTableContextMenu);
+ connect(unbanAction, &QAction::triggered, this, &RPCConsole::unbanSelectedNode);
// ban table signal handling - clear peer details when clicking a peer in the ban table
- connect(ui->banlistWidget, SIGNAL(clicked(const QModelIndex&)), this, SLOT(clearSelectedNode()));
+ connect(ui->banlistWidget, &QTableView::clicked, this, &RPCConsole::clearSelectedNode);
// ban table signal handling - ensure ban table is shown or hidden (if empty)
- connect(model->getBanTableModel(), SIGNAL(layoutChanged()), this, SLOT(showOrHideBanTableIfRequired()));
+ connect(model->getBanTableModel(), &BanTableModel::layoutChanged, this, &RPCConsole::showOrHideBanTableIfRequired);
showOrHideBanTableIfRequired();
// Provide initial values
ui->clientVersion->setText(model->formatFullVersion());
ui->clientUserAgent->setText(model->formatSubVersion());
ui->dataDir->setText(model->dataDir());
+ ui->blocksDir->setText(model->blocksDir());
ui->startupTime->setText(model->formatClientStartupTime());
ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
@@ -687,8 +684,7 @@ void RPCConsole::setClientModel(ClientModel *model)
}
if (!model) {
// Client model is being set to 0, this means shutdown() is about to be called.
- // Make sure we clean up the executor thread
- Q_EMIT stopExecutor();
+ thread.quit();
thread.wait();
}
}
@@ -696,10 +692,8 @@ void RPCConsole::setClientModel(ClientModel *model)
#ifdef ENABLE_WALLET
void RPCConsole::addWallet(WalletModel * const walletModel)
{
- const QString name = walletModel->getWalletName();
- // use name for text and internal data object (to allow to move to a wallet id later)
- QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name;
- ui->WalletSelector->addItem(display_name, name);
+ // 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)
ui->WalletSelector->setCurrentIndex(1);
@@ -712,8 +706,7 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
void RPCConsole::removeWallet(WalletModel * const walletModel)
{
- const QString name = walletModel->getWalletName();
- ui->WalletSelector->removeItem(ui->WalletSelector->findData(name));
+ ui->WalletSelector->removeItem(ui->WalletSelector->findData(QVariant::fromValue(walletModel)));
if (ui->WalletSelector->count() == 2) {
ui->WalletSelector->setVisible(false);
ui->WalletSelectorLabel->setVisible(false);
@@ -908,25 +901,25 @@ void RPCConsole::on_lineEdit_returnPressed()
cmdBeforeBrowsing = QString();
- QString walletID;
+ WalletModel* wallet_model{nullptr};
#ifdef ENABLE_WALLET
const int wallet_index = ui->WalletSelector->currentIndex();
if (wallet_index > 0) {
- walletID = (QString)ui->WalletSelector->itemData(wallet_index).value<QString>();
+ wallet_model = ui->WalletSelector->itemData(wallet_index).value<WalletModel*>();
}
- if (m_last_wallet_id != walletID) {
- if (walletID.isNull()) {
- message(CMD_REQUEST, tr("Executing command without any wallet"));
+ if (m_last_wallet_model != wallet_model) {
+ if (wallet_model) {
+ message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName()));
} else {
- message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID));
+ message(CMD_REQUEST, tr("Executing command without any wallet"));
}
- m_last_wallet_id = walletID;
+ m_last_wallet_model = wallet_model;
}
#endif
message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
- Q_EMIT cmdRequest(cmd, walletID);
+ Q_EMIT cmdRequest(cmd, m_last_wallet_model);
cmd = QString::fromStdString(strFilteredCmd);
@@ -972,15 +965,13 @@ void RPCConsole::startExecutor()
executor->moveToThread(&thread);
// Replies from executor object must go to this object
- connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
+ connect(executor, &RPCExecutor::reply, this, static_cast<void (RPCConsole::*)(int, const QString&)>(&RPCConsole::message));
+
// Requests from this object must go to executor
- connect(this, SIGNAL(cmdRequest(QString, QString)), executor, SLOT(request(QString, QString)));
+ connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request);
- // On stopExecutor signal
- // - quit the Qt event loop in the execution thread
- connect(this, SIGNAL(stopExecutor()), &thread, SLOT(quit()));
- // - queue executor for deletion (in execution thread)
- connect(&thread, SIGNAL(finished()), executor, SLOT(deleteLater()), Qt::DirectConnection);
+ // Make sure executor object is deleted in its own thread
+ connect(&thread, &QThread::finished, executor, &RPCExecutor::deleteLater);
// Default implementation of QThread::run() simply spins up an event loop in the thread,
// which is what we want.
@@ -989,10 +980,9 @@ void RPCConsole::startExecutor()
void RPCConsole::on_tabWidget_currentChanged(int index)
{
- if (ui->tabWidget->widget(index) == ui->tab_console)
+ if (ui->tabWidget->widget(index) == ui->tab_console) {
ui->lineEdit->setFocus();
- else if (ui->tabWidget->widget(index) != ui->tab_peers)
- clearSelectedNode();
+ }
}
void RPCConsole::on_openDebugLogfileButton_clicked()
@@ -1218,16 +1208,16 @@ void RPCConsole::banSelectedNode(int bantime)
// Get currently selected peer address
NodeId id = nodes.at(i).data().toLongLong();
- // Get currently selected peer address
- int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id);
- if(detailNodeRow < 0)
- return;
+ // Get currently selected peer address
+ int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id);
+ if (detailNodeRow < 0) return;
- // Find possible nodes, ban it and clear the selected node
- const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
- if(stats) {
+ // Find possible nodes, ban it and clear the selected node
+ const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
+ if (stats) {
m_node.ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime);
- }
+ m_node.disconnect(stats->nodeStats.addr);
+ }
}
clearSelectedNode();
clientModel->getBanTableModel()->refresh();
@@ -1272,7 +1262,17 @@ void RPCConsole::showOrHideBanTableIfRequired()
ui->banHeading->setVisible(visible);
}
+RPCConsole::TabTypes RPCConsole::tabFocus() const
+{
+ return (TabTypes) ui->tabWidget->currentIndex();
+}
+
void RPCConsole::setTabFocus(enum TabTypes tabType)
{
ui->tabWidget->setCurrentIndex(tabType);
}
+
+QString RPCConsole::tabTitle(TabTypes tab_type) const
+{
+ return ui->tabWidget->tabText(tab_type);
+}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 0a1a469934..79b0f3b19c 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -41,9 +41,9 @@ public:
explicit RPCConsole(interfaces::Node& node, const PlatformStyle *platformStyle, QWidget *parent);
~RPCConsole();
- static bool RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr);
- static bool RPCExecuteCommandLine(interfaces::Node& node, std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr) {
- return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, walletID);
+ static bool RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const WalletModel* wallet_model = nullptr);
+ static bool RPCExecuteCommandLine(interfaces::Node& node, std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const WalletModel* wallet_model = nullptr) {
+ return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, wallet_model);
}
void setClientModel(ClientModel *model);
@@ -65,6 +65,11 @@ public:
TAB_PEERS = 3
};
+ std::vector<TabTypes> tabs() const { return {TAB_INFO, TAB_CONSOLE, TAB_GRAPH, TAB_PEERS}; }
+
+ TabTypes tabFocus() const;
+ QString tabTitle(TabTypes tab_type) const;
+
protected:
virtual bool eventFilter(QObject* obj, QEvent *event);
void keyPressEvent(QKeyEvent *);
@@ -96,7 +101,8 @@ public Q_SLOTS:
void fontSmaller();
void setFontSize(int newSize);
/** Append the message to the message widget */
- void message(int category, const QString &message, bool html = false);
+ void message(int category, const QString &msg) { message(category, msg, false); }
+ void message(int category, const QString &message, bool html);
/** Set number of connections shown in the UI */
void setNumConnections(int count);
/** Set network state shown in the UI */
@@ -126,8 +132,7 @@ public Q_SLOTS:
Q_SIGNALS:
// For RPC command executor
- void stopExecutor();
- void cmdRequest(const QString &command, const QString &walletID);
+ void cmdRequest(const QString &command, const WalletModel* wallet_model);
private:
void startExecutor();
@@ -159,7 +164,7 @@ private:
int consoleFontSize = 0;
QCompleter *autoCompleter = nullptr;
QThread thread;
- QString m_last_wallet_id;
+ WalletModel* m_last_wallet_model{nullptr};
/** Update UI with latest network info from model. */
void updateNetworkState();
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 5c946f7c77..8a0b265834 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -1,7 +1,11 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/sendcoinsdialog.h>
#include <qt/forms/ui_sendcoinsdialog.h>
@@ -50,8 +54,8 @@ int getIndexForConfTarget(int target) {
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::SendCoinsDialog),
- clientModel(0),
- model(0),
+ clientModel(nullptr),
+ model(nullptr),
fNewRecipientAllowed(true),
fFeeMinimized(true),
platformStyle(_platformStyle)
@@ -72,13 +76,13 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
addEntry();
- connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
- connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
+ connect(ui->addButton, &QPushButton::clicked, this, &SendCoinsDialog::addEntry);
+ connect(ui->clearButton, &QPushButton::clicked, this, &SendCoinsDialog::clear);
// Coin Control
- connect(ui->pushButtonCoinControl, SIGNAL(clicked()), this, SLOT(coinControlButtonClicked()));
- connect(ui->checkBoxCoinControlChange, SIGNAL(stateChanged(int)), this, SLOT(coinControlChangeChecked(int)));
- connect(ui->lineEditCoinControlChange, SIGNAL(textEdited(const QString &)), this, SLOT(coinControlChangeEdited(const QString &)));
+ connect(ui->pushButtonCoinControl, &QPushButton::clicked, this, &SendCoinsDialog::coinControlButtonClicked);
+ connect(ui->checkBoxCoinControlChange, &QCheckBox::stateChanged, this, &SendCoinsDialog::coinControlChangeChecked);
+ connect(ui->lineEditCoinControlChange, &QValidatedLineEdit::textEdited, this, &SendCoinsDialog::coinControlChangeEdited);
// Coin Control: clipboard actions
QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this);
@@ -88,13 +92,13 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this);
QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this);
QAction *clipboardChangeAction = new QAction(tr("Copy change"), this);
- connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardQuantity()));
- connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAmount()));
- connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardFee()));
- connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAfterFee()));
- connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardBytes()));
- connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardLowOutput()));
- connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardChange()));
+ connect(clipboardQuantityAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardQuantity);
+ connect(clipboardAmountAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardAmount);
+ connect(clipboardFeeAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardFee);
+ connect(clipboardAfterFeeAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardAfterFee);
+ connect(clipboardBytesAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardBytes);
+ connect(clipboardLowOutputAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardLowOutput);
+ connect(clipboardChangeAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardChange);
ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
ui->labelCoinControlAmount->addAction(clipboardAmountAction);
ui->labelCoinControlFee->addAction(clipboardFeeAction);
@@ -115,13 +119,11 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
settings.setValue("nSmartFeeSliderPosition", 0);
if (!settings.contains("nTransactionFee"))
settings.setValue("nTransactionFee", (qint64)DEFAULT_PAY_TX_FEE);
- if (!settings.contains("fPayOnlyMinFee"))
- settings.setValue("fPayOnlyMinFee", false);
ui->groupFee->setId(ui->radioSmartFee, 0);
ui->groupFee->setId(ui->radioCustomFee, 1);
ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true);
+ ui->customFee->SetAllowEmpty(false);
ui->customFee->setValue(settings.value("nTransactionFee").toLongLong());
- ui->checkBoxMinimumFee->setChecked(settings.value("fPayOnlyMinFee").toBool());
minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool());
}
@@ -130,7 +132,7 @@ void SendCoinsDialog::setClientModel(ClientModel *_clientModel)
this->clientModel = _clientModel;
if (_clientModel) {
- connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(updateSmartFeeLabel()));
+ connect(_clientModel, &ClientModel::numBlocksChanged, this, &SendCoinsDialog::updateSmartFeeLabel);
}
}
@@ -151,13 +153,13 @@ void SendCoinsDialog::setModel(WalletModel *_model)
interfaces::WalletBalances balances = _model->wallet().getBalances();
setBalance(balances);
- connect(_model, SIGNAL(balanceChanged(interfaces::WalletBalances)), this, SLOT(setBalance(interfaces::WalletBalances)));
- connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
+ connect(_model, &WalletModel::balanceChanged, this, &SendCoinsDialog::setBalance);
+ connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::updateDisplayUnit);
updateDisplayUnit();
// Coin Control
- connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels()));
- connect(_model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool)));
+ connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
+ connect(_model->getOptionsModel(), &OptionsModel::coinControlFeaturesChanged, this, &SendCoinsDialog::coinControlFeatureChanged);
ui->frameCoinControl->setVisible(_model->getOptionsModel()->getCoinControlFeatures());
coinControlUpdateLabels();
@@ -165,19 +167,20 @@ void SendCoinsDialog::setModel(WalletModel *_model)
for (const int n : confTargets) {
ui->confTargetSelector->addItem(tr("%1 (%2 blocks)").arg(GUIUtil::formatNiceTimeOffset(n*Params().GetConsensus().nPowTargetSpacing)).arg(n));
}
- connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSmartFeeLabel()));
- connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(coinControlUpdateLabels()));
- connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateFeeSectionControls()));
- connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels()));
- connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(coinControlUpdateLabels()));
- connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(setMinimumFee()));
- connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls()));
- connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
- connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(updateSmartFeeLabel()));
- connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
- ui->customFee->setSingleStep(model->wallet().getRequiredFee(1000));
+ connect(ui->confTargetSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::updateSmartFeeLabel);
+ connect(ui->confTargetSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::coinControlUpdateLabels);
+ connect(ui->groupFee, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::updateFeeSectionControls);
+ connect(ui->groupFee, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::coinControlUpdateLabels);
+ connect(ui->customFee, &BitcoinAmountField::valueChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
+ connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::updateSmartFeeLabel);
+ connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
+ CAmount requiredFee = model->wallet().getRequiredFee(1000);
+ ui->customFee->SetMinValue(requiredFee);
+ if (ui->customFee->value() < requiredFee) {
+ ui->customFee->setValue(requiredFee);
+ }
+ ui->customFee->setSingleStep(requiredFee);
updateFeeSectionControls();
- updateMinFeeLabel();
updateSmartFeeLabel();
// set default rbf checkbox state
@@ -206,7 +209,6 @@ SendCoinsDialog::~SendCoinsDialog()
settings.setValue("nFeeRadio", ui->groupFee->checkedId());
settings.setValue("nConfTarget", getConfTargetForIndex(ui->confTargetSelector->currentIndex()));
settings.setValue("nTransactionFee", (qint64)ui->customFee->value());
- settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked());
delete ui;
}
@@ -290,7 +292,9 @@ void SendCoinsDialog::on_sendButton_clicked()
QString recipientElement;
recipientElement = "<br />";
+#ifdef ENABLE_BIP70
if (!rcp.paymentRequest.IsInitialized()) // normal payment
+#endif
{
if(rcp.label.length() > 0) // label with address
{
@@ -302,6 +306,7 @@ void SendCoinsDialog::on_sendButton_clicked()
recipientElement.append(tr("%1 to %2").arg(amount, address));
}
}
+#ifdef ENABLE_BIP70
else if(!rcp.authenticatedMerchant.isEmpty()) // authenticated payment request
{
recipientElement.append(tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.authenticatedMerchant)));
@@ -310,6 +315,7 @@ void SendCoinsDialog::on_sendButton_clicked()
{
recipientElement.append(tr("%1 to %2").arg(amount, address));
}
+#endif
formatted.append(recipientElement);
}
@@ -348,7 +354,7 @@ void SendCoinsDialog::on_sendButton_clicked()
questionString.append("<hr />");
CAmount totalAmount = currentTransaction.getTotalTransactionAmount() + txFee;
QStringList alternativeUnits;
- for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
+ for (const BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
{
if(u != model->getOptionsModel()->getDisplayUnit())
alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount));
@@ -417,10 +423,10 @@ SendCoinsEntry *SendCoinsDialog::addEntry()
SendCoinsEntry *entry = new SendCoinsEntry(platformStyle, this);
entry->setModel(model);
ui->entries->addWidget(entry);
- connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*)));
- connect(entry, SIGNAL(useAvailableBalance(SendCoinsEntry*)), this, SLOT(useAvailableBalance(SendCoinsEntry*)));
- connect(entry, SIGNAL(payAmountChanged()), this, SLOT(coinControlUpdateLabels()));
- connect(entry, SIGNAL(subtractFeeFromAmountChanged()), this, SLOT(coinControlUpdateLabels()));
+ connect(entry, &SendCoinsEntry::removeEntry, this, &SendCoinsDialog::removeEntry);
+ connect(entry, &SendCoinsEntry::useAvailableBalance, this, &SendCoinsDialog::useAvailableBalance);
+ connect(entry, &SendCoinsEntry::payAmountChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
+ connect(entry, &SendCoinsEntry::subtractFeeFromAmountChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
// Focus the field, so that entry can start immediately
entry->clear();
@@ -437,7 +443,7 @@ SendCoinsEntry *SendCoinsDialog::addEntry()
void SendCoinsDialog::updateTabsAndLabels()
{
- setupTabChain(0);
+ setupTabChain(nullptr);
coinControlUpdateLabels();
}
@@ -472,7 +478,7 @@ QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
void SendCoinsDialog::setAddress(const QString &address)
{
- SendCoinsEntry *entry = 0;
+ SendCoinsEntry *entry = nullptr;
// Replace the first entry if it is still unused
if(ui->entries->count() == 1)
{
@@ -495,7 +501,7 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
if(!fNewRecipientAllowed)
return;
- SendCoinsEntry *entry = 0;
+ SendCoinsEntry *entry = nullptr;
// Replace the first entry if it is still unused
if(ui->entries->count() == 1)
{
@@ -534,7 +540,6 @@ void SendCoinsDialog::updateDisplayUnit()
{
setBalance(model->wallet().getBalances());
ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
- updateMinFeeLabel();
updateSmartFeeLabel();
}
@@ -573,7 +578,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
msgParams.second = CClientUIInterface::MSG_ERROR;
break;
case WalletModel::AbsurdFee:
- msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->node().getMaxTxFee()));
+ msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->wallet().getDefaultMaxTxFee()));
break;
case WalletModel::PaymentRequestExpired:
msgParams.first = tr("Payment request expired.");
@@ -634,11 +639,6 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry)
}
}
-void SendCoinsDialog::setMinimumFee()
-{
- ui->customFee->setValue(model->wallet().getRequiredFee(1000));
-}
-
void SendCoinsDialog::updateFeeSectionControls()
{
ui->confTargetSelector ->setEnabled(ui->radioSmartFee->isChecked());
@@ -646,10 +646,9 @@ void SendCoinsDialog::updateFeeSectionControls()
ui->labelSmartFee2 ->setEnabled(ui->radioSmartFee->isChecked());
ui->labelSmartFee3 ->setEnabled(ui->radioSmartFee->isChecked());
ui->labelFeeEstimation ->setEnabled(ui->radioSmartFee->isChecked());
- ui->checkBoxMinimumFee ->setEnabled(ui->radioCustomFee->isChecked());
- ui->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked());
- ui->labelCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked());
- ui->customFee ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked());
+ ui->labelCustomFeeWarning ->setEnabled(ui->radioCustomFee->isChecked());
+ ui->labelCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked());
+ ui->customFee ->setEnabled(ui->radioCustomFee->isChecked());
}
void SendCoinsDialog::updateFeeMinimizedLabel()
@@ -664,14 +663,6 @@ void SendCoinsDialog::updateFeeMinimizedLabel()
}
}
-void SendCoinsDialog::updateMinFeeLabel()
-{
- if (model && model->getOptionsModel())
- ui->checkBoxMinimumFee->setText(tr("Pay only the required fee of %1").arg(
- BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->wallet().getRequiredFee(1000)) + "/kB")
- );
-}
-
void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl)
{
if (ui->radioCustomFee->isChecked()) {
@@ -897,7 +888,7 @@ SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QStri
setDefaultButton(QMessageBox::Cancel);
yesButton = button(QMessageBox::Yes);
updateYesButton();
- connect(&countDownTimer, SIGNAL(timeout()), this, SLOT(countDown()));
+ connect(&countDownTimer, &QTimer::timeout, this, &SendConfirmationDialog::countDown);
}
int SendConfirmationDialog::exec()
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index 40a1d10c2b..337a72b878 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -31,7 +31,7 @@ class SendCoinsDialog : public QDialog
Q_OBJECT
public:
- explicit SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~SendCoinsDialog();
void setClientModel(ClientModel *clientModel);
@@ -92,9 +92,7 @@ private Q_SLOTS:
void coinControlClipboardBytes();
void coinControlClipboardLowOutput();
void coinControlClipboardChange();
- void setMinimumFee();
void updateFeeSectionControls();
- void updateMinFeeLabel();
void updateSmartFeeLabel();
Q_SIGNALS:
@@ -110,7 +108,7 @@ class SendConfirmationDialog : public QMessageBox
Q_OBJECT
public:
- SendConfirmationDialog(const QString &title, const QString &text, int secDelay = SEND_CONFIRM_DELAY, QWidget *parent = 0);
+ SendConfirmationDialog(const QString &title, const QString &text, int secDelay = SEND_CONFIRM_DELAY, QWidget *parent = nullptr);
int exec();
private Q_SLOTS:
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index e8c85bc2a1..7324d759fb 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -1,7 +1,11 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/sendcoinsentry.h>
#include <qt/forms/ui_sendcoinsentry.h>
@@ -17,7 +21,7 @@
SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) :
QStackedWidget(parent),
ui(new Ui::SendCoinsEntry),
- model(0),
+ model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
@@ -40,12 +44,12 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *par
ui->payTo_is->setFont(GUIUtil::fixedPitchFont());
// Connect signals
- connect(ui->payAmount, SIGNAL(valueChanged()), this, SIGNAL(payAmountChanged()));
- connect(ui->checkboxSubtractFeeFromAmount, SIGNAL(toggled(bool)), this, SIGNAL(subtractFeeFromAmountChanged()));
- connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(deleteClicked()));
- connect(ui->deleteButton_is, SIGNAL(clicked()), this, SLOT(deleteClicked()));
- connect(ui->deleteButton_s, SIGNAL(clicked()), this, SLOT(deleteClicked()));
- connect(ui->useAvailableBalanceButton, SIGNAL(clicked()), this, SLOT(useAvailableBalanceClicked()));
+ connect(ui->payAmount, &BitcoinAmountField::valueChanged, this, &SendCoinsEntry::payAmountChanged);
+ connect(ui->checkboxSubtractFeeFromAmount, &QCheckBox::toggled, this, &SendCoinsEntry::subtractFeeFromAmountChanged);
+ connect(ui->deleteButton, &QPushButton::clicked, this, &SendCoinsEntry::deleteClicked);
+ connect(ui->deleteButton_is, &QPushButton::clicked, this, &SendCoinsEntry::deleteClicked);
+ connect(ui->deleteButton_s, &QPushButton::clicked, this, &SendCoinsEntry::deleteClicked);
+ connect(ui->useAvailableBalanceButton, &QPushButton::clicked, this, &SendCoinsEntry::useAvailableBalanceClicked);
}
SendCoinsEntry::~SendCoinsEntry()
@@ -82,7 +86,7 @@ void SendCoinsEntry::setModel(WalletModel *_model)
this->model = _model;
if (_model && _model->getOptionsModel())
- connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
+ connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsEntry::updateDisplayUnit);
clear();
}
@@ -133,9 +137,11 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
// Check input validity
bool retval = true;
+#ifdef ENABLE_BIP70
// Skip checks for payment request
if (recipient.paymentRequest.IsInitialized())
return retval;
+#endif
if (!model->validateAddress(ui->payTo->text()))
{
@@ -149,7 +155,7 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
}
// Sending a zero amount is invalid
- if (ui->payAmount->value(0) <= 0)
+ if (ui->payAmount->value(nullptr) <= 0)
{
ui->payAmount->setValid(false);
retval = false;
@@ -166,9 +172,11 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
SendCoinsRecipient SendCoinsEntry::getValue()
{
+#ifdef ENABLE_BIP70
// Payment request
if (recipient.paymentRequest.IsInitialized())
return recipient;
+#endif
// Normal payment
recipient.address = ui->payTo->text();
@@ -196,6 +204,7 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
recipient = value;
+#ifdef ENABLE_BIP70
if (recipient.paymentRequest.IsInitialized()) // payment request
{
if (recipient.authenticatedMerchant.isEmpty()) // unauthenticated
@@ -216,6 +225,7 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
}
}
else // normal payment
+#endif
{
// message
ui->messageTextLabel->setText(recipient.message);
diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h
index 76f96c61e0..42e2217130 100644
--- a/src/qt/sendcoinsentry.h
+++ b/src/qt/sendcoinsentry.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -26,7 +26,7 @@ class SendCoinsEntry : public QStackedWidget
Q_OBJECT
public:
- explicit SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
~SendCoinsEntry();
void setModel(WalletModel *model);
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 223b39dc86..71f5f2ae75 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,7 @@
#include <qt/walletmodel.h>
#include <key_io.h>
-#include <validation.h> // For strMessageMagic
+#include <util/validation.h> // For strMessageMagic
#include <wallet/wallet.h>
#include <string>
@@ -22,7 +22,7 @@
SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::SignVerifyMessageDialog),
- model(0),
+ model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
@@ -120,8 +120,8 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
return;
}
- const CKeyID* keyID = boost::get<CKeyID>(&destination);
- if (!keyID) {
+ const PKHash* pkhash = boost::get<PKHash>(&destination);
+ if (!pkhash) {
ui->addressIn_SM->setValid(false);
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
@@ -137,7 +137,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
}
CKey key;
- if (!model->wallet().getPrivKey(*keyID, key))
+ if (!model->wallet().getPrivKey(CKeyID(*pkhash), key))
{
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
@@ -198,7 +198,7 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
return;
}
- if (!boost::get<CKeyID>(&destination)) {
+ if (!boost::get<PKHash>(&destination)) {
ui->addressIn_VM->setValid(false);
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
@@ -229,7 +229,7 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
return;
}
- if (!(CTxDestination(pubkey.GetID()) == destination)) {
+ if (!(CTxDestination(PKHash(pubkey)) == destination)) {
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
return;
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 831ef68cab..0126a2920e 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,8 +14,8 @@
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
-#include <util.h>
#include <ui_interface.h>
+#include <util/system.h>
#include <version.h>
#include <QApplication>
@@ -24,8 +24,9 @@
#include <QPainter>
#include <QRadialGradient>
+
SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const NetworkStyle *networkStyle) :
- QWidget(0, f), curAlignment(0), m_node(node)
+ QWidget(nullptr, f), curAlignment(0), m_node(node)
{
// set reference point, paddings
int paddingRight = 50;
@@ -35,9 +36,7 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw
float fontFactor = 1.0;
float devicePixelRatio = 1.0;
-#if QT_VERSION > 0x050100
devicePixelRatio = static_cast<QGuiApplication*>(QCoreApplication::instance())->devicePixelRatio();
-#endif
// define text to place
QString titleText = tr(PACKAGE_NAME);
@@ -51,10 +50,8 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw
QSize splashSize(480*devicePixelRatio,320*devicePixelRatio);
pixmap = QPixmap(splashSize);
-#if QT_VERSION > 0x050100
// change to HiDPI if it makes sense
pixmap.setDevicePixelRatio(devicePixelRatio);
-#endif
QPainter pixPaint(&pixmap);
pixPaint.setPen(QColor(100,100,100));
@@ -147,10 +144,8 @@ bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) {
return QObject::eventFilter(obj, ev);
}
-void SplashScreen::slotFinish(QWidget *mainWin)
+void SplashScreen::finish()
{
- Q_UNUSED(mainWin);
-
/* If the window is minimized, hide() will be ignored. */
/* Make sure we de-minimize the splashscreen window before hiding */
if (isMinimized())
@@ -178,7 +173,7 @@ static void ShowProgress(SplashScreen *splash, const std::string &title, int nPr
#ifdef ENABLE_WALLET
void SplashScreen::ConnectWallet(std::unique_ptr<interfaces::Wallet> wallet)
{
- m_connected_wallet_handlers.emplace_back(wallet->handleShowProgress(boost::bind(ShowProgress, this, _1, _2, false)));
+ m_connected_wallet_handlers.emplace_back(wallet->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, false)));
m_connected_wallets.emplace_back(std::move(wallet));
}
#endif
@@ -186,8 +181,8 @@ void SplashScreen::ConnectWallet(std::unique_ptr<interfaces::Wallet> wallet)
void SplashScreen::subscribeToCoreSignals()
{
// Connect signals to client
- m_handler_init_message = m_node.handleInitMessage(boost::bind(InitMessage, this, _1));
- m_handler_show_progress = m_node.handleShowProgress(boost::bind(ShowProgress, this, _1, _2, _3));
+ m_handler_init_message = m_node.handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1));
+ m_handler_show_progress = m_node.handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
#ifdef ENABLE_WALLET
m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) { ConnectWallet(std::move(wallet)); });
#endif
@@ -198,7 +193,7 @@ void SplashScreen::unsubscribeFromCoreSignals()
// Disconnect signals from client
m_handler_init_message->disconnect();
m_handler_show_progress->disconnect();
- for (auto& handler : m_connected_wallet_handlers) {
+ for (const auto& handler : m_connected_wallet_handlers) {
handler->disconnect();
}
m_connected_wallet_handlers.clear();
diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h
index 9ef19675d8..f99dd0c701 100644
--- a/src/qt/splashscreen.h
+++ b/src/qt/splashscreen.h
@@ -1,12 +1,11 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_QT_SPLASHSCREEN_H
#define BITCOIN_QT_SPLASHSCREEN_H
-#include <functional>
-#include <QSplashScreen>
+#include <QWidget>
#include <memory>
@@ -37,8 +36,8 @@ protected:
void closeEvent(QCloseEvent *event);
public Q_SLOTS:
- /** Slot to call finish() method as it's not defined as slot */
- void slotFinish(QWidget *mainWin);
+ /** 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);
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index c3d33c76d4..2ba1c2604c 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -1,22 +1,23 @@
#include <qt/test/addressbooktests.h>
#include <qt/test/util.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
+#include <interfaces/chain.h>
#include <interfaces/node.h>
#include <qt/addressbookpage.h>
#include <qt/addresstablemodel.h>
#include <qt/editaddressdialog.h>
-#include <qt/callback.h>
#include <qt/optionsmodel.h>
#include <qt/platformstyle.h>
#include <qt/qvalidatedlineedit.h>
#include <qt/walletmodel.h>
#include <key.h>
-#include <pubkey.h>
#include <key_io.h>
+#include <pubkey.h>
#include <wallet/wallet.h>
+#include <QApplication>
#include <QTimer>
#include <QMessageBox>
@@ -56,7 +57,8 @@ void EditAddressAndSubmit(
void TestAddAddressesToSendBook()
{
TestChain100Setup test;
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
+ auto chain = interfaces::MakeChain();
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
@@ -93,6 +95,7 @@ void TestAddAddressesToSendBook()
}
auto check_addbook_size = [&wallet](int expected_size) {
+ LOCK(wallet->cs_wallet);
QCOMPARE(static_cast<int>(wallet->mapAddressBook.size()), expected_size);
};
@@ -139,5 +142,16 @@ void TestAddAddressesToSendBook()
void AddressBookTests::addressBookTests()
{
+#ifdef Q_OS_MAC
+ if (QApplication::platformName() == "minimal") {
+ // Disable for mac on "minimal" platform to avoid crashes inside the Qt
+ // framework when it tries to look up unimplemented cocoa functions,
+ // and fails to handle returned nulls
+ // (https://bugreports.qt.io/browse/QTBUG-49686).
+ QWARN("Skipping AddressBookTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke "
+ "with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build.");
+ return;
+ }
+#endif
TestAddAddressesToSendBook();
}
diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp
new file mode 100644
index 0000000000..da25d83175
--- /dev/null
+++ b/src/qt/test/apptests.cpp
@@ -0,0 +1,115 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <qt/test/apptests.h>
+
+#include <chainparams.h>
+#include <init.h>
+#include <qt/bitcoin.h>
+#include <qt/bitcoingui.h>
+#include <qt/networkstyle.h>
+#include <qt/rpcconsole.h>
+#include <shutdown.h>
+#include <validation.h>
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+#ifdef ENABLE_WALLET
+#include <wallet/db.h>
+#endif
+
+#include <QAction>
+#include <QEventLoop>
+#include <QLineEdit>
+#include <QScopedPointer>
+#include <QTest>
+#include <QTextEdit>
+#include <QtGlobal>
+#include <QtTest/QtTestWidgets>
+#include <QtTest/QtTestGui>
+#include <new>
+#include <string>
+#include <univalue.h>
+
+namespace {
+//! Call getblockchaininfo RPC and check first field of JSON output.
+void TestRpcCommand(RPCConsole* console)
+{
+ QEventLoop loop;
+ QTextEdit* messagesWidget = console->findChild<QTextEdit*>("messagesWidget");
+ QObject::connect(messagesWidget, &QTextEdit::textChanged, &loop, &QEventLoop::quit);
+ QLineEdit* lineEdit = console->findChild<QLineEdit*>("lineEdit");
+ QTest::keyClicks(lineEdit, "getblockchaininfo");
+ QTest::keyClick(lineEdit, Qt::Key_Return);
+ loop.exec();
+ QString output = messagesWidget->toPlainText();
+ UniValue value;
+ value.read(output.right(output.size() - output.lastIndexOf(QChar::ObjectReplacementCharacter) - 1).toStdString());
+ QCOMPARE(value["chain"].get_str(), std::string("regtest"));
+}
+} // namespace
+
+//! Entry point for BitcoinApplication tests.
+void AppTests::appTests()
+{
+#ifdef Q_OS_MAC
+ if (QApplication::platformName() == "minimal") {
+ // Disable for mac on "minimal" platform to avoid crashes inside the Qt
+ // framework when it tries to look up unimplemented cocoa functions,
+ // and fails to handle returned nulls
+ // (https://bugreports.qt.io/browse/QTBUG-49686).
+ QWARN("Skipping AppTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke "
+ "with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build.");
+ return;
+ }
+#endif
+
+ m_app.parameterSetup();
+ m_app.createOptionsModel(true /* reset settings */);
+ QScopedPointer<const NetworkStyle> style(
+ NetworkStyle::instantiate(QString::fromStdString(Params().NetworkIDString())));
+ m_app.setupPlatformStyle();
+ m_app.createWindow(style.data());
+ connect(&m_app, &BitcoinApplication::windowShown, this, &AppTests::guiTests);
+ expectCallback("guiTests");
+ m_app.baseInitialize();
+ m_app.requestInitialize();
+ m_app.exec();
+ m_app.requestShutdown();
+ m_app.exec();
+
+ // Reset global state to avoid interfering with later tests.
+ AbortShutdown();
+ UnloadBlockIndex();
+}
+
+//! Entry point for BitcoinGUI tests.
+void AppTests::guiTests(BitcoinGUI* window)
+{
+ HandleCallback callback{"guiTests", *this};
+ connect(window, &BitcoinGUI::consoleShown, this, &AppTests::consoleTests);
+ expectCallback("consoleTests");
+ QAction* action = window->findChild<QAction*>("openRPCConsoleAction");
+ action->activate(QAction::Trigger);
+}
+
+//! Entry point for RPCConsole tests.
+void AppTests::consoleTests(RPCConsole* console)
+{
+ HandleCallback callback{"consoleTests", *this};
+ TestRpcCommand(console);
+}
+
+//! Destructor to shut down after the last expected callback completes.
+AppTests::HandleCallback::~HandleCallback()
+{
+ auto& callbacks = m_app_tests.m_callbacks;
+ auto it = callbacks.find(m_callback);
+ assert(it != callbacks.end());
+ callbacks.erase(it);
+ if (callbacks.empty()) {
+ m_app_tests.m_app.quit();
+ }
+}
diff --git a/src/qt/test/apptests.h b/src/qt/test/apptests.h
new file mode 100644
index 0000000000..83bf56f1e4
--- /dev/null
+++ b/src/qt/test/apptests.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_QT_TEST_APPTESTS_H
+#define BITCOIN_QT_TEST_APPTESTS_H
+
+#include <QObject>
+#include <set>
+#include <string>
+#include <utility>
+
+class BitcoinApplication;
+class BitcoinGUI;
+class RPCConsole;
+
+class AppTests : public QObject
+{
+ Q_OBJECT
+public:
+ explicit AppTests(BitcoinApplication& app) : m_app(app) {}
+
+private Q_SLOTS:
+ void appTests();
+ void guiTests(BitcoinGUI* window);
+ void consoleTests(RPCConsole* console);
+
+private:
+ //! Add expected callback name to list of pending callbacks.
+ void expectCallback(std::string callback) { m_callbacks.emplace(std::move(callback)); }
+
+ //! RAII helper to remove no-longer-pending callback.
+ struct HandleCallback
+ {
+ std::string m_callback;
+ AppTests& m_app_tests;
+ ~HandleCallback();
+ };
+
+ //! Bitcoin application.
+ BitcoinApplication& m_app;
+
+ //! Set of pending callback names. Used to track expected callbacks and shut
+ //! down the app after the last callback has been handled and all tests have
+ //! either run or thrown exceptions. This could be a simple int counter
+ //! instead of a set of names, but the names might be useful for debugging.
+ std::multiset<std::string> m_callbacks;
+};
+
+#endif // BITCOIN_QT_TEST_APPTESTS_H
diff --git a/src/qt/test/compattests.cpp b/src/qt/test/compattests.cpp
index 3e601583c3..6750c543da 100644
--- a/src/qt/test/compattests.cpp
+++ b/src/qt/test/compattests.cpp
@@ -1,8 +1,14 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
#include <qt/paymentrequestplus.h> // this includes protobuf's port.h which defines its own bswap macos
+#endif
#include <qt/test/compattests.h>
diff --git a/src/qt/test/paymentrequestdata.h b/src/qt/test/paymentrequestdata.h
index 8e5a259f68..7f45d30973 100644
--- a/src/qt/test/paymentrequestdata.h
+++ b/src/qt/test/paymentrequestdata.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2015 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp
index 83484b5ce7..f0eca899fc 100644
--- a/src/qt/test/paymentservertests.cpp
+++ b/src/qt/test/paymentservertests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,8 +13,8 @@
#include <random.h>
#include <script/script.h>
#include <script/standard.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
@@ -39,8 +39,8 @@ X509 *parse_b64der_cert(const char* cert_data)
static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsigned char>& data)
{
RecipientCatcher sigCatcher;
- QObject::connect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
- &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));
+ QObject::connect(server, &PaymentServer::receivedPaymentRequest,
+ &sigCatcher, &RecipientCatcher::getRecipient);
// Write data to a temp file:
QTemporaryFile f;
@@ -57,8 +57,8 @@ static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsig
// which will lead to a test failure anyway.
QCoreApplication::sendEvent(&object, &event);
- QObject::disconnect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
- &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));
+ QObject::disconnect(server, &PaymentServer::receivedPaymentRequest,
+ &sigCatcher, &RecipientCatcher::getRecipient);
// Return results from sigCatcher
return sigCatcher.recipient;
@@ -181,12 +181,12 @@ void PaymentServerTests::paymentServerTests()
QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
// Test BIP70 DoS protection:
- unsigned char randData[BIP70_MAX_PAYMENTREQUEST_SIZE + 1];
- GetRandBytes(randData, sizeof(randData));
+ auto randdata = FastRandomContext().randbytes(BIP70_MAX_PAYMENTREQUEST_SIZE + 1);
+
// Write data to a temp file:
QTemporaryFile tempFile;
tempFile.open();
- tempFile.write((const char*)randData, sizeof(randData));
+ tempFile.write((const char*)randdata.data(), randdata.size());
tempFile.close();
// compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false
QCOMPARE(PaymentServer::verifySize(tempFile.size()), false);
diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h
index f022d2687b..7ef7a0a641 100644
--- a/src/qt/test/paymentservertests.h
+++ b/src/qt/test/paymentservertests.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp
index 974e7831c4..b0bd89b290 100644
--- a/src/qt/test/rpcnestedtests.cpp
+++ b/src/qt/test/rpcnestedtests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,9 +12,9 @@
#include <rpc/register.h>
#include <rpc/server.h>
#include <qt/rpcconsole.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <univalue.h>
-#include <util.h>
+#include <util/system.h>
#include <QDir>
#include <QtGlobal>
@@ -41,7 +41,7 @@ void RPCNestedTests::rpcNestedTests()
TestingSetup test;
- SetRPCWarmupFinished();
+ if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
std::string result;
std::string result2;
@@ -120,7 +120,6 @@ void RPCNestedTests::rpcNestedTests()
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest( abc , cba )");
QVERIFY(result == "[\"abc\",\"cba\"]");
-#if QT_VERSION >= 0x050300
// do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3)
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
@@ -131,5 +130,4 @@ void RPCNestedTests::rpcNestedTests()
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
-#endif
}
diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h
index 7b3b38f62e..e33f4e3da1 100644
--- a/src/qt/test/rpcnestedtests.h
+++ b/src/qt/test/rpcnestedtests.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index f0ac43a58c..a2bf53973b 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,16 +7,21 @@
#endif
#include <chainparams.h>
+#include <interfaces/node.h>
+#include <qt/bitcoin.h>
+#include <qt/test/apptests.h>
#include <qt/test/rpcnestedtests.h>
-#include <util.h>
+#include <util/system.h>
#include <qt/test/uritests.h>
#include <qt/test/compattests.h>
#ifdef ENABLE_WALLET
#include <qt/test/addressbooktests.h>
+#ifdef ENABLE_BIP70
#include <qt/test/paymentservertests.h>
+#endif // ENABLE_BIP70
#include <qt/test/wallettests.h>
-#endif
+#endif // ENABLE_WALLET
#include <QApplication>
#include <QObject>
@@ -45,12 +50,13 @@ int main(int argc, char *argv[])
{
SetupEnvironment();
SetupNetworking();
- SelectParams(CBaseChainParams::MAIN);
+ SelectParams(CBaseChainParams::REGTEST);
noui_connect();
ClearDatadirCache();
fs::path pathTemp = fs::temp_directory_path() / strprintf("test_bitcoin-qt_%lu_%i", (unsigned long)GetTime(), (int)GetRand(100000));
fs::create_directories(pathTemp);
gArgs.ForceSetArg("-datadir", pathTemp.string());
+ auto node = interfaces::MakeNode();
bool fInvalid = false;
@@ -65,16 +71,20 @@ int main(int argc, char *argv[])
// Don't remove this, it's needed to access
// QApplication:: and QCoreApplication:: in the tests
- QApplication app(argc, argv);
+ BitcoinApplication app(*node, argc, argv);
app.setApplicationName("Bitcoin-Qt-test");
SSL_library_init();
+ AppTests app_tests(app);
+ if (QTest::qExec(&app_tests) != 0) {
+ fInvalid = true;
+ }
URITests test1;
if (QTest::qExec(&test1) != 0) {
fInvalid = true;
}
-#ifdef ENABLE_WALLET
+#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
PaymentServerTests test2;
if (QTest::qExec(&test2) != 0) {
fInvalid = true;
diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp
index 59938f704a..b87d3b21ca 100644
--- a/src/qt/test/uritests.cpp
+++ b/src/qt/test/uritests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/test/util.cpp b/src/qt/test/util.cpp
index 261caaaee5..ae2fb93bf7 100644
--- a/src/qt/test/util.cpp
+++ b/src/qt/test/util.cpp
@@ -1,15 +1,13 @@
-#include <qt/callback.h>
-
#include <QApplication>
#include <QMessageBox>
-#include <QTimer>
-#include <QString>
#include <QPushButton>
+#include <QString>
+#include <QTimer>
#include <QWidget>
void ConfirmMessage(QString* text, int msec)
{
- QTimer::singleShot(msec, makeCallback([text](Callback* callback) {
+ QTimer::singleShot(msec, [text]() {
for (QWidget* widget : QApplication::topLevelWidgets()) {
if (widget->inherits("QMessageBox")) {
QMessageBox* messageBox = qobject_cast<QMessageBox*>(widget);
@@ -17,6 +15,5 @@ void ConfirmMessage(QString* text, int msec)
messageBox->defaultButton()->click();
}
}
- delete callback;
- }), SLOT(call()));
+ });
}
diff --git a/src/qt/test/util.h b/src/qt/test/util.h
index 324386c139..377f07dcba 100644
--- a/src/qt/test/util.h
+++ b/src/qt/test/util.h
@@ -1,11 +1,13 @@
#ifndef BITCOIN_QT_TEST_UTIL_H
#define BITCOIN_QT_TEST_UTIL_H
+#include <QString>
+
/**
* Press "Ok" button in message box dialog.
*
* @param text - Optionally store dialog text.
- * @param msec - Number of miliseconds to pause before triggering the callback.
+ * @param msec - Number of milliseconds to pause before triggering the callback.
*/
void ConfirmMessage(QString* text = nullptr, int msec = 0);
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index c314dadde4..21209d4994 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -1,9 +1,11 @@
#include <qt/test/wallettests.h>
#include <qt/test/util.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <interfaces/node.h>
+#include <base58.h>
#include <qt/bitcoinamountfield.h>
-#include <qt/callback.h>
#include <qt/optionsmodel.h>
#include <qt/platformstyle.h>
#include <qt/qvalidatedlineedit.h>
@@ -13,7 +15,7 @@
#include <qt/transactionview.h>
#include <qt/walletmodel.h>
#include <key_io.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <validation.h>
#include <wallet/wallet.h>
#include <qt/overviewpage.h>
@@ -39,7 +41,7 @@ namespace
//! Press "Yes" or "Cancel" buttons in modal send confirmation dialog.
void ConfirmSend(QString* text = nullptr, bool cancel = false)
{
- QTimer::singleShot(0, makeCallback([text, cancel](Callback* callback) {
+ QTimer::singleShot(0, [text, cancel]() {
for (QWidget* widget : QApplication::topLevelWidgets()) {
if (widget->inherits("SendConfirmationDialog")) {
SendConfirmationDialog* dialog = qobject_cast<SendConfirmationDialog*>(widget);
@@ -49,8 +51,7 @@ void ConfirmSend(QString* text = nullptr, bool cancel = false)
button->click();
}
}
- delete callback;
- }), SLOT(call()));
+ });
}
//! Send coins to address and return txid.
@@ -133,7 +134,8 @@ void TestGUI()
for (int i = 0; i < 5; ++i) {
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
}
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
+ auto chain = interfaces::MakeChain();
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
{
@@ -142,10 +144,15 @@ void TestGUI()
wallet->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
}
{
- LOCK(cs_main);
+ auto locked_chain = wallet->chain().lock();
+ LockAnnotation lock(::cs_main);
+
WalletRescanReserver reserver(wallet.get());
reserver.reserve();
- wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver, true);
+ CWallet::ScanResult result = wallet->ScanForWalletTransactions(locked_chain->getBlockHash(0), {} /* stop_block */, reserver, true /* fUpdate */);
+ QCOMPARE(result.status, CWallet::ScanResult::SUCCESS);
+ QCOMPARE(result.last_scanned_block, ::ChainActive().Tip()->GetBlockHash());
+ QVERIFY(result.last_failed_block.IsNull());
}
wallet->SetBroadcastTransactions(true);
@@ -164,8 +171,8 @@ void TestGUI()
// Send two transactions, and verify they are added to transaction list.
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
QCOMPARE(transactionTableModel->rowCount({}), 105);
- uint256 txid1 = SendCoins(*wallet.get(), sendCoinsDialog, CKeyID(), 5 * COIN, false /* rbf */);
- uint256 txid2 = SendCoins(*wallet.get(), sendCoinsDialog, CKeyID(), 10 * COIN, true /* rbf */);
+ uint256 txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, false /* rbf */);
+ uint256 txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN, true /* rbf */);
QCOMPARE(transactionTableModel->rowCount({}), 107);
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
@@ -243,5 +250,16 @@ void TestGUI()
void WalletTests::walletTests()
{
+#ifdef Q_OS_MAC
+ if (QApplication::platformName() == "minimal") {
+ // Disable for mac on "minimal" platform to avoid crashes inside the Qt
+ // framework when it tries to look up unimplemented cocoa functions,
+ // and fails to handle returned nulls
+ // (https://bugreports.qt.io/browse/QTBUG-49686).
+ QWARN("Skipping WalletTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke "
+ "with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build.");
+ return;
+ }
+#endif
TestGUI();
}
diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp
index a5551ec014..1588be8da3 100644
--- a/src/qt/trafficgraphwidget.cpp
+++ b/src/qt/trafficgraphwidget.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,17 +19,17 @@
TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
QWidget(parent),
- timer(0),
+ timer(nullptr),
fMax(0.0f),
nMins(0),
vSamplesIn(),
vSamplesOut(),
nLastBytesIn(0),
nLastBytesOut(0),
- clientModel(0)
+ clientModel(nullptr)
{
timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), SLOT(updateRates()));
+ connect(timer, &QTimer::timeout, this, &TrafficGraphWidget::updateRates);
}
void TrafficGraphWidget::setClientModel(ClientModel *model)
@@ -141,10 +141,10 @@ void TrafficGraphWidget::updateRates()
}
float tmax = 0.0f;
- for (float f : vSamplesIn) {
+ for (const float f : vSamplesIn) {
if(f > tmax) tmax = f;
}
- for (float f : vSamplesOut) {
+ for (const float f : vSamplesOut) {
if(f > tmax) tmax = f;
}
fMax = tmax;
diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h
index 00660574af..48bd246b34 100644
--- a/src/qt/trafficgraphwidget.h
+++ b/src/qt/trafficgraphwidget.h
@@ -20,7 +20,7 @@ class TrafficGraphWidget : public QWidget
Q_OBJECT
public:
- explicit TrafficGraphWidget(QWidget *parent = 0);
+ explicit TrafficGraphWidget(QWidget *parent = nullptr);
void setClientModel(ClientModel *model);
int getGraphRangeMins() const;
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 8297f75799..0d070d9e87 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -1,7 +1,11 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifdef HAVE_CONFIG_H
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/transactiondesc.h>
#include <qt/bitcoinunits.h>
@@ -15,7 +19,7 @@
#include <validation.h>
#include <script/script.h>
#include <timedata.h>
-#include <util.h>
+#include <util/system.h>
#include <wallet/db.h>
#include <wallet/wallet.h>
#include <policy/policy.h>
@@ -23,7 +27,7 @@
#include <stdint.h>
#include <string>
-QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks, int64_t adjustedTime)
+QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks)
{
if (!status.is_final)
{
@@ -49,11 +53,10 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i
QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
{
int numBlocks;
- int64_t adjustedTime;
interfaces::WalletTxStatus status;
interfaces::WalletOrderForm orderForm;
bool inMempool;
- interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks, adjustedTime);
+ interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks);
QString strHTML;
@@ -65,7 +68,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
CAmount nDebit = wtx.debit;
CAmount nNet = nCredit - nDebit;
- strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks, adjustedTime);
+ strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks);
strHTML += "<br>";
strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
@@ -152,13 +155,13 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
else
{
isminetype fAllFromMe = ISMINE_SPENDABLE;
- for (isminetype mine : wtx.txin_is_mine)
+ for (const isminetype mine : wtx.txin_is_mine)
{
if(fAllFromMe > mine) fAllFromMe = mine;
}
isminetype fAllToMe = ISMINE_SPENDABLE;
- for (isminetype mine : wtx.txout_is_mine)
+ for (const isminetype mine : wtx.txout_is_mine)
{
if(fAllToMe > mine) fAllToMe = mine;
}
@@ -257,6 +260,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
if (r.first == "Message")
strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
+#ifdef ENABLE_BIP70
//
// PaymentRequest info:
//
@@ -271,6 +275,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
}
}
+#endif
if (wtx.is_coinbase)
{
diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h
index cb8453cb81..cf955a433c 100644
--- a/src/qt/transactiondesc.h
+++ b/src/qt/transactiondesc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2014 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -29,7 +29,7 @@ public:
private:
TransactionDesc() {}
- static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks, int64_t adjustedTime);
+ static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks);
};
#endif // BITCOIN_QT_TRANSACTIONDESC_H
diff --git a/src/qt/transactiondescdialog.cpp b/src/qt/transactiondescdialog.cpp
index 7bf4d3351c..ca72720e00 100644
--- a/src/qt/transactiondescdialog.cpp
+++ b/src/qt/transactiondescdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/transactiondescdialog.h b/src/qt/transactiondescdialog.h
index f1371b3856..8fd3f3166a 100644
--- a/src/qt/transactiondescdialog.h
+++ b/src/qt/transactiondescdialog.h
@@ -21,7 +21,7 @@ class TransactionDescDialog : public QDialog
Q_OBJECT
public:
- explicit TransactionDescDialog(const QModelIndex &idx, QWidget *parent = 0);
+ explicit TransactionDescDialog(const QModelIndex &idx, QWidget *parent = nullptr);
~TransactionDescDialog();
private:
diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp
index 6301af7553..a631f497af 100644
--- a/src/qt/transactionfilterproxy.cpp
+++ b/src/qt/transactionfilterproxy.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h
index 226cf3f3b5..685f8d3a26 100644
--- a/src/qt/transactionfilterproxy.h
+++ b/src/qt/transactionfilterproxy.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,7 +16,7 @@ class TransactionFilterProxy : public QSortFilterProxyModel
Q_OBJECT
public:
- explicit TransactionFilterProxy(QObject *parent = 0);
+ explicit TransactionFilterProxy(QObject *parent = nullptr);
/** Earliest date that can be represented (far in the past) */
static const QDateTime MIN_DATE;
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 65f5e87d15..aa785553c8 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -1,9 +1,10 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <qt/transactionrecord.h>
+#include <chain.h>
#include <consensus/consensus.h>
#include <interfaces/wallet.h>
#include <key_io.h>
@@ -12,6 +13,7 @@
#include <stdint.h>
+#include <QDateTime>
/* Return positive answer if transaction should be shown in list.
*/
@@ -77,14 +79,14 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface
{
bool involvesWatchAddress = false;
isminetype fAllFromMe = ISMINE_SPENDABLE;
- for (isminetype mine : wtx.txin_is_mine)
+ for (const isminetype mine : wtx.txin_is_mine)
{
if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
if(fAllFromMe > mine) fAllFromMe = mine;
}
isminetype fAllToMe = ISMINE_SPENDABLE;
- for (isminetype mine : wtx.txout_is_mine)
+ for (const isminetype mine : wtx.txout_is_mine)
{
if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true;
if(fAllToMe > mine) fAllToMe = mine;
@@ -158,7 +160,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface
return parts;
}
-void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t adjustedTime)
+void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t block_time)
{
// Determine transaction status
@@ -172,10 +174,9 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int
status.depth = wtx.depth_in_main_chain;
status.cur_num_blocks = numBlocks;
- if (!wtx.is_final)
- {
- if (wtx.lock_time < LOCKTIME_THRESHOLD)
- {
+ const bool up_to_date = ((int64_t)QDateTime::currentMSecsSinceEpoch() / 1000 - block_time < MAX_BLOCK_TIME_GAP);
+ if (up_to_date && !wtx.is_final) {
+ if (wtx.lock_time < LOCKTIME_THRESHOLD) {
status.status = TransactionStatus::OpenUntilBlock;
status.open_for = wtx.lock_time - numBlocks;
}
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index a6424e74fa..3f64cefd09 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -138,7 +138,7 @@ public:
/** Update status from core wallet tx.
*/
- void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t adjustedTime);
+ void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t block_time);
/** Return whether a status update is needed.
*/
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 63a4afe191..631a9b891d 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,10 +16,10 @@
#include <core_io.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
-#include <validation.h>
#include <sync.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
+#include <validation.h>
#include <QColor>
#include <QDateTime>
@@ -27,6 +27,7 @@
#include <QIcon>
#include <QList>
+
// Amount column is right-aligned it contains numbers
static int column_alignments[] = {
Qt::AlignLeft|Qt::AlignVCenter, /* status */
@@ -58,7 +59,7 @@ struct TxLessThan
class TransactionTablePriv
{
public:
- TransactionTablePriv(TransactionTableModel *_parent) :
+ explicit TransactionTablePriv(TransactionTableModel *_parent) :
parent(_parent)
{
}
@@ -191,13 +192,13 @@ public:
// simply re-use the cached status.
interfaces::WalletTxStatus wtx;
int numBlocks;
- int64_t adjustedTime;
- if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, adjustedTime) && rec->statusUpdateNeeded(numBlocks)) {
- rec->updateStatus(wtx, numBlocks, adjustedTime);
+ int64_t block_time;
+ if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time) && rec->statusUpdateNeeded(numBlocks)) {
+ rec->updateStatus(wtx, numBlocks, block_time);
}
return rec;
}
- return 0;
+ return nullptr;
}
QString describe(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
@@ -226,7 +227,7 @@ TransactionTableModel::TransactionTableModel(const PlatformStyle *_platformStyle
columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
priv->refreshWallet(walletModel->wallet());
- connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
+ connect(walletModel->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &TransactionTableModel::updateDisplayUnit);
subscribeToCoreSignals();
}
@@ -744,8 +745,8 @@ static void ShowProgress(TransactionTableModel *ttm, const std::string &title, i
void TransactionTableModel::subscribeToCoreSignals()
{
// Connect signals to wallet
- m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2));
- m_handler_show_progress = walletModel->wallet().handleShowProgress(boost::bind(ShowProgress, this, _1, _2));
+ m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2));
+ m_handler_show_progress = walletModel->wallet().handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2));
}
void TransactionTableModel::unsubscribeFromCoreSignals()
diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h
index 8b029be5f5..7a7d98962b 100644
--- a/src/qt/transactiontablemodel.h
+++ b/src/qt/transactiontablemodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -28,7 +28,7 @@ class TransactionTableModel : public QAbstractTableModel
Q_OBJECT
public:
- explicit TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent = 0);
+ explicit TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent = nullptr);
~TransactionTableModel();
enum ColumnIndex {
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index e60a387934..762ec434a1 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,6 +19,7 @@
#include <ui_interface.h>
+#include <QApplication>
#include <QComboBox>
#include <QDateTimeEdit>
#include <QDesktopServices>
@@ -37,8 +38,8 @@
#include <QVBoxLayout>
TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
- QWidget(parent), model(0), transactionProxyModel(0),
- transactionView(0), abandonAction(0), bumpFeeAction(0), columnResizingFixer(0)
+ QWidget(parent), model(nullptr), transactionProxyModel(nullptr),
+ transactionView(nullptr), abandonAction(nullptr), bumpFeeAction(nullptr), columnResizingFixer(nullptr)
{
// Build filter row
setContentsMargins(0,0,0,0);
@@ -105,7 +106,11 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
} else {
amountWidget->setFixedWidth(100);
}
- amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
+ QDoubleValidator *amountValidator = new QDoubleValidator(0, 1e20, 8, this);
+ QLocale amountLocale(QLocale::C);
+ amountLocale.setNumberOptions(QLocale::RejectGroupSeparator);
+ amountValidator->setLocale(amountLocale);
+ amountWidget->setValidator(amountValidator);
hlayout->addWidget(amountWidget);
// Delay before filtering transactions in ms
@@ -175,29 +180,35 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
mapperThirdPartyTxUrls = new QSignalMapper(this);
// Connect actions
- connect(mapperThirdPartyTxUrls, SIGNAL(mapped(QString)), this, SLOT(openThirdPartyTxUrl(QString)));
-
- connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
- connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
- connect(watchOnlyWidget, SIGNAL(activated(int)), this, SLOT(chooseWatchonly(int)));
- connect(amountWidget, SIGNAL(textChanged(QString)), amount_typing_delay, SLOT(start()));
- connect(amount_typing_delay, SIGNAL(timeout()), this, SLOT(changedAmount()));
- connect(search_widget, SIGNAL(textChanged(QString)), prefix_typing_delay, SLOT(start()));
- connect(prefix_typing_delay, SIGNAL(timeout()), this, SLOT(changedSearch()));
-
- connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex)));
- connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
-
- connect(bumpFeeAction, SIGNAL(triggered()), this, SLOT(bumpFee()));
- connect(abandonAction, SIGNAL(triggered()), this, SLOT(abandonTx()));
- connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
- connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
- connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
- connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID()));
- connect(copyTxHexAction, SIGNAL(triggered()), this, SLOT(copyTxHex()));
- connect(copyTxPlainText, SIGNAL(triggered()), this, SLOT(copyTxPlainText()));
- connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel()));
- connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
+ connect(mapperThirdPartyTxUrls, static_cast<void (QSignalMapper::*)(const QString&)>(&QSignalMapper::mapped), this, &TransactionView::openThirdPartyTxUrl);
+
+ connect(dateWidget, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &TransactionView::chooseDate);
+ connect(typeWidget, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &TransactionView::chooseType);
+ connect(watchOnlyWidget, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &TransactionView::chooseWatchonly);
+ connect(amountWidget, &QLineEdit::textChanged, amount_typing_delay, static_cast<void (QTimer::*)()>(&QTimer::start));
+ connect(amount_typing_delay, &QTimer::timeout, this, &TransactionView::changedAmount);
+ connect(search_widget, &QLineEdit::textChanged, prefix_typing_delay, static_cast<void (QTimer::*)()>(&QTimer::start));
+ connect(prefix_typing_delay, &QTimer::timeout, this, &TransactionView::changedSearch);
+
+ connect(view, &QTableView::doubleClicked, this, &TransactionView::doubleClicked);
+ connect(view, &QTableView::customContextMenuRequested, this, &TransactionView::contextualMenu);
+
+ connect(bumpFeeAction, &QAction::triggered, this, &TransactionView::bumpFee);
+ connect(abandonAction, &QAction::triggered, this, &TransactionView::abandonTx);
+ connect(copyAddressAction, &QAction::triggered, this, &TransactionView::copyAddress);
+ connect(copyLabelAction, &QAction::triggered, this, &TransactionView::copyLabel);
+ connect(copyAmountAction, &QAction::triggered, this, &TransactionView::copyAmount);
+ connect(copyTxIDAction, &QAction::triggered, this, &TransactionView::copyTxID);
+ connect(copyTxHexAction, &QAction::triggered, this, &TransactionView::copyTxHex);
+ connect(copyTxPlainText, &QAction::triggered, this, &TransactionView::copyTxPlainText);
+ connect(editLabelAction, &QAction::triggered, this, &TransactionView::editLabel);
+ connect(showDetailsAction, &QAction::triggered, this, &TransactionView::showDetails);
+ // Double-clicking on a transaction on the transaction history page shows details
+ connect(this, &TransactionView::doubleClicked, this, &TransactionView::showDetails);
+ // Highlight transaction after fee bump
+ connect(this, &TransactionView::bumpedFee, [this](const uint256& txid) {
+ focusTransaction(txid);
+ });
}
void TransactionView::setModel(WalletModel *_model)
@@ -218,8 +229,8 @@ void TransactionView::setModel(WalletModel *_model)
transactionView->setAlternatingRowColors(true);
transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ transactionView->horizontalHeader()->setSortIndicator(TransactionTableModel::Date, Qt::DescendingOrder);
transactionView->setSortingEnabled(true);
- transactionView->sortByColumn(TransactionTableModel::Date, Qt::DescendingOrder);
transactionView->verticalHeader()->hide();
transactionView->setColumnWidth(TransactionTableModel::Status, STATUS_COLUMN_WIDTH);
@@ -243,7 +254,7 @@ void TransactionView::setModel(WalletModel *_model)
if (i == 0)
contextMenu->addSeparator();
contextMenu->addAction(thirdPartyTxUrlAction);
- connect(thirdPartyTxUrlAction, SIGNAL(triggered()), mapperThirdPartyTxUrls, SLOT(map()));
+ connect(thirdPartyTxUrlAction, &QAction::triggered, mapperThirdPartyTxUrls, static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map));
mapperThirdPartyTxUrls->setMapping(thirdPartyTxUrlAction, listUrls[i].trimmed());
}
}
@@ -253,7 +264,7 @@ void TransactionView::setModel(WalletModel *_model)
updateWatchOnlyColumn(_model->wallet().haveWatchOnly());
// Watch-only signal
- connect(_model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool)));
+ connect(_model, &WalletModel::notifyWatchonlyChanged, this, &TransactionView::updateWatchOnlyColumn);
}
}
@@ -428,9 +439,14 @@ void TransactionView::bumpFee()
hash.SetHex(hashQStr.toStdString());
// Bump tx fee over the walletModel
- if (model->bumpFee(hash)) {
+ uint256 newHash;
+ if (model->bumpFee(hash, newHash)) {
// Update the table
+ transactionView->selectionModel()->clearSelection();
model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, true);
+
+ qApp->processEvents();
+ Q_EMIT bumpedFee(newHash);
}
}
@@ -562,8 +578,8 @@ QWidget *TransactionView::createDateRangeWidget()
dateRangeWidget->setVisible(false);
// Notify on change
- connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
- connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
+ connect(dateFrom, &QDateTimeEdit::dateChanged, this, &TransactionView::dateRangeChanged);
+ connect(dateTo, &QDateTimeEdit::dateChanged, this, &TransactionView::dateRangeChanged);
return dateRangeWidget;
}
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 66dc5bc86b..e07181d1c8 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -35,7 +35,7 @@ class TransactionView : public QWidget
Q_OBJECT
public:
- explicit TransactionView(const PlatformStyle *platformStyle, QWidget *parent = 0);
+ explicit TransactionView(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
void setModel(WalletModel *model);
@@ -110,6 +110,8 @@ Q_SIGNALS:
/** Fired when a message should be reported to the user */
void message(const QString &title, const QString &message, unsigned int style);
+ void bumpedFee(const uint256& txid);
+
public Q_SLOTS:
void chooseDate(int idx);
void chooseType(int idx);
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 1da25b0761..b051dd159b 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,13 +14,16 @@
#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/intro.h>
+#ifdef ENABLE_BIP70
#include <qt/paymentrequestplus.h>
+#endif
#include <qt/guiutil.h>
#include <clientversion.h>
#include <init.h>
#include <interfaces/node.h>
-#include <util.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <stdio.h>
@@ -52,9 +55,9 @@ HelpMessageDialog::HelpMessageDialog(interfaces::Node& node, QWidget *parent, bo
{
setWindowTitle(tr("About %1").arg(tr(PACKAGE_NAME)));
+ std::string licenseInfo = LicenseInfo();
/// HTML-format the license message from the core
- QString licenseInfo = QString::fromStdString(LicenseInfo());
- QString licenseInfoHTML = licenseInfo;
+ QString licenseInfoHTML = QString::fromStdString(LicenseInfo());
// Make URLs clickable
QRegExp uri("<(.*)>", Qt::CaseSensitive, QRegExp::RegExp2);
uri.setMinimal(true); // use non-greedy matching
@@ -64,14 +67,13 @@ HelpMessageDialog::HelpMessageDialog(interfaces::Node& node, QWidget *parent, bo
ui->aboutMessage->setTextFormat(Qt::RichText);
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- text = version + "\n" + licenseInfo;
+ text = version + "\n" + QString::fromStdString(FormatParagraph(licenseInfo));
ui->aboutMessage->setText(version + "<br><br>" + licenseInfoHTML);
ui->aboutMessage->setWordWrap(true);
ui->helpMessage->setVisible(false);
} else {
setWindowTitle(tr("Command-line options"));
- QString header = "Usage:\n"
- " bitcoin-qt [command-line options] \n";
+ QString header = "Usage: bitcoin-qt [command-line options] \n";
QTextCursor cursor(ui->helpMessage->document());
cursor.insertText(version);
cursor.insertBlock();
@@ -80,7 +82,7 @@ HelpMessageDialog::HelpMessageDialog(interfaces::Node& node, QWidget *parent, bo
std::string strUsage = gArgs.GetHelpMessage();
QString coreOptions = QString::fromStdString(strUsage);
- text = version + "\n" + header + "\n" + coreOptions;
+ text = version + "\n\n" + header + "\n" + coreOptions;
QTextTableFormat tf;
tf.setBorderStyle(QTextFrameFormat::BorderStyle_None);
diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h
index f5c8af4362..f1cedff282 100644
--- a/src/qt/utilitydialog.h
+++ b/src/qt/utilitydialog.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -45,7 +45,7 @@ class ShutdownWindow : public QWidget
Q_OBJECT
public:
- explicit ShutdownWindow(QWidget *parent=0, Qt::WindowFlags f=0);
+ explicit ShutdownWindow(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::Widget);
static QWidget *showShutdownWindow(BitcoinGUI *window);
protected:
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
new file mode 100644
index 0000000000..019bd65823
--- /dev/null
+++ b/src/qt/walletcontroller.cpp
@@ -0,0 +1,169 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <qt/walletcontroller.h>
+
+#include <interfaces/handler.h>
+#include <interfaces/node.h>
+
+#include <algorithm>
+
+#include <QApplication>
+#include <QMessageBox>
+#include <QMutexLocker>
+#include <QThread>
+#include <QWindow>
+
+WalletController::WalletController(interfaces::Node& node, const PlatformStyle* platform_style, OptionsModel* options_model, QObject* parent)
+ : QObject(parent)
+ , m_node(node)
+ , m_platform_style(platform_style)
+ , m_options_model(options_model)
+{
+ m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
+ getOrCreateWallet(std::move(wallet));
+ });
+
+ for (std::unique_ptr<interfaces::Wallet>& wallet : m_node.getWallets()) {
+ getOrCreateWallet(std::move(wallet));
+ }
+
+ m_activity_thread.start();
+}
+
+// Not using the default destructor because not all member types definitions are
+// available in the header, just forward declared.
+WalletController::~WalletController()
+{
+ m_activity_thread.quit();
+ m_activity_thread.wait();
+}
+
+std::vector<WalletModel*> WalletController::getWallets() const
+{
+ QMutexLocker locker(&m_mutex);
+ return m_wallets;
+}
+
+std::vector<std::string> WalletController::getWalletsAvailableToOpen() const
+{
+ QMutexLocker locker(&m_mutex);
+ std::vector<std::string> wallets = m_node.listWalletDir();
+ for (WalletModel* wallet_model : m_wallets) {
+ auto it = std::remove(wallets.begin(), wallets.end(), wallet_model->wallet().getWalletName());
+ if (it != wallets.end()) wallets.erase(it);
+ }
+ return wallets;
+}
+
+OpenWalletActivity* WalletController::openWallet(const std::string& name, QWidget* parent)
+{
+ OpenWalletActivity* activity = new OpenWalletActivity(this, name);
+ activity->moveToThread(&m_activity_thread);
+ return activity;
+}
+
+void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent)
+{
+ QMessageBox box(parent);
+ box.setWindowTitle(tr("Close wallet"));
+ box.setText(tr("Are you sure you wish to close wallet <i>%1</i>?").arg(wallet_model->getDisplayName()));
+ box.setInformativeText(tr("Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled."));
+ box.setStandardButtons(QMessageBox::Yes|QMessageBox::Cancel);
+ box.setDefaultButton(QMessageBox::Yes);
+ if (box.exec() != QMessageBox::Yes) return;
+
+ // First remove wallet from node.
+ wallet_model->wallet().remove();
+ // Now release the model.
+ removeAndDeleteWallet(wallet_model);
+}
+
+WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet)
+{
+ QMutexLocker locker(&m_mutex);
+
+ // Return model instance if exists.
+ if (!m_wallets.empty()) {
+ std::string name = wallet->getWalletName();
+ for (WalletModel* wallet_model : m_wallets) {
+ if (wallet_model->wallet().getWalletName() == name) {
+ return wallet_model;
+ }
+ }
+ }
+
+ // Instantiate model and register it.
+ WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, m_platform_style, m_options_model, nullptr);
+ m_wallets.push_back(wallet_model);
+
+ connect(wallet_model, &WalletModel::unload, [this, wallet_model] {
+ // Defer removeAndDeleteWallet when no modal widget is active.
+ // TODO: remove this workaround by removing usage of QDiallog::exec.
+ if (QApplication::activeModalWidget()) {
+ connect(qApp, &QApplication::focusWindowChanged, wallet_model, [this, wallet_model]() {
+ if (!QApplication::activeModalWidget()) {
+ removeAndDeleteWallet(wallet_model);
+ }
+ }, Qt::QueuedConnection);
+ } else {
+ removeAndDeleteWallet(wallet_model);
+ }
+ });
+
+ // Re-emit coinsSent signal from wallet model.
+ connect(wallet_model, &WalletModel::coinsSent, this, &WalletController::coinsSent);
+
+ // Notify walletAdded signal on the GUI thread.
+ if (QThread::currentThread() == thread()) {
+ addWallet(wallet_model);
+ } else {
+ // Handler callback runs in a different thread so fix wallet model thread affinity.
+ wallet_model->moveToThread(thread());
+ QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model));
+ }
+
+ return wallet_model;
+}
+
+void WalletController::addWallet(WalletModel* wallet_model)
+{
+ // Take ownership of the wallet model and register it.
+ wallet_model->setParent(this);
+ Q_EMIT walletAdded(wallet_model);
+}
+
+void WalletController::removeAndDeleteWallet(WalletModel* wallet_model)
+{
+ // Unregister wallet model.
+ {
+ QMutexLocker locker(&m_mutex);
+ m_wallets.erase(std::remove(m_wallets.begin(), m_wallets.end(), wallet_model));
+ }
+ Q_EMIT walletRemoved(wallet_model);
+ // Currently this can trigger the unload since the model can hold the last
+ // CWallet shared pointer.
+ delete wallet_model;
+}
+
+
+OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, const std::string& name)
+ : m_wallet_controller(wallet_controller)
+ , m_name(name)
+{}
+
+void OpenWalletActivity::open()
+{
+ std::string error, warning;
+ std::unique_ptr<interfaces::Wallet> wallet = m_wallet_controller->m_node.loadWallet(m_name, error, warning);
+ if (!warning.empty()) {
+ Q_EMIT message(QMessageBox::Warning, QString::fromStdString(warning));
+ }
+ if (wallet) {
+ Q_EMIT opened(m_wallet_controller->getOrCreateWallet(std::move(wallet)));
+ } else {
+ Q_EMIT message(QMessageBox::Critical, QString::fromStdString(error));
+ }
+ Q_EMIT finished();
+}
diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h
new file mode 100644
index 0000000000..19b3a82253
--- /dev/null
+++ b/src/qt/walletcontroller.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_QT_WALLETCONTROLLER_H
+#define BITCOIN_QT_WALLETCONTROLLER_H
+
+#include <qt/walletmodel.h>
+#include <sync.h>
+
+#include <list>
+#include <memory>
+#include <vector>
+
+#include <QMessageBox>
+#include <QMutex>
+#include <QThread>
+
+class OptionsModel;
+class PlatformStyle;
+
+namespace interfaces {
+class Handler;
+class Node;
+} // namespace interfaces
+
+class OpenWalletActivity;
+
+/**
+ * Controller between interfaces::Node, WalletModel instances and the GUI.
+ */
+class WalletController : public QObject
+{
+ Q_OBJECT
+
+ WalletModel* getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet);
+ void removeAndDeleteWallet(WalletModel* wallet_model);
+
+public:
+ WalletController(interfaces::Node& node, const PlatformStyle* platform_style, OptionsModel* options_model, QObject* parent);
+ ~WalletController();
+
+ std::vector<WalletModel*> getWallets() const;
+ std::vector<std::string> getWalletsAvailableToOpen() const;
+
+ OpenWalletActivity* openWallet(const std::string& name, QWidget* parent = nullptr);
+ void closeWallet(WalletModel* wallet_model, QWidget* parent = nullptr);
+
+private Q_SLOTS:
+ void addWallet(WalletModel* wallet_model);
+
+Q_SIGNALS:
+ void walletAdded(WalletModel* wallet_model);
+ void walletRemoved(WalletModel* wallet_model);
+
+ void coinsSent(WalletModel* wallet_model, SendCoinsRecipient recipient, QByteArray transaction);
+
+private:
+ QThread m_activity_thread;
+ interfaces::Node& m_node;
+ const PlatformStyle* const m_platform_style;
+ OptionsModel* const m_options_model;
+ mutable QMutex m_mutex;
+ std::vector<WalletModel*> m_wallets;
+ std::unique_ptr<interfaces::Handler> m_handler_load_wallet;
+
+ friend class OpenWalletActivity;
+};
+
+class OpenWalletActivity : public QObject
+{
+ Q_OBJECT
+
+public:
+ OpenWalletActivity(WalletController* wallet_controller, const std::string& name);
+
+public Q_SLOTS:
+ void open();
+
+Q_SIGNALS:
+ void message(QMessageBox::Icon icon, const QString text);
+ void finished();
+ void opened(WalletModel* wallet_model);
+
+private:
+ WalletController* const m_wallet_controller;
+ std::string const m_name;
+};
+
+#endif // BITCOIN_QT_WALLETCONTROLLER_H
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index c5a13f61f4..94413547d4 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -40,16 +40,11 @@ void WalletFrame::setClientModel(ClientModel *_clientModel)
this->clientModel = _clientModel;
}
-bool WalletFrame::addWallet(WalletModel *walletModel)
+void WalletFrame::addWallet(WalletModel *walletModel)
{
- if (!gui || !clientModel || !walletModel) {
- return false;
- }
+ if (!gui || !clientModel || !walletModel) return;
- const QString name = walletModel->getWalletName();
- if (mapWalletViews.count(name) > 0) {
- return false;
- }
+ if (mapWalletViews.count(walletModel) > 0) return;
WalletView *walletView = new WalletView(platformStyle, this);
walletView->setBitcoinGUI(gui);
@@ -65,42 +60,38 @@ bool WalletFrame::addWallet(WalletModel *walletModel)
}
walletStack->addWidget(walletView);
- mapWalletViews[name] = walletView;
+ mapWalletViews[walletModel] = walletView;
// Ensure a walletView is able to show the main window
- connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized()));
-
- connect(walletView, SIGNAL(outOfSyncWarningClicked()), this, SLOT(outOfSyncWarningClicked()));
+ connect(walletView, &WalletView::showNormalIfMinimized, [this]{
+ gui->showNormalIfMinimized();
+ });
- return true;
+ connect(walletView, &WalletView::outOfSyncWarningClicked, this, &WalletFrame::outOfSyncWarningClicked);
}
-bool WalletFrame::setCurrentWallet(const QString& name)
+void WalletFrame::setCurrentWallet(WalletModel* wallet_model)
{
- if (mapWalletViews.count(name) == 0)
- return false;
+ if (mapWalletViews.count(wallet_model) == 0) return;
- WalletView *walletView = mapWalletViews.value(name);
+ WalletView *walletView = mapWalletViews.value(wallet_model);
walletStack->setCurrentWidget(walletView);
assert(walletView);
walletView->updateEncryptionStatus();
- return true;
}
-bool WalletFrame::removeWallet(const QString &name)
+void WalletFrame::removeWallet(WalletModel* wallet_model)
{
- if (mapWalletViews.count(name) == 0)
- return false;
+ if (mapWalletViews.count(wallet_model) == 0) return;
- WalletView *walletView = mapWalletViews.take(name);
+ WalletView *walletView = mapWalletViews.take(wallet_model);
walletStack->removeWidget(walletView);
delete walletView;
- return true;
}
void WalletFrame::removeAllWallets()
{
- QMap<QString, WalletView*>::const_iterator i;
+ QMap<WalletModel*, WalletView*>::const_iterator i;
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
walletStack->removeWidget(i.value());
mapWalletViews.clear();
@@ -118,35 +109,35 @@ bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient)
void WalletFrame::showOutOfSyncWarning(bool fShow)
{
bOutOfSync = fShow;
- QMap<QString, WalletView*>::const_iterator i;
+ QMap<WalletModel*, WalletView*>::const_iterator i;
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
i.value()->showOutOfSyncWarning(fShow);
}
void WalletFrame::gotoOverviewPage()
{
- QMap<QString, WalletView*>::const_iterator i;
+ QMap<WalletModel*, WalletView*>::const_iterator i;
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
i.value()->gotoOverviewPage();
}
void WalletFrame::gotoHistoryPage()
{
- QMap<QString, WalletView*>::const_iterator i;
+ QMap<WalletModel*, WalletView*>::const_iterator i;
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
i.value()->gotoHistoryPage();
}
void WalletFrame::gotoReceiveCoinsPage()
{
- QMap<QString, WalletView*>::const_iterator i;
+ QMap<WalletModel*, WalletView*>::const_iterator i;
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
i.value()->gotoReceiveCoinsPage();
}
void WalletFrame::gotoSendCoinsPage(QString addr)
{
- QMap<QString, WalletView*>::const_iterator i;
+ QMap<WalletModel*, WalletView*>::const_iterator i;
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
i.value()->gotoSendCoinsPage(addr);
}
@@ -207,11 +198,17 @@ void WalletFrame::usedReceivingAddresses()
walletView->usedReceivingAddresses();
}
-WalletView *WalletFrame::currentWalletView()
+WalletView* WalletFrame::currentWalletView() const
{
return qobject_cast<WalletView*>(walletStack->currentWidget());
}
+WalletModel* WalletFrame::currentWalletModel() const
+{
+ WalletView* wallet_view = currentWalletView();
+ return wallet_view ? wallet_view->getWalletModel() : nullptr;
+}
+
void WalletFrame::outOfSyncWarningClicked()
{
Q_EMIT requestedSyncWarningInfo();
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index 6eedcf370c..156653f47d 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2016 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -31,14 +31,14 @@ class WalletFrame : public QFrame
Q_OBJECT
public:
- explicit WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui = 0);
+ explicit WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui = nullptr);
~WalletFrame();
void setClientModel(ClientModel *clientModel);
- bool addWallet(WalletModel *walletModel);
- bool setCurrentWallet(const QString& name);
- bool removeWallet(const QString &name);
+ void addWallet(WalletModel *walletModel);
+ void setCurrentWallet(WalletModel* wallet_model);
+ void removeWallet(WalletModel* wallet_model);
void removeAllWallets();
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
@@ -53,14 +53,15 @@ private:
QStackedWidget *walletStack;
BitcoinGUI *gui;
ClientModel *clientModel;
- QMap<QString, WalletView*> mapWalletViews;
+ QMap<WalletModel*, WalletView*> mapWalletViews;
bool bOutOfSync;
const PlatformStyle *platformStyle;
public:
- WalletView *currentWalletView();
+ WalletView* currentWalletView() const;
+ WalletModel* currentWalletModel() const;
public Q_SLOTS:
/** Switch to overview (home) page */
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index cd55b40b71..fd392b7cf7 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -1,7 +1,11 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/walletmodel.h>
#include <qt/addresstablemodel.h>
@@ -16,7 +20,7 @@
#include <interfaces/node.h>
#include <key_io.h>
#include <ui_interface.h>
-#include <util.h> // for GetBoolArg
+#include <util/system.h> // for GetBoolArg
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
@@ -29,22 +33,20 @@
WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *_optionsModel, QObject *parent) :
- QObject(parent), m_wallet(std::move(wallet)), m_node(node), optionsModel(_optionsModel), addressTableModel(0),
- transactionTableModel(0),
- recentRequestsTableModel(0),
+ QObject(parent), m_wallet(std::move(wallet)), m_node(node), optionsModel(_optionsModel), addressTableModel(nullptr),
+ transactionTableModel(nullptr),
+ recentRequestsTableModel(nullptr),
cachedEncryptionStatus(Unencrypted),
cachedNumBlocks(0)
{
fHaveWatchOnly = m_wallet->haveWatchOnly();
- fForceCheckBalanceChanged = false;
-
addressTableModel = new AddressTableModel(this);
transactionTableModel = new TransactionTableModel(platformStyle, this);
recentRequestsTableModel = new RecentRequestsTableModel(this);
// This timer will be fired repeatedly to update the balance
pollTimer = new QTimer(this);
- connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged()));
+ connect(pollTimer, &QTimer::timeout, this, &WalletModel::pollBalanceChanged);
pollTimer->start(MODEL_UPDATE_DELAY);
subscribeToCoreSignals();
@@ -142,6 +144,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
if (rcp.fSubtractFeeFromAmount)
fSubtractFeeFromAmount = true;
+#ifdef ENABLE_BIP70
if (rcp.paymentRequest.IsInitialized())
{ // PaymentRequest...
CAmount subtotal = 0;
@@ -164,6 +167,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
total += subtotal;
}
else
+#endif
{ // User-entered bitcoin address / amount:
if(!validateAddress(rcp.address))
{
@@ -218,9 +222,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
}
// reject absurdly high fee. (This can never happen because the
- // wallet caps the fee at maxTxFee. This merely serves as a
+ // wallet caps the fee at m_default_max_tx_fee. This merely serves as a
// belt-and-suspenders check)
- if (nFeeRequired > m_node.getMaxTxFee())
+ if (nFeeRequired > m_wallet->getDefaultMaxTxFee())
return AbsurdFee;
}
@@ -235,6 +239,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
std::vector<std::pair<std::string, std::string>> vOrderForm;
for (const SendCoinsRecipient &rcp : transaction.getRecipients())
{
+#ifdef ENABLE_BIP70
if (rcp.paymentRequest.IsInitialized())
{
// Make sure any payment requests involved are still valid.
@@ -247,13 +252,15 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
rcp.paymentRequest.SerializeToString(&value);
vOrderForm.emplace_back("PaymentRequest", std::move(value));
}
- else if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example)
+ else
+#endif
+ if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example)
vOrderForm.emplace_back("Message", rcp.message.toStdString());
}
auto& newTx = transaction.getWtx();
std::string rejectReason;
- if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), {} /* fromAccount */, rejectReason))
+ if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), rejectReason))
return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason));
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
@@ -266,7 +273,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
for (const SendCoinsRecipient &rcp : transaction.getRecipients())
{
// Don't touch the address book when we have a payment request
+#ifdef ENABLE_BIP70
if (!rcp.paymentRequest.IsInitialized())
+#endif
{
std::string strAddress = rcp.address.toStdString();
CTxDestination dest = DecodeDestination(strAddress);
@@ -367,7 +376,7 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
static void NotifyUnload(WalletModel* walletModel)
{
qDebug() << "NotifyUnload";
- QMetaObject::invokeMethod(walletModel, "unload", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(walletModel, "unload");
}
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel)
@@ -414,15 +423,21 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly
Q_ARG(bool, fHaveWatchonly));
}
+static void NotifyCanGetAddressesChanged(WalletModel* walletmodel)
+{
+ QMetaObject::invokeMethod(walletmodel, "canGetAddressesChanged");
+}
+
void WalletModel::subscribeToCoreSignals()
{
// Connect signals to wallet
- m_handler_unload = m_wallet->handleUnload(boost::bind(&NotifyUnload, this));
- m_handler_status_changed = m_wallet->handleStatusChanged(boost::bind(&NotifyKeyStoreStatusChanged, this));
- m_handler_address_book_changed = m_wallet->handleAddressBookChanged(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
- m_handler_transaction_changed = m_wallet->handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2));
- m_handler_show_progress = m_wallet->handleShowProgress(boost::bind(ShowProgress, this, _1, _2));
- m_handler_watch_only_changed = m_wallet->handleWatchOnlyChanged(boost::bind(NotifyWatchonlyChanged, this, _1));
+ m_handler_unload = m_wallet->handleUnload(std::bind(&NotifyUnload, this));
+ m_handler_status_changed = m_wallet->handleStatusChanged(std::bind(&NotifyKeyStoreStatusChanged, this));
+ m_handler_address_book_changed = m_wallet->handleAddressBookChanged(std::bind(NotifyAddressBookChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
+ m_handler_transaction_changed = m_wallet->handleTransactionChanged(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2));
+ m_handler_show_progress = m_wallet->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2));
+ m_handler_watch_only_changed = m_wallet->handleWatchOnlyChanged(std::bind(NotifyWatchonlyChanged, this, std::placeholders::_1));
+ m_handler_can_get_addrs_changed = m_wallet->handleCanGetAddressesChanged(boost::bind(NotifyCanGetAddressesChanged, this));
}
void WalletModel::unsubscribeFromCoreSignals()
@@ -434,6 +449,7 @@ void WalletModel::unsubscribeFromCoreSignals()
m_handler_transaction_changed->disconnect();
m_handler_show_progress->disconnect();
m_handler_watch_only_changed->disconnect();
+ m_handler_can_get_addrs_changed->disconnect();
}
// WalletModel::UnlockContext implementation
@@ -492,7 +508,7 @@ bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t
return m_wallet->addDestData(dest, key, sRequest);
}
-bool WalletModel::bumpFee(uint256 hash)
+bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
{
CCoinControl coin_control;
coin_control.m_signal_bip125_rbf = true;
@@ -501,7 +517,7 @@ bool WalletModel::bumpFee(uint256 hash)
CAmount new_fee;
CMutableTransaction mtx;
if (!m_wallet->createBumpTransaction(hash, coin_control, 0 /* totalFee */, errors, old_fee, new_fee, mtx)) {
- QMessageBox::critical(0, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
+ QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
(errors.size() ? QString::fromStdString(errors[0]) : "") +")");
return false;
}
@@ -540,13 +556,12 @@ bool WalletModel::bumpFee(uint256 hash)
// sign bumped transaction
if (!m_wallet->signBumpTransaction(mtx)) {
- QMessageBox::critical(0, tr("Fee bump error"), tr("Can't sign transaction."));
+ QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't sign transaction."));
return false;
}
// commit the bumped transaction
- uint256 txid;
- if(!m_wallet->commitBumpTransaction(hash, std::move(mtx), errors, txid)) {
- QMessageBox::critical(0, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" +
+ if(!m_wallet->commitBumpTransaction(hash, std::move(mtx), errors, new_hash)) {
+ QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" +
QString::fromStdString(errors[0])+")");
return false;
}
@@ -563,11 +578,22 @@ bool WalletModel::privateKeysDisabled() const
return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
}
+bool WalletModel::canGetAddresses() const
+{
+ return m_wallet->canGetAddresses();
+}
+
QString WalletModel::getWalletName() const
{
return QString::fromStdString(m_wallet->getWalletName());
}
+QString WalletModel::getDisplayName() const
+{
+ const QString name = getWalletName();
+ return name.isEmpty() ? "["+tr("default wallet")+"]" : name;
+}
+
bool WalletModel::isMultiwallet()
{
return m_node.getWallets().size() > 1;
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index d8935c2fa8..b123befbb4 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,13 @@
#include <serialize.h>
#include <script/standard.h>
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#ifdef ENABLE_BIP70
#include <qt/paymentrequestplus.h>
+#endif
#include <qt/walletmodeltransaction.h>
#include <interfaces/wallet.h>
@@ -63,8 +69,14 @@ public:
// If from a payment request, this is used for storing the memo
QString message;
+#ifdef ENABLE_BIP70
// If from a payment request, paymentRequest.IsInitialized() will be true
PaymentRequestPlus paymentRequest;
+#else
+ // If building with BIP70 is disabled, keep the payment request around as
+ // serialized string to ensure load/store is lossless
+ std::string sPaymentRequest;
+#endif
// Empty if no authentication or invalid signature/cert/etc.
QString authenticatedMerchant;
@@ -80,9 +92,11 @@ public:
std::string sAddress = address.toStdString();
std::string sLabel = label.toStdString();
std::string sMessage = message.toStdString();
+#ifdef ENABLE_BIP70
std::string sPaymentRequest;
if (!ser_action.ForRead() && paymentRequest.IsInitialized())
paymentRequest.SerializeToString(&sPaymentRequest);
+#endif
std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString();
READWRITE(this->nVersion);
@@ -98,8 +112,10 @@ public:
address = QString::fromStdString(sAddress);
label = QString::fromStdString(sLabel);
message = QString::fromStdString(sMessage);
+#ifdef ENABLE_BIP70
if (!sPaymentRequest.empty())
paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()));
+#endif
authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
}
}
@@ -111,7 +127,7 @@ class WalletModel : public QObject
Q_OBJECT
public:
- explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *optionsModel, QObject *parent = 0);
+ explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *optionsModel, QObject *parent = nullptr);
~WalletModel();
enum StatusCode // Returned by sendCoins
@@ -194,15 +210,17 @@ public:
void loadReceiveRequests(std::vector<std::string>& vReceiveRequests);
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest);
- bool bumpFee(uint256 hash);
+ bool bumpFee(uint256 hash, uint256& new_hash);
static bool isWalletEnabled();
bool privateKeysDisabled() const;
+ bool canGetAddresses() const;
interfaces::Node& node() const { return m_node; }
interfaces::Wallet& wallet() const { return *m_wallet; }
QString getWalletName() const;
+ QString getDisplayName() const;
bool isMultiwallet();
@@ -215,10 +233,11 @@ private:
std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
std::unique_ptr<interfaces::Handler> m_handler_show_progress;
std::unique_ptr<interfaces::Handler> m_handler_watch_only_changed;
+ std::unique_ptr<interfaces::Handler> m_handler_can_get_addrs_changed;
interfaces::Node& m_node;
bool fHaveWatchOnly;
- bool fForceCheckBalanceChanged;
+ bool fForceCheckBalanceChanged{false};
// Wallet has an options model for wallet-specific options
// (transaction fee, for example)
@@ -266,6 +285,9 @@ Q_SIGNALS:
// Signal that wallet is about to be removed
void unload();
+ // Notify that there are now keys in the keypool
+ void canGetAddressesChanged();
+
public Q_SLOTS:
/* Wallet status might have changed */
void updateStatus();
diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp
index d5187d6634..2694d67800 100644
--- a/src/qt/walletmodeltransaction.cpp
+++ b/src/qt/walletmodeltransaction.cpp
@@ -1,7 +1,11 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifdef HAVE_CONFIG_H
+#include <config/bitcoin-config.h>
+#endif
+
#include <qt/walletmodeltransaction.h>
#include <interfaces/node.h>
@@ -25,7 +29,7 @@ std::unique_ptr<interfaces::PendingWalletTx>& WalletModelTransaction::getWtx()
unsigned int WalletModelTransaction::getTransactionSize()
{
- return wtx ? wtx->getVirtualSize() : 0;
+ return wtx ? GetVirtualTransactionSize(wtx->get()) : 0;
}
CAmount WalletModelTransaction::getTransactionFee() const
@@ -46,6 +50,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
{
SendCoinsRecipient& rcp = (*it);
+#ifdef ENABLE_BIP70
if (rcp.paymentRequest.IsInitialized())
{
CAmount subtotal = 0;
@@ -62,6 +67,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
rcp.amount = subtotal;
}
else // normal recipient (no payment request)
+#endif
{
if (i == nChangePosRet)
i++;
diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h
index 9f91326109..289aee847b 100644
--- a/src/qt/walletmodeltransaction.h
+++ b/src/qt/walletmodeltransaction.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,6 +8,7 @@
#include <qt/walletmodel.h>
#include <memory>
+#include <amount.h>
#include <QObject>
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index c53a2910e5..5f6f93d948 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -32,8 +32,8 @@
WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent):
QStackedWidget(parent),
- clientModel(0),
- walletModel(0),
+ clientModel(nullptr),
+ walletModel(nullptr),
platformStyle(_platformStyle)
{
// Create tabs
@@ -66,22 +66,20 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent):
addWidget(sendCoinsPage);
// Clicking on a transaction on the overview pre-selects the transaction on the transaction history page
- connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));
- connect(overviewPage, SIGNAL(outOfSyncWarningClicked()), this, SLOT(requestedSyncWarningInfo()));
+ connect(overviewPage, &OverviewPage::transactionClicked, transactionView, static_cast<void (TransactionView::*)(const QModelIndex&)>(&TransactionView::focusTransaction));
- // Highlight transaction after send
- connect(sendCoinsPage, SIGNAL(coinsSent(uint256)), transactionView, SLOT(focusTransaction(uint256)));
+ connect(overviewPage, &OverviewPage::outOfSyncWarningClicked, this, &WalletView::requestedSyncWarningInfo);
- // Double-clicking on a transaction on the transaction history page shows details
- connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));
+ // Highlight transaction after send
+ connect(sendCoinsPage, &SendCoinsDialog::coinsSent, transactionView, static_cast<void (TransactionView::*)(const uint256&)>(&TransactionView::focusTransaction));
// Clicking on "Export" allows to export the transaction list
- connect(exportButton, SIGNAL(clicked()), transactionView, SLOT(exportClicked()));
+ connect(exportButton, &QPushButton::clicked, transactionView, &TransactionView::exportClicked);
// Pass through messages from sendCoinsPage
- connect(sendCoinsPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
+ connect(sendCoinsPage, &SendCoinsDialog::message, this, &WalletView::message);
// Pass through messages from transactionView
- connect(transactionView, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
+ connect(transactionView, &TransactionView::message, this, &WalletView::message);
}
WalletView::~WalletView()
@@ -93,22 +91,24 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui)
if (gui)
{
// Clicking on a transaction on the overview page simply sends you to transaction history page
- connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), gui, SLOT(gotoHistoryPage()));
+ connect(overviewPage, &OverviewPage::transactionClicked, gui, &BitcoinGUI::gotoHistoryPage);
// Navigate to transaction history page after send
- connect(sendCoinsPage, SIGNAL(coinsSent(uint256)), gui, SLOT(gotoHistoryPage()));
+ connect(sendCoinsPage, &SendCoinsDialog::coinsSent, gui, &BitcoinGUI::gotoHistoryPage);
// Receive and report messages
- connect(this, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));
+ connect(this, &WalletView::message, [gui](const QString &title, const QString &message, unsigned int style) {
+ gui->message(title, message, style);
+ });
// Pass through encryption status changed signals
- connect(this, SIGNAL(encryptionStatusChanged()), gui, SLOT(updateWalletStatus()));
+ connect(this, &WalletView::encryptionStatusChanged, gui, &BitcoinGUI::updateWalletStatus);
// Pass through transaction notifications
- connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString)));
+ connect(this, &WalletView::incomingTransaction, gui, &BitcoinGUI::incomingTransaction);
// Connect HD enabled state signal
- connect(this, SIGNAL(hdEnabledStatusChanged()), gui, SLOT(updateWalletStatus()));
+ connect(this, &WalletView::hdEnabledStatusChanged, gui, &BitcoinGUI::updateWalletStatus);
}
}
@@ -135,24 +135,23 @@ void WalletView::setWalletModel(WalletModel *_walletModel)
if (_walletModel)
{
// Receive and pass through messages from wallet model
- connect(_walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
+ connect(_walletModel, &WalletModel::message, this, &WalletView::message);
// Handle changes in encryption status
- connect(_walletModel, SIGNAL(encryptionStatusChanged()), this, SIGNAL(encryptionStatusChanged()));
+ connect(_walletModel, &WalletModel::encryptionStatusChanged, this, &WalletView::encryptionStatusChanged);
updateEncryptionStatus();
// update HD status
Q_EMIT hdEnabledStatusChanged();
// Balloon pop-up for new transaction
- connect(_walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(processNewTransaction(QModelIndex,int,int)));
+ connect(_walletModel->getTransactionTableModel(), &TransactionTableModel::rowsInserted, this, &WalletView::processNewTransaction);
// Ask for passphrase if needed
- connect(_walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
+ connect(_walletModel, &WalletModel::requireUnlock, this, &WalletView::unlockWallet);
// Show progress dialog
- connect(_walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
+ connect(_walletModel, &WalletModel::showProgress, this, &WalletView::showProgress);
}
}
@@ -293,9 +292,7 @@ void WalletView::usedSendingAddresses()
if(!walletModel)
return;
- usedSendingAddressesPage->show();
- usedSendingAddressesPage->raise();
- usedSendingAddressesPage->activateWindow();
+ GUIUtil::bringToFront(usedSendingAddressesPage);
}
void WalletView::usedReceivingAddresses()
@@ -303,31 +300,24 @@ void WalletView::usedReceivingAddresses()
if(!walletModel)
return;
- usedReceivingAddressesPage->show();
- usedReceivingAddressesPage->raise();
- usedReceivingAddressesPage->activateWindow();
+ GUIUtil::bringToFront(usedReceivingAddressesPage);
}
void WalletView::showProgress(const QString &title, int nProgress)
{
- if (nProgress == 0)
- {
- progressDialog = new QProgressDialog(title, "", 0, 100);
+ if (nProgress == 0) {
+ progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100);
+ GUIUtil::PolishProgressDialog(progressDialog);
progressDialog->setWindowModality(Qt::ApplicationModal);
progressDialog->setMinimumDuration(0);
progressDialog->setAutoClose(false);
progressDialog->setValue(0);
- progressDialog->setCancelButtonText(tr("Cancel"));
- }
- else if (nProgress == 100)
- {
- if (progressDialog)
- {
+ } else if (nProgress == 100) {
+ if (progressDialog) {
progressDialog->close();
progressDialog->deleteLater();
}
- }
- else if (progressDialog) {
+ } else if (progressDialog) {
if (progressDialog->wasCanceled()) {
getWalletModel()->wallet().abortRescan();
} else {
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index 878a5966d6..e29c4c52f5 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp
index 122d6f0b12..08cae76add 100644
--- a/src/qt/winshutdownmonitor.cpp
+++ b/src/qt/winshutdownmonitor.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,7 +6,7 @@
#if defined(Q_OS_WIN)
#include <shutdown.h>
-#include <util.h>
+#include <util/system.h>
#include <windows.h>
diff --git a/src/qt/winshutdownmonitor.h b/src/qt/winshutdownmonitor.h
index c8a523a538..8edb98c744 100644
--- a/src/qt/winshutdownmonitor.h
+++ b/src/qt/winshutdownmonitor.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/random.cpp b/src/random.cpp
index fee6c2d92a..de26e6de1a 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,12 +12,15 @@
#include <wincrypt.h>
#endif
#include <logging.h> // for LogPrint()
-#include <utiltime.h> // for GetTime()
+#include <sync.h> // for WAIT_LOCK
+#include <util/time.h> // for GetTime()
#include <stdlib.h>
#include <chrono>
#include <thread>
+#include <support/allocators/secure.h>
+
#ifndef WIN32
#include <fcntl.h>
#include <sys/time.h>
@@ -34,7 +37,7 @@
#include <sys/random.h>
#endif
#ifdef HAVE_SYSCTL_ARND
-#include <utilstrencodings.h> // for ARRAYLEN
+#include <util/strencodings.h> // for ARRAYLEN
#include <sys/sysctl.h>
#endif
@@ -46,6 +49,7 @@
#include <openssl/err.h>
#include <openssl/rand.h>
+#include <openssl/conf.h>
[[noreturn]] static void RandFailure()
{
@@ -53,7 +57,7 @@
std::abort();
}
-static inline int64_t GetPerformanceCounter()
+static inline int64_t GetPerformanceCounter() noexcept
{
// Read the hardware time stamp counter when available.
// See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
@@ -73,73 +77,196 @@ static inline int64_t GetPerformanceCounter()
#endif
}
-
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
-static std::atomic<bool> hwrand_initialized{false};
-static bool rdrand_supported = false;
+static bool g_rdrand_supported = false;
+static bool g_rdseed_supported = false;
static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
-static void RDRandInit()
+static constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000;
+#ifdef bit_RDRND
+static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND, "Unexpected value for bit_RDRND");
+#endif
+#ifdef bit_RDSEED
+static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED, "Unexpected value for bit_RDSEED");
+#endif
+static void inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d)
+{
+ // We can't use __get_cpuid as it doesn't support subleafs.
+#ifdef __GNUC__
+ __cpuid_count(leaf, subleaf, a, b, c, d);
+#else
+ __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf));
+#endif
+}
+
+static void InitHardwareRand()
{
uint32_t eax, ebx, ecx, edx;
- if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & CPUID_F1_ECX_RDRAND)) {
+ GetCPUID(1, 0, eax, ebx, ecx, edx);
+ if (ecx & CPUID_F1_ECX_RDRAND) {
+ g_rdrand_supported = true;
+ }
+ GetCPUID(7, 0, eax, ebx, ecx, edx);
+ if (ebx & CPUID_F7_EBX_RDSEED) {
+ g_rdseed_supported = true;
+ }
+}
+
+static void ReportHardwareRand()
+{
+ // This must be done in a separate function, as HWRandInit() may be indirectly called
+ // from global constructors, before logging is initialized.
+ if (g_rdseed_supported) {
+ LogPrintf("Using RdSeed as additional entropy source\n");
+ }
+ if (g_rdrand_supported) {
LogPrintf("Using RdRand as an additional entropy source\n");
- rdrand_supported = true;
}
- hwrand_initialized.store(true);
}
+
+/** Read 64 bits of entropy using rdrand.
+ *
+ * Must only be called when RdRand is supported.
+ */
+static uint64_t GetRdRand() noexcept
+{
+ // RdRand may very rarely fail. Invoke it up to 10 times in a loop to reduce this risk.
+#ifdef __i386__
+ uint8_t ok;
+ uint32_t r1, r2;
+ for (int i = 0; i < 10; ++i) {
+ __asm__ volatile (".byte 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdrand %eax
+ if (ok) break;
+ }
+ for (int i = 0; i < 10; ++i) {
+ __asm__ volatile (".byte 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r2), "=q"(ok) :: "cc"); // rdrand %eax
+ if (ok) break;
+ }
+ return (((uint64_t)r2) << 32) | r1;
+#elif defined(__x86_64__) || defined(__amd64__)
+ uint8_t ok;
+ uint64_t r1;
+ for (int i = 0; i < 10; ++i) {
+ __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdrand %rax
+ if (ok) break;
+ }
+ return r1;
#else
-static void RDRandInit() {}
+#error "RdRand is only supported on x86 and x86_64"
#endif
+}
-static bool GetHWRand(unsigned char* ent32) {
-#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
- assert(hwrand_initialized.load(std::memory_order_relaxed));
- if (rdrand_supported) {
- uint8_t ok;
- // Not all assemblers support the rdrand instruction, write it in hex.
+/** Read 64 bits of entropy using rdseed.
+ *
+ * Must only be called when RdSeed is supported.
+ */
+static uint64_t GetRdSeed() noexcept
+{
+ // RdSeed may fail when the HW RNG is overloaded. Loop indefinitely until enough entropy is gathered,
+ // but pause after every failure.
#ifdef __i386__
- for (int iter = 0; iter < 4; ++iter) {
- uint32_t r1, r2;
- __asm__ volatile (".byte 0x0f, 0xc7, 0xf0;" // rdrand %eax
- ".byte 0x0f, 0xc7, 0xf2;" // rdrand %edx
- "setc %2" :
- "=a"(r1), "=d"(r2), "=q"(ok) :: "cc");
- if (!ok) return false;
- WriteLE32(ent32 + 8 * iter, r1);
- WriteLE32(ent32 + 8 * iter + 4, r2);
- }
+ uint8_t ok;
+ uint32_t r1, r2;
+ do {
+ __asm__ volatile (".byte 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %eax
+ if (ok) break;
+ __asm__ volatile ("pause");
+ } while(true);
+ do {
+ __asm__ volatile (".byte 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r2), "=q"(ok) :: "cc"); // rdseed %eax
+ if (ok) break;
+ __asm__ volatile ("pause");
+ } while(true);
+ return (((uint64_t)r2) << 32) | r1;
+#elif defined(__x86_64__) || defined(__amd64__)
+ uint8_t ok;
+ uint64_t r1;
+ do {
+ __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %rax
+ if (ok) break;
+ __asm__ volatile ("pause");
+ } while(true);
+ return r1;
+#else
+#error "RdSeed is only supported on x86 and x86_64"
+#endif
+}
+
#else
- uint64_t r1, r2, r3, r4;
- __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0, " // rdrand %rax
- "0x48, 0x0f, 0xc7, 0xf3, " // rdrand %rbx
- "0x48, 0x0f, 0xc7, 0xf1, " // rdrand %rcx
- "0x48, 0x0f, 0xc7, 0xf2; " // rdrand %rdx
- "setc %4" :
- "=a"(r1), "=b"(r2), "=c"(r3), "=d"(r4), "=q"(ok) :: "cc");
- if (!ok) return false;
- WriteLE64(ent32, r1);
- WriteLE64(ent32 + 8, r2);
- WriteLE64(ent32 + 16, r3);
- WriteLE64(ent32 + 24, r4);
+/* Access to other hardware random number generators could be added here later,
+ * assuming it is sufficiently fast (in the order of a few hundred CPU cycles).
+ * Slower sources should probably be invoked separately, and/or only from
+ * RandAddSeedSleep (which is called during idle background operation).
+ */
+static void InitHardwareRand() {}
+static void ReportHardwareRand() {}
#endif
- return true;
+
+/** Add 64 bits of entropy gathered from hardware to hasher. Do nothing if not supported. */
+static void SeedHardwareFast(CSHA512& hasher) noexcept {
+#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
+ if (g_rdrand_supported) {
+ uint64_t out = GetRdRand();
+ hasher.Write((const unsigned char*)&out, sizeof(out));
+ return;
}
#endif
- return false;
}
-void RandAddSeed()
-{
- // Seed with CPU performance counter
- int64_t nCounter = GetPerformanceCounter();
- RAND_add(&nCounter, sizeof(nCounter), 1.5);
- memory_cleanse((void*)&nCounter, sizeof(nCounter));
+/** Add 256 bits of entropy gathered from hardware to hasher. Do nothing if not supported. */
+static void SeedHardwareSlow(CSHA512& hasher) noexcept {
+#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
+ // When we want 256 bits of entropy, prefer RdSeed over RdRand, as it's
+ // guaranteed to produce independent randomness on every call.
+ if (g_rdseed_supported) {
+ for (int i = 0; i < 4; ++i) {
+ uint64_t out = GetRdSeed();
+ hasher.Write((const unsigned char*)&out, sizeof(out));
+ }
+ return;
+ }
+ // When falling back to RdRand, XOR the result of 1024 results.
+ // This guarantees a reseeding occurs between each.
+ if (g_rdrand_supported) {
+ for (int i = 0; i < 4; ++i) {
+ uint64_t out = 0;
+ for (int j = 0; j < 1024; ++j) out ^= GetRdRand();
+ hasher.Write((const unsigned char*)&out, sizeof(out));
+ }
+ return;
+ }
+#endif
}
-static void RandAddSeedPerfmon()
+/** Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher. */
+static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA512& hasher) noexcept
{
- RandAddSeed();
+ CSHA512 inner_hasher;
+ inner_hasher.Write(seed, sizeof(seed));
+ // Hash loop
+ unsigned char buffer[64];
+ int64_t stop = GetTimeMicros() + microseconds;
+ do {
+ for (int i = 0; i < 1000; ++i) {
+ inner_hasher.Finalize(buffer);
+ inner_hasher.Reset();
+ inner_hasher.Write(buffer, sizeof(buffer));
+ }
+ // Benchmark operation and feed it into outer hasher.
+ int64_t perf = GetPerformanceCounter();
+ hasher.Write((const unsigned char*)&perf, sizeof(perf));
+ } while (GetTimeMicros() < stop);
+
+ // Produce output from inner state and feed it to outer hasher.
+ inner_hasher.Finalize(buffer);
+ hasher.Write(buffer, sizeof(buffer));
+ // Try to clean up.
+ inner_hasher.Reset();
+ memory_cleanse(buffer, sizeof(buffer));
+}
+
+static void RandAddSeedPerfmon(CSHA512& hasher)
+{
#ifdef WIN32
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
@@ -163,15 +290,15 @@ static void RandAddSeedPerfmon()
}
RegCloseKey(HKEY_PERFORMANCE_DATA);
if (ret == ERROR_SUCCESS) {
- RAND_add(vData.data(), nSize, nSize / 100.0);
+ hasher.Write(vData.data(), nSize);
memory_cleanse(vData.data(), nSize);
- LogPrint(BCLog::RAND, "%s: %lu bytes\n", __func__, nSize);
} else {
- static bool warned = false; // Warn only once
- if (!warned) {
- LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
- warned = true;
- }
+ // Performance data is only a best-effort attempt at improving the
+ // situation when the OS randomness (and other sources) aren't
+ // adequate. As a result, failure to read it is isn't considered critical,
+ // so we don't call RandFailure().
+ // TODO: Add logging when the logger is made functional before global
+ // constructors have been invoked.
}
#endif
}
@@ -271,106 +398,281 @@ void GetOSRand(unsigned char *ent32)
#endif
}
-void GetRandBytes(unsigned char* buf, int num)
+void LockingCallbackOpenSSL(int mode, int i, const char* file, int line);
+
+namespace {
+
+class RNGState {
+ Mutex m_mutex;
+ /* The RNG state consists of 256 bits of entropy, taken from the output of
+ * one operation's SHA512 output, and fed as input to the next one.
+ * Carrying 256 bits of entropy should be sufficient to guarantee
+ * unpredictability as long as any entropy source was ever unpredictable
+ * to an attacker. To protect against situations where an attacker might
+ * observe the RNG's state, fresh entropy is always mixed when
+ * GetStrongRandBytes is called.
+ */
+ unsigned char m_state[32] GUARDED_BY(m_mutex) = {0};
+ uint64_t m_counter GUARDED_BY(m_mutex) = 0;
+ bool m_strongly_seeded GUARDED_BY(m_mutex) = false;
+ std::unique_ptr<Mutex[]> m_mutex_openssl;
+
+public:
+ RNGState() noexcept
+ {
+ InitHardwareRand();
+
+ // Init OpenSSL library multithreading support
+ m_mutex_openssl.reset(new Mutex[CRYPTO_num_locks()]);
+ CRYPTO_set_locking_callback(LockingCallbackOpenSSL);
+
+ // OpenSSL can optionally load a config file which lists optional loadable modules and engines.
+ // We don't use them so we don't require the config. However some of our libs may call functions
+ // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing
+ // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
+ // that the config appears to have been loaded and there are no modules/engines available.
+ OPENSSL_no_config();
+ }
+
+ ~RNGState()
+ {
+ // Securely erase the memory used by the OpenSSL PRNG
+ RAND_cleanup();
+ // Shutdown OpenSSL library multithreading support
+ CRYPTO_set_locking_callback(nullptr);
+ }
+
+ /** Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher.
+ *
+ * If this function has never been called with strong_seed = true, false is returned.
+ */
+ bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed) noexcept
+ {
+ assert(num <= 32);
+ unsigned char buf[64];
+ static_assert(sizeof(buf) == CSHA512::OUTPUT_SIZE, "Buffer needs to have hasher's output size");
+ bool ret;
+ {
+ LOCK(m_mutex);
+ ret = (m_strongly_seeded |= strong_seed);
+ // Write the current state of the RNG into the hasher
+ hasher.Write(m_state, 32);
+ // Write a new counter number into the state
+ hasher.Write((const unsigned char*)&m_counter, sizeof(m_counter));
+ ++m_counter;
+ // Finalize the hasher
+ hasher.Finalize(buf);
+ // Store the last 32 bytes of the hash output as new RNG state.
+ memcpy(m_state, buf + 32, 32);
+ }
+ // If desired, copy (up to) the first 32 bytes of the hash output as output.
+ if (num) {
+ assert(out != nullptr);
+ memcpy(out, buf, num);
+ }
+ // Best effort cleanup of internal state
+ hasher.Reset();
+ memory_cleanse(buf, 64);
+ return ret;
+ }
+
+ Mutex& GetOpenSSLMutex(int i) { return m_mutex_openssl[i]; }
+};
+
+RNGState& GetRNGState() noexcept
{
- if (RAND_bytes(buf, num) != 1) {
- RandFailure();
+ // This C++11 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];
+}
+}
+
+void LockingCallbackOpenSSL(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
+{
+ RNGState& rng = GetRNGState();
+
+ if (mode & CRYPTO_LOCK) {
+ rng.GetOpenSSLMutex(i).lock();
+ } else {
+ rng.GetOpenSSLMutex(i).unlock();
}
}
-static void AddDataToRng(void* data, size_t len);
+/* A note on the use of noexcept in the seeding functions below:
+ *
+ * None of the RNG code should ever throw any exception, with the sole exception
+ * of MilliSleep in SeedSleep, which can (and does) support interruptions which
+ * cause a boost::thread_interrupted to be thrown.
+ *
+ * This means that SeedSleep, and all functions that invoke it are throwing.
+ * However, we know that GetRandBytes() and GetStrongRandBytes() never trigger
+ * this sleeping logic, so they are noexcept. The same is true for all the
+ * GetRand*() functions that use GetRandBytes() indirectly.
+ *
+ * TODO: After moving away from interruptible boost-based thread management,
+ * everything can become noexcept here.
+ */
-void RandAddSeedSleep()
+static void SeedTimestamp(CSHA512& hasher) noexcept
{
- int64_t nPerfCounter1 = GetPerformanceCounter();
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
- int64_t nPerfCounter2 = GetPerformanceCounter();
+ int64_t perfcounter = GetPerformanceCounter();
+ hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
+}
- // Combine with and update state
- AddDataToRng(&nPerfCounter1, sizeof(nPerfCounter1));
- AddDataToRng(&nPerfCounter2, sizeof(nPerfCounter2));
+static void SeedFast(CSHA512& hasher) noexcept
+{
+ unsigned char buffer[32];
- memory_cleanse(&nPerfCounter1, sizeof(nPerfCounter1));
- memory_cleanse(&nPerfCounter2, sizeof(nPerfCounter2));
+ // Stack pointer to indirectly commit to thread/callstack
+ const unsigned char* ptr = buffer;
+ hasher.Write((const unsigned char*)&ptr, sizeof(ptr));
+
+ // Hardware randomness is very fast when available; use it always.
+ SeedHardwareFast(hasher);
+
+ // High-precision timestamp
+ SeedTimestamp(hasher);
}
+static void SeedSlow(CSHA512& hasher) noexcept
+{
+ unsigned char buffer[32];
-static std::mutex cs_rng_state;
-static unsigned char rng_state[32] = {0};
-static uint64_t rng_counter = 0;
+ // Everything that the 'fast' seeder includes
+ SeedFast(hasher);
-static void AddDataToRng(void* data, size_t len) {
- CSHA512 hasher;
- hasher.Write((const unsigned char*)&len, sizeof(len));
- hasher.Write((const unsigned char*)data, len);
- unsigned char buf[64];
- {
- std::unique_lock<std::mutex> lock(cs_rng_state);
- hasher.Write(rng_state, sizeof(rng_state));
- hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter));
- ++rng_counter;
- hasher.Finalize(buf);
- memcpy(rng_state, buf + 32, 32);
+ // OS randomness
+ GetOSRand(buffer);
+ hasher.Write(buffer, sizeof(buffer));
+
+ // OpenSSL RNG (for now)
+ RAND_bytes(buffer, sizeof(buffer));
+ hasher.Write(buffer, sizeof(buffer));
+
+ // High-precision timestamp.
+ //
+ // Note that we also commit to a timestamp in the Fast seeder, so we indirectly commit to a
+ // benchmark of all the entropy gathering sources in this function).
+ SeedTimestamp(hasher);
+}
+
+/** Extract entropy from rng, strengthen it, and feed it into hasher. */
+static void SeedStrengthen(CSHA512& hasher, RNGState& rng) noexcept
+{
+ static std::atomic<int64_t> last_strengthen{0};
+ int64_t last_time = last_strengthen.load();
+ int64_t current_time = GetTimeMicros();
+ if (current_time > last_time + 60000000) { // Only run once a minute
+ // Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
+ unsigned char strengthen_seed[32];
+ rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
+ // Strengthen it for 10ms (100ms on first run), and feed it into hasher.
+ Strengthen(strengthen_seed, last_time == 0 ? 100000 : 10000, hasher);
+ last_strengthen = current_time;
}
- memory_cleanse(buf, 64);
}
-void GetStrongRandBytes(unsigned char* out, int num)
+static void SeedSleep(CSHA512& hasher, RNGState& rng)
{
- assert(num <= 32);
- CSHA512 hasher;
- unsigned char buf[64];
+ // Everything that the 'fast' seeder includes
+ SeedFast(hasher);
+
+ // High-precision timestamp
+ SeedTimestamp(hasher);
+
+ // Sleep for 1ms
+ MilliSleep(1);
+
+ // High-precision timestamp after sleeping (as we commit to both the time before and after, this measures the delay)
+ SeedTimestamp(hasher);
+
+ // Windows performance monitor data (once every 10 minutes)
+ RandAddSeedPerfmon(hasher);
+
+ // Strengthen every minute
+ SeedStrengthen(hasher, rng);
+}
+
+static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
+{
+#ifdef WIN32
+ RAND_screen();
+#endif
+
+ // Gather 256 bits of hardware randomness, if available
+ SeedHardwareSlow(hasher);
+
+ // Everything that the 'slow' seeder includes.
+ SeedSlow(hasher);
+
+ // Windows performance monitor data.
+ RandAddSeedPerfmon(hasher);
+
+ // Strengthen
+ SeedStrengthen(hasher, rng);
+}
+
+enum class RNGLevel {
+ FAST, //!< Automatically called by GetRandBytes
+ SLOW, //!< Automatically called by GetStrongRandBytes
+ SLEEP, //!< Called by RandAddSeedSleep()
+};
- // First source: OpenSSL's RNG
- RandAddSeedPerfmon();
- GetRandBytes(buf, 32);
- hasher.Write(buf, 32);
+static void ProcRand(unsigned char* out, int num, RNGLevel level)
+{
+ // Make sure the RNG is initialized first (as all Seed* function possibly need hwrand to be available).
+ RNGState& rng = GetRNGState();
- // Second source: OS RNG
- GetOSRand(buf);
- hasher.Write(buf, 32);
+ assert(num <= 32);
- // Third source: HW RNG, if available.
- if (GetHWRand(buf)) {
- hasher.Write(buf, 32);
+ CSHA512 hasher;
+ switch (level) {
+ case RNGLevel::FAST:
+ SeedFast(hasher);
+ break;
+ case RNGLevel::SLOW:
+ SeedSlow(hasher);
+ break;
+ case RNGLevel::SLEEP:
+ SeedSleep(hasher, rng);
+ break;
}
// Combine with and update state
- {
- std::unique_lock<std::mutex> lock(cs_rng_state);
- hasher.Write(rng_state, sizeof(rng_state));
- hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter));
- ++rng_counter;
- hasher.Finalize(buf);
- memcpy(rng_state, buf + 32, 32);
+ if (!rng.MixExtract(out, num, std::move(hasher), false)) {
+ // On the first invocation, also seed with SeedStartup().
+ CSHA512 startup_hasher;
+ SeedStartup(startup_hasher, rng);
+ rng.MixExtract(out, num, std::move(startup_hasher), true);
}
- // Produce output
- memcpy(out, buf, num);
- memory_cleanse(buf, 64);
+ // For anything but the 'fast' level, feed the resulting RNG output (after an additional hashing step) back into OpenSSL.
+ if (level != RNGLevel::FAST) {
+ unsigned char buf[64];
+ CSHA512().Write(out, num).Finalize(buf);
+ RAND_add(buf, sizeof(buf), num);
+ memory_cleanse(buf, 64);
+ }
}
-uint64_t GetRand(uint64_t nMax)
-{
- if (nMax == 0)
- return 0;
+void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
+void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
+void RandAddSeedSleep() { ProcRand(nullptr, 0, RNGLevel::SLEEP); }
- // The range of the random source must be a multiple of the modulus
- // to give every possible output value an equal possibility
- uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
- uint64_t nRand = 0;
- do {
- GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
- } while (nRand >= nRange);
- return (nRand % nMax);
+bool g_mock_deterministic_tests{false};
+
+uint64_t GetRand(uint64_t nMax) noexcept
+{
+ return FastRandomContext(g_mock_deterministic_tests).randrange(nMax);
}
-int GetRandInt(int nMax)
+int GetRandInt(int nMax) noexcept
{
return GetRand(nMax);
}
-uint256 GetRandHash()
+uint256 GetRandHash() noexcept
{
uint256 hash;
GetRandBytes((unsigned char*)&hash, sizeof(hash));
@@ -384,7 +686,7 @@ void FastRandomContext::RandomSeed()
requires_seed = false;
}
-uint256 FastRandomContext::rand256()
+uint256 FastRandomContext::rand256() noexcept
{
if (bytebuf_size < 32) {
FillByteBuffer();
@@ -397,14 +699,15 @@ uint256 FastRandomContext::rand256()
std::vector<unsigned char> FastRandomContext::randbytes(size_t len)
{
+ if (requires_seed) RandomSeed();
std::vector<unsigned char> ret(len);
if (len > 0) {
- rng.Output(&ret[0], len);
+ rng.Keystream(&ret[0], len);
}
return ret;
}
-FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
+FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
{
rng.SetKey(seed.begin(), 32);
}
@@ -447,13 +750,15 @@ bool Random_SanityCheck()
if (stop == start) return false;
// We called GetPerformanceCounter. Use it as entropy.
- RAND_add((const unsigned char*)&start, sizeof(start), 1);
- RAND_add((const unsigned char*)&stop, sizeof(stop), 1);
+ CSHA512 to_add;
+ to_add.Write((const unsigned char*)&start, sizeof(start));
+ to_add.Write((const unsigned char*)&stop, sizeof(stop));
+ GetRNGState().MixExtract(nullptr, 0, std::move(to_add), false);
return true;
}
-FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
+FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
{
if (!fDeterministic) {
return;
@@ -462,7 +767,24 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete
rng.SetKey(seed.begin(), 32);
}
+FastRandomContext& FastRandomContext::operator=(FastRandomContext&& from) noexcept
+{
+ requires_seed = from.requires_seed;
+ rng = from.rng;
+ std::copy(std::begin(from.bytebuf), std::end(from.bytebuf), std::begin(bytebuf));
+ bytebuf_size = from.bytebuf_size;
+ bitbuf = from.bitbuf;
+ bitbuf_size = from.bitbuf_size;
+ from.requires_seed = true;
+ from.bytebuf_size = 0;
+ from.bitbuf_size = 0;
+ return *this;
+}
+
void RandomInit()
{
- RDRandInit();
+ // Invoke RNG code to trigger initialization (if not already performed)
+ ProcRand(nullptr, 0, RNGLevel::FAST);
+
+ ReportHardwareRand();
}
diff --git a/src/random.h b/src/random.h
index 1d6b13a537..75d037738d 100644
--- a/src/random.h
+++ b/src/random.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,33 +13,86 @@
#include <stdint.h>
#include <limits>
-/* Seed OpenSSL PRNG with additional entropy data */
-void RandAddSeed();
+/**
+ * Overall design of the RNG and entropy sources.
+ *
+ * We maintain a single global 256-bit RNG state for all high-quality randomness.
+ * The following (classes of) functions interact with that state by mixing in new
+ * entropy, and optionally extracting random output from it:
+ *
+ * - The GetRand*() class of functions, as well as construction of FastRandomContext objects,
+ * perform 'fast' seeding, consisting of mixing in:
+ * - A stack pointer (indirectly committing to calling thread and call stack)
+ * - A high-precision timestamp (rdtsc when available, c++ high_resolution_clock otherwise)
+ * - 64 bits from the hardware RNG (rdrand) when available.
+ * These entropy sources are very fast, and only designed to protect against situations
+ * where a VM state restore/copy results in multiple systems with the same randomness.
+ * FastRandomContext on the other hand does not protect against this once created, but
+ * is even faster (and acceptable to use inside tight loops).
+ *
+ * - The GetStrongRand*() class of function perform 'slow' seeding, including everything
+ * that fast seeding includes, but additionally:
+ * - OS entropy (/dev/urandom, getrandom(), ...). The application will terminate if
+ * this entropy source fails.
+ * - Bytes from OpenSSL's RNG (which itself may be seeded from various sources)
+ * - Another high-precision timestamp (indirectly committing to a benchmark of all the
+ * previous sources).
+ * These entropy sources are slower, but designed to make sure the RNG state contains
+ * fresh data that is unpredictable to attackers.
+ *
+ * - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally:
+ * - A high-precision timestamp before and after sleeping 1ms.
+ * - (On Windows) Once every 10 minutes, performance monitoring data from the OS.
+ - - Once every minute, strengthen the entropy for 10 ms using repeated SHA512.
+ * These just exploit the fact the system is idle to improve the quality of the RNG
+ * slightly.
+ *
+ * On first use of the RNG (regardless of what function is called first), all entropy
+ * sources used in the 'slow' seeder are included, but also:
+ * - 256 bits from the hardware RNG (rdseed or rdrand) when available.
+ * - (On Windows) Performance monitoring data from the OS.
+ * - (On Windows) Through OpenSSL, the screen contents.
+ * - Strengthen the entropy for 100 ms using repeated SHA512.
+ *
+ * When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and
+ * (up to) the first 32 bytes of H are produced as output, while the last 32 bytes
+ * become the new RNG state.
+*/
/**
- * Functions to gather random data via the OpenSSL PRNG
+ * Generate random data via the internal PRNG.
+ *
+ * These functions are designed to be fast (sub microsecond), but do not necessarily
+ * meaningfully add entropy to the PRNG state.
+ *
+ * Thread-safe.
*/
-void GetRandBytes(unsigned char* buf, int num);
-uint64_t GetRand(uint64_t nMax);
-int GetRandInt(int nMax);
-uint256 GetRandHash();
+void GetRandBytes(unsigned char* buf, int num) noexcept;
+uint64_t GetRand(uint64_t nMax) noexcept;
+int GetRandInt(int nMax) noexcept;
+uint256 GetRandHash() noexcept;
/**
- * Add a little bit of randomness to the output of GetStrongRangBytes.
- * This sleeps for a millisecond, so should only be called when there is
- * no other work to be done.
+ * Gather entropy from various sources, feed it into the internal PRNG, and
+ * generate random data using it.
+ *
+ * This function will cause failure whenever the OS RNG fails.
+ *
+ * Thread-safe.
*/
-void RandAddSeedSleep();
+void GetStrongRandBytes(unsigned char* buf, int num) noexcept;
/**
- * Function to gather random data from multiple sources, failing whenever any
- * of those sources fail to provide a result.
+ * Sleep for 1ms, gather entropy from various sources, and feed them to the PRNG state.
+ *
+ * Thread-safe.
*/
-void GetStrongRandBytes(unsigned char* buf, int num);
+void RandAddSeedSleep();
/**
* Fast randomness source. This is seeded once with secure random data, but
- * is completely deterministic and insecure after that.
+ * is completely deterministic and does not gather more entropy after that.
+ *
* This class is not thread-safe.
*/
class FastRandomContext {
@@ -60,7 +113,7 @@ private:
if (requires_seed) {
RandomSeed();
}
- rng.Output(bytebuf, sizeof(bytebuf));
+ rng.Keystream(bytebuf, sizeof(bytebuf));
bytebuf_size = sizeof(bytebuf);
}
@@ -71,13 +124,21 @@ private:
}
public:
- explicit FastRandomContext(bool fDeterministic = false);
+ explicit FastRandomContext(bool fDeterministic = false) noexcept;
/** Initialize with explicit seed (only for testing) */
- explicit FastRandomContext(const uint256& seed);
+ explicit FastRandomContext(const uint256& seed) noexcept;
+
+ // Do not permit copying a FastRandomContext (move it, or create a new one to get reseeded).
+ FastRandomContext(const FastRandomContext&) = delete;
+ FastRandomContext(FastRandomContext&&) = delete;
+ FastRandomContext& operator=(const FastRandomContext&) = delete;
+
+ /** Move a FastRandomContext. If the original one is used again, it will be reseeded. */
+ FastRandomContext& operator=(FastRandomContext&& from) noexcept;
/** Generate a random 64-bit integer. */
- uint64_t rand64()
+ uint64_t rand64() noexcept
{
if (bytebuf_size < 8) FillByteBuffer();
uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size);
@@ -86,7 +147,7 @@ public:
}
/** Generate a random (bits)-bit integer. */
- uint64_t randbits(int bits) {
+ uint64_t randbits(int bits) noexcept {
if (bits == 0) {
return 0;
} else if (bits > 32) {
@@ -101,7 +162,7 @@ public:
}
/** Generate a random integer in the range [0..range). */
- uint64_t randrange(uint64_t range)
+ uint64_t randrange(uint64_t range) noexcept
{
--range;
int bits = CountBits(range);
@@ -115,21 +176,44 @@ public:
std::vector<unsigned char> randbytes(size_t len);
/** Generate a random 32-bit integer. */
- uint32_t rand32() { return randbits(32); }
+ uint32_t rand32() noexcept { return randbits(32); }
/** generate a random uint256. */
- uint256 rand256();
+ uint256 rand256() noexcept;
/** Generate a random boolean. */
- bool randbool() { return randbits(1); }
+ bool randbool() noexcept { return randbits(1); }
// Compatibility with the C++11 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(); }
- inline uint64_t operator()() { return rand64(); }
+ inline uint64_t operator()() noexcept { return rand64(); }
};
+/** More efficient than using std::shuffle on a FastRandomContext.
+ *
+ * This is more efficient as std::shuffle will consume entropy in groups of
+ * 64 bits at the time and throw away most.
+ *
+ * This also works around a bug in libstdc++ std::shuffle that may cause
+ * type::operator=(type&&) to be invoked on itself, which the library's
+ * debug mode detects and panics on. This is a known issue, see
+ * https://stackoverflow.com/questions/22915325/avoiding-self-assignment-in-stdshuffle
+ */
+template<typename I, typename R>
+void Shuffle(I first, I last, R&& rng)
+{
+ while (first != last) {
+ size_t j = rng.randrange(last - first);
+ if (j) {
+ using std::swap;
+ swap(*first, *(first + j));
+ }
+ ++first;
+ }
+}
+
/* Number of random bytes returned by GetOSRand.
* When changing this constant make sure to change all call sites, and make
* sure that the underlying OS APIs for all platforms support the number.
@@ -147,7 +231,12 @@ void GetOSRand(unsigned char *ent32);
*/
bool Random_SanityCheck();
-/** Initialize the RNG. */
+/**
+ * Initialize global RNG state and log any CPU features that are used.
+ *
+ * Calling this function is optional. RNG state will be initialized when first
+ * needed if it is not called.
+ */
void RandomInit();
#endif // BITCOIN_RANDOM_H
diff --git a/src/rest.cpp b/src/rest.cpp
index a5f164497d..ab409947d3 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -1,22 +1,23 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <attributes.h>
#include <chain.h>
#include <chainparams.h>
#include <core_io.h>
+#include <httpserver.h>
#include <index/txindex.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
-#include <validation.h>
-#include <httpserver.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <streams.h>
#include <sync.h>
#include <txmempool.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
+#include <validation.h>
#include <version.h>
#include <boost/algorithm/string.hpp>
@@ -105,15 +106,6 @@ static std::string AvailableDataFormatsString()
return formats;
}
-static bool ParseHashStr(const std::string& strReq, uint256& v)
-{
- if (!IsHex(strReq) || (strReq.size() != 64))
- return false;
-
- v.SetHex(strReq);
- return true;
-}
-
static bool CheckWarmup(HTTPRequest* req)
{
std::string statusmessage;
@@ -144,26 +136,28 @@ static bool rest_headers(HTTPRequest* req,
if (!ParseHashStr(hashStr, hash))
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
+ const CBlockIndex* tip = nullptr;
std::vector<const CBlockIndex *> headers;
headers.reserve(count);
{
LOCK(cs_main);
+ tip = ::ChainActive().Tip();
const CBlockIndex* pindex = LookupBlockIndex(hash);
- while (pindex != nullptr && chainActive.Contains(pindex)) {
+ while (pindex != nullptr && ::ChainActive().Contains(pindex)) {
headers.push_back(pindex);
if (headers.size() == (unsigned long)count)
break;
- pindex = chainActive.Next(pindex);
+ pindex = ::ChainActive().Next(pindex);
}
}
- CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
- for (const CBlockIndex *pindex : headers) {
- ssHeader << pindex->GetBlockHeader();
- }
-
switch (rf) {
case RetFormat::BINARY: {
+ CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
+ for (const CBlockIndex *pindex : headers) {
+ ssHeader << pindex->GetBlockHeader();
+ }
+
std::string binaryHeader = ssHeader.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryHeader);
@@ -171,6 +165,11 @@ static bool rest_headers(HTTPRequest* req,
}
case RetFormat::HEX: {
+ CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
+ for (const CBlockIndex *pindex : headers) {
+ ssHeader << pindex->GetBlockHeader();
+ }
+
std::string strHex = HexStr(ssHeader.begin(), ssHeader.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
@@ -178,11 +177,8 @@ static bool rest_headers(HTTPRequest* req,
}
case RetFormat::JSON: {
UniValue jsonHeaders(UniValue::VARR);
- {
- LOCK(cs_main);
- for (const CBlockIndex *pindex : headers) {
- jsonHeaders.push_back(blockheaderToJSON(pindex));
- }
+ for (const CBlockIndex *pindex : headers) {
+ jsonHeaders.push_back(blockheaderToJSON(tip, pindex));
}
std::string strJSON = jsonHeaders.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
@@ -210,8 +206,10 @@ static bool rest_block(HTTPRequest* req,
CBlock block;
CBlockIndex* pblockindex = nullptr;
+ CBlockIndex* tip = nullptr;
{
LOCK(cs_main);
+ tip = ::ChainActive().Tip();
pblockindex = LookupBlockIndex(hash);
if (!pblockindex) {
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
@@ -224,11 +222,10 @@ static bool rest_block(HTTPRequest* req,
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}
- CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
- ssBlock << block;
-
switch (rf) {
case RetFormat::BINARY: {
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
+ ssBlock << block;
std::string binaryBlock = ssBlock.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryBlock);
@@ -236,6 +233,8 @@ static bool rest_block(HTTPRequest* req,
}
case RetFormat::HEX: {
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
+ ssBlock << block;
std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
@@ -243,11 +242,7 @@ static bool rest_block(HTTPRequest* req,
}
case RetFormat::JSON: {
- UniValue objBlock;
- {
- LOCK(cs_main);
- objBlock = blockToJSON(block, pblockindex, showTxDetails);
- }
+ UniValue objBlock = blockToJSON(block, tip, pblockindex, showTxDetails);
std::string strJSON = objBlock.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
req->WriteReply(HTTP_OK, strJSON);
@@ -305,7 +300,7 @@ static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart)
switch (rf) {
case RetFormat::JSON: {
- UniValue mempoolInfoObject = mempoolInfoToJSON();
+ UniValue mempoolInfoObject = MempoolInfoToJSON(::mempool);
std::string strJSON = mempoolInfoObject.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
@@ -327,7 +322,7 @@ static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPar
switch (rf) {
case RetFormat::JSON: {
- UniValue mempoolObject = mempoolToJSON(true);
+ UniValue mempoolObject = MempoolToJSON(::mempool, true);
std::string strJSON = mempoolObject.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
@@ -357,14 +352,14 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
CTransactionRef tx;
uint256 hashBlock = uint256();
- if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
+ if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock))
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
- ssTx << tx;
-
switch (rf) {
case RetFormat::BINARY: {
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
+ ssTx << tx;
+
std::string binaryTx = ssTx.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryTx);
@@ -372,6 +367,9 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
}
case RetFormat::HEX: {
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
+ ssTx << tx;
+
std::string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
@@ -464,7 +462,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
oss >> fCheckMemPool;
oss >> vOutPoints;
}
- } catch (const std::ios_base::failure& e) {
+ } catch (const std::ios_base::failure&) {
// abort in case of unreadable binary data
return RESTERR(req, HTTP_BAD_REQUEST, "Parse error");
}
@@ -524,7 +522,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
// serialize data
// use exact same output as mentioned in Bip64
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
- ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs;
+ ssGetUTXOResponse << ::ChainActive().Height() << ::ChainActive().Tip()->GetBlockHash() << bitmap << outs;
std::string ssGetUTXOResponseString = ssGetUTXOResponse.str();
req->WriteHeader("Content-Type", "application/octet-stream");
@@ -534,7 +532,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
case RetFormat::HEX: {
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
- ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs;
+ ssGetUTXOResponse << ::ChainActive().Height() << ::ChainActive().Tip()->GetBlockHash() << bitmap << outs;
std::string strHex = HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
@@ -547,8 +545,8 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
// pack in some essentials
// use more or less the same output as mentioned in Bip64
- objGetUTXOResponse.pushKV("chainHeight", chainActive.Height());
- objGetUTXOResponse.pushKV("chaintipHash", chainActive.Tip()->GetBlockHash().GetHex());
+ objGetUTXOResponse.pushKV("chainHeight", ::ChainActive().Height());
+ objGetUTXOResponse.pushKV("chaintipHash", ::ChainActive().Tip()->GetBlockHash().GetHex());
objGetUTXOResponse.pushKV("bitmap", bitmapStringRepresentation);
UniValue utxos(UniValue::VARR);
@@ -577,6 +575,52 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
}
}
+static bool rest_blockhash_by_height(HTTPRequest* req,
+ const std::string& str_uri_part)
+{
+ if (!CheckWarmup(req)) return false;
+ std::string height_str;
+ const RetFormat rf = ParseDataFormat(height_str, str_uri_part);
+
+ int32_t blockheight;
+ if (!ParseInt32(height_str, &blockheight) || blockheight < 0) {
+ return RESTERR(req, HTTP_BAD_REQUEST, "Invalid height: " + SanitizeString(height_str));
+ }
+
+ CBlockIndex* pblockindex = nullptr;
+ {
+ LOCK(cs_main);
+ if (blockheight > ::ChainActive().Height()) {
+ return RESTERR(req, HTTP_NOT_FOUND, "Block height out of range");
+ }
+ pblockindex = ::ChainActive()[blockheight];
+ }
+ switch (rf) {
+ case RetFormat::BINARY: {
+ CDataStream ss_blockhash(SER_NETWORK, PROTOCOL_VERSION);
+ ss_blockhash << pblockindex->GetBlockHash();
+ req->WriteHeader("Content-Type", "application/octet-stream");
+ req->WriteReply(HTTP_OK, ss_blockhash.str());
+ return true;
+ }
+ case RetFormat::HEX: {
+ req->WriteHeader("Content-Type", "text/plain");
+ req->WriteReply(HTTP_OK, pblockindex->GetBlockHash().GetHex() + "\n");
+ return true;
+ }
+ case RetFormat::JSON: {
+ req->WriteHeader("Content-Type", "application/json");
+ UniValue resp = UniValue(UniValue::VOBJ);
+ resp.pushKV("blockhash", pblockindex->GetBlockHash().GetHex());
+ req->WriteReply(HTTP_OK, resp.write() + "\n");
+ return true;
+ }
+ default: {
+ return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
+ }
+ }
+}
+
static const struct {
const char* prefix;
bool (*handler)(HTTPRequest* req, const std::string& strReq);
@@ -589,13 +633,13 @@ static const struct {
{"/rest/mempool/contents", rest_mempool_contents},
{"/rest/headers/", rest_headers},
{"/rest/getutxos", rest_getutxos},
+ {"/rest/blockhashbyheight/", rest_blockhash_by_height},
};
-bool StartREST()
+void StartREST()
{
for (unsigned int i = 0; i < ARRAYLEN(uri_prefixes); i++)
RegisterHTTPHandler(uri_prefixes[i].prefix, false, uri_prefixes[i].handler);
- return true;
}
void InterruptREST()
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 46dec4ca6e..56018caf24 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,28 +7,34 @@
#include <amount.h>
#include <base58.h>
+#include <blockfilter.h>
#include <chain.h>
#include <chainparams.h>
-#include <checkpoints.h>
#include <coins.h>
#include <consensus/validation.h>
-#include <validation.h>
#include <core_io.h>
+#include <hash.h>
+#include <index/blockfilterindex.h>
#include <index/txindex.h>
#include <key_io.h>
#include <policy/feerate.h>
#include <policy/policy.h>
+#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <rpc/server.h>
+#include <rpc/util.h>
#include <script/descriptor.h>
#include <streams.h>
#include <sync.h>
#include <txdb.h>
#include <txmempool.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#include <hash.h>
+#include <undo.h>
+#include <util/strencodings.h>
+#include <util/system.h>
+#include <util/validation.h>
+#include <validation.h>
#include <validationinterface.h>
+#include <versionbitsinfo.h>
#include <warnings.h>
#include <assert.h>
@@ -36,7 +42,6 @@
#include <univalue.h>
-#include <boost/algorithm/string.hpp>
#include <boost/thread/thread.hpp> // boost::thread::interrupt
#include <memory>
@@ -49,7 +54,7 @@ struct CUpdatedBlock
int height;
};
-static std::mutex cs_blockchange;
+static Mutex cs_blockchange;
static std::condition_variable cond_blockchange;
static CUpdatedBlock latestblock;
@@ -57,10 +62,7 @@ static CUpdatedBlock latestblock;
*/
double GetDifficulty(const CBlockIndex* blockindex)
{
- if (blockindex == nullptr)
- {
- return 1.0;
- }
+ assert(blockindex);
int nShift = (blockindex->nBits >> 24) & 0xff;
double dDiff =
@@ -80,15 +82,25 @@ double GetDifficulty(const CBlockIndex* blockindex)
return dDiff;
}
-UniValue blockheaderToJSON(const CBlockIndex* blockindex)
+static int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* blockindex, const CBlockIndex*& next)
{
- AssertLockHeld(cs_main);
+ next = tip->GetAncestor(blockindex->nHeight + 1);
+ if (next && next->pprev == blockindex) {
+ return tip->nHeight - blockindex->nHeight + 1;
+ }
+ next = nullptr;
+ return blockindex == tip ? 1 : -1;
+}
+
+UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex)
+{
+ // Serialize passed information without accessing chain state of the active chain!
+ AssertLockNotHeld(cs_main); // For performance reasons
+
UniValue result(UniValue::VOBJ);
result.pushKV("hash", blockindex->GetBlockHash().GetHex());
- int confirmations = -1;
- // Only report confirmations if the block is on the main chain
- if (chainActive.Contains(blockindex))
- confirmations = chainActive.Height() - blockindex->nHeight + 1;
+ const CBlockIndex* pnext;
+ int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
result.pushKV("confirmations", confirmations);
result.pushKV("height", blockindex->nHeight);
result.pushKV("version", blockindex->nVersion);
@@ -104,24 +116,23 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
if (blockindex->pprev)
result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex());
- CBlockIndex *pnext = chainActive.Next(blockindex);
if (pnext)
result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
return result;
}
-UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails)
+UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails)
{
- AssertLockHeld(cs_main);
+ // Serialize passed information without accessing chain state of the active chain!
+ AssertLockNotHeld(cs_main); // For performance reasons
+
UniValue result(UniValue::VOBJ);
result.pushKV("hash", blockindex->GetBlockHash().GetHex());
- int confirmations = -1;
- // Only report confirmations if the block is on the main chain
- if (chainActive.Contains(blockindex))
- confirmations = chainActive.Height() - blockindex->nHeight + 1;
+ const CBlockIndex* pnext;
+ int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
result.pushKV("confirmations", confirmations);
- result.pushKV("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS));
- result.pushKV("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION));
+ result.pushKV("strippedsize", (int)::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS));
+ result.pushKV("size", (int)::GetSerializeSize(block, PROTOCOL_VERSION));
result.pushKV("weight", (int)::GetBlockWeight(block));
result.pushKV("height", blockindex->nHeight);
result.pushKV("version", block.nVersion);
@@ -150,7 +161,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
if (blockindex->pprev)
result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex());
- CBlockIndex *pnext = chainActive.Next(blockindex);
if (pnext)
result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
return result;
@@ -160,34 +170,40 @@ static UniValue getblockcount(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getblockcount\n"
- "\nReturns the number of blocks in the longest blockchain.\n"
- "\nResult:\n"
+ RPCHelpMan{"getblockcount",
+ "\nReturns the number of blocks in the longest blockchain.\n",
+ {},
+ RPCResult{
"n (numeric) The current block count\n"
- "\nExamples:\n"
- + HelpExampleCli("getblockcount", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getblockcount", "")
+ HelpExampleRpc("getblockcount", "")
- );
+ },
+ }.ToString());
LOCK(cs_main);
- return chainActive.Height();
+ return ::ChainActive().Height();
}
static UniValue getbestblockhash(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getbestblockhash\n"
- "\nReturns the hash of the best (tip) block in the longest blockchain.\n"
- "\nResult:\n"
- "\"hex\" (string) the block hash hex encoded\n"
- "\nExamples:\n"
- + HelpExampleCli("getbestblockhash", "")
+ RPCHelpMan{"getbestblockhash",
+ "\nReturns the hash of the best (tip) block in the longest blockchain.\n",
+ {},
+ RPCResult{
+ "\"hex\" (string) the block hash, hex-encoded\n"
+ },
+ RPCExamples{
+ HelpExampleCli("getbestblockhash", "")
+ HelpExampleRpc("getbestblockhash", "")
- );
+ },
+ }.ToString());
LOCK(cs_main);
- return chainActive.Tip()->GetBlockHash().GetHex();
+ return ::ChainActive().Tip()->GetBlockHash().GetHex();
}
void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex)
@@ -204,27 +220,30 @@ static UniValue waitfornewblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
- "waitfornewblock (timeout)\n"
- "\nWaits for a specific new block and returns useful info about it.\n"
- "\nReturns the current block on timeout or exit.\n"
- "\nArguments:\n"
- "1. timeout (int, optional, default=0) Time in milliseconds to wait for a response. 0 indicates no timeout.\n"
- "\nResult:\n"
+ RPCHelpMan{"waitfornewblock",
+ "\nWaits for a specific new block and returns useful info about it.\n"
+ "\nReturns the current block on timeout or exit.\n",
+ {
+ {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
+ },
+ RPCResult{
"{ (json object)\n"
" \"hash\" : { (string) The blockhash\n"
" \"height\" : { (int) Block height\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("waitfornewblock", "1000")
+ },
+ RPCExamples{
+ HelpExampleCli("waitfornewblock", "1000")
+ HelpExampleRpc("waitfornewblock", "1000")
- );
+ },
+ }.ToString());
int timeout = 0;
if (!request.params[0].isNull())
timeout = request.params[0].get_int();
CUpdatedBlock block;
{
- std::unique_lock<std::mutex> lock(cs_blockchange);
+ WAIT_LOCK(cs_blockchange, lock);
block = latestblock;
if(timeout)
cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&block]{return latestblock.height != block.height || latestblock.hash != block.hash || !IsRPCRunning(); });
@@ -242,31 +261,34 @@ static UniValue waitforblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "waitforblock <blockhash> (timeout)\n"
- "\nWaits for a specific new block and returns useful info about it.\n"
- "\nReturns the current block on timeout or exit.\n"
- "\nArguments:\n"
- "1. \"blockhash\" (required, string) Block hash to wait for.\n"
- "2. timeout (int, optional, default=0) Time in milliseconds to wait for a response. 0 indicates no timeout.\n"
- "\nResult:\n"
+ RPCHelpMan{"waitforblock",
+ "\nWaits for a specific new block and returns useful info about it.\n"
+ "\nReturns the current block on timeout or exit.\n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Block hash to wait for."},
+ {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
+ },
+ RPCResult{
"{ (json object)\n"
" \"hash\" : { (string) The blockhash\n"
" \"height\" : { (int) Block height\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
+ },
+ RPCExamples{
+ HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
+ HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
- );
+ },
+ }.ToString());
int timeout = 0;
- uint256 hash = uint256S(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
if (!request.params[1].isNull())
timeout = request.params[1].get_int();
CUpdatedBlock block;
{
- std::unique_lock<std::mutex> lock(cs_blockchange);
+ WAIT_LOCK(cs_blockchange, lock);
if(timeout)
cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&hash]{return latestblock.hash == hash || !IsRPCRunning();});
else
@@ -284,22 +306,25 @@ static UniValue waitforblockheight(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "waitforblockheight <height> (timeout)\n"
- "\nWaits for (at least) block height and returns the height and hash\n"
- "of the current tip.\n"
- "\nReturns the current block on timeout or exit.\n"
- "\nArguments:\n"
- "1. height (required, int) Block height to wait for (int)\n"
- "2. timeout (int, optional, default=0) Time in milliseconds to wait for a response. 0 indicates no timeout.\n"
- "\nResult:\n"
+ RPCHelpMan{"waitforblockheight",
+ "\nWaits for (at least) block height and returns the height and hash\n"
+ "of the current tip.\n"
+ "\nReturns the current block on timeout or exit.\n",
+ {
+ {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "Block height to wait for."},
+ {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
+ },
+ RPCResult{
"{ (json object)\n"
" \"hash\" : { (string) The blockhash\n"
" \"height\" : { (int) Block height\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("waitforblockheight", "\"100\", 1000")
+ },
+ RPCExamples{
+ HelpExampleCli("waitforblockheight", "\"100\", 1000")
+ HelpExampleRpc("waitforblockheight", "\"100\", 1000")
- );
+ },
+ }.ToString());
int timeout = 0;
int height = request.params[0].get_int();
@@ -309,7 +334,7 @@ static UniValue waitforblockheight(const JSONRPCRequest& request)
CUpdatedBlock block;
{
- std::unique_lock<std::mutex> lock(cs_blockchange);
+ WAIT_LOCK(cs_blockchange, lock);
if(timeout)
cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&height]{return latestblock.height >= height || !IsRPCRunning();});
else
@@ -326,12 +351,15 @@ static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 0) {
throw std::runtime_error(
- "syncwithvalidationinterfacequeue\n"
- "\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n"
- "\nExamples:\n"
- + HelpExampleCli("syncwithvalidationinterfacequeue","")
+ RPCHelpMan{"syncwithvalidationinterfacequeue",
+ "\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n",
+ {},
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("syncwithvalidationinterfacequeue","")
+ HelpExampleRpc("syncwithvalidationinterfacequeue","")
- );
+ },
+ }.ToString());
}
SyncWithValidationInterfaceQueue();
return NullUniValue;
@@ -341,22 +369,27 @@ static UniValue getdifficulty(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getdifficulty\n"
- "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
- "\nResult:\n"
+ RPCHelpMan{"getdifficulty",
+ "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n",
+ {},
+ RPCResult{
"n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
- "\nExamples:\n"
- + HelpExampleCli("getdifficulty", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getdifficulty", "")
+ HelpExampleRpc("getdifficulty", "")
- );
+ },
+ }.ToString());
LOCK(cs_main);
- return GetDifficulty(chainActive.Tip());
+ return GetDifficulty(::ChainActive().Tip());
}
static std::string EntryDescriptionString()
{
- return " \"size\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n"
+ return " \"vsize\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n"
+ " \"size\" : n, (numeric) (DEPRECATED) same as vsize. Only returned if bitcoind is started with -deprecatedrpc=size\n"
+ " size will be completely removed in v0.20.\n"
" \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)\n"
" \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority (DEPRECATED)\n"
" \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
@@ -379,12 +412,13 @@ static std::string EntryDescriptionString()
" ... ]\n"
" \"spentby\" : [ (array) unconfirmed transactions spending outputs from this transaction\n"
" \"transactionid\", (string) child transaction id\n"
- " ... ]\n";
+ " ... ]\n"
+ " \"bip125-replaceable\" : true|false, (boolean) Whether this transaction could be replaced due to BIP125 (replace-by-fee)\n";
}
-static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs)
+static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
{
- AssertLockHeld(mempool.cs);
+ AssertLockHeld(pool.cs);
UniValue fees(UniValue::VOBJ);
fees.pushKV("base", ValueFromAmount(e.GetFee()));
@@ -393,7 +427,8 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK
fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants()));
info.pushKV("fees", fees);
- info.pushKV("size", (int)e.GetTxSize());
+ info.pushKV("vsize", (int)e.GetTxSize());
+ if (IsDeprecatedRPCEnabled("size")) info.pushKV("size", (int)e.GetTxSize());
info.pushKV("fee", ValueFromAmount(e.GetFee()));
info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee()));
info.pushKV("time", e.GetTime());
@@ -404,12 +439,12 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK
info.pushKV("ancestorcount", e.GetCountWithAncestors());
info.pushKV("ancestorsize", e.GetSizeWithAncestors());
info.pushKV("ancestorfees", e.GetModFeesWithAncestors());
- info.pushKV("wtxid", mempool.vTxHashes[e.vTxHashesIdx].first.ToString());
+ info.pushKV("wtxid", pool.vTxHashes[e.vTxHashesIdx].first.ToString());
const CTransaction& tx = e.GetTx();
std::set<std::string> setDepends;
for (const CTxIn& txin : tx.vin)
{
- if (mempool.exists(txin.prevout.hash))
+ if (pool.exists(txin.prevout.hash))
setDepends.insert(txin.prevout.hash.ToString());
}
@@ -422,34 +457,44 @@ static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCK
info.pushKV("depends", depends);
UniValue spent(UniValue::VARR);
- const CTxMemPool::txiter &it = mempool.mapTx.find(tx.GetHash());
- const CTxMemPool::setEntries &setChildren = mempool.GetMemPoolChildren(it);
- for (const CTxMemPool::txiter &childiter : setChildren) {
+ const CTxMemPool::txiter& it = pool.mapTx.find(tx.GetHash());
+ const CTxMemPool::setEntries& setChildren = pool.GetMemPoolChildren(it);
+ for (CTxMemPool::txiter childiter : setChildren) {
spent.push_back(childiter->GetTx().GetHash().ToString());
}
info.pushKV("spentby", spent);
+
+ // Add opt-in RBF status
+ bool rbfStatus = false;
+ RBFTransactionState rbfState = IsRBFOptIn(tx, pool);
+ if (rbfState == RBFTransactionState::UNKNOWN) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not in mempool");
+ } else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) {
+ rbfStatus = true;
+ }
+
+ info.pushKV("bip125-replaceable", rbfStatus);
}
-UniValue mempoolToJSON(bool fVerbose)
+UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose)
{
- if (fVerbose)
- {
- LOCK(mempool.cs);
+ if (verbose) {
+ LOCK(pool.cs);
UniValue o(UniValue::VOBJ);
- for (const CTxMemPoolEntry& e : mempool.mapTx)
- {
+ for (const CTxMemPoolEntry& e : pool.mapTx) {
const uint256& hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
- entryToJSON(info, e);
- o.pushKV(hash.ToString(), info);
+ entryToJSON(pool, info, e);
+ // Mempool has unique entries so there is no advantage in using
+ // UniValue::pushKV, which checks if the key already exists in O(N).
+ // UniValue::__pushKV is used instead which currently is O(1).
+ o.__pushKV(hash.ToString(), info);
}
return o;
- }
- else
- {
+ } else {
std::vector<uint256> vtxid;
- mempool.queryHashes(vtxid);
+ pool.queryHashes(vtxid);
UniValue a(UniValue::VARR);
for (const uint256& hash : vtxid)
@@ -463,12 +508,13 @@ static UniValue getrawmempool(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
- "getrawmempool ( verbose )\n"
- "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
- "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n"
- "\nArguments:\n"
- "1. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"
- "\nResult: (for verbose = false):\n"
+ RPCHelpMan{"getrawmempool",
+ "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
+ "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n",
+ {
+ {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"},
+ },
+ RPCResult{"for verbose = false",
"[ (json array of string)\n"
" \"transactionid\" (string) The transaction id\n"
" ,...\n"
@@ -479,42 +525,50 @@ static UniValue getrawmempool(const JSONRPCRequest& request)
+ EntryDescriptionString()
+ " }, ...\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getrawmempool", "true")
+ },
+ RPCExamples{
+ HelpExampleCli("getrawmempool", "true")
+ HelpExampleRpc("getrawmempool", "true")
- );
+ },
+ }.ToString());
bool fVerbose = false;
if (!request.params[0].isNull())
fVerbose = request.params[0].get_bool();
- return mempoolToJSON(fVerbose);
+ return MempoolToJSON(::mempool, fVerbose);
}
static UniValue getmempoolancestors(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
- "getmempoolancestors txid (verbose)\n"
- "\nIf txid is in the mempool, returns all in-mempool ancestors.\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The transaction id (must be in mempool)\n"
- "2. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"
- "\nResult (for verbose=false):\n"
+ RPCHelpMan{"getmempoolancestors",
+ "\nIf txid is in the mempool, returns all in-mempool ancestors.\n",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
+ {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"},
+ },
+ {
+ RPCResult{"for verbose = false",
"[ (json array of strings)\n"
" \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n"
" ,...\n"
"]\n"
- "\nResult (for verbose=true):\n"
+ },
+ RPCResult{"for verbose = true",
"{ (json object)\n"
" \"transactionid\" : { (json object)\n"
+ EntryDescriptionString()
+ " }, ...\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getmempoolancestors", "\"mytxid\"")
+ },
+ },
+ RPCExamples{
+ HelpExampleCli("getmempoolancestors", "\"mytxid\"")
+ HelpExampleRpc("getmempoolancestors", "\"mytxid\"")
- );
+ },
+ }.ToString());
}
bool fVerbose = false;
@@ -548,7 +602,7 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
const CTxMemPoolEntry &e = *ancestorIt;
const uint256& _hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
- entryToJSON(info, e);
+ entryToJSON(::mempool, info, e);
o.pushKV(_hash.ToString(), info);
}
return o;
@@ -559,26 +613,32 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
- "getmempooldescendants txid (verbose)\n"
- "\nIf txid is in the mempool, returns all in-mempool descendants.\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The transaction id (must be in mempool)\n"
- "2. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"
- "\nResult (for verbose=false):\n"
+ RPCHelpMan{"getmempooldescendants",
+ "\nIf txid is in the mempool, returns all in-mempool descendants.\n",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
+ {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"},
+ },
+ {
+ RPCResult{"for verbose = false",
"[ (json array of strings)\n"
" \"transactionid\" (string) The transaction id of an in-mempool descendant transaction\n"
" ,...\n"
"]\n"
- "\nResult (for verbose=true):\n"
+ },
+ RPCResult{"for verbose = true",
"{ (json object)\n"
" \"transactionid\" : { (json object)\n"
+ EntryDescriptionString()
+ " }, ...\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getmempooldescendants", "\"mytxid\"")
+ },
+ },
+ RPCExamples{
+ HelpExampleCli("getmempooldescendants", "\"mytxid\"")
+ HelpExampleRpc("getmempooldescendants", "\"mytxid\"")
- );
+ },
+ }.ToString());
}
bool fVerbose = false;
@@ -612,7 +672,7 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request)
const CTxMemPoolEntry &e = *descendantIt;
const uint256& _hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
- entryToJSON(info, e);
+ entryToJSON(::mempool, info, e);
o.pushKV(_hash.ToString(), info);
}
return o;
@@ -623,18 +683,21 @@ static UniValue getmempoolentry(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
- "getmempoolentry txid\n"
- "\nReturns mempool data for given transaction\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The transaction id (must be in mempool)\n"
- "\nResult:\n"
+ RPCHelpMan{"getmempoolentry",
+ "\nReturns mempool data for given transaction\n",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"},
+ },
+ RPCResult{
"{ (json object)\n"
+ EntryDescriptionString()
+ "}\n"
- "\nExamples:\n"
- + HelpExampleCli("getmempoolentry", "\"mytxid\"")
+ },
+ RPCExamples{
+ HelpExampleCli("getmempoolentry", "\"mytxid\"")
+ HelpExampleRpc("getmempoolentry", "\"mytxid\"")
- );
+ },
+ }.ToString());
}
uint256 hash = ParseHashV(request.params[0], "parameter 1");
@@ -648,7 +711,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request)
const CTxMemPoolEntry &e = *it;
UniValue info(UniValue::VOBJ);
- entryToJSON(info, e);
+ entryToJSON(::mempool, info, e);
return info;
}
@@ -656,24 +719,27 @@ static UniValue getblockhash(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "getblockhash height\n"
- "\nReturns hash of block in best-block-chain at height provided.\n"
- "\nArguments:\n"
- "1. height (numeric, required) The height index\n"
- "\nResult:\n"
+ RPCHelpMan{"getblockhash",
+ "\nReturns hash of block in best-block-chain at height provided.\n",
+ {
+ {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The height index"},
+ },
+ RPCResult{
"\"hash\" (string) The block hash\n"
- "\nExamples:\n"
- + HelpExampleCli("getblockhash", "1000")
+ },
+ RPCExamples{
+ HelpExampleCli("getblockhash", "1000")
+ HelpExampleRpc("getblockhash", "1000")
- );
+ },
+ }.ToString());
LOCK(cs_main);
int nHeight = request.params[0].get_int();
- if (nHeight < 0 || nHeight > chainActive.Height())
+ if (nHeight < 0 || nHeight > ::ChainActive().Height())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
- CBlockIndex* pblockindex = chainActive[nHeight];
+ CBlockIndex* pblockindex = ::ChainActive()[nHeight];
return pblockindex->GetBlockHash().GetHex();
}
@@ -681,13 +747,15 @@ static UniValue getblockheader(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "getblockheader \"hash\" ( verbose )\n"
- "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
- "If verbose is true, returns an Object with information about blockheader <hash>.\n"
- "\nArguments:\n"
- "1. \"hash\" (string, required) The block hash\n"
- "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
- "\nResult (for verbose = true):\n"
+ RPCHelpMan{"getblockheader",
+ "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
+ "If verbose is true, returns an Object with information about blockheader <hash>.\n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
+ {"verbose", RPCArg::Type::BOOL, /* default */ "true", "true for a json object, false for the hex-encoded data"},
+ },
+ {
+ RPCResult{"for verbose = true",
"{\n"
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
@@ -705,23 +773,31 @@ static UniValue getblockheader(const JSONRPCRequest& request)
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
" \"nextblockhash\" : \"hash\", (string) The hash of the next block\n"
"}\n"
- "\nResult (for verbose=false):\n"
+ },
+ RPCResult{"for verbose=false",
"\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
- "\nExamples:\n"
- + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ },
+ },
+ RPCExamples{
+ HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
- );
-
- LOCK(cs_main);
+ },
+ }.ToString());
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "hash"));
bool fVerbose = true;
if (!request.params[1].isNull())
fVerbose = request.params[1].get_bool();
- const CBlockIndex* pblockindex = LookupBlockIndex(hash);
+ const CBlockIndex* pblockindex;
+ const CBlockIndex* tip;
+ {
+ LOCK(cs_main);
+ pblockindex = LookupBlockIndex(hash);
+ tip = ::ChainActive().Tip();
+ }
+
if (!pblockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
@@ -734,7 +810,7 @@ static UniValue getblockheader(const JSONRPCRequest& request)
return strHex;
}
- return blockheaderToJSON(pblockindex);
+ return blockheaderToJSON(tip, pblockindex);
}
static CBlock GetBlockChecked(const CBlockIndex* pblockindex)
@@ -756,20 +832,35 @@ static CBlock GetBlockChecked(const CBlockIndex* pblockindex)
return block;
}
+static CBlockUndo GetUndoChecked(const CBlockIndex* pblockindex)
+{
+ CBlockUndo blockUndo;
+ if (IsBlockPruned(pblockindex)) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available (pruned data)");
+ }
+
+ if (!UndoReadFromDisk(blockUndo, pblockindex)) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk");
+ }
+
+ return blockUndo;
+}
+
static UniValue getblock(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
- throw std::runtime_error(
- "getblock \"blockhash\" ( verbosity ) \n"
- "\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
- "If verbosity is 1, returns an Object with information about block <hash>.\n"
- "If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n"
- "\nArguments:\n"
- "1. \"blockhash\" (string, required) The block hash\n"
- "2. verbosity (numeric, optional, default=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data\n"
- "\nResult (for verbosity = 0):\n"
+ const RPCHelpMan help{"getblock",
+ "\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
+ "If verbosity is 1, returns an Object with information about block <hash>.\n"
+ "If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
+ {"verbosity", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
+ },
+ {
+ RPCResult{"for verbosity = 0",
"\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
- "\nResult (for verbosity = 1):\n"
+ },
+ RPCResult{"for verbosity = 1",
"{\n"
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
@@ -794,7 +885,8 @@ static UniValue getblock(const JSONRPCRequest& request)
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
" \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
"}\n"
- "\nResult (for verbosity = 2):\n"
+ },
+ RPCResult{"for verbosity = 2",
"{\n"
" ..., Same output as verbosity = 1.\n"
" \"tx\" : [ (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result.\n"
@@ -802,15 +894,19 @@ static UniValue getblock(const JSONRPCRequest& request)
" ],\n"
" ,... Same output as verbosity = 1.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ },
+ },
+ RPCExamples{
+ HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
- );
+ },
+ };
- LOCK(cs_main);
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
+ }
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
int verbosity = 1;
if (!request.params[1].isNull()) {
@@ -820,12 +916,20 @@ static UniValue getblock(const JSONRPCRequest& request)
verbosity = request.params[1].get_bool() ? 1 : 0;
}
- const CBlockIndex* pblockindex = LookupBlockIndex(hash);
- if (!pblockindex) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
- }
+ CBlock block;
+ const CBlockIndex* pblockindex;
+ const CBlockIndex* tip;
+ {
+ LOCK(cs_main);
+ pblockindex = LookupBlockIndex(hash);
+ tip = ::ChainActive().Tip();
- const CBlock block = GetBlockChecked(pblockindex);
+ if (!pblockindex) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+ }
+
+ block = GetBlockChecked(pblockindex);
+ }
if (verbosity <= 0)
{
@@ -835,7 +939,7 @@ static UniValue getblock(const JSONRPCRequest& request)
return strHex;
}
- return blockToJSON(block, pblockindex, verbosity >= 2);
+ return blockToJSON(block, tip, pblockindex, verbosity >= 2);
}
struct CCoinsStats
@@ -913,15 +1017,19 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "pruneblockchain\n"
- "\nArguments:\n"
- "1. \"height\" (numeric, required) The block height to prune up to. May be set to a discrete height, or a unix timestamp\n"
- " to prune blocks whose block time is at least 2 hours older than the provided timestamp.\n"
- "\nResult:\n"
+ RPCHelpMan{"pruneblockchain", "",
+ {
+ {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or a unix timestamp\n"
+ " to prune blocks whose block time is at least 2 hours older than the provided timestamp."},
+ },
+ RPCResult{
"n (numeric) Height of the last block pruned.\n"
- "\nExamples:\n"
- + HelpExampleCli("pruneblockchain", "1000")
- + HelpExampleRpc("pruneblockchain", "1000"));
+ },
+ RPCExamples{
+ HelpExampleCli("pruneblockchain", "1000")
+ + HelpExampleRpc("pruneblockchain", "1000")
+ },
+ }.ToString());
if (!fPruneMode)
throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode.");
@@ -936,7 +1044,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
// too low to be a block time (corresponds to timestamp from Sep 2001).
if (heightParam > 1000000000) {
// Add a 2 hour buffer to include blocks which might have had old timestamps
- CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW);
+ CBlockIndex* pindex = ::ChainActive().FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0);
if (!pindex) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp.");
}
@@ -944,7 +1052,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
}
unsigned int height = (unsigned int) heightParam;
- unsigned int chainHeight = (unsigned int) chainActive.Height();
+ unsigned int chainHeight = (unsigned int) ::ChainActive().Height();
if (chainHeight < Params().PruneAfterHeight())
throw JSONRPCError(RPC_MISC_ERROR, "Blockchain is too short for pruning.");
else if (height > chainHeight)
@@ -962,10 +1070,11 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "gettxoutsetinfo\n"
- "\nReturns statistics about the unspent transaction output set.\n"
- "Note this call may take some time.\n"
- "\nResult:\n"
+ RPCHelpMan{"gettxoutsetinfo",
+ "\nReturns statistics about the unspent transaction output set.\n"
+ "Note this call may take some time.\n",
+ {},
+ RPCResult{
"{\n"
" \"height\":n, (numeric) The current block height (index)\n"
" \"bestblock\": \"hex\", (string) The hash of the block at the tip of the chain\n"
@@ -976,10 +1085,12 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
" \"disk_size\": n, (numeric) The estimated size of the chainstate on disk\n"
" \"total_amount\": x.xxx (numeric) The total amount\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("gettxoutsetinfo", "")
+ },
+ RPCExamples{
+ HelpExampleCli("gettxoutsetinfo", "")
+ HelpExampleRpc("gettxoutsetinfo", "")
- );
+ },
+ }.ToString());
UniValue ret(UniValue::VOBJ);
@@ -1004,14 +1115,14 @@ UniValue gettxout(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
throw std::runtime_error(
- "gettxout \"txid\" n ( include_mempool )\n"
- "\nReturns details about an unspent transaction output.\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The transaction id\n"
- "2. \"n\" (numeric, required) vout number\n"
- "3. \"include_mempool\" (boolean, optional) Whether to include the mempool. Default: true."
- " Note that an unspent output that is spent in the mempool won't appear.\n"
- "\nResult:\n"
+ RPCHelpMan{"gettxout",
+ "\nReturns details about an unspent transaction output.\n",
+ {
+ {"txid", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction id"},
+ {"n", RPCArg::Type::NUM, RPCArg::Optional::NO, "vout number"},
+ {"include_mempool", RPCArg::Type::BOOL, /* default */ "true", "Whether to include the mempool. Note that an unspent output that is spent in the mempool won't appear."},
+ },
+ RPCResult{
"{\n"
" \"bestblock\": \"hash\", (string) The hash of the block at the tip of the chain\n"
" \"confirmations\" : n, (numeric) The number of confirmations\n"
@@ -1028,22 +1139,22 @@ UniValue gettxout(const JSONRPCRequest& request)
" },\n"
" \"coinbase\" : true|false (boolean) Coinbase or not\n"
"}\n"
-
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nGet unspent transactions\n"
+ HelpExampleCli("listunspent", "") +
"\nView the details\n"
+ HelpExampleCli("gettxout", "\"txid\" 1") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("gettxout", "\"txid\", 1")
- );
+ },
+ }.ToString());
LOCK(cs_main);
UniValue ret(UniValue::VOBJ);
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "txid"));
int n = request.params[1].get_int();
COutPoint out(hash, n);
bool fMempool = true;
@@ -1085,17 +1196,20 @@ static UniValue verifychain(const JSONRPCRequest& request)
int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS);
if (request.fHelp || request.params.size() > 2)
throw std::runtime_error(
- "verifychain ( checklevel nblocks )\n"
- "\nVerifies blockchain database.\n"
- "\nArguments:\n"
- "1. checklevel (numeric, optional, 0-4, default=" + strprintf("%d", nCheckLevel) + ") How thorough the block verification is.\n"
- "2. nblocks (numeric, optional, default=" + strprintf("%d", nCheckDepth) + ", 0=all) The number of blocks to check.\n"
- "\nResult:\n"
+ RPCHelpMan{"verifychain",
+ "\nVerifies blockchain database.\n",
+ {
+ {"checklevel", RPCArg::Type::NUM, /* default */ strprintf("%d, range=0-4", nCheckLevel), "How thorough the block verification is."},
+ {"nblocks", RPCArg::Type::NUM, /* default */ strprintf("%d, 0=all", nCheckDepth), "The number of blocks to check."},
+ },
+ RPCResult{
"true|false (boolean) Verified or not\n"
- "\nExamples:\n"
- + HelpExampleCli("verifychain", "")
+ },
+ RPCExamples{
+ HelpExampleCli("verifychain", "")
+ HelpExampleRpc("verifychain", "")
- );
+ },
+ }.ToString());
LOCK(cs_main);
@@ -1108,7 +1222,7 @@ static UniValue verifychain(const JSONRPCRequest& request)
}
/** Implementation of IsSuperMajority with better feedback */
-static UniValue SoftForkMajorityDesc(int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
+static UniValue SoftForkMajorityDesc(int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
{
UniValue rv(UniValue::VOBJ);
bool activated = false;
@@ -1128,7 +1242,7 @@ static UniValue SoftForkMajorityDesc(int version, CBlockIndex* pindex, const Con
return rv;
}
-static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
+static UniValue SoftForkDesc(const std::string &name, int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
{
UniValue rv(UniValue::VOBJ);
rv.pushKV("id", name);
@@ -1182,9 +1296,10 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getblockchaininfo\n"
- "Returns an object containing various state info regarding blockchain processing.\n"
- "\nResult:\n"
+ RPCHelpMan{"getblockchaininfo",
+ "Returns an object containing various state info regarding blockchain processing.\n",
+ {},
+ RPCResult{
"{\n"
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
" \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
@@ -1227,27 +1342,30 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
" }\n"
" \"warnings\" : \"...\", (string) any network and blockchain warnings.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getblockchaininfo", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getblockchaininfo", "")
+ HelpExampleRpc("getblockchaininfo", "")
- );
+ },
+ }.ToString());
LOCK(cs_main);
+ const CBlockIndex* tip = ::ChainActive().Tip();
UniValue obj(UniValue::VOBJ);
obj.pushKV("chain", Params().NetworkIDString());
- obj.pushKV("blocks", (int)chainActive.Height());
+ obj.pushKV("blocks", (int)::ChainActive().Height());
obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1);
- obj.pushKV("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex());
- obj.pushKV("difficulty", (double)GetDifficulty(chainActive.Tip()));
- obj.pushKV("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast());
- obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip()));
+ obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
+ obj.pushKV("difficulty", (double)GetDifficulty(tip));
+ obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
+ obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
obj.pushKV("initialblockdownload", IsInitialBlockDownload());
- obj.pushKV("chainwork", chainActive.Tip()->nChainWork.GetHex());
+ obj.pushKV("chainwork", tip->nChainWork.GetHex());
obj.pushKV("size_on_disk", CalculateCurrentUsage());
obj.pushKV("pruned", fPruneMode);
if (fPruneMode) {
- CBlockIndex* block = chainActive.Tip();
+ const CBlockIndex* block = tip;
assert(block);
while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
block = block->pprev;
@@ -1264,7 +1382,6 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
}
const Consensus::Params& consensusParams = Params().GetConsensus();
- CBlockIndex* tip = chainActive.Tip();
UniValue softforks(UniValue::VARR);
UniValue bip9_softforks(UniValue::VOBJ);
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
@@ -1299,10 +1416,11 @@ static UniValue getchaintips(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getchaintips\n"
- "Return information about all known tips in the block tree,"
- " including the main chain as well as orphaned branches.\n"
- "\nResult:\n"
+ RPCHelpMan{"getchaintips",
+ "Return information about all known tips in the block tree,"
+ " including the main chain as well as orphaned branches.\n",
+ {},
+ RPCResult{
"[\n"
" {\n"
" \"height\": xxxx, (numeric) height of the chain tip\n"
@@ -1323,19 +1441,21 @@ static UniValue getchaintips(const JSONRPCRequest& request)
"3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
"4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
"5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
- "\nExamples:\n"
- + HelpExampleCli("getchaintips", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getchaintips", "")
+ HelpExampleRpc("getchaintips", "")
- );
+ },
+ }.ToString());
LOCK(cs_main);
/*
- * Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them.
+ * Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks which do not have another orphan building off of them.
* Algorithm:
* - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
* - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
- * - add chainActive.Tip()
+ * - add ::ChainActive().Tip()
*/
std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
std::set<const CBlockIndex*> setOrphans;
@@ -1343,7 +1463,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex)
{
- if (!chainActive.Contains(item.second)) {
+ if (!::ChainActive().Contains(item.second)) {
setOrphans.insert(item.second);
setPrevs.insert(item.second->pprev);
}
@@ -1357,7 +1477,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
}
// Always report the currently active tip.
- setTips.insert(chainActive.Tip());
+ setTips.insert(::ChainActive().Tip());
/* Construct the output array. */
UniValue res(UniValue::VARR);
@@ -1367,17 +1487,17 @@ static UniValue getchaintips(const JSONRPCRequest& request)
obj.pushKV("height", block->nHeight);
obj.pushKV("hash", block->phashBlock->GetHex());
- const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
+ const int branchLen = block->nHeight - ::ChainActive().FindFork(block)->nHeight;
obj.pushKV("branchlen", branchLen);
std::string status;
- if (chainActive.Contains(block)) {
+ if (::ChainActive().Contains(block)) {
// This block is part of the currently active chain.
status = "active";
} else if (block->nStatus & BLOCK_FAILED_MASK) {
// This block or one of its ancestors is invalid.
status = "invalid";
- } else if (block->nChainTx == 0) {
+ } else if (!block->HaveTxsDownloaded()) {
// This block cannot be connected because full block data for it or one of its parents is missing.
status = "headers-only";
} else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
@@ -1398,15 +1518,18 @@ static UniValue getchaintips(const JSONRPCRequest& request)
return res;
}
-UniValue mempoolInfoToJSON()
+UniValue MempoolInfoToJSON(const CTxMemPool& pool)
{
+ // Make sure this call is atomic in the pool.
+ LOCK(pool.cs);
UniValue ret(UniValue::VOBJ);
- ret.pushKV("size", (int64_t) mempool.size());
- ret.pushKV("bytes", (int64_t) mempool.GetTotalTxSize());
- ret.pushKV("usage", (int64_t) mempool.DynamicMemoryUsage());
+ ret.pushKV("loaded", pool.IsLoaded());
+ ret.pushKV("size", (int64_t)pool.size());
+ ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
+ ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
ret.pushKV("maxmempool", (int64_t) maxmempool);
- ret.pushKV("mempoolminfee", ValueFromAmount(std::max(mempool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK()));
+ ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK()));
ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
return ret;
@@ -1416,10 +1539,12 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getmempoolinfo\n"
- "\nReturns details on the active state of the TX memory pool.\n"
- "\nResult:\n"
+ RPCHelpMan{"getmempoolinfo",
+ "\nReturns details on the active state of the TX memory pool.\n",
+ {},
+ RPCResult{
"{\n"
+ " \"loaded\": true|false (boolean) True if the mempool is fully loaded\n"
" \"size\": xxxxx, (numeric) Current tx count\n"
" \"bytes\": xxxxx, (numeric) Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted\n"
" \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n"
@@ -1427,32 +1552,35 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request)
" \"mempoolminfee\": xxxxx (numeric) Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee\n"
" \"minrelaytxfee\": xxxxx (numeric) Current minimum relay fee for transactions\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getmempoolinfo", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getmempoolinfo", "")
+ HelpExampleRpc("getmempoolinfo", "")
- );
+ },
+ }.ToString());
- return mempoolInfoToJSON();
+ return MempoolInfoToJSON(::mempool);
}
static UniValue preciousblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "preciousblock \"blockhash\"\n"
- "\nTreats a block as if it were received before others with the same work.\n"
- "\nA later preciousblock call can override the effect of an earlier one.\n"
- "\nThe effects of preciousblock are not retained across restarts.\n"
- "\nArguments:\n"
- "1. \"blockhash\" (string, required) the hash of the block to mark as precious\n"
- "\nResult:\n"
- "\nExamples:\n"
- + HelpExampleCli("preciousblock", "\"blockhash\"")
+ RPCHelpMan{"preciousblock",
+ "\nTreats a block as if it were received before others with the same work.\n"
+ "\nA later preciousblock call can override the effect of an earlier one.\n"
+ "\nThe effects of preciousblock are not retained across restarts.\n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as precious"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("preciousblock", "\"blockhash\"")
+ HelpExampleRpc("preciousblock", "\"blockhash\"")
- );
+ },
+ }.ToString());
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
CBlockIndex* pblockindex;
{
@@ -1477,29 +1605,30 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "invalidateblock \"blockhash\"\n"
- "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
- "\nArguments:\n"
- "1. \"blockhash\" (string, required) the hash of the block to mark as invalid\n"
- "\nResult:\n"
- "\nExamples:\n"
- + HelpExampleCli("invalidateblock", "\"blockhash\"")
+ RPCHelpMan{"invalidateblock",
+ "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as invalid"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("invalidateblock", "\"blockhash\"")
+ HelpExampleRpc("invalidateblock", "\"blockhash\"")
- );
+ },
+ }.ToString());
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
CValidationState state;
+ CBlockIndex* pblockindex;
{
LOCK(cs_main);
- CBlockIndex* pblockindex = LookupBlockIndex(hash);
+ pblockindex = LookupBlockIndex(hash);
if (!pblockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
-
- InvalidateBlock(state, Params(), pblockindex);
}
+ InvalidateBlock(state, Params(), pblockindex);
if (state.IsValid()) {
ActivateBestChain(state, Params());
@@ -1516,19 +1645,20 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "reconsiderblock \"blockhash\"\n"
- "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
- "This can be used to undo the effects of invalidateblock.\n"
- "\nArguments:\n"
- "1. \"blockhash\" (string, required) the hash of the block to reconsider\n"
- "\nResult:\n"
- "\nExamples:\n"
- + HelpExampleCli("reconsiderblock", "\"blockhash\"")
+ RPCHelpMan{"reconsiderblock",
+ "\nRemoves invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n"
+ "This can be used to undo the effects of invalidateblock.\n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to reconsider"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("reconsiderblock", "\"blockhash\"")
+ HelpExampleRpc("reconsiderblock", "\"blockhash\"")
- );
+ },
+ }.ToString());
- std::string strHash = request.params[0].get_str();
- uint256 hash(uint256S(strHash));
+ uint256 hash(ParseHashV(request.params[0], "blockhash"));
{
LOCK(cs_main);
@@ -1554,12 +1684,13 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2)
throw std::runtime_error(
- "getchaintxstats ( nblocks blockhash )\n"
- "\nCompute statistics about the total number and rate of transactions in the chain.\n"
- "\nArguments:\n"
- "1. nblocks (numeric, optional) Size of the window in number of blocks (default: one month).\n"
- "2. \"blockhash\" (string, optional) The hash of the block that ends the window.\n"
- "\nResult:\n"
+ RPCHelpMan{"getchaintxstats",
+ "\nCompute statistics about the total number and rate of transactions in the chain.\n",
+ {
+ {"nblocks", RPCArg::Type::NUM, /* default */ "one month", "Size of the window in number of blocks"},
+ {"blockhash", RPCArg::Type::STR_HEX, /* default */ "chain tip", "The hash of the block that ends the window."},
+ },
+ RPCResult{
"{\n"
" \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n"
" \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
@@ -1569,25 +1700,27 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
" \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n"
" \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getchaintxstats", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getchaintxstats", "")
+ HelpExampleRpc("getchaintxstats", "2016")
- );
+ },
+ }.ToString());
const CBlockIndex* pindex;
int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
if (request.params[1].isNull()) {
LOCK(cs_main);
- pindex = chainActive.Tip();
+ pindex = ::ChainActive().Tip();
} else {
- uint256 hash = uint256S(request.params[1].get_str());
+ uint256 hash(ParseHashV(request.params[1], "blockhash"));
LOCK(cs_main);
pindex = LookupBlockIndex(hash);
if (!pindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
- if (!chainActive.Contains(pindex)) {
+ if (!::ChainActive().Contains(pindex)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain");
}
}
@@ -1640,6 +1773,35 @@ static T CalculateTruncatedMedian(std::vector<T>& scores)
}
}
+void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight)
+{
+ if (scores.empty()) {
+ return;
+ }
+
+ std::sort(scores.begin(), scores.end());
+
+ // 10th, 25th, 50th, 75th, and 90th percentile weight units.
+ const double weights[NUM_GETBLOCKSTATS_PERCENTILES] = {
+ total_weight / 10.0, total_weight / 4.0, total_weight / 2.0, (total_weight * 3.0) / 4.0, (total_weight * 9.0) / 10.0
+ };
+
+ int64_t next_percentile_index = 0;
+ int64_t cumulative_weight = 0;
+ for (const auto& element : scores) {
+ cumulative_weight += element.second;
+ while (next_percentile_index < NUM_GETBLOCKSTATS_PERCENTILES && cumulative_weight >= weights[next_percentile_index]) {
+ result[next_percentile_index] = element.first;
+ ++next_percentile_index;
+ }
+ }
+
+ // Fill any remaining percentiles with the last value.
+ for (int64_t i = next_percentile_index; i < NUM_GETBLOCKSTATS_PERCENTILES; i++) {
+ result[i] = scores.back().first;
+ }
+}
+
template<typename T>
static inline bool SetHasKeys(const std::set<T>& set) {return false;}
template<typename T, typename Tk, typename... Args>
@@ -1653,33 +1815,37 @@ static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t)
static UniValue getblockstats(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) {
- throw std::runtime_error(
- "getblockstats hash_or_height ( stats )\n"
- "\nCompute per block statistics for a given window. All amounts are in satoshis.\n"
- "It won't work for some heights with pruning.\n"
- "It won't work without -txindex for utxo_size_inc, *fee or *feerate stats.\n"
- "\nArguments:\n"
- "1. \"hash_or_height\" (string or numeric, required) The block hash or height of the target block\n"
- "2. \"stats\" (array, optional) Values to plot, by default all values (see result below)\n"
- " [\n"
- " \"height\", (string, optional) Selected statistic\n"
- " \"time\", (string, optional) Selected statistic\n"
- " ,...\n"
- " ]\n"
- "\nResult:\n"
+ const RPCHelpMan help{"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", "", {"", "string or numeric"}},
+ {"stats", RPCArg::Type::ARR, /* default */ "all values", "Values to plot (see result below)",
+ {
+ {"height", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"},
+ {"time", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"},
+ },
+ "stats"},
+ },
+ RPCResult{
"{ (json object)\n"
" \"avgfee\": xxxxx, (numeric) Average fee in the block\n"
" \"avgfeerate\": xxxxx, (numeric) Average feerate (in satoshis per virtual byte)\n"
" \"avgtxsize\": xxxxx, (numeric) Average transaction size\n"
" \"blockhash\": xxxxx, (string) The block hash (to check for potential reorgs)\n"
+ " \"feerate_percentiles\": [ (array of numeric) Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)\n"
+ " \"10th_percentile_feerate\", (numeric) The 10th percentile feerate\n"
+ " \"25th_percentile_feerate\", (numeric) The 25th percentile feerate\n"
+ " \"50th_percentile_feerate\", (numeric) The 50th percentile feerate\n"
+ " \"75th_percentile_feerate\", (numeric) The 75th percentile feerate\n"
+ " \"90th_percentile_feerate\", (numeric) The 90th percentile feerate\n"
+ " ],\n"
" \"height\": xxxxx, (numeric) The height of the block\n"
" \"ins\": xxxxx, (numeric) The number of inputs (excluding coinbase)\n"
" \"maxfee\": xxxxx, (numeric) Maximum fee in the block\n"
" \"maxfeerate\": xxxxx, (numeric) Maximum feerate (in satoshis per virtual byte)\n"
" \"maxtxsize\": xxxxx, (numeric) Maximum transaction size\n"
" \"medianfee\": xxxxx, (numeric) Truncated median fee in the block\n"
- " \"medianfeerate\": xxxxx, (numeric) Truncated median feerate (in satoshis per virtual byte)\n"
" \"mediantime\": xxxxx, (numeric) The block median time past\n"
" \"mediantxsize\": xxxxx, (numeric) Truncated median transaction size\n"
" \"minfee\": xxxxx, (numeric) Minimum fee in the block\n"
@@ -1699,10 +1865,14 @@ static UniValue getblockstats(const JSONRPCRequest& request)
" \"utxo_increase\": xxxxx, (numeric) The increase/decrease in the number of unspent outputs\n"
" \"utxo_size_inc\": xxxxx, (numeric) The increase/decrease in size for the utxo index (not discounting op_return and similar)\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
+ },
+ RPCExamples{
+ HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
+ HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
- );
+ },
+ };
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
}
LOCK(cs_main);
@@ -1710,7 +1880,7 @@ static UniValue getblockstats(const JSONRPCRequest& request)
CBlockIndex* pindex;
if (request.params[0].isNum()) {
const int height = request.params[0].get_int();
- const int current_tip = chainActive.Height();
+ const int current_tip = ::ChainActive().Height();
if (height < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d is negative", height));
}
@@ -1718,15 +1888,14 @@ static UniValue getblockstats(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d after current tip %d", height, current_tip));
}
- pindex = chainActive[height];
+ pindex = ::ChainActive()[height];
} else {
- const std::string strHash = request.params[0].get_str();
- const uint256 hash(uint256S(strHash));
+ const uint256 hash(ParseHashV(request.params[0], "hash_or_height"));
pindex = LookupBlockIndex(hash);
if (!pindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
- if (!chainActive.Contains(pindex)) {
+ if (!::ChainActive().Contains(pindex)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Block is not in chain %s", Params().NetworkIDString()));
}
}
@@ -1743,17 +1912,18 @@ static UniValue getblockstats(const JSONRPCRequest& request)
}
const CBlock block = GetBlockChecked(pindex);
+ const CBlockUndo blockUndo = GetUndoChecked(pindex);
const bool do_all = stats.size() == 0; // Calculate everything if nothing selected (default)
const bool do_mediantxsize = do_all || stats.count("mediantxsize") != 0;
const bool do_medianfee = do_all || stats.count("medianfee") != 0;
- const bool do_medianfeerate = do_all || stats.count("medianfeerate") != 0;
- const bool loop_inputs = do_all || do_medianfee || do_medianfeerate ||
+ const bool do_feerate_percentiles = do_all || stats.count("feerate_percentiles") != 0;
+ const bool loop_inputs = do_all || do_medianfee || do_feerate_percentiles ||
SetHasKeys(stats, "utxo_size_inc", "totalfee", "avgfee", "avgfeerate", "minfee", "maxfee", "minfeerate", "maxfeerate");
const bool loop_outputs = do_all || loop_inputs || stats.count("total_out");
const bool do_calculate_size = do_mediantxsize ||
SetHasKeys(stats, "total_size", "avgtxsize", "mintxsize", "maxtxsize", "swtotal_size");
- const bool do_calculate_weight = do_all || SetHasKeys(stats, "total_weight", "avgfeerate", "swtotal_weight", "avgfeerate", "medianfeerate", "minfeerate", "maxfeerate");
+ const bool do_calculate_weight = do_all || SetHasKeys(stats, "total_weight", "avgfeerate", "swtotal_weight", "avgfeerate", "feerate_percentiles", "minfeerate", "maxfeerate");
const bool do_calculate_sw = do_all || SetHasKeys(stats, "swtxs", "swtotal_size", "swtotal_weight");
CAmount maxfee = 0;
@@ -1773,17 +1943,18 @@ static UniValue getblockstats(const JSONRPCRequest& request)
int64_t total_weight = 0;
int64_t utxo_size_inc = 0;
std::vector<CAmount> fee_array;
- std::vector<CAmount> feerate_array;
+ std::vector<std::pair<CAmount, int64_t>> feerate_array;
std::vector<int64_t> txsize_array;
- for (const auto& tx : block.vtx) {
+ for (size_t i = 0; i < block.vtx.size(); ++i) {
+ const auto& tx = block.vtx.at(i);
outputs += tx->vout.size();
CAmount tx_total_out = 0;
if (loop_outputs) {
for (const CTxOut& out : tx->vout) {
tx_total_out += out.nValue;
- utxo_size_inc += GetSerializeSize(out, SER_NETWORK, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD;
+ utxo_size_inc += GetSerializeSize(out, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD;
}
}
@@ -1819,22 +1990,13 @@ static UniValue getblockstats(const JSONRPCRequest& request)
}
if (loop_inputs) {
-
- if (!g_txindex) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more of the selected stats requires -txindex enabled");
- }
CAmount tx_total_in = 0;
- for (const CTxIn& in : tx->vin) {
- CTransactionRef tx_in;
- uint256 hashBlock;
- if (!GetTransaction(in.prevout.hash, tx_in, Params().GetConsensus(), hashBlock, false)) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, std::string("Unexpected internal error (tx index seems corrupt)"));
- }
-
- CTxOut prevoutput = tx_in->vout[in.prevout.n];
+ const auto& txundo = blockUndo.vtxundo.at(i - 1);
+ for (const Coin& coin: txundo.vprevout) {
+ const CTxOut& prevoutput = coin.out;
tx_total_in += prevoutput.nValue;
- utxo_size_inc -= GetSerializeSize(prevoutput, SER_NETWORK, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD;
+ utxo_size_inc -= GetSerializeSize(prevoutput, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD;
}
CAmount txfee = tx_total_in - tx_total_out;
@@ -1848,26 +2010,34 @@ static UniValue getblockstats(const JSONRPCRequest& request)
// New feerate uses satoshis per virtual byte instead of per serialized byte
CAmount feerate = weight ? (txfee * WITNESS_SCALE_FACTOR) / weight : 0;
- if (do_medianfeerate) {
- feerate_array.push_back(feerate);
+ if (do_feerate_percentiles) {
+ feerate_array.emplace_back(std::make_pair(feerate, weight));
}
maxfeerate = std::max(maxfeerate, feerate);
minfeerate = std::min(minfeerate, feerate);
}
}
+ CAmount feerate_percentiles[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
+ CalculatePercentilesByWeight(feerate_percentiles, feerate_array, total_weight);
+
+ UniValue feerates_res(UniValue::VARR);
+ for (int64_t i = 0; i < NUM_GETBLOCKSTATS_PERCENTILES; i++) {
+ feerates_res.push_back(feerate_percentiles[i]);
+ }
+
UniValue ret_all(UniValue::VOBJ);
ret_all.pushKV("avgfee", (block.vtx.size() > 1) ? totalfee / (block.vtx.size() - 1) : 0);
ret_all.pushKV("avgfeerate", total_weight ? (totalfee * WITNESS_SCALE_FACTOR) / total_weight : 0); // Unit: sat/vbyte
ret_all.pushKV("avgtxsize", (block.vtx.size() > 1) ? total_size / (block.vtx.size() - 1) : 0);
ret_all.pushKV("blockhash", pindex->GetBlockHash().GetHex());
+ ret_all.pushKV("feerate_percentiles", feerates_res);
ret_all.pushKV("height", (int64_t)pindex->nHeight);
ret_all.pushKV("ins", inputs);
ret_all.pushKV("maxfee", maxfee);
ret_all.pushKV("maxfeerate", maxfeerate);
ret_all.pushKV("maxtxsize", maxtxsize);
ret_all.pushKV("medianfee", CalculateTruncatedMedian(fee_array));
- ret_all.pushKV("medianfeerate", CalculateTruncatedMedian(feerate_array));
ret_all.pushKV("mediantime", pindex->GetMedianTimePast());
ret_all.pushKV("mediantxsize", CalculateTruncatedMedian(txsize_array));
ret_all.pushKV("minfee", (minfee == MAX_MONEY) ? 0 : minfee);
@@ -1906,19 +2076,22 @@ static UniValue savemempool(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
- "savemempool\n"
- "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n"
- "\nExamples:\n"
- + HelpExampleCli("savemempool", "")
+ RPCHelpMan{"savemempool",
+ "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n",
+ {},
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("savemempool", "")
+ HelpExampleRpc("savemempool", "")
- );
+ },
+ }.ToString());
}
- if (!g_is_mempool_loaded) {
+ if (!::mempool.IsLoaded()) {
throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
}
- if (!DumpMempool()) {
+ if (!DumpMempool(::mempool)) {
throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
}
@@ -1989,47 +2162,55 @@ UniValue scantxoutset(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "scantxoutset <action> ( <scanobjects> )\n"
- "\nEXPERIMENTAL warning: this call may be removed or changed in future releases.\n"
- "\nScans the unspent transaction output set for entries that match certain output descriptors.\n"
- "Examples of output descriptors are:\n"
- " addr(<address>) Outputs whose scriptPubKey corresponds to the specified address (does not include P2PK)\n"
- " raw(<hex script>) Outputs whose scriptPubKey equals the specified hex scripts\n"
- " combo(<pubkey>) P2PK, P2PKH, P2WPKH, and P2SH-P2WPKH outputs for the given pubkey\n"
- " pkh(<pubkey>) P2PKH outputs for the given pubkey\n"
- " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
- "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
- "or more path elements separated by \"/\", and optionally ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n"
- "unhardened or hardened child keys.\n"
- "In the latter case, a range needs to be specified by below if different from 1000.\n"
- "For more information on output descriptors, see the documentation at TODO\n"
- "\nArguments:\n"
- "1. \"action\" (string, required) The action to execute\n"
+ RPCHelpMan{"scantxoutset",
+ "\nEXPERIMENTAL warning: this call may be removed or changed in future releases.\n"
+ "\nScans the unspent transaction output set for entries that match certain output descriptors.\n"
+ "Examples of output descriptors are:\n"
+ " addr(<address>) Outputs whose scriptPubKey corresponds to the specified address (does not include P2PK)\n"
+ " raw(<hex script>) Outputs whose scriptPubKey equals the specified hex scripts\n"
+ " combo(<pubkey>) P2PK, P2PKH, P2WPKH, and P2SH-P2WPKH outputs for the given pubkey\n"
+ " pkh(<pubkey>) P2PKH outputs for the given pubkey\n"
+ " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
+ "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
+ "or more path elements separated by \"/\", and optionally ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n"
+ "unhardened or hardened child keys.\n"
+ "In the latter case, a range needs to be specified by below if different from 1000.\n"
+ "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n",
+ {
+ {"action", RPCArg::Type::STR, RPCArg::Optional::NO, "The action to execute\n"
" \"start\" for starting a scan\n"
" \"abort\" for aborting the current scan (returns true when abort was successful)\n"
- " \"status\" for progress report (in %) of the current scan\n"
- "2. \"scanobjects\" (array, required) Array of scan objects\n"
- " [ Every scan object is either a string descriptor or an object:\n"
- " \"descriptor\", (string, optional) An output descriptor\n"
- " { (object, optional) An object with output descriptor and metadata\n"
- " \"desc\": \"descriptor\", (string, required) An output descriptor\n"
- " \"range\": n, (numeric, optional) Up to what child index HD chains should be explored (default: 1000)\n"
- " },\n"
- " ...\n"
- " ]\n"
- "\nResult:\n"
+ " \"status\" for progress report (in %) of the current scan"},
+ {"scanobjects", RPCArg::Type::ARR, RPCArg::Optional::NO, "Array of scan objects\n"
+ " Every scan object is either a string descriptor or an object:",
+ {
+ {"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"},
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with output descriptor and metadata",
+ {
+ {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"},
+ {"range", RPCArg::Type::RANGE, /* default */ "1000", "The range of HD chain indexes to explore (either end or [begin,end])"},
+ },
+ },
+ },
+ "[scanobjects,...]"},
+ },
+ RPCResult{
"{\n"
" \"unspents\": [\n"
" {\n"
" \"txid\" : \"transactionid\", (string) The transaction id\n"
" \"vout\": n, (numeric) the vout value\n"
" \"scriptPubKey\" : \"script\", (string) the script key\n"
+ " \"desc\" : \"descriptor\", (string) A specialized descriptor for the matched scriptPubKey\n"
" \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " of the unspent output\n"
" \"height\" : n, (numeric) Height of the unspent transaction output\n"
" }\n"
" ,...], \n"
" \"total_amount\" : x.xxx, (numeric) The total amount of all found unspent outputs in " + CURRENCY_UNIT + "\n"
"]\n"
+ },
+ RPCExamples{""},
+ }.ToString()
);
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});
@@ -2058,12 +2239,13 @@ UniValue scantxoutset(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
}
std::set<CScript> needles;
+ std::map<CScript, std::string> descriptors;
CAmount total_in = 0;
// loop through the scan objects
for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
std::string desc_str;
- int range = 1000;
+ std::pair<int64_t, int64_t> range = {0, 1000};
if (scanobject.isStr()) {
desc_str = scanobject.get_str();
} else if (scanobject.isObject()) {
@@ -2072,8 +2254,7 @@ UniValue scantxoutset(const JSONRPCRequest& request)
desc_str = desc_uni.get_str();
UniValue range_uni = find_value(scanobject, "range");
if (!range_uni.isNull()) {
- range = range_uni.get_int();
- if (range < 0 || range > 1000000) throw JSONRPCError(RPC_INVALID_PARAMETER, "range out of range");
+ range = ParseDescriptorRange(range_uni);
}
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan object needs to be either a string or an object");
@@ -2084,13 +2265,20 @@ UniValue scantxoutset(const JSONRPCRequest& request)
if (!desc) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor '%s'", desc_str));
}
- if (!desc->IsRange()) range = 0;
- for (int i = 0; i <= range; ++i) {
+ if (!desc->IsRange()) {
+ range.first = 0;
+ range.second = 0;
+ }
+ for (int i = range.first; i <= range.second; ++i) {
std::vector<CScript> scripts;
if (!desc->Expand(i, provider, scripts, provider)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys: '%s'", desc_str));
}
- needles.insert(scripts.begin(), scripts.end());
+ for (const auto& script : scripts) {
+ std::string inferred = InferDescriptor(script, provider)->ToString();
+ needles.emplace(script);
+ descriptors.emplace(std::move(script), std::move(inferred));
+ }
}
}
@@ -2123,6 +2311,7 @@ UniValue scantxoutset(const JSONRPCRequest& request)
unspent.pushKV("txid", outpoint.hash.GetHex());
unspent.pushKV("vout", (int32_t)outpoint.n);
unspent.pushKV("scriptPubKey", HexStr(txo.scriptPubKey.begin(), txo.scriptPubKey.end()));
+ unspent.pushKV("desc", descriptors[txo.scriptPubKey]);
unspent.pushKV("amount", ValueFromAmount(txo.nValue));
unspent.pushKV("height", (int32_t)coin.nHeight);
@@ -2136,6 +2325,86 @@ UniValue scantxoutset(const JSONRPCRequest& request)
return result;
}
+static UniValue getblockfilter(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
+ throw std::runtime_error(
+ RPCHelpMan{"getblockfilter",
+ "\nRetrieve a BIP 157 content filter for a particular block.\n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hash of the block"},
+ {"filtertype", RPCArg::Type::STR, /*default*/ "basic", "The type name of the filter"},
+ },
+ RPCResult{
+ "{\n"
+ " \"filter\" : (string) the hex-encoded filter data\n"
+ " \"header\" : (string) the hex-encoded filter header\n"
+ "}\n"
+ },
+ RPCExamples{
+ HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"")
+ }
+ }.ToString()
+ );
+ }
+
+ uint256 block_hash = ParseHashV(request.params[0], "blockhash");
+ std::string filtertype_name = "basic";
+ if (!request.params[1].isNull()) {
+ filtertype_name = request.params[1].get_str();
+ }
+
+ BlockFilterType filtertype;
+ if (!BlockFilterTypeByName(filtertype_name, filtertype)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown filtertype");
+ }
+
+ BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
+ if (!index) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Index is not enabled for filtertype " + filtertype_name);
+ }
+
+ const CBlockIndex* block_index;
+ bool block_was_connected;
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(block_hash);
+ if (!block_index) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+ }
+ block_was_connected = block_index->IsValid(BLOCK_VALID_SCRIPTS);
+ }
+
+ bool index_ready = index->BlockUntilSyncedToCurrentChain();
+
+ BlockFilter filter;
+ uint256 filter_header;
+ if (!index->LookupFilter(block_index, filter) ||
+ !index->LookupFilterHeader(block_index, filter_header)) {
+ int err_code;
+ std::string errmsg = "Filter not found.";
+
+ if (!block_was_connected) {
+ err_code = RPC_INVALID_ADDRESS_OR_KEY;
+ errmsg += " Block was not connected to active chain.";
+ } else if (!index_ready) {
+ err_code = RPC_MISC_ERROR;
+ errmsg += " Block filters are still in the process of being indexed.";
+ } else {
+ err_code = RPC_INTERNAL_ERROR;
+ errmsg += " This error is unexpected and indicates index corruption.";
+ }
+
+ throw JSONRPCError(err_code, errmsg);
+ }
+
+ UniValue ret(UniValue::VOBJ);
+ ret.pushKV("filter", HexStr(filter.GetEncodedFilter()));
+ ret.pushKV("header", filter_header.GetHex());
+ return ret;
+}
+
+// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
@@ -2162,6 +2431,7 @@ static const CRPCCommand commands[] =
{ "blockchain", "preciousblock", &preciousblock, {"blockhash"} },
{ "blockchain", "scantxoutset", &scantxoutset, {"action", "scanobjects"} },
+ { "blockchain", "getblockfilter", &getblockfilter, {"blockhash", "filtertype"} },
/* Not shown in help */
{ "hidden", "invalidateblock", &invalidateblock, {"blockhash"} },
@@ -2171,6 +2441,7 @@ static const CRPCCommand commands[] =
{ "hidden", "waitforblockheight", &waitforblockheight, {"height","timeout"} },
{ "hidden", "syncwithvalidationinterfacequeue", &syncwithvalidationinterfacequeue, {} },
};
+// clang-format on
void RegisterBlockchainRPCCommands(CRPCTable &t)
{
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index 3aa8de2d2b..ff461fbcbc 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -1,17 +1,27 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_RPC_BLOCKCHAIN_H
#define BITCOIN_RPC_BLOCKCHAIN_H
+#include <amount.h>
+#include <sync.h>
+
+#include <stdint.h>
+#include <vector>
+
+extern RecursiveMutex cs_main;
+
class CBlock;
class CBlockIndex;
+class CTxMemPool;
class UniValue;
+static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5;
+
/**
- * Get the difficulty of the net wrt to the given block index, or the chain tip if
- * not provided.
+ * Get the difficulty of the net wrt to the given block index.
*
* @return A floating point number that is a multiple of the main net minimum
* difficulty (4295032833 hashes).
@@ -22,15 +32,18 @@ double GetDifficulty(const CBlockIndex* blockindex);
void RPCNotifyBlockChange(bool ibd, const CBlockIndex *);
/** Block description to JSON */
-UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
+UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails = false) LOCKS_EXCLUDED(cs_main);
/** Mempool information to JSON */
-UniValue mempoolInfoToJSON();
+UniValue MempoolInfoToJSON(const CTxMemPool& pool);
/** Mempool to JSON */
-UniValue mempoolToJSON(bool fVerbose = false);
+UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose = false);
/** Block header to JSON */
-UniValue blockheaderToJSON(const CBlockIndex* blockindex);
+UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex) LOCKS_EXCLUDED(cs_main);
+
+/** Used by getblockstats to get feerates at different percentiles by weight */
+void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight);
#endif
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index eb6b164075..4144a17bc3 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -1,11 +1,11 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <rpc/client.h>
#include <rpc/protocol.h>
-#include <util.h>
+#include <util/system.h>
#include <set>
#include <stdint.h>
@@ -18,6 +18,7 @@ public:
std::string paramName; //!< parameter name
};
+// clang-format off
/**
* Specify a (method, idx, name) here if the argument is a non-string RPC
* argument and needs to be converted from JSON.
@@ -27,8 +28,6 @@ public:
static const CRPCConvertParam vRPCConvertParams[] =
{
{ "setmocktime", 0, "timestamp" },
- { "generate", 0, "nblocks" },
- { "generate", 1, "maxtries" },
{ "generatetoaddress", 0, "nblocks" },
{ "generatetoaddress", 2, "maxtries" },
{ "getnetworkhashps", 0, "nblocks" },
@@ -40,15 +39,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "settxfee", 0, "amount" },
{ "sethdseed", 0, "newkeypool" },
{ "getreceivedbyaddress", 1, "minconf" },
- { "getreceivedbyaccount", 1, "minconf" },
{ "getreceivedbylabel", 1, "minconf" },
{ "listreceivedbyaddress", 0, "minconf" },
{ "listreceivedbyaddress", 1, "include_empty" },
{ "listreceivedbyaddress", 2, "include_watchonly" },
- { "listreceivedbyaddress", 3, "address_filter" },
- { "listreceivedbyaccount", 0, "minconf" },
- { "listreceivedbyaccount", 1, "include_empty" },
- { "listreceivedbyaccount", 2, "include_watchonly" },
{ "listreceivedbylabel", 0, "minconf" },
{ "listreceivedbylabel", 1, "include_empty" },
{ "listreceivedbylabel", 2, "include_watchonly" },
@@ -59,15 +53,9 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "waitforblockheight", 1, "timeout" },
{ "waitforblock", 1, "timeout" },
{ "waitfornewblock", 0, "timeout" },
- { "move", 2, "amount" },
- { "move", 3, "minconf" },
- { "sendfrom", 2, "amount" },
- { "sendfrom", 3, "minconf" },
{ "listtransactions", 1, "count" },
{ "listtransactions", 2, "skip" },
{ "listtransactions", 3, "include_watchonly" },
- { "listaccounts", 0, "minconf" },
- { "listaccounts", 1, "include_watchonly" },
{ "walletpassphrase", 1, "timeout" },
{ "getblocktemplate", 0, "template_request" },
{ "listsinceblock", 1, "target_confirmations" },
@@ -78,6 +66,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendmany", 4, "subtractfeefrom" },
{ "sendmany", 5 , "replaceable" },
{ "sendmany", 6 , "conf_target" },
+ { "deriveaddresses", 1, "range" },
{ "scantxoutset", 1, "scanobjects" },
{ "addmultisigaddress", 0, "nrequired" },
{ "addmultisigaddress", 1, "keys" },
@@ -99,23 +88,22 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "createrawtransaction", 2, "locktime" },
{ "createrawtransaction", 3, "replaceable" },
{ "decoderawtransaction", 1, "iswitness" },
- { "signrawtransaction", 1, "prevtxs" },
- { "signrawtransaction", 2, "privkeys" },
{ "signrawtransactionwithkey", 1, "privkeys" },
{ "signrawtransactionwithkey", 2, "prevtxs" },
{ "signrawtransactionwithwallet", 1, "prevtxs" },
{ "sendrawtransaction", 1, "allowhighfees" },
+ { "sendrawtransaction", 1, "maxfeerate" },
{ "testmempoolaccept", 0, "rawtxs" },
{ "testmempoolaccept", 1, "allowhighfees" },
+ { "testmempoolaccept", 1, "maxfeerate" },
{ "combinerawtransaction", 0, "txs" },
{ "fundrawtransaction", 1, "options" },
{ "fundrawtransaction", 2, "iswitness" },
{ "walletcreatefundedpsbt", 0, "inputs" },
{ "walletcreatefundedpsbt", 1, "outputs" },
{ "walletcreatefundedpsbt", 2, "locktime" },
- { "walletcreatefundedpsbt", 3, "replaceable" },
- { "walletcreatefundedpsbt", 4, "options" },
- { "walletcreatefundedpsbt", 5, "bip32derivs" },
+ { "walletcreatefundedpsbt", 3, "options" },
+ { "walletcreatefundedpsbt", 4, "bip32derivs" },
{ "walletprocesspsbt", 1, "sign" },
{ "walletprocesspsbt", 3, "bip32derivs" },
{ "createpsbt", 0, "inputs" },
@@ -123,6 +111,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "createpsbt", 2, "locktime" },
{ "createpsbt", 3, "replaceable" },
{ "combinepsbt", 0, "txs"},
+ { "joinpsbts", 0, "txs"},
{ "finalizepsbt", 1, "extract"},
{ "converttopsbt", 1, "permitsigdata"},
{ "converttopsbt", 2, "iswitness"},
@@ -158,7 +147,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "logging", 0, "include" },
{ "logging", 1, "exclude" },
{ "disconnectnode", 1, "nodeid" },
- { "addwitnessaddress", 1, "p2sh" },
// Echo with conversion (For testing only)
{ "echojson", 0, "arg0" },
{ "echojson", 1, "arg1" },
@@ -173,7 +161,11 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "rescanblockchain", 0, "start_height"},
{ "rescanblockchain", 1, "stop_height"},
{ "createwallet", 1, "disable_private_keys"},
+ { "createwallet", 2, "blank"},
+ { "getnodeaddresses", 0, "count"},
+ { "stop", 0, "wait" },
};
+// clang-format on
class CRPCConvertTable
{
diff --git a/src/rpc/client.h b/src/rpc/client.h
index e09e1dedf3..b9fee5bbb3 100644
--- a/src/rpc/client.h
+++ b/src/rpc/client.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2016 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index e751587dc7..1831562100 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -10,45 +10,40 @@
#include <consensus/params.h>
#include <consensus/validation.h>
#include <core_io.h>
-#include <validation.h>
#include <key_io.h>
#include <miner.h>
#include <net.h>
#include <policy/fees.h>
#include <pow.h>
#include <rpc/blockchain.h>
-#include <rpc/mining.h>
#include <rpc/server.h>
+#include <rpc/util.h>
+#include <script/script.h>
#include <shutdown.h>
#include <txmempool.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <univalue.h>
+#include <util/fees.h>
+#include <util/strencodings.h>
+#include <util/system.h>
+#include <util/validation.h>
+#include <validation.h>
#include <validationinterface.h>
+#include <versionbitsinfo.h>
#include <warnings.h>
#include <memory>
#include <stdint.h>
-unsigned int ParseConfirmTarget(const UniValue& value)
-{
- int target = value.get_int();
- unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
- if (target < 1 || (unsigned int)target > max_target) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid conf_target, must be between %u - %u", 1, max_target));
- }
- return (unsigned int)target;
-}
-
/**
* Return average network hashes per second based on the last 'lookup' blocks,
* or from the last difficulty change if 'lookup' is nonpositive.
* If 'height' is nonnegative, compute the estimate at the time when a given block was found.
*/
static UniValue GetNetworkHashPS(int lookup, int height) {
- CBlockIndex *pb = chainActive.Tip();
+ CBlockIndex *pb = ::ChainActive().Tip();
- if (height >= 0 && height < chainActive.Height())
- pb = chainActive[height];
+ if (height >= 0 && height < ::ChainActive().Height())
+ pb = ::ChainActive()[height];
if (pb == nullptr || !pb->nHeight)
return 0;
@@ -85,25 +80,28 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2)
throw std::runtime_error(
- "getnetworkhashps ( nblocks height )\n"
- "\nReturns the estimated network hashes per second based on the last n blocks.\n"
- "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
- "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
- "\nArguments:\n"
- "1. nblocks (numeric, optional, default=120) The number of blocks, or -1 for blocks since last difficulty change.\n"
- "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n"
- "\nResult:\n"
+ RPCHelpMan{"getnetworkhashps",
+ "\nReturns the estimated network hashes per second based on the last n blocks.\n"
+ "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
+ "Pass in [height] to estimate the network speed at the time when a certain block was found.\n",
+ {
+ {"nblocks", RPCArg::Type::NUM, /* default */ "120", "The number of blocks, or -1 for blocks since last difficulty change."},
+ {"height", RPCArg::Type::NUM, /* default */ "-1", "To estimate at the time of the given height."},
+ },
+ RPCResult{
"x (numeric) Hashes per second estimated\n"
- "\nExamples:\n"
- + HelpExampleCli("getnetworkhashps", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getnetworkhashps", "")
+ HelpExampleRpc("getnetworkhashps", "")
- );
+ },
+ }.ToString());
LOCK(cs_main);
return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1);
}
-UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript)
+static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
{
static const int nInnerLoopCount = 0x10000;
int nHeightEnd = 0;
@@ -111,20 +109,20 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
{ // Don't keep cs_main locked
LOCK(cs_main);
- nHeight = chainActive.Height();
+ nHeight = ::ChainActive().Height();
nHeightEnd = nHeight+nGenerate;
}
unsigned int nExtraNonce = 0;
UniValue blockHashes(UniValue::VARR);
while (nHeight < nHeightEnd && !ShutdownRequested())
{
- std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript));
+ std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbase_script));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
{
LOCK(cs_main);
- IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
+ IncrementExtraNonce(pblock, ::ChainActive().Tip(), nExtraNonce);
}
while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
++pblock->nNonce;
@@ -141,12 +139,6 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
-
- //mark script as important because it was used at least for one coinbase output if the script came from the wallet
- if (keepScript)
- {
- coinbaseScript->KeepScript();
- }
}
return blockHashes;
}
@@ -155,18 +147,23 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
throw std::runtime_error(
- "generatetoaddress nblocks address (maxtries)\n"
- "\nMine blocks immediately to a specified address (before the RPC call returns)\n"
- "\nArguments:\n"
- "1. nblocks (numeric, required) How many blocks are generated immediately.\n"
- "2. address (string, required) The address to send the newly generated bitcoin to.\n"
- "3. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
- "\nResult:\n"
+ RPCHelpMan{"generatetoaddress",
+ "\nMine blocks immediately to a specified address (before the RPC call returns)\n",
+ {
+ {"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated immediately."},
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The address to send the newly generated bitcoin to."},
+ {"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."},
+ },
+ RPCResult{
"[ blockhashes ] (array) hashes of blocks generated\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nGenerate 11 blocks to myaddress\n"
+ HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
- );
+ + "If you are running the bitcoin core wallet, you can get a new address to send the newly generated bitcoin to with:\n"
+ + HelpExampleCli("getnewaddress", "")
+ },
+ }.ToString());
int nGenerate = request.params[0].get_int();
uint64_t nMaxTries = 1000000;
@@ -179,42 +176,44 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
}
- std::shared_ptr<CReserveScript> coinbaseScript = std::make_shared<CReserveScript>();
- coinbaseScript->reserveScript = GetScriptForDestination(destination);
+ CScript coinbase_script = GetScriptForDestination(destination);
- return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
+ return generateBlocks(coinbase_script, nGenerate, nMaxTries);
}
static UniValue getmininginfo(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0)
+ if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
- "getmininginfo\n"
- "\nReturns a json object containing mining-related information."
- "\nResult:\n"
- "{\n"
- " \"blocks\": nnn, (numeric) The current block\n"
- " \"currentblockweight\": nnn, (numeric) The last block weight\n"
- " \"currentblocktx\": nnn, (numeric) The last block transaction\n"
- " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
- " \"networkhashps\": nnn, (numeric) The network hashes per second\n"
- " \"pooledtx\": n (numeric) The size of the mempool\n"
- " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
- " \"warnings\": \"...\" (string) any network and blockchain warnings\n"
- "}\n"
- "\nExamples:\n"
- + HelpExampleCli("getmininginfo", "")
+ RPCHelpMan{"getmininginfo",
+ "\nReturns a json object containing mining-related information.",
+ {},
+ RPCResult{
+ "{\n"
+ " \"blocks\": nnn, (numeric) The current block\n"
+ " \"currentblockweight\": nnn, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)\n"
+ " \"currentblocktx\": nnn, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)\n"
+ " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
+ " \"networkhashps\": nnn, (numeric) The network hashes per second\n"
+ " \"pooledtx\": n (numeric) The size of the mempool\n"
+ " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
+ " \"warnings\": \"...\" (string) any network and blockchain warnings\n"
+ "}\n"
+ },
+ RPCExamples{
+ HelpExampleCli("getmininginfo", "")
+ HelpExampleRpc("getmininginfo", "")
- );
-
+ },
+ }.ToString());
+ }
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
- obj.pushKV("blocks", (int)chainActive.Height());
- obj.pushKV("currentblockweight", (uint64_t)nLastBlockWeight);
- obj.pushKV("currentblocktx", (uint64_t)nLastBlockTx);
- obj.pushKV("difficulty", (double)GetDifficulty(chainActive.Tip()));
+ obj.pushKV("blocks", (int)::ChainActive().Height());
+ if (BlockAssembler::m_last_block_weight) obj.pushKV("currentblockweight", *BlockAssembler::m_last_block_weight);
+ if (BlockAssembler::m_last_block_num_txs) obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs);
+ obj.pushKV("difficulty", (double)GetDifficulty(::ChainActive().Tip()));
obj.pushKV("networkhashps", getnetworkhashps(request));
obj.pushKV("pooledtx", (uint64_t)mempool.size());
obj.pushKV("chain", Params().NetworkIDString());
@@ -228,26 +227,29 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 3)
throw std::runtime_error(
- "prioritisetransaction <txid> <dummy value> <fee delta>\n"
- "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The transaction id.\n"
- "2. dummy (numeric, optional) API-Compatibility for previous API. Must be zero or null.\n"
- " DEPRECATED. For forward compatibility use named arguments and omit this parameter.\n"
- "3. fee_delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
+ 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"
+ " 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"
" The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
- " considers the transaction as it would have paid a higher (or lower) fee.\n"
- "\nResult:\n"
+ " considers the transaction as it would have paid a higher (or lower) fee."},
+ },
+ RPCResult{
"true (boolean) Returns true\n"
- "\nExamples:\n"
- + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
+ },
+ RPCExamples{
+ HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
+ HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
- );
+ },
+ }.ToString());
LOCK(cs_main);
- uint256 hash = ParseHashStr(request.params[0].get_str(), "txid");
+ uint256 hash(ParseHashV(request.params[0], "txid"));
CAmount nAmount = request.params[2].get_int64();
if (!(request.params[1].isNull() || request.params[1].get_real() == 0)) {
@@ -291,31 +293,32 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
- "getblocktemplate ( TemplateRequest )\n"
- "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
- "It returns data needed to construct a block to work on.\n"
- "For full specification, see BIPs 22, 23, 9, and 145:\n"
- " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
- " https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n"
- " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
- " https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n"
-
- "\nArguments:\n"
- "1. template_request (json object, optional) A json object in the following spec\n"
- " {\n"
- " \"mode\":\"template\" (string, optional) This must be set to \"template\", \"proposal\" (see BIP 23), or omitted\n"
- " \"capabilities\":[ (array, optional) A list of strings\n"
- " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
- " ,...\n"
- " ],\n"
- " \"rules\":[ (array, optional) A list of strings\n"
- " \"support\" (string) client side supported softfork deployment\n"
- " ,...\n"
- " ]\n"
- " }\n"
- "\n"
-
- "\nResult:\n"
+ RPCHelpMan{"getblocktemplate",
+ "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
+ "It returns data needed to construct a block to work on.\n"
+ "For full specification, see BIPs 22, 23, 9, and 145:\n"
+ " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
+ " https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n"
+ " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
+ " https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n",
+ {
+ {"template_request", RPCArg::Type::OBJ, RPCArg::Optional::NO, "A json object in the following spec",
+ {
+ {"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",
+ {
+ {"support", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"},
+ },
+ },
+ {"rules", RPCArg::Type::ARR, RPCArg::Optional::NO, "A list of strings",
+ {
+ {"support", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported softfork deployment"},
+ },
+ },
+ },
+ "\"template_request\""},
+ },
+ RPCResult{
"{\n"
" \"version\" : n, (numeric) The preferred block version\n"
" \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n"
@@ -359,11 +362,12 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
" \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n"
" \"height\" : n (numeric) The height of the next block\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("getblocktemplate", "")
- + HelpExampleRpc("getblocktemplate", "")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("getblocktemplate", "{\"rules\": [\"segwit\"]}")
+ + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}")
+ },
+ }.ToString());
LOCK(cs_main);
@@ -405,7 +409,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
return "duplicate-inconclusive";
}
- CBlockIndex* const pindexPrev = chainActive.Tip();
+ CBlockIndex* const pindexPrev = ::ChainActive().Tip();
// TestBlockValidity only supports blocks built on the current Tip
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
return "inconclusive-not-best-prevblk";
@@ -436,10 +440,10 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
- throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!");
+ throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
if (IsInitialBlockDownload())
- throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
+ throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME " is in initial sync and waiting for blocks...");
static unsigned int nTransactionsUpdatedLast;
@@ -455,13 +459,13 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
// Format: <hashBestChain><nTransactionsUpdatedLast>
std::string lpstr = lpval.get_str();
- hashWatchedChain.SetHex(lpstr.substr(0, 64));
+ hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
}
else
{
// NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
- hashWatchedChain = chainActive.Tip()->GetBlockHash();
+ hashWatchedChain = ::ChainActive().Tip()->GetBlockHash();
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
}
@@ -470,7 +474,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
{
checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);
- WaitableLock lock(g_best_block_mutex);
+ WAIT_LOCK(g_best_block_mutex, lock);
while (g_best_block == hashWatchedChain && IsRPCRunning())
{
if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout)
@@ -490,34 +494,29 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
}
const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
- // If the caller is indicating segwit support, then allow CreateNewBlock()
- // to select witness transactions, after segwit activates (otherwise
- // don't).
- bool fSupportsSegwit = setClientRules.find(segwit_info.name) != setClientRules.end();
+ // GBT must be called with 'segwit' set in the rules
+ if (setClientRules.count(segwit_info.name) != 1) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "getblocktemplate must be called with the segwit rule set (call with {\"rules\": [\"segwit\"]})");
+ }
// Update block
static CBlockIndex* pindexPrev;
static int64_t nStart;
static std::unique_ptr<CBlockTemplate> pblocktemplate;
- // Cache whether the last invocation was with segwit support, to avoid returning
- // a segwit-block to a non-segwit caller.
- static bool fLastTemplateSupportsSegwit = true;
- if (pindexPrev != chainActive.Tip() ||
- (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5) ||
- fLastTemplateSupportsSegwit != fSupportsSegwit)
+ if (pindexPrev != ::ChainActive().Tip() ||
+ (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
{
// Clear pindexPrev so future calls make a new block, despite any failures from here on
pindexPrev = nullptr;
// Store the pindexBest used before CreateNewBlock, to avoid races
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
- CBlockIndex* pindexPrevNew = chainActive.Tip();
+ CBlockIndex* pindexPrevNew = ::ChainActive().Tip();
nStart = GetTime();
- fLastTemplateSupportsSegwit = fSupportsSegwit;
// Create new block
CScript scriptDummy = CScript() << OP_TRUE;
- pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit);
+ pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy);
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
@@ -647,7 +646,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
result.pushKV("transactions", transactions);
result.pushKV("coinbaseaux", aux);
result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
- result.pushKV("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast));
+ result.pushKV("longpollid", ::ChainActive().Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast));
result.pushKV("target", hashTarget.GetHex());
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
result.pushKV("mutable", aMutable);
@@ -669,7 +668,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
result.pushKV("bits", strprintf("%08x", pblock->nBits));
result.pushKV("height", (int64_t)(pindexPrev->nHeight+1));
- if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) {
+ if (!pblocktemplate->vchCoinbaseCommitment.empty()) {
result.pushKV("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()));
}
@@ -699,18 +698,19 @@ static UniValue submitblock(const JSONRPCRequest& request)
// We allow 2 arguments for compliance with BIP22. Argument 2 is ignored.
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
- "submitblock \"hexdata\" ( \"dummy\" )\n"
- "\nAttempts to submit new block to network.\n"
- "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
-
- "\nArguments\n"
- "1. \"hexdata\" (string, required) the hex-encoded block data to submit\n"
- "2. \"dummy\" (optional) dummy value, for compatibility with BIP22. This value is ignored.\n"
- "\nResult:\n"
- "\nExamples:\n"
- + HelpExampleCli("submitblock", "\"mydata\"")
+ RPCHelpMan{"submitblock",
+ "\nAttempts to submit new block to network.\n"
+ "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n",
+ {
+ {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block data to submit"},
+ {"dummy", RPCArg::Type::STR, /* default */ "ignored", "dummy value, for compatibility with BIP22. This value is ignored."},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("submitblock", "\"mydata\"")
+ HelpExampleRpc("submitblock", "\"mydata\"")
- );
+ },
+ }.ToString());
}
std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>();
@@ -750,11 +750,7 @@ static UniValue submitblock(const JSONRPCRequest& request)
RegisterValidationInterface(&sc);
bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block);
UnregisterValidationInterface(&sc);
- if (!new_block) {
- if (!accepted) {
- // TODO Maybe pass down fNewBlock to AcceptBlockHeader, so it is properly set to true in this case?
- return "invalid";
- }
+ if (!new_block && accepted) {
return "duplicate";
}
if (!sc.found) {
@@ -763,33 +759,68 @@ static UniValue submitblock(const JSONRPCRequest& request)
return BIP22ValidationResult(sc.state);
}
-static UniValue estimatefee(const JSONRPCRequest& request)
+static UniValue submitheader(const JSONRPCRequest& request)
{
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "estimatefee was removed in v0.17.\n"
- "Clients should use estimatesmartfee.");
+ if (request.fHelp || request.params.size() != 1) {
+ throw std::runtime_error(
+ RPCHelpMan{"submitheader",
+ "\nDecode the given hexdata as a header and submit it as a candidate chain tip if valid."
+ "\nThrows when the header is invalid.\n",
+ {
+ {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"},
+ },
+ RPCResult{
+ "None"
+ },
+ RPCExamples{
+ HelpExampleCli("submitheader", "\"aabbcc\"") +
+ HelpExampleRpc("submitheader", "\"aabbcc\"")
+ },
+ }.ToString());
+ }
+
+ CBlockHeader h;
+ if (!DecodeHexBlockHeader(h, request.params[0].get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block header decode failed");
+ }
+ {
+ LOCK(cs_main);
+ if (!LookupBlockIndex(h.hashPrevBlock)) {
+ throw JSONRPCError(RPC_VERIFY_ERROR, "Must submit previous header (" + h.hashPrevBlock.GetHex() + ") first");
+ }
+ }
+
+ CValidationState state;
+ ProcessNewBlockHeaders({h}, state, Params(), /* ppindex */ nullptr, /* first_invalid */ nullptr);
+ if (state.IsValid()) return NullUniValue;
+ if (state.IsError()) {
+ throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
+ }
+ throw JSONRPCError(RPC_VERIFY_ERROR, state.GetRejectReason());
}
static UniValue estimatesmartfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "estimatesmartfee conf_target (\"estimate_mode\")\n"
- "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
- "confirmation within conf_target blocks if possible and return the number of blocks\n"
- "for which the estimate is valid. Uses virtual transaction size as defined\n"
- "in BIP 141 (witness data is discounted).\n"
- "\nArguments:\n"
- "1. conf_target (numeric) Confirmation target in blocks (1 - 1008)\n"
- "2. \"estimate_mode\" (string, optional, default=CONSERVATIVE) The fee estimate mode.\n"
+ RPCHelpMan{"estimatesmartfee",
+ "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
+ "confirmation within conf_target blocks if possible and return the number of blocks\n"
+ "for which the estimate is valid. Uses virtual transaction size as defined\n"
+ "in BIP 141 (witness data is discounted).\n",
+ {
+ {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "CONSERVATIVE", "The fee estimate mode.\n"
" Whether to return a more conservative estimate which also satisfies\n"
" a longer history. A conservative estimate potentially returns a\n"
" higher feerate and is more likely to be sufficient for the desired\n"
" target, but is not as responsive to short term drops in the\n"
" prevailing fee market. Must be one of:\n"
- " \"UNSET\" (defaults to CONSERVATIVE)\n"
+ " \"UNSET\"\n"
" \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\"\n"
- "\nResult:\n"
+ " \"CONSERVATIVE\""},
+ },
+ RPCResult{
"{\n"
" \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n"
" \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\n"
@@ -800,13 +831,16 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request)
"fee estimation is able to return based on how long it has been running.\n"
"An error is returned if not enough transactions and blocks\n"
"have been observed to make an estimate for any number of blocks.\n"
- "\nExample:\n"
- + HelpExampleCli("estimatesmartfee", "6")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("estimatesmartfee", "6")
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
- unsigned int conf_target = ParseConfirmTarget(request.params[0]);
+ unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+ unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
bool conservative = true;
if (!request.params[1].isNull()) {
FeeEstimateMode fee_mode;
@@ -834,20 +868,21 @@ static UniValue estimaterawfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "estimaterawfee conf_target (threshold)\n"
- "\nWARNING: This interface is unstable and may disappear or change!\n"
- "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n"
- " implementation of fee estimation. The parameters it can be called with\n"
- " and the results it returns will change if the internal implementation changes.\n"
- "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
- "confirmation within conf_target blocks if possible. Uses virtual transaction size as\n"
- "defined in BIP 141 (witness data is discounted).\n"
- "\nArguments:\n"
- "1. conf_target (numeric) Confirmation target in blocks (1 - 1008)\n"
- "2. threshold (numeric, optional) The proportion of transactions in a given feerate range that must have been\n"
+ RPCHelpMan{"estimaterawfee",
+ "\nWARNING: This interface is unstable and may disappear or change!\n"
+ "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n"
+ " implementation of fee estimation. The parameters it can be called with\n"
+ " and the results it returns will change if the internal implementation changes.\n"
+ "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
+ "confirmation within conf_target blocks if possible. Uses virtual transaction size as\n"
+ "defined in BIP 141 (witness data is discounted).\n",
+ {
+ {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
+ {"threshold", RPCArg::Type::NUM, /* default */ "0.95", "The proportion of transactions in a given feerate range that must have been\n"
" confirmed within conf_target in order to consider those feerates as high enough and proceed to check\n"
- " lower buckets. Default: 0.95\n"
- "\nResult:\n"
+ " lower buckets."},
+ },
+ RPCResult{
"{\n"
" \"short\" : { (json object, optional) estimate for short time horizon\n"
" \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n"
@@ -869,13 +904,16 @@ static UniValue estimaterawfee(const JSONRPCRequest& request)
"}\n"
"\n"
"Results are returned for any horizon which tracks blocks up to the confirmation target.\n"
- "\nExample:\n"
- + HelpExampleCli("estimaterawfee", "6 0.9")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("estimaterawfee", "6 0.9")
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
- unsigned int conf_target = ParseConfirmTarget(request.params[0]);
+ unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+ unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
double threshold = 0.95;
if (!request.params[1].isNull()) {
threshold = request.params[1].get_real();
@@ -886,7 +924,7 @@ static UniValue estimaterawfee(const JSONRPCRequest& request)
UniValue result(UniValue::VOBJ);
- for (FeeEstimateHorizon horizon : {FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}) {
+ for (const FeeEstimateHorizon horizon : {FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}) {
CFeeRate feeRate;
EstimationResult buckets;
@@ -932,6 +970,7 @@ static UniValue estimaterawfee(const JSONRPCRequest& request)
return result;
}
+// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
@@ -940,15 +979,16 @@ static const CRPCCommand commands[] =
{ "mining", "prioritisetransaction", &prioritisetransaction, {"txid","dummy","fee_delta"} },
{ "mining", "getblocktemplate", &getblocktemplate, {"template_request"} },
{ "mining", "submitblock", &submitblock, {"hexdata","dummy"} },
+ { "mining", "submitheader", &submitheader, {"hexdata"} },
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
- { "hidden", "estimatefee", &estimatefee, {} },
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
{ "hidden", "estimaterawfee", &estimaterawfee, {"conf_target", "threshold"} },
};
+// clang-format on
void RegisterMiningRPCCommands(CRPCTable &t)
{
diff --git a/src/rpc/mining.h b/src/rpc/mining.h
deleted file mode 100644
index 8d46273159..0000000000
--- a/src/rpc/mining.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2017 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_RPC_MINING_H
-#define BITCOIN_RPC_MINING_H
-
-#include <script/script.h>
-
-#include <univalue.h>
-
-/** Generate blocks (mine) */
-UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript);
-
-/** Check bounds on a command line confirm target */
-unsigned int ParseConfirmTarget(const UniValue& value);
-
-#endif
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 09812bb980..7008a83143 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,17 +16,15 @@
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/util.h>
+#include <script/descriptor.h>
#include <timedata.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#ifdef ENABLE_WALLET
-#include <wallet/rpcwallet.h>
-#include <wallet/wallet.h>
-#include <wallet/walletdb.h>
-#endif
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <util/validation.h>
#include <warnings.h>
#include <stdint.h>
+#include <tuple>
#ifdef HAVE_MALLOC_INFO
#include <malloc.h>
#endif
@@ -37,28 +35,27 @@ static UniValue validateaddress(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "validateaddress \"address\"\n"
- "\nReturn information about the given bitcoin address.\n"
- "DEPRECATION WARNING: Parts of this command have been deprecated and moved to getaddressinfo. Clients must\n"
- "transition to using getaddressinfo to access this information before upgrading to v0.18. The following deprecated\n"
- "fields have moved to getaddressinfo and will only be shown here with -deprecatedrpc=validateaddress: ismine, iswatchonly,\n"
- "script, hex, pubkeys, sigsrequired, pubkey, addresses, embedded, iscompressed, account, timestamp, hdkeypath, kdmasterkeyid.\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address to validate\n"
- "\nResult:\n"
+ RPCHelpMan{"validateaddress",
+ "\nReturn information about the given bitcoin address.\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to validate"},
+ },
+ RPCResult{
"{\n"
" \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
" \"address\" : \"address\", (string) The bitcoin address validated\n"
- " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
+ " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n"
" \"isscript\" : true|false, (boolean) If the key is a script\n"
" \"iswitness\" : true|false, (boolean) If the address is a witness address\n"
" \"witness_version\" : version (numeric, optional) The version number of the witness program\n"
" \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ },
+ RPCExamples{
+ HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
- );
+ },
+ }.ToString());
CTxDestination dest = DecodeDestination(request.params[0].get_str());
bool isValid = IsValidDestination(dest);
@@ -67,57 +64,47 @@ static UniValue validateaddress(const JSONRPCRequest& request)
ret.pushKV("isvalid", isValid);
if (isValid)
{
+ std::string currentAddress = EncodeDestination(dest);
+ ret.pushKV("address", currentAddress);
-#ifdef ENABLE_WALLET
- if (HasWallets() && IsDeprecatedRPCEnabled("validateaddress")) {
- ret.pushKVs(getaddressinfo(request));
- }
-#endif
- if (ret["address"].isNull()) {
- std::string currentAddress = EncodeDestination(dest);
- ret.pushKV("address", currentAddress);
+ CScript scriptPubKey = GetScriptForDestination(dest);
+ ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
- CScript scriptPubKey = GetScriptForDestination(dest);
- ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
-
- UniValue detail = DescribeAddress(dest);
- ret.pushKVs(detail);
- }
+ UniValue detail = DescribeAddress(dest);
+ ret.pushKVs(detail);
}
return ret;
}
-// Needed even with !ENABLE_WALLET, to pass (ignored) pointers around
-class CWallet;
-
static UniValue createmultisig(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
{
- std::string msg = "createmultisig nrequired [\"key\",...] ( \"address_type\" )\n"
- "\nCreates a multi-signature address with n signature of m keys required.\n"
- "It returns a json object with the address and redeemScript.\n"
- "\nArguments:\n"
- "1. nrequired (numeric, required) The number of required signatures out of the n keys.\n"
- "2. \"keys\" (string, required) A json array of hex-encoded public keys\n"
- " [\n"
- " \"key\" (string) The hex-encoded public key\n"
- " ,...\n"
- " ]\n"
- "3. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is legacy.\n"
-
- "\nResult:\n"
+ std::string msg =
+ RPCHelpMan{"createmultisig",
+ "\nCreates a multi-signature address with n signature of m keys required.\n"
+ "It returns a json object with the address and redeemScript.\n",
+ {
+ {"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys."},
+ {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of hex-encoded public keys.",
+ {
+ {"key", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The hex-encoded public key"},
+ }},
+ {"address_type", RPCArg::Type::STR, /* default */ "legacy", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ },
+ RPCResult{
"{\n"
" \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
" \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
"}\n"
-
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate a multisig address from 2 public keys\n"
+ HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"")
- ;
+ },
+ }.ToString();
throw std::runtime_error(msg);
}
@@ -130,8 +117,7 @@ static UniValue createmultisig(const JSONRPCRequest& request)
if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) {
pubkeys.push_back(HexToPubKey(keys[i].get_str()));
} else {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\nNote that from v0.16, createmultisig no longer accepts addresses."
- " Users must use addmultisigaddress to create multisig addresses with addresses known to the wallet.", keys[i].get_str()));
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\n.", keys[i].get_str()));
}
}
@@ -155,28 +141,150 @@ static UniValue createmultisig(const JSONRPCRequest& request)
return result;
}
+UniValue getdescriptorinfo(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 1) {
+ throw std::runtime_error(
+ RPCHelpMan{"getdescriptorinfo",
+ {"\nAnalyses a descriptor.\n"},
+ {
+ {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."},
+ },
+ RPCResult{
+ "{\n"
+ " \"descriptor\" : \"desc\", (string) The descriptor in canonical form, without private keys\n"
+ " \"isrange\" : true|false, (boolean) Whether the descriptor is ranged\n"
+ " \"issolvable\" : true|false, (boolean) Whether the descriptor is solvable\n"
+ " \"hasprivatekeys\" : true|false, (boolean) Whether the input descriptor contained at least one private key\n"
+ "}\n"
+ },
+ RPCExamples{
+ "Analyse a descriptor\n" +
+ HelpExampleCli("getdescriptorinfo", "\"wpkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)\"")
+ }}.ToString()
+ );
+ }
+
+ RPCTypeCheck(request.params, {UniValue::VSTR});
+
+ FlatSigningProvider provider;
+ auto desc = Parse(request.params[0].get_str(), provider);
+ if (!desc) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor"));
+ }
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("descriptor", desc->ToString());
+ result.pushKV("isrange", desc->IsRange());
+ result.pushKV("issolvable", desc->IsSolvable());
+ result.pushKV("hasprivatekeys", provider.keys.size() > 0);
+ return result;
+}
+
+UniValue deriveaddresses(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.empty() || request.params.size() > 2) {
+ throw std::runtime_error(
+ RPCHelpMan{"deriveaddresses",
+ {"\nDerives one or more addresses corresponding to an output descriptor.\n"
+ "Examples of output descriptors are:\n"
+ " pkh(<pubkey>) P2PKH outputs for the given pubkey\n"
+ " wpkh(<pubkey>) Native segwit P2PKH outputs for the given pubkey\n"
+ " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
+ " raw(<hex script>) Outputs whose scriptPubKey equals the specified hex scripts\n"
+ "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
+ "or more path elements separated by \"/\", where \"h\" represents a hardened child key.\n"
+ "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."},
+ },
+ RPCResult{
+ "[ address ] (array) the derived addresses\n"
+ },
+ RPCExamples{
+ "First three native segwit receive addresses\n" +
+ HelpExampleCli("deriveaddresses", "\"wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#trd0mf0l\" \"[0,2]\"")
+ }}.ToString()
+ );
+ }
+
+ 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;
+ int64_t range_end = 0;
+
+ if (request.params.size() >= 2 && !request.params[1].isNull()) {
+ std::tie(range_begin, range_end) = ParseDescriptorRange(request.params[1]);
+ }
+
+ FlatSigningProvider key_provider;
+ auto desc = Parse(desc_str, key_provider, /* require_checksum = */ true);
+ if (!desc) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor"));
+ }
+
+ if (!desc->IsRange() && request.params.size() > 1) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for an un-ranged descriptor");
+ }
+
+ if (desc->IsRange() && request.params.size() == 1) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Range must be specified for a ranged descriptor");
+ }
+
+ UniValue addresses(UniValue::VARR);
+
+ for (int i = range_begin; i <= range_end; ++i) {
+ FlatSigningProvider provider;
+ std::vector<CScript> scripts;
+ if (!desc->Expand(i, key_provider, scripts, provider)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
+ }
+
+ for (const CScript &script : scripts) {
+ CTxDestination dest;
+ if (!ExtractDestination(script, dest)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Descriptor does not have a corresponding address"));
+ }
+
+ addresses.push_back(EncodeDestination(dest));
+ }
+ }
+
+ // This should not be possible, but an assert seems overkill:
+ if (addresses.empty()) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Unexpected empty result");
+ }
+
+ return addresses;
+}
+
static UniValue verifymessage(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 3)
throw std::runtime_error(
- "verifymessage \"address\" \"signature\" \"message\"\n"
- "\nVerify a signed message\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address to use for the signature.\n"
- "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
- "3. \"message\" (string, required) The message that was signed.\n"
- "\nResult:\n"
+ RPCHelpMan{"verifymessage",
+ "\nVerify a signed message\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."},
+ {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."},
+ {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
+ },
+ RPCResult{
"true|false (boolean) If the signature is verified or not.\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nUnlock the wallet for 30 seconds\n"
+ HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
"\nCreate the signature\n"
+ HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
"\nVerify the signature\n"
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
- "\nAs json rpc\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
- );
+ },
+ }.ToString());
LOCK(cs_main);
@@ -189,8 +297,8 @@ static UniValue verifymessage(const JSONRPCRequest& request)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
}
- const CKeyID *keyID = boost::get<CKeyID>(&destination);
- if (!keyID) {
+ const PKHash *pkhash = boost::get<PKHash>(&destination);
+ if (!pkhash) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
}
@@ -208,28 +316,31 @@ static UniValue verifymessage(const JSONRPCRequest& request)
if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
return false;
- return (pubkey.GetID() == *keyID);
+ return (pubkey.GetID() == *pkhash);
}
static UniValue signmessagewithprivkey(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 2)
throw std::runtime_error(
- "signmessagewithprivkey \"privkey\" \"message\"\n"
- "\nSign a message with the private key of an address\n"
- "\nArguments:\n"
- "1. \"privkey\" (string, required) The private key to sign the message with.\n"
- "2. \"message\" (string, required) The message to create a signature of.\n"
- "\nResult:\n"
+ RPCHelpMan{"signmessagewithprivkey",
+ "\nSign a message with the private key of an address\n",
+ {
+ {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."},
+ {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
+ },
+ RPCResult{
"\"signature\" (string) The signature of the message encoded in base 64\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate the signature\n"
+ HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
"\nVerify the signature\n"
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
- "\nAs json rpc\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
- );
+ },
+ }.ToString());
std::string strPrivkey = request.params[0].get_str();
std::string strMessage = request.params[1].get_str();
@@ -254,11 +365,15 @@ static UniValue setmocktime(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "setmocktime timestamp\n"
- "\nSet the local time to given timestamp (-regtest only)\n"
- "\nArguments:\n"
- "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
- " Pass 0 to go back to using the system time."
+ RPCHelpMan{"setmocktime",
+ "\nSet the local time to given timestamp (-regtest only)\n",
+ {
+ {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Unix seconds-since-epoch timestamp\n"
+ " Pass 0 to go back to using the system time."},
+ },
+ RPCResults{},
+ RPCExamples{""},
+ }.ToString()
);
if (!Params().MineBlocksOnDemand())
@@ -316,13 +431,15 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request)
*/
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
- "getmemoryinfo (\"mode\")\n"
- "Returns an object containing information about memory usage.\n"
- "Arguments:\n"
- "1. \"mode\" determines what kind of information is returned. This argument is optional, the default mode is \"stats\".\n"
+ RPCHelpMan{"getmemoryinfo",
+ "Returns an object containing information about memory usage.\n",
+ {
+ {"mode", RPCArg::Type::STR, /* default */ "\"stats\"", "determines what kind of information is returned.\n"
" - \"stats\" returns general statistics about memory usage in the daemon.\n"
- " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+).\n"
- "\nResult (mode \"stats\"):\n"
+ " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+)."},
+ },
+ {
+ RPCResult{"mode \"stats\"",
"{\n"
" \"locked\": { (json object) Information about locked memory manager\n"
" \"used\": xxxxx, (numeric) Number of bytes used\n"
@@ -333,12 +450,16 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request)
" \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
" }\n"
"}\n"
- "\nResult (mode \"mallocinfo\"):\n"
+ },
+ RPCResult{"mode \"mallocinfo\"",
"\"<malloc version=\"1\">...\"\n"
- "\nExamples:\n"
- + HelpExampleCli("getmemoryinfo", "")
+ },
+ },
+ RPCExamples{
+ HelpExampleCli("getmemoryinfo", "")
+ HelpExampleRpc("getmemoryinfo", "")
- );
+ },
+ }.ToString());
std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str();
if (mode == "stats") {
@@ -363,9 +484,9 @@ static void EnableOrDisableLogCategories(UniValue cats, bool enable) {
bool success;
if (enable) {
- success = g_logger->EnableCategory(cat);
+ success = LogInstance().EnableCategory(cat);
} else {
- success = g_logger->DisableCategory(cat);
+ success = LogInstance().DisableCategory(cat);
}
if (!success) {
@@ -378,7 +499,7 @@ UniValue logging(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2) {
throw std::runtime_error(
- "logging ( <include> <exclude> )\n"
+ RPCHelpMan{"logging",
"Gets and sets the logging configuration.\n"
"When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n"
"When called with arguments, adds or removes categories from debug logging and return the lists above.\n"
@@ -388,36 +509,38 @@ UniValue logging(const JSONRPCRequest& request)
"In addition, the following are available as category names with special meanings:\n"
" - \"all\", \"1\" : represent all logging categories.\n"
" - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n"
- "\nArguments:\n"
- "1. \"include\" (array of strings, optional) A json array of categories to add debug logging\n"
- " [\n"
- " \"category\" (string) the valid logging category\n"
- " ,...\n"
- " ]\n"
- "2. \"exclude\" (array of strings, optional) A json array of categories to remove debug logging\n"
- " [\n"
- " \"category\" (string) the valid logging category\n"
- " ,...\n"
- " ]\n"
- "\nResult:\n"
+ ,
+ {
+ {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of categories to add debug logging",
+ {
+ {"include_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
+ }},
+ {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of categories to remove debug logging",
+ {
+ {"exclude_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
+ }},
+ },
+ RPCResult{
"{ (json object where keys are the logging categories, and values indicates its status\n"
- " \"category\": 0|1, (numeric) if being debug logged or not. 0:inactive, 1:active\n"
+ " \"category\": true|false, (bool) if being debug logged or not. false:inactive, true:active\n"
" ...\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
- + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
+ + HelpExampleRpc("logging", "[\"all\"], [\"libevent\"]")
+ },
+ }.ToString());
}
- uint32_t original_log_categories = g_logger->GetCategoryMask();
+ uint32_t original_log_categories = LogInstance().GetCategoryMask();
if (request.params[0].isArray()) {
EnableOrDisableLogCategories(request.params[0], true);
}
if (request.params[1].isArray()) {
EnableOrDisableLogCategories(request.params[1], false);
}
- uint32_t updated_log_categories = g_logger->GetCategoryMask();
+ uint32_t updated_log_categories = LogInstance().GetCategoryMask();
uint32_t changed_log_categories = original_log_categories ^ updated_log_categories;
// Update libevent logging if BCLog::LIBEVENT has changed.
@@ -426,8 +549,8 @@ UniValue logging(const JSONRPCRequest& request)
// Throw an error if the user has explicitly asked to change only the libevent
// flag and it failed.
if (changed_log_categories & BCLog::LIBEVENT) {
- if (!UpdateHTTPServerLogging(g_logger->WillLogCategory(BCLog::LIBEVENT))) {
- g_logger->DisableCategory(BCLog::LIBEVENT);
+ if (!UpdateHTTPServerLogging(LogInstance().WillLogCategory(BCLog::LIBEVENT))) {
+ LogInstance().DisableCategory(BCLog::LIBEVENT);
if (changed_log_categories == BCLog::LIBEVENT) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1.");
}
@@ -447,34 +570,29 @@ static UniValue echo(const JSONRPCRequest& request)
{
if (request.fHelp)
throw std::runtime_error(
- "echo|echojson \"message\" ...\n"
- "\nSimply echo back the input arguments. This command is for testing.\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."
+ RPCHelpMan{"echo|echojson ...",
+ "\nSimply echo back the input arguments. This command is for testing.\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.",
+ {},
+ RPCResults{},
+ RPCExamples{""},
+ }.ToString()
);
return request.params;
}
-static UniValue getinfo_deprecated(const JSONRPCRequest& request)
-{
- throw JSONRPCError(RPC_METHOD_NOT_FOUND,
- "getinfo\n"
- "\nThis call was removed in version 0.16.0. Use the appropriate fields from:\n"
- "- getblockchaininfo: blocks, difficulty, chain\n"
- "- getnetworkinfo: version, protocolversion, timeoffset, connections, proxy, relayfee, warnings\n"
- "- getwalletinfo: balance, keypoololdest, keypoolsize, paytxfee, unlocked_until, walletversion\n"
- "\nbitcoin-cli has the option -getinfo to collect and format these in the old format."
- );
-}
-
+// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
{ "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
{ "control", "logging", &logging, {"include", "exclude"}},
- { "util", "validateaddress", &validateaddress, {"address"} }, /* uses wallet if enabled */
- { "util", "createmultisig", &createmultisig, {"nrequired","keys"} },
+ { "util", "validateaddress", &validateaddress, {"address"} },
+ { "util", "createmultisig", &createmultisig, {"nrequired","keys","address_type"} },
+ { "util", "deriveaddresses", &deriveaddresses, {"descriptor", "range"} },
+ { "util", "getdescriptorinfo", &getdescriptorinfo, {"descriptor"} },
{ "util", "verifymessage", &verifymessage, {"address","signature","message"} },
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
@@ -482,8 +600,8 @@ static const CRPCCommand commands[] =
{ "hidden", "setmocktime", &setmocktime, {"timestamp"}},
{ "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
{ "hidden", "echojson", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
- { "hidden", "getinfo", &getinfo_deprecated, {}},
};
+// clang-format on
void RegisterMiscRPCCommands(CRPCTable &t)
{
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 8fa56e9335..e49c3e031f 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -1,23 +1,26 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <rpc/server.h>
+#include <banman.h>
#include <chainparams.h>
#include <clientversion.h>
#include <core_io.h>
-#include <validation.h>
#include <net.h>
#include <net_processing.h>
#include <netbase.h>
#include <policy/policy.h>
+#include <policy/settings.h>
#include <rpc/protocol.h>
+#include <rpc/util.h>
#include <sync.h>
#include <timedata.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
+#include <util/system.h>
+#include <validation.h>
#include <version.h>
#include <warnings.h>
@@ -27,14 +30,17 @@ static UniValue getconnectioncount(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getconnectioncount\n"
- "\nReturns the number of connections to other nodes.\n"
- "\nResult:\n"
+ RPCHelpMan{"getconnectioncount",
+ "\nReturns the number of connections to other nodes.\n",
+ {},
+ RPCResult{
"n (numeric) The connection count\n"
- "\nExamples:\n"
- + HelpExampleCli("getconnectioncount", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getconnectioncount", "")
+ HelpExampleRpc("getconnectioncount", "")
- );
+ },
+ }.ToString());
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
@@ -46,14 +52,17 @@ static UniValue ping(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "ping\n"
- "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
- "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
- "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n"
- "\nExamples:\n"
- + HelpExampleCli("ping", "")
+ RPCHelpMan{"ping",
+ "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
+ "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
+ "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",
+ {},
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("ping", "")
+ HelpExampleRpc("ping", "")
- );
+ },
+ }.ToString());
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
@@ -69,9 +78,10 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getpeerinfo\n"
- "\nReturns data about each connected network node as a json array of objects.\n"
- "\nResult:\n"
+ RPCHelpMan{"getpeerinfo",
+ "\nReturns data about each connected network node as a json array of objects.\n",
+ {},
+ RPCResult{
"[\n"
" {\n"
" \"id\": n, (numeric) Peer index\n"
@@ -102,21 +112,28 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
" ...\n"
" ],\n"
" \"whitelisted\": true|false, (boolean) Whether the peer is whitelisted\n"
+ " \"minfeefilter\": n, (numeric) The minimum fee rate for transactions this peer accepts\n"
" \"bytessent_per_msg\": {\n"
- " \"addr\": n, (numeric) The total bytes sent aggregated by message type\n"
+ " \"msg\": n, (numeric) The total bytes sent aggregated by message type\n"
+ " When a message type is not listed in this json object, the bytes sent are 0.\n"
+ " Only known message types can appear as keys in the object.\n"
" ...\n"
" },\n"
" \"bytesrecv_per_msg\": {\n"
- " \"addr\": n, (numeric) The total bytes received aggregated by message type\n"
+ " \"msg\": n, (numeric) The total bytes received aggregated by message type\n"
+ " When a message type is not listed in this json object, the bytes received are 0.\n"
+ " Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'.\n"
" ...\n"
" }\n"
" }\n"
" ,...\n"
"]\n"
- "\nExamples:\n"
- + HelpExampleCli("getpeerinfo", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getpeerinfo", "")
+ HelpExampleRpc("getpeerinfo", "")
- );
+ },
+ }.ToString());
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
@@ -163,22 +180,23 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
obj.pushKV("synced_headers", statestats.nSyncHeight);
obj.pushKV("synced_blocks", statestats.nCommonHeight);
UniValue heights(UniValue::VARR);
- for (int height : statestats.vHeightInFlight) {
+ for (const int height : statestats.vHeightInFlight) {
heights.push_back(height);
}
obj.pushKV("inflight", heights);
}
obj.pushKV("whitelisted", stats.fWhitelisted);
+ obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter));
UniValue sendPerMsgCmd(UniValue::VOBJ);
- for (const mapMsgCmdSize::value_type &i : stats.mapSendBytesPerMsgCmd) {
+ for (const auto& i : stats.mapSendBytesPerMsgCmd) {
if (i.second > 0)
sendPerMsgCmd.pushKV(i.first, i.second);
}
obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
UniValue recvPerMsgCmd(UniValue::VOBJ);
- for (const mapMsgCmdSize::value_type &i : stats.mapRecvBytesPerMsgCmd) {
+ for (const auto& i : stats.mapRecvBytesPerMsgCmd) {
if (i.second > 0)
recvPerMsgCmd.pushKV(i.first, i.second);
}
@@ -198,18 +216,21 @@ static UniValue addnode(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 2 ||
(strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
throw std::runtime_error(
- "addnode \"node\" \"add|remove|onetry\"\n"
- "\nAttempts to add or remove a node from the addnode list.\n"
- "Or try a connection to a node once.\n"
- "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
- "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n"
- "\nArguments:\n"
- "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
- "2. \"command\" (string, required) 'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once\n"
- "\nExamples:\n"
- + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
+ RPCHelpMan{"addnode",
+ "\nAttempts to add or remove a node from the addnode list.\n"
+ "Or try a connection to a node once.\n"
+ "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
+ "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n",
+ {
+ {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"},
+ {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
+ HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
- );
+ },
+ }.ToString());
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
@@ -241,19 +262,22 @@ static UniValue disconnectnode(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3)
throw std::runtime_error(
- "disconnectnode \"[address]\" [nodeid]\n"
- "\nImmediately disconnects from the specified peer node.\n"
- "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
- "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n"
- "\nArguments:\n"
- "1. \"address\" (string, optional) The IP address/port of the node\n"
- "2. \"nodeid\" (number, optional) The node ID (see getpeerinfo for node IDs)\n"
- "\nExamples:\n"
- + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
+ RPCHelpMan{"disconnectnode",
+ "\nImmediately disconnects from the specified peer node.\n"
+ "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
+ "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
+ {
+ {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"},
+ {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
+ HelpExampleCli("disconnectnode", "\"\" 1")
+ HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
+ HelpExampleRpc("disconnectnode", "\"\", 1")
- );
+ },
+ }.ToString());
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
@@ -284,12 +308,13 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
- "getaddednodeinfo ( \"node\" )\n"
- "\nReturns information about the given added node, or all added nodes\n"
- "(note that onetry addnodes are not listed here)\n"
- "\nArguments:\n"
- "1. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
- "\nResult:\n"
+ RPCHelpMan{"getaddednodeinfo",
+ "\nReturns information about the given added node, or all added nodes\n"
+ "(note that onetry addnodes are not listed here)\n",
+ {
+ {"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."},
+ },
+ RPCResult{
"[\n"
" {\n"
" \"addednode\" : \"192.168.0.201\", (string) The node IP address or name (as provided to addnode)\n"
@@ -303,10 +328,12 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request)
" }\n"
" ,...\n"
"]\n"
- "\nExamples:\n"
- + HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
+ },
+ RPCExamples{
+ HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
+ HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")
- );
+ },
+ }.ToString());
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
@@ -351,10 +378,11 @@ static UniValue getnettotals(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 0)
throw std::runtime_error(
- "getnettotals\n"
- "\nReturns information about network traffic, including bytes in, bytes out,\n"
- "and current time.\n"
- "\nResult:\n"
+ RPCHelpMan{"getnettotals",
+ "\nReturns information about network traffic, including bytes in, bytes out,\n"
+ "and current time.\n",
+ {},
+ RPCResult{
"{\n"
" \"totalbytesrecv\": n, (numeric) Total bytes received\n"
" \"totalbytessent\": n, (numeric) Total bytes sent\n"
@@ -369,10 +397,12 @@ static UniValue getnettotals(const JSONRPCRequest& request)
" \"time_left_in_cycle\": t (numeric) Seconds left in current time cycle\n"
" }\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getnettotals", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getnettotals", "")
+ HelpExampleRpc("getnettotals", "")
- );
+ },
+ }.ToString());
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
@@ -404,7 +434,7 @@ static UniValue GetNetworksInfo()
UniValue obj(UniValue::VOBJ);
GetProxy(network, proxy);
obj.pushKV("name", GetNetworkName(network));
- obj.pushKV("limited", IsLimited(network));
+ obj.pushKV("limited", !IsReachable(network));
obj.pushKV("reachable", IsReachable(network));
obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
@@ -417,9 +447,10 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "getnetworkinfo\n"
- "Returns an object containing various state info regarding P2P networking.\n"
- "\nResult:\n"
+ RPCHelpMan{"getnetworkinfo",
+ "Returns an object containing various state info regarding P2P networking.\n",
+ {},
+ RPCResult{
"{\n"
" \"version\": xxxxx, (numeric) the server version\n"
" \"subversion\": \"/Satoshi:x.x.x/\", (string) the server subversion string\n"
@@ -451,10 +482,12 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
" ]\n"
" \"warnings\": \"...\" (string) any network and blockchain warnings\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getnetworkinfo", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getnetworkinfo", "")
+ HelpExampleRpc("getnetworkinfo", "")
- );
+ },
+ }.ToString());
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
@@ -463,7 +496,7 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
obj.pushKV("protocolversion",PROTOCOL_VERSION);
if(g_connman)
obj.pushKV("localservices", strprintf("%016x", g_connman->GetLocalServices()));
- obj.pushKV("localrelay", fRelayTxes);
+ obj.pushKV("localrelay", g_relay_txes);
obj.pushKV("timeoffset", GetTimeOffset());
if (g_connman) {
obj.pushKV("networkactive", g_connman->GetNetworkActive());
@@ -491,26 +524,30 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
static UniValue setban(const JSONRPCRequest& request)
{
+ const RPCHelpMan help{"setban",
+ "\nAttempts to add or remove an IP/Subnet from the banned list.\n",
+ {
+ {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
+ {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add an IP/Subnet to the list, 'remove' to remove an IP/Subnet from the list"},
+ {"bantime", RPCArg::Type::NUM, /* default */ "0", "time in seconds how long (or until when if [absolute] is set) the IP is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)"},
+ {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp in seconds since epoch (Jan 1 1970 GMT)"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
+ + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
+ + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
+ },
+ };
std::string strCommand;
if (!request.params[1].isNull())
strCommand = request.params[1].get_str();
- if (request.fHelp || request.params.size() < 2 ||
- (strCommand != "add" && strCommand != "remove"))
- throw std::runtime_error(
- "setban \"subnet\" \"add|remove\" (bantime) (absolute)\n"
- "\nAttempts to add or remove an IP/Subnet from the banned list.\n"
- "\nArguments:\n"
- "1. \"subnet\" (string, required) The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)\n"
- "2. \"command\" (string, required) 'add' to add an IP/Subnet to the list, 'remove' to remove an IP/Subnet from the list\n"
- "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the IP is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n"
- "4. \"absolute\" (boolean, optional) If set, the bantime must be an absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
- "\nExamples:\n"
- + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
- + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
- + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
- );
- if(!g_connman)
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
+ throw std::runtime_error(help.ToString());
+ }
+ if (!g_banman) {
+ throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
+ }
CSubNet subNet;
CNetAddr netAddr;
@@ -532,8 +569,9 @@ static UniValue setban(const JSONRPCRequest& request)
if (strCommand == "add")
{
- if (isSubnet ? g_connman->IsBanned(subNet) : g_connman->IsBanned(netAddr))
+ if (isSubnet ? g_banman->IsBanned(subNet) : g_banman->IsBanned(netAddr)) {
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
+ }
int64_t banTime = 0; //use standard bantime if not specified
if (!request.params[2].isNull())
@@ -543,12 +581,23 @@ static UniValue setban(const JSONRPCRequest& request)
if (request.params[3].isTrue())
absolute = true;
- isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
+ if (isSubnet) {
+ g_banman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute);
+ if (g_connman) {
+ g_connman->DisconnectNode(subNet);
+ }
+ } else {
+ g_banman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
+ if (g_connman) {
+ g_connman->DisconnectNode(netAddr);
+ }
+ }
}
else if(strCommand == "remove")
{
- if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) ))
+ if (!( isSubnet ? g_banman->Unban(subNet) : g_banman->Unban(netAddr) )) {
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously banned.");
+ }
}
return NullUniValue;
}
@@ -557,18 +606,22 @@ static UniValue listbanned(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "listbanned\n"
- "\nList all banned IPs/Subnets.\n"
- "\nExamples:\n"
- + HelpExampleCli("listbanned", "")
+ RPCHelpMan{"listbanned",
+ "\nList all banned IPs/Subnets.\n",
+ {},
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("listbanned", "")
+ HelpExampleRpc("listbanned", "")
- );
+ },
+ }.ToString());
- if(!g_connman)
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ if(!g_banman) {
+ throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
+ }
banmap_t banMap;
- g_connman->GetBanned(banMap);
+ g_banman->GetBanned(banMap);
UniValue bannedAddresses(UniValue::VARR);
for (const auto& entry : banMap)
@@ -590,16 +643,20 @@ static UniValue clearbanned(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "clearbanned\n"
- "\nClear all banned IPs.\n"
- "\nExamples:\n"
- + HelpExampleCli("clearbanned", "")
+ RPCHelpMan{"clearbanned",
+ "\nClear all banned IPs.\n",
+ {},
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("clearbanned", "")
+ HelpExampleRpc("clearbanned", "")
- );
- if(!g_connman)
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ },
+ }.ToString());
+ if (!g_banman) {
+ throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
+ }
- g_connman->ClearBanned();
+ g_banman->ClearBanned();
return NullUniValue;
}
@@ -608,10 +665,14 @@ static UniValue setnetworkactive(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
- "setnetworkactive true|false\n"
- "\nDisable/enable all p2p network activity.\n"
- "\nArguments:\n"
- "1. \"state\" (boolean, required) true to enable networking, false to disable\n"
+ RPCHelpMan{"setnetworkactive",
+ "\nDisable/enable all p2p network activity.\n",
+ {
+ {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
+ },
+ RPCResults{},
+ RPCExamples{""},
+ }.ToString()
);
}
@@ -624,6 +685,61 @@ static UniValue setnetworkactive(const JSONRPCRequest& request)
return g_connman->GetNetworkActive();
}
+static UniValue getnodeaddresses(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 1) {
+ throw std::runtime_error(
+ RPCHelpMan{"getnodeaddresses",
+ "\nReturn known addresses which can potentially be used to find new nodes in the network\n",
+ {
+ {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + std::to_string(ADDRMAN_GETADDR_MAX) + " or " + std::to_string(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."},
+ },
+ RPCResult{
+ "[\n"
+ " {\n"
+ " \"time\": ttt, (numeric) Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen\n"
+ " \"services\": n, (numeric) The services offered\n"
+ " \"address\": \"host\", (string) The address of the node\n"
+ " \"port\": n (numeric) The port of the node\n"
+ " }\n"
+ " ,....\n"
+ "]\n"
+ },
+ RPCExamples{
+ HelpExampleCli("getnodeaddresses", "8")
+ + HelpExampleRpc("getnodeaddresses", "8")
+ },
+ }.ToString());
+ }
+ if (!g_connman) {
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ }
+
+ int count = 1;
+ if (!request.params[0].isNull()) {
+ count = request.params[0].get_int();
+ if (count <= 0) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
+ }
+ }
+ // returns a shuffled list of CAddress
+ std::vector<CAddress> vAddr = g_connman->GetAddresses();
+ UniValue ret(UniValue::VARR);
+
+ int address_return_count = std::min<int>(count, vAddr.size());
+ for (int i = 0; i < address_return_count; ++i) {
+ UniValue obj(UniValue::VOBJ);
+ const CAddress& addr = vAddr[i];
+ obj.pushKV("time", (int)addr.nTime);
+ obj.pushKV("services", (uint64_t)addr.nServices);
+ obj.pushKV("address", addr.ToStringIP());
+ obj.pushKV("port", addr.GetPort());
+ ret.push_back(obj);
+ }
+ return ret;
+}
+
+// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
@@ -639,7 +755,9 @@ static const CRPCCommand commands[] =
{ "network", "listbanned", &listbanned, {} },
{ "network", "clearbanned", &clearbanned, {} },
{ "network", "setnetworkactive", &setnetworkactive, {"state"} },
+ { "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
};
+// clang-format on
void RegisterNetRPCCommands(CRPCTable &t)
{
diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp
index 0635b757c6..23999b305a 100644
--- a/src/rpc/protocol.cpp
+++ b/src/rpc/protocol.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,13 +7,11 @@
#include <random.h>
#include <tinyformat.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <util/time.h>
#include <version.h>
-#include <fstream>
-
/**
* JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
* but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
@@ -85,9 +83,9 @@ bool GenerateAuthCookie(std::string *cookie_out)
/** the umask determines what permissions are used to create this file -
* these are set to 077 in init.cpp unless overridden with -sysperms.
*/
- std::ofstream file;
+ fsbridge::ofstream file;
fs::path filepath_tmp = GetAuthCookieFile(true);
- file.open(filepath_tmp.string().c_str());
+ file.open(filepath_tmp);
if (!file.is_open()) {
LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath_tmp.string());
return false;
@@ -109,10 +107,10 @@ bool GenerateAuthCookie(std::string *cookie_out)
bool GetAuthCookie(std::string *cookie_out)
{
- std::ifstream file;
+ fsbridge::ifstream file;
std::string cookie;
fs::path filepath = GetAuthCookieFile();
- file.open(filepath.string().c_str());
+ file.open(filepath);
if (!file.is_open())
return false;
std::getline(file, cookie);
@@ -128,7 +126,7 @@ void DeleteAuthCookie()
try {
fs::remove(GetAuthCookieFile());
} catch (const fs::filesystem_error& e) {
- LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, e.what());
+ LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, fsbridge::get_filesystem_error_message(e));
}
}
diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h
index 6954aed252..6bcbccbd4f 100644
--- a/src/rpc/protocol.h
+++ b/src/rpc/protocol.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index bb94e11fea..b3926786db 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -1,41 +1,53 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
#include <coins.h>
#include <compat/byteswap.h>
+#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <index/txindex.h>
-#include <keystore.h>
-#include <validation.h>
-#include <validationinterface.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <key_io.h>
+#include <keystore.h>
#include <merkleblock.h>
-#include <net.h>
+#include <node/coin.h>
+#include <node/psbt.h>
+#include <node/transaction.h>
#include <policy/policy.h>
#include <policy/rbf.h>
+#include <policy/settings.h>
#include <primitives/transaction.h>
-#include <rpc/rawtransaction.h>
+#include <psbt.h>
+#include <rpc/rawtransaction_util.h>
#include <rpc/server.h>
+#include <rpc/util.h>
#include <script/script.h>
#include <script/script_error.h>
#include <script/sign.h>
#include <script/standard.h>
-#include <txmempool.h>
#include <uint256.h>
-#include <utilstrencodings.h>
-#ifdef ENABLE_WALLET
-#include <wallet/rpcwallet.h>
-#endif
+#include <util/bip32.h>
+#include <util/moneystr.h>
+#include <util/strencodings.h>
+#include <validation.h>
+#include <validationinterface.h>
-#include <future>
+
+#include <numeric>
#include <stdint.h>
#include <univalue.h>
+/** High fee for sendrawtransaction and testmempoolaccept.
+ * By default, transaction with a fee higher than this will be rejected by the
+ * RPCs. This can be overriden with the maxfeerate argument.
+ */
+constexpr static CAmount DEFAULT_MAX_RAW_TX_FEE{COIN / 10};
static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
@@ -52,8 +64,8 @@ static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue&
entry.pushKV("blockhash", hashBlock.GetHex());
CBlockIndex* pindex = LookupBlockIndex(hashBlock);
if (pindex) {
- if (chainActive.Contains(pindex)) {
- entry.pushKV("confirmations", 1 + chainActive.Height() - pindex->nHeight);
+ if (::ChainActive().Contains(pindex)) {
+ entry.pushKV("confirmations", 1 + ::ChainActive().Height() - pindex->nHeight);
entry.pushKV("time", pindex->GetBlockTime());
entry.pushKV("blocktime", pindex->GetBlockTime());
}
@@ -65,30 +77,30 @@ static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue&
static UniValue getrawtransaction(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
- throw std::runtime_error(
- "getrawtransaction \"txid\" ( verbose \"blockhash\" )\n"
+ const RPCHelpMan help{
+ "getrawtransaction",
+ "\nReturn the raw transaction data.\n"
- "\nNOTE: By default this function only works for mempool transactions. If the -txindex option is\n"
- "enabled, it also works for blockchain transactions. If the block which contains the transaction\n"
- "is known, its hash can be provided even for nodes without -txindex. Note that if a blockhash is\n"
- "provided, only that block will be searched and if the transaction is in the mempool or other\n"
- "blocks, or if this node does not have the given block available, the transaction will not be found.\n"
- "DEPRECATED: for now, it also works for transactions with unspent outputs.\n"
+ "\nBy default this function only works for mempool transactions. When called with a blockhash\n"
+ "argument, getrawtransaction will return the transaction if the specified block is available and\n"
+ "the transaction is found in that block. When called without a blockhash argument, getrawtransaction\n"
+ "will return the transaction if it is in the mempool, or if -txindex is enabled and the transaction\n"
+ "is in a block in the blockchain.\n"
- "\nReturn the raw transaction data.\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'.\n"
+ "\nHint: Use gettransaction for wallet transactions.\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The transaction id\n"
- "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n"
- "3. \"blockhash\" (string, optional) The block in which to look for the transaction\n"
-
- "\nResult (if verbose is not set or set to false):\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'.\n",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
+ {"verbose", RPCArg::Type::BOOL, /* 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"},
+ },
+ {
+ RPCResult{"if verbose is not set or set to false",
"\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
-
- "\nResult (if verbose is set to true):\n"
+ },
+ RPCResult{"if verbose is set to true",
"{\n"
" \"in_active_chain\": b, (bool) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n"
" \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n"
@@ -131,17 +143,23 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
" ],\n"
" \"blockhash\" : \"hash\", (string) the block hash\n"
" \"confirmations\" : n, (numeric) The confirmations\n"
- " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"time\" : ttt, (numeric) Same as \"blocktime\"\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("getrawtransaction", "\"mytxid\"")
+ },
+ },
+ RPCExamples{
+ HelpExampleCli("getrawtransaction", "\"mytxid\"")
+ HelpExampleCli("getrawtransaction", "\"mytxid\" true")
+ HelpExampleRpc("getrawtransaction", "\"mytxid\", true")
+ HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"")
+ HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"")
- );
+ },
+ };
+
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
+ }
bool in_active_chain = true;
uint256 hash = ParseHashV(request.params[0], "parameter 1");
@@ -166,7 +184,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
if (!blockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found");
}
- in_active_chain = chainActive.Contains(blockindex);
+ in_active_chain = ::ChainActive().Contains(blockindex);
}
bool f_txindex_ready = false;
@@ -176,7 +194,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
CTransactionRef tx;
uint256 hash_block;
- if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, true, blockindex)) {
+ if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, blockindex)) {
std::string errmsg;
if (blockindex) {
if (!(blockindex->nStatus & BLOCK_HAVE_DATA)) {
@@ -207,21 +225,25 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
{
if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2))
throw std::runtime_error(
- "gettxoutproof [\"txid\",...] ( blockhash )\n"
- "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n"
- "\nNOTE: By default this function only works sometimes. This is when there is an\n"
- "unspent output in the utxo for this transaction. To make it always work,\n"
- "you need to maintain a transaction index, using the -txindex command line option or\n"
- "specify the block in which the transaction is included manually (by blockhash).\n"
- "\nArguments:\n"
- "1. \"txids\" (string) A json array of txids to filter\n"
- " [\n"
- " \"txid\" (string) A transaction hash\n"
- " ,...\n"
- " ]\n"
- "2. \"blockhash\" (string, optional) If specified, looks for txid in the block with this hash\n"
- "\nResult:\n"
+ RPCHelpMan{"gettxoutproof",
+ "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n"
+ "\nNOTE: By default this function only works sometimes. This is when there is an\n"
+ "unspent output in the utxo for this transaction. To make it always work,\n"
+ "you need to maintain a transaction index, using the -txindex command line option or\n"
+ "specify the block in which the transaction is included manually (by blockhash).\n",
+ {
+ {"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of txids to filter",
+ {
+ {"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"},
+ },
+ RPCResult{
"\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n"
+ },
+ RPCExamples{""},
+ }.ToString()
);
std::set<uint256> setTxids;
@@ -229,9 +251,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
UniValue txids = request.params[0].get_array();
for (unsigned int idx = 0; idx < txids.size(); idx++) {
const UniValue& txid = txids[idx];
- if (txid.get_str().length() != 64 || !IsHex(txid.get_str()))
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid txid ")+txid.get_str());
- uint256 hash(uint256S(txid.get_str()));
+ uint256 hash(ParseHashV(txid, "txid"));
if (setTxids.count(hash))
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ")+txid.get_str());
setTxids.insert(hash);
@@ -242,7 +262,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
uint256 hashBlock;
if (!request.params[1].isNull()) {
LOCK(cs_main);
- hashBlock = uint256S(request.params[1].get_str());
+ hashBlock = ParseHashV(request.params[1], "blockhash");
pblockindex = LookupBlockIndex(hashBlock);
if (!pblockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
@@ -254,7 +274,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
for (const auto& tx : setTxids) {
const Coin& coin = AccessByTxid(*pcoinsTip, tx);
if (!coin.IsSpent()) {
- pblockindex = chainActive[coin.nHeight];
+ pblockindex = ::ChainActive()[coin.nHeight];
break;
}
}
@@ -271,7 +291,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
if (pblockindex == nullptr)
{
CTransactionRef tx;
- if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock, false) || hashBlock.IsNull())
+ if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock) || hashBlock.IsNull())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
pblockindex = LookupBlockIndex(hashBlock);
if (!pblockindex) {
@@ -301,13 +321,17 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "verifytxoutproof \"proof\"\n"
- "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n"
- "and throwing an RPC error if the block is not in our best chain\n"
- "\nArguments:\n"
- "1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n"
- "\nResult:\n"
+ RPCHelpMan{"verifytxoutproof",
+ "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n"
+ "and throwing an RPC error if the block is not in our best chain\n",
+ {
+ {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"},
+ },
+ RPCResult{
"[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n"
+ },
+ RPCExamples{""},
+ }.ToString()
);
CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
@@ -324,7 +348,7 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request)
LOCK(cs_main);
const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash());
- if (!pindex || !chainActive.Contains(pindex) || pindex->nTx == 0) {
+ if (!pindex || !::ChainActive().Contains(pindex) || pindex->nTx == 0) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
}
@@ -338,157 +362,59 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request)
return res;
}
-CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf)
-{
- if (inputs_in.isNull() || outputs_in.isNull())
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
-
- UniValue inputs = inputs_in.get_array();
- const bool outputs_is_obj = outputs_in.isObject();
- UniValue outputs = outputs_is_obj ? outputs_in.get_obj() : outputs_in.get_array();
-
- CMutableTransaction rawTx;
-
- if (!locktime.isNull()) {
- int64_t nLockTime = locktime.get_int64();
- if (nLockTime < 0 || nLockTime > std::numeric_limits<uint32_t>::max())
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
- rawTx.nLockTime = nLockTime;
- }
-
- bool rbfOptIn = rbf.isTrue();
-
- for (unsigned int idx = 0; idx < inputs.size(); idx++) {
- const UniValue& input = inputs[idx];
- const UniValue& o = input.get_obj();
-
- uint256 txid = ParseHashO(o, "txid");
-
- const UniValue& vout_v = find_value(o, "vout");
- if (!vout_v.isNum())
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
- int nOutput = vout_v.get_int();
- if (nOutput < 0)
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
-
- uint32_t nSequence;
- if (rbfOptIn) {
- nSequence = MAX_BIP125_RBF_SEQUENCE;
- } else if (rawTx.nLockTime) {
- nSequence = std::numeric_limits<uint32_t>::max() - 1;
- } else {
- nSequence = std::numeric_limits<uint32_t>::max();
- }
-
- // set the sequence number if passed in the parameters object
- const UniValue& sequenceObj = find_value(o, "sequence");
- if (sequenceObj.isNum()) {
- int64_t seqNr64 = sequenceObj.get_int64();
- if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
- } else {
- nSequence = (uint32_t)seqNr64;
- }
- }
-
- CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
-
- rawTx.vin.push_back(in);
- }
-
- std::set<CTxDestination> destinations;
- if (!outputs_is_obj) {
- // Translate array of key-value pairs into dict
- UniValue outputs_dict = UniValue(UniValue::VOBJ);
- for (size_t i = 0; i < outputs.size(); ++i) {
- const UniValue& output = outputs[i];
- if (!output.isObject()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair not an object as expected");
- }
- if (output.size() != 1) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair must contain exactly one key");
- }
- outputs_dict.pushKVs(output);
- }
- outputs = std::move(outputs_dict);
- }
- for (const std::string& name_ : outputs.getKeys()) {
- if (name_ == "data") {
- std::vector<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data");
-
- CTxOut out(0, CScript() << OP_RETURN << data);
- rawTx.vout.push_back(out);
- } else {
- CTxDestination destination = DecodeDestination(name_);
- if (!IsValidDestination(destination)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
- }
-
- if (!destinations.insert(destination).second) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
- }
-
- CScript scriptPubKey = GetScriptForDestination(destination);
- CAmount nAmount = AmountFromValue(outputs[name_]);
-
- CTxOut out(nAmount, scriptPubKey);
- rawTx.vout.push_back(out);
- }
- }
-
- if (!rbf.isNull() && rbfOptIn != SignalsOptInRBF(rawTx)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number(s) contradict replaceable option");
- }
-
- return rawTx;
-}
-
static UniValue createrawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
throw std::runtime_error(
- // clang-format off
- "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] [{\"address\":amount},{\"data\":\"hex\"},...] ( locktime ) ( replaceable )\n"
- "\nCreate a transaction spending the given inputs and creating new outputs.\n"
- "Outputs can be addresses or data.\n"
- "Returns hex-encoded raw transaction.\n"
- "Note that the transaction's inputs are not signed, and\n"
- "it is not stored in the wallet or transmitted to the network.\n"
-
- "\nArguments:\n"
- "1. \"inputs\" (array, required) A json array of json objects\n"
- " [\n"
- " {\n"
- " \"txid\":\"id\", (string, required) The transaction id\n"
- " \"vout\":n, (numeric, required) The output number\n"
- " \"sequence\":n (numeric, optional) The sequence number\n"
- " } \n"
- " ,...\n"
- " ]\n"
- "2. \"outputs\" (array, required) a json array with outputs (key-value pairs)\n"
- " [\n"
- " {\n"
- " \"address\": x.xxx, (obj, optional) A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + "\n"
- " },\n"
- " {\n"
- " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex encoded data\n"
- " }\n"
- " ,... More key-value pairs of the above form. For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
- " accepted as second parameter.\n"
- " ]\n"
- "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
- "4. replaceable (boolean, optional, default=false) 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.\n"
- "\nResult:\n"
+ RPCHelpMan{"createrawtransaction",
+ "\nCreate a transaction spending the given inputs and creating new outputs.\n"
+ "Outputs can be addresses or data.\n"
+ "Returns hex-encoded raw transaction.\n"
+ "Note that the transaction's inputs are not signed, and\n"
+ "it is not stored in the wallet or transmitted to the network.\n",
+ {
+ {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects",
+ {
+ {"", 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 number"},
+ {"sequence", RPCArg::Type::NUM, /* default */ "depends on the value of the 'replaceable' and 'locktime' arguments", "The sequence number"},
+ },
+ },
+ },
+ },
+ {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n"
+ "That is, each address can only appear once and there can only be one 'data' object.\n"
+ "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
+ " accepted as second parameter.",
+ {
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT},
+ },
+ },
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"},
+ },
+ },
+ },
+ },
+ {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
+ {"replaceable", RPCArg::Type::BOOL, /* default */ "false", "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."},
+ },
+ RPCResult{
"\"transaction\" (string) hex string of the transaction\n"
-
- "\nExamples:\n"
- + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"")
+ },
+ RPCExamples{
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"")
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"address\\\":0.01}]\"")
+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
- // clang-format on
- );
+ },
+ }.ToString());
}
RPCTypeCheck(request.params, {
@@ -501,22 +427,21 @@ static UniValue createrawtransaction(const JSONRPCRequest& request)
CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3]);
- return EncodeHexTx(rawTx);
+ return EncodeHexTx(CTransaction(rawTx));
}
static UniValue decoderawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "decoderawtransaction \"hexstring\" ( iswitness )\n"
- "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
-
- "\nArguments:\n"
- "1. \"hexstring\" (string, required) The transaction hex string\n"
- "2. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction\n"
- " If iswitness is not present, heuristic tests will be used in decoding\n"
-
- "\nResult:\n"
+ RPCHelpMan{"decoderawtransaction",
+ "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n",
+ {
+ {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"},
+ {"iswitness", RPCArg::Type::BOOL, /* default */ "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"},
+ },
+ RPCResult{
"{\n"
" \"txid\" : \"id\", (string) The transaction id\n"
" \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n"
@@ -556,13 +481,13 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request)
" ,...\n"
" ],\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("decoderawtransaction", "\"hexstring\"")
+ },
+ RPCExamples{
+ HelpExampleCli("decoderawtransaction", "\"hexstring\"")
+ HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
- );
+ },
+ }.ToString());
- LOCK(cs_main);
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
CMutableTransaction mtx;
@@ -580,30 +505,54 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request)
return result;
}
+static std::string GetAllOutputTypes()
+{
+ std::string ret;
+ for (int i = TX_NONSTANDARD; i <= TX_WITNESS_UNKNOWN; ++i) {
+ if (i != TX_NONSTANDARD) ret += ", ";
+ ret += GetTxnOutputType(static_cast<txnouttype>(i));
+ }
+ return ret;
+}
+
static UniValue decodescript(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
- "decodescript \"hexstring\"\n"
- "\nDecode a hex-encoded script.\n"
- "\nArguments:\n"
- "1. \"hexstring\" (string) the hex encoded script\n"
- "\nResult:\n"
+ const RPCHelpMan help{"decodescript",
+ "\nDecode a hex-encoded script.\n",
+ {
+ {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"},
+ },
+ RPCResult{
"{\n"
- " \"asm\":\"asm\", (string) Script public key\n"
- " \"hex\":\"hex\", (string) hex encoded public key\n"
- " \"type\":\"type\", (string) The output type\n"
- " \"reqSigs\": n, (numeric) The required signatures\n"
- " \"addresses\": [ (json array of string)\n"
- " \"address\" (string) bitcoin address\n"
+ " \"asm\":\"asm\", (string) Script public key\n"
+ " \"type\":\"type\", (string) The output type (e.g. "+GetAllOutputTypes()+")\n"
+ " \"reqSigs\": n, (numeric) The required signatures\n"
+ " \"addresses\": [ (json array of string)\n"
+ " \"address\" (string) bitcoin address\n"
" ,...\n"
" ],\n"
- " \"p2sh\",\"address\" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).\n"
+ " \"p2sh\":\"str\" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).\n"
+ " \"segwit\": { (json object) Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness).\n"
+ " \"asm\":\"str\", (string) String representation of the script public key\n"
+ " \"hex\":\"hexstr\", (string) Hex string of the script public key\n"
+ " \"type\":\"str\", (string) The type of the script public key (e.g. witness_v0_keyhash or witness_v0_scripthash)\n"
+ " \"reqSigs\": n, (numeric) The required signatures (always 1)\n"
+ " \"addresses\": [ (json array of string) (always length 1)\n"
+ " \"address\" (string) segwit address\n"
+ " ,...\n"
+ " ],\n"
+ " \"p2sh-segwit\":\"str\" (string) address of the P2SH script wrapping this witness redeem script.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("decodescript", "\"hexstring\"")
+ },
+ RPCExamples{
+ HelpExampleCli("decodescript", "\"hexstring\"")
+ HelpExampleRpc("decodescript", "\"hexstring\"")
- );
+ },
+ };
+
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
+ }
RPCTypeCheck(request.params, {UniValue::VSTR});
@@ -615,7 +564,7 @@ static UniValue decodescript(const JSONRPCRequest& request)
} else {
// Empty scripts are valid
}
- ScriptPubKeyToUniv(script, r, false);
+ ScriptPubKeyToUniv(script, r, /* fIncludeHex */ false);
UniValue type;
type = find_value(r, "type");
@@ -623,13 +572,12 @@ static UniValue decodescript(const JSONRPCRequest& request)
if (type.isStr() && type.get_str() != "scripthash") {
// P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
// don't return the address for a P2SH of the P2SH.
- r.pushKV("p2sh", EncodeDestination(CScriptID(script)));
+ r.pushKV("p2sh", EncodeDestination(ScriptHash(script)));
// P2SH and witness programs cannot be wrapped in P2WSH, if this script
// is a witness program, don't return addresses for a segwit programs.
if (type.get_str() == "pubkey" || type.get_str() == "pubkeyhash" || type.get_str() == "multisig" || type.get_str() == "nonstandard") {
- txnouttype which_type;
std::vector<std::vector<unsigned char>> solutions_data;
- Solver(script, which_type, solutions_data);
+ txnouttype which_type = Solver(script, solutions_data);
// Uncompressed pubkeys cannot be used with segwit checksigs.
// If the script contains an uncompressed pubkey, skip encoding of a segwit program.
if ((which_type == TX_PUBKEY) || (which_type == TX_MULTISIG)) {
@@ -650,8 +598,8 @@ static UniValue decodescript(const JSONRPCRequest& request)
// Newer segwit program versions should be considered when then become available.
segwitScr = GetScriptForDestination(WitnessV0ScriptHash(script));
}
- ScriptPubKeyToUniv(segwitScr, sr, true);
- sr.pushKV("p2sh-segwit", EncodeDestination(CScriptID(segwitScr)));
+ ScriptPubKeyToUniv(segwitScr, sr, /* fIncludeHex */ true);
+ sr.pushKV("p2sh-segwit", EncodeDestination(ScriptHash(segwitScr)));
r.pushKV("segwit", sr);
}
}
@@ -659,46 +607,28 @@ static UniValue decodescript(const JSONRPCRequest& request)
return r;
}
-/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
-static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
-{
- UniValue entry(UniValue::VOBJ);
- entry.pushKV("txid", txin.prevout.hash.ToString());
- entry.pushKV("vout", (uint64_t)txin.prevout.n);
- UniValue witness(UniValue::VARR);
- for (unsigned int i = 0; i < txin.scriptWitness.stack.size(); i++) {
- witness.push_back(HexStr(txin.scriptWitness.stack[i].begin(), txin.scriptWitness.stack[i].end()));
- }
- entry.pushKV("witness", witness);
- entry.pushKV("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
- entry.pushKV("sequence", (uint64_t)txin.nSequence);
- entry.pushKV("error", strMessage);
- vErrorsRet.push_back(entry);
-}
-
static UniValue combinerawtransaction(const JSONRPCRequest& request)
{
-
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "combinerawtransaction [\"hexstring\",...]\n"
- "\nCombine multiple partially signed transactions into one transaction.\n"
- "The combined transaction may be another partially signed transaction or a \n"
- "fully signed transaction."
-
- "\nArguments:\n"
- "1. \"txs\" (string) A json array of hex strings of partially signed transactions\n"
- " [\n"
- " \"hexstring\" (string) A transaction hash\n"
- " ,...\n"
- " ]\n"
-
- "\nResult:\n"
+ RPCHelpMan{"combinerawtransaction",
+ "\nCombine multiple partially signed transactions into one transaction.\n"
+ "The combined transaction may be another partially signed transaction or a \n"
+ "fully signed transaction.",
+ {
+ {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of hex strings of partially signed transactions",
+ {
+ {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"},
+ },
+ },
+ },
+ RPCResult{
"\"hex\" (string) The hex-encoded raw transaction with signature(s)\n"
-
- "\nExamples:\n"
- + HelpExampleCli("combinerawtransaction", "[\"myhex1\", \"myhex2\", \"myhex3\"]")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("combinerawtransaction", "[\"myhex1\", \"myhex2\", \"myhex3\"]")
+ },
+ }.ToString());
UniValue txs = request.params[0].get_array();
@@ -758,187 +688,50 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
UpdateInput(txin, sigdata);
}
- return EncodeHexTx(mergedTx);
-}
-
-UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType)
-{
- // Fetch previous transactions (inputs):
- CCoinsView viewDummy;
- CCoinsViewCache view(&viewDummy);
- {
- LOCK2(cs_main, mempool.cs);
- CCoinsViewCache &viewChain = *pcoinsTip;
- CCoinsViewMemPool viewMempool(&viewChain, mempool);
- view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
-
- for (const CTxIn& txin : mtx.vin) {
- view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
- }
-
- view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
- }
-
- // Add previous txouts given in the RPC call:
- if (!prevTxsUnival.isNull()) {
- UniValue prevTxs = prevTxsUnival.get_array();
- for (unsigned int idx = 0; idx < prevTxs.size(); ++idx) {
- const UniValue& p = prevTxs[idx];
- if (!p.isObject()) {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
- }
-
- UniValue prevOut = p.get_obj();
-
- RPCTypeCheckObj(prevOut,
- {
- {"txid", UniValueType(UniValue::VSTR)},
- {"vout", UniValueType(UniValue::VNUM)},
- {"scriptPubKey", UniValueType(UniValue::VSTR)},
- });
-
- uint256 txid = ParseHashO(prevOut, "txid");
-
- int nOut = find_value(prevOut, "vout").get_int();
- if (nOut < 0) {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
- }
-
- COutPoint out(txid, nOut);
- std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
- CScript scriptPubKey(pkData.begin(), pkData.end());
-
- {
- const Coin& coin = view.AccessCoin(out);
- if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) {
- std::string err("Previous output scriptPubKey mismatch:\n");
- err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+
- ScriptToAsmStr(scriptPubKey);
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
- }
- Coin newcoin;
- newcoin.out.scriptPubKey = scriptPubKey;
- newcoin.out.nValue = MAX_MONEY;
- if (prevOut.exists("amount")) {
- newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
- }
- newcoin.nHeight = 1;
- view.AddCoin(out, std::move(newcoin), true);
- }
-
- // if redeemScript given and not using the local wallet (private keys
- // given), add redeemScript to the keystore so it can be signed:
- if (is_temp_keystore && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash())) {
- RPCTypeCheckObj(prevOut,
- {
- {"redeemScript", UniValueType(UniValue::VSTR)},
- });
- UniValue v = find_value(prevOut, "redeemScript");
- if (!v.isNull()) {
- std::vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
- CScript redeemScript(rsData.begin(), rsData.end());
- keystore->AddCScript(redeemScript);
- // Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
- keystore->AddCScript(GetScriptForWitness(redeemScript));
- }
- }
- }
- }
-
- int nHashType = ParseSighashString(hashType);
-
- bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
-
- // Script verification errors
- UniValue vErrors(UniValue::VARR);
-
- // Use CTransaction for the constant parts of the
- // transaction to avoid rehashing.
- const CTransaction txConst(mtx);
- // Sign what we can:
- for (unsigned int i = 0; i < mtx.vin.size(); i++) {
- CTxIn& txin = mtx.vin[i];
- const Coin& coin = view.AccessCoin(txin.prevout);
- if (coin.IsSpent()) {
- TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
- continue;
- }
- const CScript& prevPubKey = coin.out.scriptPubKey;
- const CAmount& amount = coin.out.nValue;
-
- SignatureData sigdata = DataFromTransaction(mtx, i, coin.out);
- // Only sign SIGHASH_SINGLE if there's a corresponding output:
- if (!fHashSingle || (i < mtx.vout.size())) {
- ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
- }
-
- UpdateInput(txin, sigdata);
-
- // amount must be specified for valid segwit signature
- if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
- throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin.out.ToString()));
- }
-
- ScriptError serror = SCRIPT_ERR_OK;
- if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
- if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
- // Unable to sign input and verification failed (possible attempt to partially sign).
- TxInErrorToJSON(txin, vErrors, "Unable to sign input, invalid stack size (possibly missing key)");
- } else {
- TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
- }
- }
- }
- bool fComplete = vErrors.empty();
-
- UniValue result(UniValue::VOBJ);
- result.pushKV("hex", EncodeHexTx(mtx));
- result.pushKV("complete", fComplete);
- if (!vErrors.empty()) {
- result.pushKV("errors", vErrors);
- }
-
- return result;
+ return EncodeHexTx(CTransaction(mergedTx));
}
static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
throw std::runtime_error(
- "signrawtransactionwithkey \"hexstring\" [\"privatekey1\",...] ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] sighashtype )\n"
- "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
- "The second argument is an array of base58-encoded private\n"
- "keys that will be the only keys used to sign the transaction.\n"
- "The third optional argument (may be null) is an array of previous transaction outputs that\n"
- "this transaction depends on but may not yet be in the block chain.\n"
-
- "\nArguments:\n"
- "1. \"hexstring\" (string, required) The transaction hex string\n"
- "2. \"privkeys\" (string, required) A json array of base58-encoded private keys for signing\n"
- " [ (json array of strings)\n"
- " \"privatekey\" (string) private key in base58-encoding\n"
- " ,...\n"
- " ]\n"
- "3. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n"
- " [ (json array of json objects, or 'null' if none provided)\n"
- " {\n"
- " \"txid\":\"id\", (string, required) The transaction id\n"
- " \"vout\":n, (numeric, required) The output number\n"
- " \"scriptPubKey\": \"hex\", (string, required) script key\n"
- " \"redeemScript\": \"hex\", (string, required for P2SH or P2WSH) redeem script\n"
- " \"amount\": value (numeric, required) The amount spent\n"
- " }\n"
- " ,...\n"
- " ]\n"
- "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
+ RPCHelpMan{"signrawtransactionwithkey",
+ "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
+ "The second argument is an array of base58-encoded private\n"
+ "keys that will be the only keys used to sign the transaction.\n"
+ "The third optional argument (may be null) is an array of previous transaction outputs that\n"
+ "this transaction depends on but may not yet be in the block chain.\n",
+ {
+ {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
+ {"privkeys", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base58-encoded private keys for signing",
+ {
+ {"privatekey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "private key in base58-encoding"},
+ },
+ },
+ {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of previous dependent transaction outputs",
+ {
+ {"", 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 number"},
+ {"scriptPubKey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "script key"},
+ {"redeemScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2SH) redeem script"},
+ {"witnessScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2WSH or P2SH-P2WSH) witness script"},
+ {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::OMITTED, "(required for Segwit inputs) the amount spent"},
+ },
+ },
+ },
+ },
+ {"sighashtype", RPCArg::Type::STR, /* default */ "ALL", "The signature hash type. Must be one of:\n"
" \"ALL\"\n"
" \"NONE\"\n"
" \"SINGLE\"\n"
" \"ALL|ANYONECANPAY\"\n"
" \"NONE|ANYONECANPAY\"\n"
" \"SINGLE|ANYONECANPAY\"\n"
-
- "\nResult:\n"
+ },
+ },
+ RPCResult{
"{\n"
" \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
@@ -953,11 +746,12 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
" ,...\n"
" ]\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("signrawtransactionwithkey", "\"myhex\"")
+ },
+ RPCExamples{
+ HelpExampleCli("signrawtransactionwithkey", "\"myhex\"")
+ HelpExampleRpc("signrawtransactionwithkey", "\"myhex\"")
- );
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
@@ -977,218 +771,96 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
keystore.AddKey(key);
}
- return SignTransaction(mtx, request.params[2], &keystore, true, request.params[3]);
-}
-
-UniValue signrawtransaction(const JSONRPCRequest& request)
-{
-#ifdef ENABLE_WALLET
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-#endif
-
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
- throw std::runtime_error(
- "signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n"
- "\nDEPRECATED. Sign inputs for raw transaction (serialized, hex-encoded).\n"
- "The second optional argument (may be null) is an array of previous transaction outputs that\n"
- "this transaction depends on but may not yet be in the block chain.\n"
- "The third optional argument (may be null) is an array of base58-encoded private\n"
- "keys that, if given, will be the only keys used to sign the transaction.\n"
-#ifdef ENABLE_WALLET
- + HelpRequiringPassphrase(pwallet) + "\n"
-#endif
- "\nArguments:\n"
- "1. \"hexstring\" (string, required) The transaction hex string\n"
- "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n"
- " [ (json array of json objects, or 'null' if none provided)\n"
- " {\n"
- " \"txid\":\"id\", (string, required) The transaction id\n"
- " \"vout\":n, (numeric, required) The output number\n"
- " \"scriptPubKey\": \"hex\", (string, required) script key\n"
- " \"redeemScript\": \"hex\", (string, required for P2SH or P2WSH) redeem script\n"
- " \"amount\": value (numeric, required) The amount spent\n"
- " }\n"
- " ,...\n"
- " ]\n"
- "3. \"privkeys\" (string, optional) A json array of base58-encoded private keys for signing\n"
- " [ (json array of strings, or 'null' if none provided)\n"
- " \"privatekey\" (string) private key in base58-encoding\n"
- " ,...\n"
- " ]\n"
- "4. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
- " \"ALL\"\n"
- " \"NONE\"\n"
- " \"SINGLE\"\n"
- " \"ALL|ANYONECANPAY\"\n"
- " \"NONE|ANYONECANPAY\"\n"
- " \"SINGLE|ANYONECANPAY\"\n"
-
- "\nResult:\n"
- "{\n"
- " \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
- " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
- " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
- " {\n"
- " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
- " \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
- " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
- " \"sequence\" : n, (numeric) Script sequence number\n"
- " \"error\" : \"text\" (string) Verification or signing error related to the input\n"
- " }\n"
- " ,...\n"
- " ]\n"
- "}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("signrawtransaction", "\"myhex\"")
- + HelpExampleRpc("signrawtransaction", "\"myhex\"")
- );
-
- if (!IsDeprecatedRPCEnabled("signrawtransaction")) {
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "signrawtransaction is deprecated and will be fully removed in v0.18. "
- "To use signrawtransaction in v0.17, restart bitcoind with -deprecatedrpc=signrawtransaction.\n"
- "Projects should transition to using signrawtransactionwithkey and signrawtransactionwithwallet before upgrading to v0.18");
+ // Fetch previous transactions (inputs):
+ std::map<COutPoint, Coin> coins;
+ for (const CTxIn& txin : mtx.vin) {
+ coins[txin.prevout]; // Create empty map entry keyed by prevout.
}
+ FindCoins(coins);
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
-
- // Make a JSONRPCRequest to pass on to the right signrawtransaction* command
- JSONRPCRequest new_request;
- new_request.id = request.id;
- new_request.params.setArray();
-
- // For signing with private keys
- if (!request.params[2].isNull()) {
- new_request.params.push_back(request.params[0]);
- // Note: the prevtxs and privkeys are reversed for signrawtransactionwithkey
- new_request.params.push_back(request.params[2]);
- new_request.params.push_back(request.params[1]);
- new_request.params.push_back(request.params[3]);
- return signrawtransactionwithkey(new_request);
- } else {
-#ifdef ENABLE_WALLET
- // Otherwise sign with the wallet which does not take a privkeys parameter
- new_request.params.push_back(request.params[0]);
- new_request.params.push_back(request.params[1]);
- new_request.params.push_back(request.params[3]);
- return signrawtransactionwithwallet(new_request);
-#else
- // If we have made it this far, then wallet is disabled and no private keys were given, so fail here.
- throw JSONRPCError(RPC_INVALID_PARAMETER, "No private keys available.");
-#endif
- }
+ return SignTransaction(mtx, request.params[2], &keystore, coins, true, request.params[3]);
}
static UniValue sendrawtransaction(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
- throw std::runtime_error(
- "sendrawtransaction \"hexstring\" ( allowhighfees )\n"
- "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
- "\nAlso see createrawtransaction and signrawtransaction calls.\n"
- "\nArguments:\n"
- "1. \"hexstring\" (string, required) The hex string of the raw transaction)\n"
- "2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
- "\nResult:\n"
+ const RPCHelpMan help{"sendrawtransaction",
+ "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n"
+ "\nAlso see createrawtransaction and signrawtransactionwithkey calls.\n",
+ {
+ {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
+ {"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE),
+ "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +
+ "/kB.\nSet to 0 to accept any fee rate.\n"},
+ },
+ RPCResult{
"\"hex\" (string) The transaction hash in hex\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate a transaction\n"
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
"Sign the transaction, and get back the hex\n"
- + HelpExampleCli("signrawtransaction", "\"myhex\"") +
+ + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
"\nSend the transaction (signed hex)\n"
+ HelpExampleCli("sendrawtransaction", "\"signedhex\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
- );
+ },
+ };
- std::promise<void> promise;
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
+ }
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
+ RPCTypeCheck(request.params, {
+ UniValue::VSTR,
+ UniValueType(), // NUM or BOOL, checked later
+ });
// parse hex string from parameter
CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
- const uint256& hashTx = tx->GetHash();
-
- CAmount nMaxRawTxFee = maxTxFee;
- if (!request.params[1].isNull() && request.params[1].get_bool())
- nMaxRawTxFee = 0;
- { // cs_main scope
- LOCK(cs_main);
- CCoinsViewCache &view = *pcoinsTip;
- bool fHaveChain = false;
- for (size_t o = 0; !fHaveChain && o < tx->vout.size(); o++) {
- const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
- fHaveChain = !existingCoin.IsSpent();
- }
- bool fHaveMempool = mempool.exists(hashTx);
- if (!fHaveMempool && !fHaveChain) {
- // push to local node and sync with wallets
- CValidationState state;
- bool fMissingInputs;
- if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
- nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) {
- if (state.IsInvalid()) {
- throw JSONRPCError(RPC_TRANSACTION_REJECTED, FormatStateMessage(state));
- } else {
- if (fMissingInputs) {
- throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
- }
- throw JSONRPCError(RPC_TRANSACTION_ERROR, FormatStateMessage(state));
- }
- } else {
- // If wallet is enabled, ensure that the wallet has been made aware
- // of the new transaction prior to returning. This prevents a race
- // where a user might call sendrawtransaction with a transaction
- // to/from their wallet, immediately call some wallet RPC, and get
- // a stale result because callbacks have not yet been processed.
- CallFunctionInValidationInterfaceQueue([&promise] {
- promise.set_value();
- });
- }
- } else if (fHaveChain) {
- throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
- } else {
- // Make sure we don't block forever if re-sending
- // a transaction already in mempool.
- promise.set_value();
+ CAmount max_raw_tx_fee = DEFAULT_MAX_RAW_TX_FEE;
+ // TODO: temporary migration code for old clients. Remove in v0.20
+ if (request.params[1].isBool()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0.");
+ } else if (!request.params[1].isNull()) {
+ size_t weight = GetTransactionWeight(*tx);
+ CFeeRate fr(AmountFromValue(request.params[1]));
+ // the +3/4 part rounds the value up, and is the same formula used when
+ // calculating the fee for a transaction
+ // (see GetVirtualTransactionSize)
+ max_raw_tx_fee = fr.GetFee((weight+3)/4);
}
- } // cs_main
-
- promise.get_future().wait();
-
- if(!g_connman)
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
-
- CInv inv(MSG_TX, hashTx);
- g_connman->ForEachNode([&inv](CNode* pnode)
- {
- pnode->PushInventory(inv);
- });
+ uint256 txid;
+ std::string err_string;
+ const TransactionError err = BroadcastTransaction(tx, txid, err_string, max_raw_tx_fee);
+ if (TransactionError::OK != err) {
+ throw JSONRPCTransactionError(err, err_string);
+ }
- return hashTx.GetHex();
+ return txid.GetHex();
}
static UniValue testmempoolaccept(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
- throw std::runtime_error(
- // clang-format off
- "testmempoolaccept [\"rawtxs\"] ( allowhighfees )\n"
- "\nReturns if raw transaction (serialized, hex-encoded) would be accepted by mempool.\n"
- "\nThis checks if the transaction violates the consensus or policy rules.\n"
- "\nSee sendrawtransaction call.\n"
- "\nArguments:\n"
- "1. [\"rawtxs\"] (array, required) An array of hex strings of raw transactions.\n"
- " Length must be one for now.\n"
- "2. allowhighfees (boolean, optional, default=false) Allow high fees\n"
- "\nResult:\n"
+ const RPCHelpMan help{"testmempoolaccept",
+ "\nReturns result of mempool acceptance tests indicating if raw transaction (serialized, hex-encoded) would be accepted by mempool.\n"
+ "\nThis checks if the transaction violates the consensus or policy rules.\n"
+ "\nSee sendrawtransaction call.\n",
+ {
+ {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings of raw transactions.\n"
+ " Length must be one for now.",
+ {
+ {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
+ },
+ },
+ {"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE), "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + "/kB\n"},
+ },
+ RPCResult{
"[ (array) The result of the mempool acceptance test for each raw transaction in the input array.\n"
" Length is exactly one for now.\n"
" {\n"
@@ -1197,20 +869,28 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
" \"reject-reason\" (string) Rejection string (only present when 'allowed' is false)\n"
" }\n"
"]\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate a transaction\n"
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") +
"Sign the transaction, and get back the hex\n"
- + HelpExampleCli("signrawtransaction", "\"myhex\"") +
+ + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
"\nTest acceptance of the transaction (signed hex)\n"
- + HelpExampleCli("testmempoolaccept", "\"signedhex\"") +
- "\nAs a json rpc call\n"
+ + HelpExampleCli("testmempoolaccept", "[\"signedhex\"]") +
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
- // clang-format on
- );
+ },
+ };
+
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
}
- RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VBOOL});
+ RPCTypeCheck(request.params, {
+ UniValue::VARR,
+ UniValueType(), // NUM or BOOL, checked later
+ });
+
if (request.params[0].get_array().size() != 1) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Array must contain exactly one raw transaction for now");
}
@@ -1222,9 +902,17 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
const uint256& tx_hash = tx->GetHash();
- CAmount max_raw_tx_fee = ::maxTxFee;
- if (!request.params[1].isNull() && request.params[1].get_bool()) {
- max_raw_tx_fee = 0;
+ CAmount max_raw_tx_fee = DEFAULT_MAX_RAW_TX_FEE;
+ // TODO: temporary migration code for old clients. Remove in v0.20
+ if (request.params[1].isBool()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0.");
+ } else if (!request.params[1].isNull()) {
+ size_t weight = GetTransactionWeight(*tx);
+ CFeeRate fr(AmountFromValue(request.params[1]));
+ // the +3/4 part rounds the value up, and is the same formula used when
+ // calculating the fee for a transaction
+ // (see GetVirtualTransactionSize)
+ max_raw_tx_fee = fr.GetFee((weight+3)/4);
}
UniValue result(UniValue::VARR);
@@ -1277,13 +965,12 @@ UniValue decodepsbt(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "decodepsbt \"psbt\"\n"
- "\nReturn a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.\n"
-
- "\nArguments:\n"
- "1. \"psbt\" (string, required) The PSBT base64 string\n"
-
- "\nResult:\n"
+ RPCHelpMan{"decodepsbt",
+ "\nReturn a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.\n",
+ {
+ {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"},
+ },
+ RPCResult{
"{\n"
" \"tx\" : { (json object) The decoded network-serialized unsigned transaction.\n"
" ... The layout is the same as the output of decoderawtransaction.\n"
@@ -1370,17 +1057,18 @@ UniValue decodepsbt(const JSONRPCRequest& request)
" ]\n"
" \"fee\" : fee (numeric, optional) The transaction fee paid if all UTXOs slots in the PSBT have been filled.\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("decodepsbt", "\"psbt\"")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("decodepsbt", "\"psbt\"")
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR});
// Unserialize the transactions
PartiallySignedTransaction psbtx;
std::string error;
- if (!DecodePSBT(psbtx, request.params[0].get_str(), error)) {
+ if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}
@@ -1460,11 +1148,8 @@ UniValue decodepsbt(const JSONRPCRequest& request)
UniValue keypath(UniValue::VOBJ);
keypath.pushKV("pubkey", HexStr(entry.first));
- uint32_t fingerprint = entry.second.at(0);
- keypath.pushKV("master_fingerprint", strprintf("%08x", bswap_32(fingerprint)));
-
- entry.second.erase(entry.second.begin());
- keypath.pushKV("path", WriteHDKeypath(entry.second));
+ keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint)));
+ keypath.pushKV("path", WriteHDKeypath(entry.second.path));
keypaths.push_back(keypath);
}
in.pushKV("bip32_derivs", keypaths);
@@ -1522,12 +1207,8 @@ UniValue decodepsbt(const JSONRPCRequest& request)
for (auto entry : output.hd_keypaths) {
UniValue keypath(UniValue::VOBJ);
keypath.pushKV("pubkey", HexStr(entry.first));
-
- uint32_t fingerprint = entry.second.at(0);
- keypath.pushKV("master_fingerprint", strprintf("%08x", bswap_32(fingerprint)));
-
- entry.second.erase(entry.second.begin());
- keypath.pushKV("path", WriteHDKeypath(entry.second));
+ keypath.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(entry.second.fingerprint)));
+ keypath.pushKV("path", WriteHDKeypath(entry.second.path));
keypaths.push_back(keypath);
}
out.pushKV("bip32_derivs", keypaths);
@@ -1559,50 +1240,47 @@ UniValue combinepsbt(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "combinepsbt [\"psbt\",...]\n"
- "\nCombine multiple partially signed Bitcoin transactions into one transaction.\n"
- "Implements the Combiner role.\n"
- "\nArguments:\n"
- "1. \"txs\" (string) A json array of base64 strings of partially signed transactions\n"
- " [\n"
- " \"psbt\" (string) A base64 string of a PSBT\n"
- " ,...\n"
- " ]\n"
-
- "\nResult:\n"
+ RPCHelpMan{"combinepsbt",
+ "\nCombine multiple partially signed Bitcoin transactions into one transaction.\n"
+ "Implements the Combiner role.\n",
+ {
+ {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base64 strings of partially signed transactions",
+ {
+ {"psbt", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A base64 string of a PSBT"},
+ },
+ },
+ },
+ RPCResult{
" \"psbt\" (string) The base64-encoded partially signed transaction\n"
- "\nExamples:\n"
- + HelpExampleCli("combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]")
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VARR}, true);
// Unserialize the transactions
std::vector<PartiallySignedTransaction> psbtxs;
UniValue txs = request.params[0].get_array();
+ if (txs.empty()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Parameter 'txs' cannot be empty");
+ }
for (unsigned int i = 0; i < txs.size(); ++i) {
PartiallySignedTransaction psbtx;
std::string error;
- if (!DecodePSBT(psbtx, txs[i].get_str(), error)) {
+ if (!DecodeBase64PSBT(psbtx, txs[i].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}
psbtxs.push_back(psbtx);
}
- PartiallySignedTransaction merged_psbt(psbtxs[0]); // Copy the first one
-
- // Merge
- for (auto it = std::next(psbtxs.begin()); it != psbtxs.end(); ++it) {
- if (*it != merged_psbt) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "PSBTs do not refer to the same transactions.");
- }
- merged_psbt.Merge(*it);
- }
- if (!merged_psbt.IsSane()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Merged PSBT is inconsistent");
+ PartiallySignedTransaction merged_psbt;
+ const TransactionError error = CombinePSBTs(merged_psbt, psbtxs);
+ if (error != TransactionError::OK) {
+ throw JSONRPCTransactionError(error);
}
- UniValue result(UniValue::VOBJ);
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << merged_psbt;
return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size());
@@ -1612,62 +1290,57 @@ UniValue finalizepsbt(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "finalizepsbt \"psbt\" ( extract )\n"
- "Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n"
- "network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n"
- "created which has the final_scriptSig and final_scriptWitness fields filled for inputs that are complete.\n"
- "Implements the Finalizer and Extractor roles.\n"
- "\nArguments:\n"
- "1. \"psbt\" (string) A base64 string of a PSBT\n"
- "2. \"extract\" (boolean, optional, default=true) If true and the transaction is complete, \n"
- " extract and return the complete transaction in normal network serialization instead of the PSBT.\n"
-
- "\nResult:\n"
+ RPCHelpMan{"finalizepsbt",
+ "Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n"
+ "network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n"
+ "created which has the final_scriptSig and final_scriptWitness fields filled for inputs that are complete.\n"
+ "Implements the Finalizer and Extractor roles.\n",
+ {
+ {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"},
+ {"extract", RPCArg::Type::BOOL, /* default */ "true", "If true and the transaction is complete,\n"
+ " extract and return the complete transaction in normal network serialization instead of the PSBT."},
+ },
+ RPCResult{
"{\n"
" \"psbt\" : \"value\", (string) The base64-encoded partially signed transaction if not extracted\n"
" \"hex\" : \"value\", (string) The hex-encoded network transaction if extracted\n"
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
" ]\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("finalizepsbt", "\"psbt\"")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("finalizepsbt", "\"psbt\"")
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true);
// Unserialize the transactions
PartiallySignedTransaction psbtx;
std::string error;
- if (!DecodePSBT(psbtx, request.params[0].get_str(), error)) {
+ if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}
- // Get all of the previous transactions
- bool complete = true;
- for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
- PSBTInput& input = psbtx.inputs.at(i);
+ bool extract = request.params[1].isNull() || (!request.params[1].isNull() && request.params[1].get_bool());
- SignatureData sigdata;
- complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, *psbtx.tx, input, sigdata, i, 1);
- }
+ CMutableTransaction mtx;
+ bool complete = FinalizeAndExtractPSBT(psbtx, mtx);
UniValue result(UniValue::VOBJ);
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
- bool extract = request.params[1].isNull() || (!request.params[1].isNull() && request.params[1].get_bool());
+ std::string result_str;
+
if (complete && extract) {
- CMutableTransaction mtx(*psbtx.tx);
- for (unsigned int i = 0; i < mtx.vin.size(); ++i) {
- mtx.vin[i].scriptSig = psbtx.inputs[i].final_script_sig;
- mtx.vin[i].scriptWitness = psbtx.inputs[i].final_script_witness;
- }
ssTx << mtx;
- result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
+ result_str = HexStr(ssTx.str());
+ result.pushKV("hex", result_str);
} else {
ssTx << psbtx;
- result.push_back(Pair("psbt", EncodeBase64((unsigned char*)ssTx.data(), ssTx.size())));
+ result_str = EncodeBase64(ssTx.str());
+ result.pushKV("psbt", result_str);
}
- result.push_back(Pair("complete", complete));
+ result.pushKV("complete", complete);
return result;
}
@@ -1676,38 +1349,49 @@ UniValue createpsbt(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
throw std::runtime_error(
- "createpsbt [{\"txid\":\"id\",\"vout\":n},...] [{\"address\":amount},{\"data\":\"hex\"},...] ( locktime ) ( replaceable )\n"
- "\nCreates a transaction in the Partially Signed Transaction format.\n"
- "Implements the Creator role.\n"
- "\nArguments:\n"
- "1. \"inputs\" (array, required) A json array of json objects\n"
- " [\n"
- " {\n"
- " \"txid\":\"id\", (string, required) The transaction id\n"
- " \"vout\":n, (numeric, required) The output number\n"
- " \"sequence\":n (numeric, optional) The sequence number\n"
- " } \n"
- " ,...\n"
- " ]\n"
- "2. \"outputs\" (array, required) a json array with outputs (key-value pairs)\n"
- " [\n"
- " {\n"
- " \"address\": x.xxx, (obj, optional) A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + "\n"
- " },\n"
- " {\n"
- " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex encoded data\n"
- " }\n"
- " ,... More key-value pairs of the above form. For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
- " accepted as second parameter.\n"
- " ]\n"
- "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
- "4. replaceable (boolean, optional, default=false) 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.\n"
- "\nResult:\n"
+ RPCHelpMan{"createpsbt",
+ "\nCreates a transaction in the Partially Signed Transaction format.\n"
+ "Implements the Creator role.\n",
+ {
+ {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects",
+ {
+ {"", 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 number"},
+ {"sequence", RPCArg::Type::NUM, /* default */ "depends on the value of the 'replaceable' and 'locktime' arguments", "The sequence number"},
+ },
+ },
+ },
+ },
+ {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n"
+ "That is, each address can only appear once and there can only be one 'data' object.\n"
+ "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
+ " accepted as second parameter.",
+ {
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT},
+ },
+ },
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"},
+ },
+ },
+ },
+ },
+ {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
+ {"replaceable", RPCArg::Type::BOOL, /* default */ "false", "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."},
+ },
+ RPCResult{
" \"psbt\" (string) The resulting raw transaction (base64-encoded string)\n"
- "\nExamples:\n"
- + HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
+ },
+ }.ToString());
RPCTypeCheck(request.params, {
@@ -1741,25 +1425,28 @@ UniValue converttopsbt(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
- "converttopsbt \"hexstring\" ( permitsigdata iswitness )\n"
- "\nConverts a network serialized transaction to a PSBT. This should be used only with createrawtransaction and fundrawtransaction\n"
- "createpsbt and walletcreatefundedpsbt should be used for new applications.\n"
- "\nArguments:\n"
- "1. \"hexstring\" (string, required) The hex string of a raw transaction\n"
- "2. permitsigdata (boolean, optional, default=false) If true, any signatures in the input will be discarded and conversion.\n"
- " will continue. If false, RPC will fail if any signatures are present.\n"
- "3. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction.\n"
+ RPCHelpMan{"converttopsbt",
+ "\nConverts a network serialized transaction to a PSBT. This should be used only with createrawtransaction and fundrawtransaction\n"
+ "createpsbt and walletcreatefundedpsbt should be used for new applications.\n",
+ {
+ {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of a raw transaction"},
+ {"permitsigdata", RPCArg::Type::BOOL, /* default */ "false", "If true, any signatures in the input will be discarded and conversion.\n"
+ " will continue. If false, RPC will fail if any signatures are present."},
+ {"iswitness", RPCArg::Type::BOOL, /* default */ "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. If true, only witness deserializaion\n"
- " will be tried. If false, only non-witness deserialization wil be tried. Only has an effect if\n"
- " permitsigdata is true.\n"
- "\nResult:\n"
+ " will be tried. If false, only non-witness deserialization will be tried. Only has an effect if\n"
+ " permitsigdata is true."},
+ },
+ RPCResult{
" \"psbt\" (string) The resulting raw transaction (base64-encoded string)\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate a transaction\n"
+ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") +
"\nConvert the transaction to a PSBT\n"
+ HelpExampleCli("converttopsbt", "\"rawtransaction\"")
- );
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VBOOL}, true);
@@ -1777,7 +1464,7 @@ UniValue converttopsbt(const JSONRPCRequest& request)
// Remove all scriptSigs and scriptWitnesses from inputs
for (CTxIn& input : tx.vin) {
- if ((!input.scriptSig.empty() || !input.scriptWitness.IsNull()) && (request.params[1].isNull() || (!request.params[1].isNull() && request.params[1].get_bool()))) {
+ if ((!input.scriptSig.empty() || !input.scriptWitness.IsNull()) && !permitsigdata) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Inputs must not have scriptSigs and scriptWitnesses");
}
input.scriptSig.clear();
@@ -1801,6 +1488,247 @@ UniValue converttopsbt(const JSONRPCRequest& request)
return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size());
}
+UniValue utxoupdatepsbt(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 1) {
+ throw std::runtime_error(
+ RPCHelpMan{"utxoupdatepsbt",
+ "\nUpdates a PSBT with witness UTXOs retrieved from the UTXO set or the mempool.\n",
+ {
+ {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
+ },
+ RPCResult {
+ " \"psbt\" (string) The base64-encoded partially signed transaction with inputs updated\n"
+ },
+ RPCExamples {
+ HelpExampleCli("utxoupdatepsbt", "\"psbt\"")
+ }}.ToString());
+ }
+
+ RPCTypeCheck(request.params, {UniValue::VSTR}, true);
+
+ // Unserialize the transactions
+ PartiallySignedTransaction psbtx;
+ std::string error;
+ if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
+ }
+
+ // Fetch previous transactions (inputs):
+ CCoinsView viewDummy;
+ CCoinsViewCache view(&viewDummy);
+ {
+ LOCK2(cs_main, mempool.cs);
+ CCoinsViewCache &viewChain = *pcoinsTip;
+ CCoinsViewMemPool viewMempool(&viewChain, mempool);
+ view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
+
+ for (const CTxIn& txin : psbtx.tx->vin) {
+ view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail.
+ }
+
+ view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
+ }
+
+ // Fill the inputs
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ PSBTInput& input = psbtx.inputs.at(i);
+
+ if (input.non_witness_utxo || !input.witness_utxo.IsNull()) {
+ continue;
+ }
+
+ const Coin& coin = view.AccessCoin(psbtx.tx->vin[i].prevout);
+
+ std::vector<std::vector<unsigned char>> solutions_data;
+ txnouttype which_type = Solver(coin.out.scriptPubKey, solutions_data);
+ if (which_type == TX_WITNESS_V0_SCRIPTHASH || which_type == TX_WITNESS_V0_KEYHASH || which_type == TX_WITNESS_UNKNOWN) {
+ input.witness_utxo = coin.out;
+ }
+ }
+
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << psbtx;
+ return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size());
+}
+
+UniValue joinpsbts(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 1) {
+ throw std::runtime_error(
+ RPCHelpMan{"joinpsbts",
+ "\nJoins multiple distinct PSBTs with different inputs and outputs into one PSBT with inputs and outputs from all of the PSBTs\n"
+ "No input in any of the PSBTs can be in more than one of the PSBTs.\n",
+ {
+ {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base64 strings of partially signed transactions",
+ {
+ {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
+ }}
+ },
+ RPCResult {
+ " \"psbt\" (string) The base64-encoded partially signed transaction\n"
+ },
+ RPCExamples {
+ HelpExampleCli("joinpsbts", "\"psbt\"")
+ }}.ToString());
+ }
+
+ RPCTypeCheck(request.params, {UniValue::VARR}, true);
+
+ // Unserialize the transactions
+ std::vector<PartiallySignedTransaction> psbtxs;
+ UniValue txs = request.params[0].get_array();
+
+ if (txs.size() <= 1) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "At least two PSBTs are required to join PSBTs.");
+ }
+
+ int32_t best_version = 1;
+ uint32_t best_locktime = 0xffffffff;
+ for (unsigned int i = 0; i < txs.size(); ++i) {
+ PartiallySignedTransaction psbtx;
+ std::string error;
+ if (!DecodeBase64PSBT(psbtx, txs[i].get_str(), error)) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
+ }
+ psbtxs.push_back(psbtx);
+ // Choose the highest version number
+ if (psbtx.tx->nVersion > best_version) {
+ best_version = psbtx.tx->nVersion;
+ }
+ // Choose the lowest lock time
+ if (psbtx.tx->nLockTime < best_locktime) {
+ best_locktime = psbtx.tx->nLockTime;
+ }
+ }
+
+ // Create a blank psbt where everything will be added
+ PartiallySignedTransaction merged_psbt;
+ merged_psbt.tx = CMutableTransaction();
+ merged_psbt.tx->nVersion = best_version;
+ merged_psbt.tx->nLockTime = best_locktime;
+
+ // Merge
+ for (auto& psbt : psbtxs) {
+ for (unsigned int i = 0; i < psbt.tx->vin.size(); ++i) {
+ if (!merged_psbt.AddInput(psbt.tx->vin[i], psbt.inputs[i])) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", psbt.tx->vin[i].prevout.hash.ToString().c_str(), psbt.tx->vin[i].prevout.n));
+ }
+ }
+ for (unsigned int i = 0; i < psbt.tx->vout.size(); ++i) {
+ merged_psbt.AddOutput(psbt.tx->vout[i], psbt.outputs[i]);
+ }
+ merged_psbt.unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
+ }
+
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << merged_psbt;
+ return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size());
+}
+
+UniValue analyzepsbt(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 1) {
+ throw std::runtime_error(
+ RPCHelpMan{"analyzepsbt",
+ "\nAnalyzes and provides information about the current status of a PSBT and its inputs\n",
+ {
+ {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
+ },
+ RPCResult {
+ "{\n"
+ " \"inputs\" : [ (array of json objects)\n"
+ " {\n"
+ " \"has_utxo\" : true|false (boolean) Whether a UTXO is provided\n"
+ " \"is_final\" : true|false (boolean) Whether the input is finalized\n"
+ " \"missing\" : { (json object, optional) Things that are missing that are required to complete this input\n"
+ " \"pubkeys\" : [ (array, optional)\n"
+ " \"keyid\" (string) Public key ID, hash160 of the public key, of a public key whose BIP 32 derivation path is missing\n"
+ " ]\n"
+ " \"signatures\" : [ (array, optional)\n"
+ " \"keyid\" (string) Public key ID, hash160 of the public key, of a public key whose signature is missing\n"
+ " ]\n"
+ " \"redeemscript\" : \"hash\" (string, optional) Hash160 of the redeemScript that is missing\n"
+ " \"witnessscript\" : \"hash\" (string, optional) SHA256 of the witnessScript that is missing\n"
+ " }\n"
+ " \"next\" : \"role\" (string, optional) Role of the next person that this input needs to go to\n"
+ " }\n"
+ " ,...\n"
+ " ]\n"
+ " \"estimated_vsize\" : vsize (numeric, optional) Estimated vsize of the final signed transaction\n"
+ " \"estimated_feerate\" : feerate (numeric, optional) Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled.\n"
+ " \"fee\" : fee (numeric, optional) The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled.\n"
+ " \"next\" : \"role\" (string) Role of the next person that this psbt needs to go to\n"
+ "}\n"
+ },
+ RPCExamples {
+ HelpExampleCli("analyzepsbt", "\"psbt\"")
+ }}.ToString());
+ }
+
+ RPCTypeCheck(request.params, {UniValue::VSTR});
+
+ // Unserialize the transaction
+ PartiallySignedTransaction psbtx;
+ std::string error;
+ if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
+ }
+
+ PSBTAnalysis psbta = AnalyzePSBT(psbtx);
+
+ UniValue result(UniValue::VOBJ);
+ UniValue inputs_result(UniValue::VARR);
+ for (const auto& input : psbta.inputs) {
+ UniValue input_univ(UniValue::VOBJ);
+ UniValue missing(UniValue::VOBJ);
+
+ input_univ.pushKV("has_utxo", input.has_utxo);
+ input_univ.pushKV("is_final", input.is_final);
+ input_univ.pushKV("next", PSBTRoleName(input.next));
+
+ if (!input.missing_pubkeys.empty()) {
+ UniValue missing_pubkeys_univ(UniValue::VARR);
+ for (const CKeyID& pubkey : input.missing_pubkeys) {
+ missing_pubkeys_univ.push_back(HexStr(pubkey));
+ }
+ missing.pushKV("pubkeys", missing_pubkeys_univ);
+ }
+ if (!input.missing_redeem_script.IsNull()) {
+ missing.pushKV("redeemscript", HexStr(input.missing_redeem_script));
+ }
+ if (!input.missing_witness_script.IsNull()) {
+ missing.pushKV("witnessscript", HexStr(input.missing_witness_script));
+ }
+ if (!input.missing_sigs.empty()) {
+ UniValue missing_sigs_univ(UniValue::VARR);
+ for (const CKeyID& pubkey : input.missing_sigs) {
+ missing_sigs_univ.push_back(HexStr(pubkey));
+ }
+ missing.pushKV("signatures", missing_sigs_univ);
+ }
+ if (!missing.getKeys().empty()) {
+ input_univ.pushKV("missing", missing);
+ }
+ inputs_result.push_back(input_univ);
+ }
+ result.pushKV("inputs", inputs_result);
+
+ if (psbta.estimated_vsize != nullopt) {
+ result.pushKV("estimated_vsize", (int)*psbta.estimated_vsize);
+ }
+ if (psbta.estimated_feerate != nullopt) {
+ result.pushKV("estimated_feerate", ValueFromAmount(psbta.estimated_feerate->GetFeePerK()));
+ }
+ if (psbta.fee != nullopt) {
+ result.pushKV("fee", ValueFromAmount(*psbta.fee));
+ }
+ result.pushKV("next", PSBTRoleName(psbta.next));
+
+ return result;
+}
+
+// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
@@ -1808,20 +1736,23 @@ static const CRPCCommand commands[] =
{ "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} },
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring","iswitness"} },
{ "rawtransactions", "decodescript", &decodescript, {"hexstring"} },
- { "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","allowhighfees"} },
+ { "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","allowhighfees|maxfeerate"} },
{ "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
- { "rawtransactions", "signrawtransaction", &signrawtransaction, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */
{ "rawtransactions", "signrawtransactionwithkey", &signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} },
- { "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","allowhighfees"} },
+ { "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","allowhighfees|maxfeerate"} },
{ "rawtransactions", "decodepsbt", &decodepsbt, {"psbt"} },
{ "rawtransactions", "combinepsbt", &combinepsbt, {"txs"} },
{ "rawtransactions", "finalizepsbt", &finalizepsbt, {"psbt", "extract"} },
{ "rawtransactions", "createpsbt", &createpsbt, {"inputs","outputs","locktime","replaceable"} },
{ "rawtransactions", "converttopsbt", &converttopsbt, {"hexstring","permitsigdata","iswitness"} },
+ { "rawtransactions", "utxoupdatepsbt", &utxoupdatepsbt, {"psbt"} },
+ { "rawtransactions", "joinpsbts", &joinpsbts, {"txs"} },
+ { "rawtransactions", "analyzepsbt", &analyzepsbt, {"psbt"} },
{ "blockchain", "gettxoutproof", &gettxoutproof, {"txids", "blockhash"} },
{ "blockchain", "verifytxoutproof", &verifytxoutproof, {"proof"} },
};
+// clang-format on
void RegisterRawTransactionRPCCommands(CRPCTable &t)
{
diff --git a/src/rpc/rawtransaction.h b/src/rpc/rawtransaction.h
deleted file mode 100644
index 52dccc90e8..0000000000
--- a/src/rpc/rawtransaction.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2017 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_RPC_RAWTRANSACTION_H
-#define BITCOIN_RPC_RAWTRANSACTION_H
-
-class CBasicKeyStore;
-struct CMutableTransaction;
-class UniValue;
-
-/** Sign a transaction with the given keystore and previous transactions */
-UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxs, CBasicKeyStore *keystore, bool tempKeystore, const UniValue& hashType);
-
-/** Create a transaction from univalue parameters */
-CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf);
-
-#endif // BITCOIN_RPC_RAWTRANSACTION_H
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
new file mode 100644
index 0000000000..8af491977c
--- /dev/null
+++ b/src/rpc/rawtransaction_util.cpp
@@ -0,0 +1,283 @@
+// Copyright (c) 2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <rpc/rawtransaction_util.h>
+
+#include <coins.h>
+#include <core_io.h>
+#include <interfaces/chain.h>
+#include <key_io.h>
+#include <keystore.h>
+#include <policy/policy.h>
+#include <primitives/transaction.h>
+#include <rpc/protocol.h>
+#include <rpc/util.h>
+#include <tinyformat.h>
+#include <univalue.h>
+#include <util/rbf.h>
+#include <util/strencodings.h>
+
+CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf)
+{
+ if (inputs_in.isNull() || outputs_in.isNull())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
+
+ UniValue inputs = inputs_in.get_array();
+ const bool outputs_is_obj = outputs_in.isObject();
+ UniValue outputs = outputs_is_obj ? outputs_in.get_obj() : outputs_in.get_array();
+
+ CMutableTransaction rawTx;
+
+ if (!locktime.isNull()) {
+ int64_t nLockTime = locktime.get_int64();
+ if (nLockTime < 0 || nLockTime > LOCKTIME_MAX)
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
+ rawTx.nLockTime = nLockTime;
+ }
+
+ bool rbfOptIn = rbf.isTrue();
+
+ for (unsigned int idx = 0; idx < inputs.size(); idx++) {
+ const UniValue& input = inputs[idx];
+ const UniValue& o = input.get_obj();
+
+ uint256 txid = ParseHashO(o, "txid");
+
+ const UniValue& vout_v = find_value(o, "vout");
+ if (!vout_v.isNum())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
+ int nOutput = vout_v.get_int();
+ if (nOutput < 0)
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
+
+ uint32_t nSequence;
+ if (rbfOptIn) {
+ nSequence = MAX_BIP125_RBF_SEQUENCE; /* CTxIn::SEQUENCE_FINAL - 2 */
+ } else if (rawTx.nLockTime) {
+ nSequence = CTxIn::SEQUENCE_FINAL - 1;
+ } else {
+ nSequence = CTxIn::SEQUENCE_FINAL;
+ }
+
+ // set the sequence number if passed in the parameters object
+ const UniValue& sequenceObj = find_value(o, "sequence");
+ if (sequenceObj.isNum()) {
+ int64_t seqNr64 = sequenceObj.get_int64();
+ if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
+ } else {
+ nSequence = (uint32_t)seqNr64;
+ }
+ }
+
+ CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
+
+ rawTx.vin.push_back(in);
+ }
+
+ if (!outputs_is_obj) {
+ // Translate array of key-value pairs into dict
+ UniValue outputs_dict = UniValue(UniValue::VOBJ);
+ for (size_t i = 0; i < outputs.size(); ++i) {
+ const UniValue& output = outputs[i];
+ if (!output.isObject()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair not an object as expected");
+ }
+ if (output.size() != 1) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair must contain exactly one key");
+ }
+ outputs_dict.pushKVs(output);
+ }
+ outputs = std::move(outputs_dict);
+ }
+
+ // Duplicate checking
+ std::set<CTxDestination> destinations;
+ bool has_data{false};
+
+ for (const std::string& name_ : outputs.getKeys()) {
+ if (name_ == "data") {
+ if (has_data) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, duplicate key: data");
+ }
+ has_data = true;
+ std::vector<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data");
+
+ CTxOut out(0, CScript() << OP_RETURN << data);
+ rawTx.vout.push_back(out);
+ } else {
+ CTxDestination destination = DecodeDestination(name_);
+ if (!IsValidDestination(destination)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
+ }
+
+ if (!destinations.insert(destination).second) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
+ }
+
+ CScript scriptPubKey = GetScriptForDestination(destination);
+ CAmount nAmount = AmountFromValue(outputs[name_]);
+
+ CTxOut out(nAmount, scriptPubKey);
+ rawTx.vout.push_back(out);
+ }
+ }
+
+ if (!rbf.isNull() && rawTx.vin.size() > 0 && rbfOptIn != SignalsOptInRBF(CTransaction(rawTx))) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number(s) contradict replaceable option");
+ }
+
+ return rawTx;
+}
+
+/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
+static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
+{
+ UniValue entry(UniValue::VOBJ);
+ entry.pushKV("txid", txin.prevout.hash.ToString());
+ entry.pushKV("vout", (uint64_t)txin.prevout.n);
+ UniValue witness(UniValue::VARR);
+ for (unsigned int i = 0; i < txin.scriptWitness.stack.size(); i++) {
+ witness.push_back(HexStr(txin.scriptWitness.stack[i].begin(), txin.scriptWitness.stack[i].end()));
+ }
+ entry.pushKV("witness", witness);
+ entry.pushKV("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
+ entry.pushKV("sequence", (uint64_t)txin.nSequence);
+ entry.pushKV("error", strMessage);
+ vErrorsRet.push_back(entry);
+}
+
+UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore* keystore, std::map<COutPoint, Coin>& coins, bool is_temp_keystore, const UniValue& hashType)
+{
+ // Add previous txouts given in the RPC call:
+ if (!prevTxsUnival.isNull()) {
+ UniValue prevTxs = prevTxsUnival.get_array();
+ for (unsigned int idx = 0; idx < prevTxs.size(); ++idx) {
+ const UniValue& p = prevTxs[idx];
+ if (!p.isObject()) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
+ }
+
+ UniValue prevOut = p.get_obj();
+
+ RPCTypeCheckObj(prevOut,
+ {
+ {"txid", UniValueType(UniValue::VSTR)},
+ {"vout", UniValueType(UniValue::VNUM)},
+ {"scriptPubKey", UniValueType(UniValue::VSTR)},
+ });
+
+ uint256 txid = ParseHashO(prevOut, "txid");
+
+ int nOut = find_value(prevOut, "vout").get_int();
+ if (nOut < 0) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
+ }
+
+ COutPoint out(txid, nOut);
+ std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
+ CScript scriptPubKey(pkData.begin(), pkData.end());
+
+ {
+ auto coin = coins.find(out);
+ if (coin != coins.end() && !coin->second.IsSpent() && coin->second.out.scriptPubKey != scriptPubKey) {
+ std::string err("Previous output scriptPubKey mismatch:\n");
+ err = err + ScriptToAsmStr(coin->second.out.scriptPubKey) + "\nvs:\n"+
+ ScriptToAsmStr(scriptPubKey);
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
+ }
+ Coin newcoin;
+ newcoin.out.scriptPubKey = scriptPubKey;
+ newcoin.out.nValue = MAX_MONEY;
+ if (prevOut.exists("amount")) {
+ newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
+ }
+ newcoin.nHeight = 1;
+ coins[out] = std::move(newcoin);
+ }
+
+ // if redeemScript and private keys were given, add redeemScript to the keystore so it can be signed
+ if (is_temp_keystore && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash())) {
+ RPCTypeCheckObj(prevOut,
+ {
+ {"redeemScript", UniValueType(UniValue::VSTR)},
+ {"witnessScript", UniValueType(UniValue::VSTR)},
+ }, true);
+ UniValue rs = find_value(prevOut, "redeemScript");
+ if (!rs.isNull()) {
+ std::vector<unsigned char> rsData(ParseHexV(rs, "redeemScript"));
+ CScript redeemScript(rsData.begin(), rsData.end());
+ keystore->AddCScript(redeemScript);
+ // Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
+ // This is only for compatibility, it is encouraged to use the explicit witnessScript field instead.
+ keystore->AddCScript(GetScriptForWitness(redeemScript));
+ }
+ UniValue ws = find_value(prevOut, "witnessScript");
+ if (!ws.isNull()) {
+ std::vector<unsigned char> wsData(ParseHexV(ws, "witnessScript"));
+ CScript witnessScript(wsData.begin(), wsData.end());
+ keystore->AddCScript(witnessScript);
+ // Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
+ keystore->AddCScript(GetScriptForWitness(witnessScript));
+ }
+ }
+ }
+ }
+
+ int nHashType = ParseSighashString(hashType);
+
+ bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
+
+ // Script verification errors
+ UniValue vErrors(UniValue::VARR);
+
+ // Use CTransaction for the constant parts of the
+ // transaction to avoid rehashing.
+ const CTransaction txConst(mtx);
+ // Sign what we can:
+ for (unsigned int i = 0; i < mtx.vin.size(); i++) {
+ CTxIn& txin = mtx.vin[i];
+ auto coin = coins.find(txin.prevout);
+ if (coin == coins.end() || coin->second.IsSpent()) {
+ TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
+ continue;
+ }
+ const CScript& prevPubKey = coin->second.out.scriptPubKey;
+ const CAmount& amount = coin->second.out.nValue;
+
+ SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
+ // Only sign SIGHASH_SINGLE if there's a corresponding output:
+ if (!fHashSingle || (i < mtx.vout.size())) {
+ ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
+ }
+
+ UpdateInput(txin, sigdata);
+
+ // amount must be specified for valid segwit signature
+ if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
+ throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin->second.out.ToString()));
+ }
+
+ ScriptError serror = SCRIPT_ERR_OK;
+ if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
+ if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
+ // Unable to sign input and verification failed (possible attempt to partially sign).
+ TxInErrorToJSON(txin, vErrors, "Unable to sign input, invalid stack size (possibly missing key)");
+ } else {
+ TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
+ }
+ }
+ }
+ bool fComplete = vErrors.empty();
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("hex", EncodeHexTx(CTransaction(mtx)));
+ result.pushKV("complete", fComplete);
+ if (!vErrors.empty()) {
+ result.pushKV("errors", vErrors);
+ }
+
+ return result;
+}
diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
new file mode 100644
index 0000000000..c115d33a77
--- /dev/null
+++ b/src/rpc/rawtransaction_util.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_RPC_RAWTRANSACTION_UTIL_H
+#define BITCOIN_RPC_RAWTRANSACTION_UTIL_H
+
+#include <map>
+
+class CBasicKeyStore;
+class UniValue;
+struct CMutableTransaction;
+class Coin;
+class COutPoint;
+
+/**
+ * Sign a transaction with the given keystore and previous transactions
+ *
+ * @param mtx The transaction to-be-signed
+ * @param prevTxs Array of previous txns outputs that tx depends on but may not yet be in the block chain
+ * @param keystore Temporary keystore containing signing keys
+ * @param coins Map of unspent outputs - coins in mempool and current chain UTXO set, may be extended by previous txns outputs after call
+ * @param tempKeystore Whether to use temporary keystore
+ * @param hashType The signature hash type
+ * @returns JSON object with details of signed transaction
+ */
+UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxs, CBasicKeyStore* keystore, std::map<COutPoint, Coin>& coins, bool tempKeystore, const UniValue& hashType);
+
+/** Create a transaction from univalue parameters */
+CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf);
+
+#endif // BITCOIN_RPC_RAWTRANSACTION_UTIL_H
diff --git a/src/rpc/register.h b/src/rpc/register.h
index b689740681..374a1e3db8 100644
--- a/src/rpc/register.h
+++ b/src/rpc/register.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2016 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index e46bf2f765..9df4070cbb 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,15 +8,14 @@
#include <fs.h>
#include <key_io.h>
#include <random.h>
+#include <rpc/util.h>
#include <shutdown.h>
#include <sync.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
+#include <util/system.h>
-#include <boost/bind.hpp>
#include <boost/signals2/signal.hpp>
-#include <boost/algorithm/string/case_conv.hpp> // for to_upper()
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
@@ -24,141 +23,69 @@
#include <unordered_map>
static CCriticalSection cs_rpcWarmup;
-static bool fRPCRunning = false;
+static std::atomic<bool> g_rpc_running{false};
static bool fRPCInWarmup GUARDED_BY(cs_rpcWarmup) = true;
static std::string rpcWarmupStatus GUARDED_BY(cs_rpcWarmup) = "RPC server started";
/* Timer-creating functions */
static RPCTimerInterface* timerInterface = nullptr;
/* Map of name to timer. */
static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers;
+static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler);
-static struct CRPCSignals
-{
- boost::signals2::signal<void ()> Started;
- boost::signals2::signal<void ()> Stopped;
- boost::signals2::signal<void (const CRPCCommand&)> PreCommand;
-} g_rpcSignals;
-
-void RPCServer::OnStarted(std::function<void ()> slot)
-{
- g_rpcSignals.Started.connect(slot);
-}
-
-void RPCServer::OnStopped(std::function<void ()> slot)
+struct RPCCommandExecutionInfo
{
- g_rpcSignals.Stopped.connect(slot);
-}
+ std::string method;
+ int64_t start;
+};
-void RPCTypeCheck(const UniValue& params,
- const std::list<UniValueType>& typesExpected,
- bool fAllowNull)
+struct RPCServerInfo
{
- 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++;
- }
-}
+ Mutex mutex;
+ std::list<RPCCommandExecutionInfo> active_commands GUARDED_BY(mutex);
+};
-void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
-{
- if (!typeExpected.typeAny && value.type() != typeExpected.type) {
- throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected.type), uvTypeName(value.type())));
- }
-}
+static RPCServerInfo g_rpc_server_info;
-void RPCTypeCheckObj(const UniValue& o,
- const std::map<std::string, UniValueType>& typesExpected,
- bool fAllowNull,
- bool fStrict)
+struct RPCCommandExecution
{
- for (const auto& t : typesExpected) {
- const UniValue& v = find_value(o, t.first);
- if (!fAllowNull && v.isNull())
- throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
-
- if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) {
- std::string err = strprintf("Expected type %s for %s, got %s",
- uvTypeName(t.second.type), t.first, uvTypeName(v.type()));
- throw JSONRPCError(RPC_TYPE_ERROR, err);
- }
+ std::list<RPCCommandExecutionInfo>::iterator it;
+ explicit RPCCommandExecution(const std::string& method)
+ {
+ LOCK(g_rpc_server_info.mutex);
+ it = g_rpc_server_info.active_commands.insert(g_rpc_server_info.active_commands.end(), {method, GetTimeMicros()});
}
-
- if (fStrict)
+ ~RPCCommandExecution()
{
- for (const std::string& k : o.getKeys())
- {
- if (typesExpected.count(k) == 0)
- {
- std::string err = strprintf("Unexpected key %s", k);
- throw JSONRPCError(RPC_TYPE_ERROR, err);
- }
- }
+ LOCK(g_rpc_server_info.mutex);
+ g_rpc_server_info.active_commands.erase(it);
}
-}
+};
-CAmount AmountFromValue(const UniValue& value)
+static struct CRPCSignals
{
- if (!value.isNum() && !value.isStr())
- throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
- CAmount amount;
- if (!ParseFixedPoint(value.getValStr(), 8, &amount))
- throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
- if (!MoneyRange(amount))
- throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
- return amount;
-}
+ boost::signals2::signal<void ()> Started;
+ boost::signals2::signal<void ()> Stopped;
+} g_rpcSignals;
-uint256 ParseHashV(const UniValue& v, std::string strName)
-{
- std::string strHex;
- if (v.isStr())
- strHex = v.get_str();
- if (!IsHex(strHex)) // Note: IsHex("") is false
- throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
- if (64 != strHex.length())
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d)", strName, 64, strHex.length()));
- uint256 result;
- result.SetHex(strHex);
- return result;
-}
-uint256 ParseHashO(const UniValue& o, std::string strKey)
+void RPCServer::OnStarted(std::function<void ()> slot)
{
- return ParseHashV(find_value(o, strKey), strKey);
-}
-std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
-{
- std::string strHex;
- if (v.isStr())
- strHex = v.get_str();
- if (!IsHex(strHex))
- throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
- return ParseHex(strHex);
+ g_rpcSignals.Started.connect(slot);
}
-std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
+
+void RPCServer::OnStopped(std::function<void ()> slot)
{
- return ParseHexV(find_value(o, strKey), strKey);
+ g_rpcSignals.Stopped.connect(slot);
}
-/**
- * Note: This interface may still be subject to change.
- */
-
std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& helpreq) const
{
std::string strRet;
std::string category;
- std::set<rpcfn_type> setDone;
+ std::set<intptr_t> setDone;
std::vector<std::pair<std::string, const CRPCCommand*> > vCommands;
for (const auto& entry : mapCommands)
- vCommands.push_back(make_pair(entry.second->category + entry.first, entry.second));
+ vCommands.push_back(make_pair(entry.second.front()->category + entry.first, entry.second.front()));
sort(vCommands.begin(), vCommands.end());
JSONRPCRequest jreq(helpreq);
@@ -174,9 +101,9 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest&
jreq.strMethod = strMethod;
try
{
- rpcfn_type pfn = pcmd->actor;
- if (setDone.insert(pfn).second)
- (*pfn)(jreq);
+ UniValue unused_result;
+ if (setDone.insert(pcmd->unique_id).second)
+ pcmd->actor(jreq, unused_result, true /* last_handler */);
}
catch (const std::exception& e)
{
@@ -192,9 +119,7 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest&
if (!category.empty())
strRet += "\n";
category = pcmd->category;
- std::string firstLetter = category.substr(0,1);
- boost::to_upper(firstLetter);
- strRet += "== " + firstLetter + category.substr(1) + " ==\n";
+ strRet += "== " + Capitalize(category) + " ==\n";
}
}
strRet += strHelp + "\n";
@@ -210,12 +135,16 @@ UniValue help(const JSONRPCRequest& jsonRequest)
{
if (jsonRequest.fHelp || jsonRequest.params.size() > 1)
throw std::runtime_error(
- "help ( \"command\" )\n"
- "\nList all commands, or get help for a specified command.\n"
- "\nArguments:\n"
- "1. \"command\" (string, optional) The command to get help on\n"
- "\nResult:\n"
+ RPCHelpMan{"help",
+ "\nList all commands, or get help for a specified command.\n",
+ {
+ {"command", RPCArg::Type::STR, /* default */ "all commands", "The command to get help on"},
+ },
+ RPCResult{
"\"text\" (string) The help text\n"
+ },
+ RPCExamples{""},
+ }.ToString()
);
std::string strCommand;
@@ -229,43 +158,96 @@ UniValue help(const JSONRPCRequest& jsonRequest)
UniValue stop(const JSONRPCRequest& jsonRequest)
{
// Accept the deprecated and ignored 'detach' boolean argument
+ // Also accept the hidden 'wait' integer argument (milliseconds)
+ // For instance, 'stop 1000' makes the call wait 1 second before returning
+ // to the client (intended for testing)
if (jsonRequest.fHelp || jsonRequest.params.size() > 1)
throw std::runtime_error(
- "stop\n"
- "\nStop Bitcoin server.");
+ RPCHelpMan{"stop",
+ "\nStop Bitcoin server.",
+ {},
+ RPCResults{},
+ RPCExamples{""},
+ }.ToString());
// Event loop will exit after current HTTP requests have been handled, so
// this reply will get back to the client.
StartShutdown();
+ if (jsonRequest.params[0].isNum()) {
+ MilliSleep(jsonRequest.params[0].get_int());
+ }
return "Bitcoin server stopping";
}
static UniValue uptime(const JSONRPCRequest& jsonRequest)
{
- if (jsonRequest.fHelp || jsonRequest.params.size() > 1)
+ if (jsonRequest.fHelp || jsonRequest.params.size() > 0)
throw std::runtime_error(
- "uptime\n"
- "\nReturns the total uptime of the server.\n"
- "\nResult:\n"
+ RPCHelpMan{"uptime",
+ "\nReturns the total uptime of the server.\n",
+ {},
+ RPCResult{
"ttt (numeric) The number of seconds that the server has been running\n"
- "\nExamples:\n"
- + HelpExampleCli("uptime", "")
+ },
+ RPCExamples{
+ HelpExampleCli("uptime", "")
+ HelpExampleRpc("uptime", "")
- );
+ },
+ }.ToString());
return GetTime() - GetStartupTime();
}
-/**
- * Call Table
- */
+static UniValue getrpcinfo(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 0) {
+ throw std::runtime_error(
+ RPCHelpMan{"getrpcinfo",
+ "\nReturns details of the RPC server.\n",
+ {},
+ RPCResult{
+ "{\n"
+ " \"active_commands\" (array) All active commands\n"
+ " [\n"
+ " { (object) Information about an active command\n"
+ " \"method\" (string) The name of the RPC command \n"
+ " \"duration\" (numeric) The running time in microseconds\n"
+ " },...\n"
+ " ]\n"
+ "}\n"
+ },
+ RPCExamples{
+ HelpExampleCli("getrpcinfo", "")
+ + HelpExampleRpc("getrpcinfo", "")},
+ }.ToString()
+ );
+ }
+
+ LOCK(g_rpc_server_info.mutex);
+ UniValue active_commands(UniValue::VARR);
+ for (const RPCCommandExecutionInfo& info : g_rpc_server_info.active_commands) {
+ UniValue entry(UniValue::VOBJ);
+ entry.pushKV("method", info.method);
+ entry.pushKV("duration", GetTimeMicros() - info.start);
+ active_commands.push_back(entry);
+ }
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("active_commands", active_commands);
+
+ return result;
+}
+
+// clang-format off
static const CRPCCommand vRPCCommands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
/* Overall control/query calls */
+ { "control", "getrpcinfo", &getrpcinfo, {} },
{ "control", "help", &help, {"command"} },
- { "control", "stop", &stop, {} },
+ { "control", "stop", &stop, {"wait"} },
{ "control", "uptime", &uptime, {} },
};
+// clang-format on
CRPCTable::CRPCTable()
{
@@ -275,36 +257,36 @@ CRPCTable::CRPCTable()
const CRPCCommand *pcmd;
pcmd = &vRPCCommands[vcidx];
- mapCommands[pcmd->name] = pcmd;
+ mapCommands[pcmd->name].push_back(pcmd);
}
}
-const CRPCCommand *CRPCTable::operator[](const std::string &name) const
-{
- std::map<std::string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
- if (it == mapCommands.end())
- return nullptr;
- return (*it).second;
-}
-
bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd)
{
if (IsRPCRunning())
return false;
- // don't allow overwriting for now
- std::map<std::string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
- if (it != mapCommands.end())
- return false;
-
- mapCommands[name] = pcmd;
+ mapCommands[name].push_back(pcmd);
return true;
}
+bool CRPCTable::removeCommand(const std::string& name, const CRPCCommand* pcmd)
+{
+ auto it = mapCommands.find(name);
+ if (it != mapCommands.end()) {
+ auto new_end = std::remove(it->second.begin(), it->second.end(), pcmd);
+ if (it->second.end() != new_end) {
+ it->second.erase(new_end, it->second.end());
+ return true;
+ }
+ }
+ return false;
+}
+
void StartRPC()
{
LogPrint(BCLog::RPC, "Starting RPC\n");
- fRPCRunning = true;
+ g_rpc_running = true;
g_rpcSignals.Started();
}
@@ -312,7 +294,7 @@ void InterruptRPC()
{
LogPrint(BCLog::RPC, "Interrupting RPC\n");
// Interrupt e.g. running longpolls
- fRPCRunning = false;
+ g_rpc_running = false;
}
void StopRPC()
@@ -325,7 +307,7 @@ void StopRPC()
bool IsRPCRunning()
{
- return fRPCRunning;
+ return g_rpc_running;
}
void SetRPCWarmupStatus(const std::string& newStatus)
@@ -481,19 +463,28 @@ UniValue CRPCTable::execute(const JSONRPCRequest &request) const
}
// Find method
- const CRPCCommand *pcmd = tableRPC[request.strMethod];
- if (!pcmd)
- throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
-
- g_rpcSignals.PreCommand(*pcmd);
+ auto it = mapCommands.find(request.strMethod);
+ if (it != mapCommands.end()) {
+ UniValue result;
+ for (const auto& command : it->second) {
+ if (ExecuteCommand(*command, request, result, &command == &it->second.back())) {
+ return result;
+ }
+ }
+ }
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
+}
+static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler)
+{
try
{
+ RPCCommandExecution execution(request.strMethod);
// Execute, convert arguments to array if necessary
if (request.params.isObject()) {
- return pcmd->actor(transformNamedArguments(request, pcmd->argNames));
+ return command.actor(transformNamedArguments(request, command.argNames), result, last_handler);
} else {
- return pcmd->actor(request);
+ return command.actor(request, result, last_handler);
}
}
catch (const std::exception& e)
@@ -505,25 +496,10 @@ UniValue CRPCTable::execute(const JSONRPCRequest &request) const
std::vector<std::string> CRPCTable::listCommands() const
{
std::vector<std::string> commandList;
- typedef std::map<std::string, const CRPCCommand*> commandMap;
-
- std::transform( mapCommands.begin(), mapCommands.end(),
- std::back_inserter(commandList),
- boost::bind(&commandMap::value_type::first,_1) );
+ for (const auto& i : mapCommands) commandList.emplace_back(i.first);
return commandList;
}
-std::string HelpExampleCli(const std::string& methodname, const std::string& args)
-{
- return "> bitcoin-cli " + methodname + " " + args + "\n";
-}
-
-std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
-{
- return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
- "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
-}
-
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
{
if (!timerInterface)
@@ -541,7 +517,7 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface)
timerInterface = nullptr;
}
-void RPCRunLater(const std::string& name, std::function<void(void)> func, int64_t nSeconds)
+void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds)
{
if (!timerInterface)
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
diff --git a/src/rpc/server.h b/src/rpc/server.h
index a9dbfbd21f..431ff0bb7c 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -27,15 +27,6 @@ namespace RPCServer
void OnStopped(std::function<void ()> slot);
}
-/** Wrapper for UniValue::VType, which includes typeAny:
- * Used to denote don't care type. */
-struct UniValueType {
- UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {}
- UniValueType() : typeAny(true) {}
- bool typeAny;
- UniValue::VType type;
-};
-
class JSONRPCRequest
{
public:
@@ -65,26 +56,6 @@ void SetRPCWarmupFinished();
/* returns the current warmup state. */
bool RPCIsInWarmup(std::string *outStatus);
-/**
- * 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.
-*/
-void RPCTypeCheckObj(const UniValue& o,
- const std::map<std::string, UniValueType>& typesExpected,
- bool fAllowNull = false,
- bool fStrict = false);
-
/** Opaque base class for timers returned by NewTimerFunc.
* This provides no methods at the moment, but makes sure that delete
* cleans up the whole state.
@@ -110,7 +81,7 @@ public:
* This is needed to cope with the case in which there is no HTTP server, but
* only GUI RPC console, and to break the dependency of pcserver on httprpc.
*/
- virtual RPCTimerBase* NewTimer(std::function<void(void)>& func, int64_t millis) = 0;
+ virtual RPCTimerBase* NewTimer(std::function<void()>& func, int64_t millis) = 0;
};
/** Set the factory function for timers */
@@ -124,17 +95,38 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface);
* Run func nSeconds from now.
* Overrides previous timer <name> (if any).
*/
-void RPCRunLater(const std::string& name, std::function<void(void)> func, int64_t nSeconds);
+void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds);
typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest);
class CRPCCommand
{
public:
+ //! RPC method handler reading request and assigning result. Should return
+ //! true if request is fully handled, false if it should be passed on to
+ //! subsequent handlers.
+ using Actor = std::function<bool(const JSONRPCRequest& request, UniValue& result, bool last_handler)>;
+
+ //! Constructor taking Actor callback supporting multiple handlers.
+ CRPCCommand(std::string category, std::string name, Actor actor, std::vector<std::string> args, intptr_t unique_id)
+ : category(std::move(category)), name(std::move(name)), actor(std::move(actor)), argNames(std::move(args)),
+ unique_id(unique_id)
+ {
+ }
+
+ //! Simplified constructor taking plain rpcfn_type function pointer.
+ CRPCCommand(const char* category, const char* name, rpcfn_type fn, std::initializer_list<const char*> args)
+ : CRPCCommand(category, name,
+ [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn(request); return true; },
+ {args.begin(), args.end()}, intptr_t(fn))
+ {
+ }
+
std::string category;
std::string name;
- rpcfn_type actor;
+ Actor actor;
std::vector<std::string> argNames;
+ intptr_t unique_id;
};
/**
@@ -143,10 +135,9 @@ public:
class CRPCTable
{
private:
- std::map<std::string, const CRPCCommand*> mapCommands;
+ std::map<std::string, std::vector<const CRPCCommand*>> mapCommands;
public:
CRPCTable();
- const CRPCCommand* operator[](const std::string& name) const;
std::string help(const std::string& name, const JSONRPCRequest& helpreq) const;
/**
@@ -169,9 +160,7 @@ public:
*
* Returns false if RPC server is already running (dump concurrency protection).
*
- * Commands cannot be overwritten (returns false).
- *
- * Commands with different method names but the same callback function will
+ * Commands with different method names but the same unique_id will
* be considered aliases, and only the first registered method name will
* show up in the help text command listing. Aliased commands do not have
* to have the same behavior. Server and client code can distinguish
@@ -179,25 +168,13 @@ public:
* register different names, types, and numbers of parameters.
*/
bool appendCommand(const std::string& name, const CRPCCommand* pcmd);
+ bool removeCommand(const std::string& name, const CRPCCommand* pcmd);
};
bool IsDeprecatedRPCEnabled(const std::string& method);
extern CRPCTable tableRPC;
-/**
- * Utilities: convert hex-encoded Values
- * (throws error if not hex).
- */
-extern uint256 ParseHashV(const UniValue& v, std::string strName);
-extern uint256 ParseHashO(const UniValue& o, std::string strKey);
-extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
-extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
-
-extern CAmount AmountFromValue(const UniValue& value);
-extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
-extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
-
void StartRPC();
void InterruptRPC();
void StopRPC();
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index e72b1c4840..9cdb22001f 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -1,13 +1,120 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <key_io.h>
#include <keystore.h>
-#include <rpc/protocol.h>
#include <rpc/util.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
+
+#include <tuple>
+
+InitInterfaces* g_rpc_interfaces = nullptr;
+
+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("Expected type %s, got %s", uvTypeName(typeExpected.type), uvTypeName(value.type())));
+ }
+}
+
+void RPCTypeCheckObj(const UniValue& o,
+ const std::map<std::string, UniValueType>& typesExpected,
+ bool fAllowNull,
+ bool fStrict)
+{
+ for (const auto& t : typesExpected) {
+ const UniValue& v = find_value(o, t.first);
+ if (!fAllowNull && v.isNull())
+ throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
+
+ if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) {
+ std::string err = strprintf("Expected type %s for %s, got %s",
+ uvTypeName(t.second.type), t.first, uvTypeName(v.type()));
+ throw JSONRPCError(RPC_TYPE_ERROR, err);
+ }
+ }
+
+ if (fStrict)
+ {
+ for (const std::string& k : o.getKeys())
+ {
+ if (typesExpected.count(k) == 0)
+ {
+ std::string err = strprintf("Unexpected key %s", k);
+ throw JSONRPCError(RPC_TYPE_ERROR, err);
+ }
+ }
+ }
+}
+
+CAmount AmountFromValue(const UniValue& value)
+{
+ if (!value.isNum() && !value.isStr())
+ throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
+ CAmount amount;
+ if (!ParseFixedPoint(value.getValStr(), 8, &amount))
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
+ if (!MoneyRange(amount))
+ throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
+ return amount;
+}
+
+uint256 ParseHashV(const UniValue& v, std::string strName)
+{
+ std::string strHex(v.get_str());
+ if (64 != strHex.length())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d, for '%s')", strName, 64, strHex.length(), strHex));
+ if (!IsHex(strHex)) // Note: IsHex("") is false
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
+ return uint256S(strHex);
+}
+uint256 ParseHashO(const UniValue& o, std::string strKey)
+{
+ return ParseHashV(find_value(o, strKey), strKey);
+}
+std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
+{
+ std::string strHex;
+ if (v.isStr())
+ strHex = v.get_str();
+ if (!IsHex(strHex))
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
+ return ParseHex(strHex);
+}
+std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
+{
+ return ParseHexV(find_value(o, strKey), strKey);
+}
+
+std::string HelpExampleCli(const std::string& methodname, const std::string& args)
+{
+ return "> bitcoin-cli " + methodname + " " + args + "\n";
+}
+
+std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
+{
+ return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
+ "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
+}
// Converts a hex string to a public key if possible
CPubKey HexToPubKey(const std::string& hex_in)
@@ -76,7 +183,7 @@ public:
return UniValue(UniValue::VOBJ);
}
- UniValue operator()(const CKeyID& keyID) const
+ UniValue operator()(const PKHash& keyID) const
{
UniValue obj(UniValue::VOBJ);
obj.pushKV("isscript", false);
@@ -84,7 +191,7 @@ public:
return obj;
}
- UniValue operator()(const CScriptID& scriptID) const
+ UniValue operator()(const ScriptHash& scriptID) const
{
UniValue obj(UniValue::VOBJ);
obj.pushKV("isscript", true);
@@ -126,3 +233,455 @@ UniValue DescribeAddress(const CTxDestination& dest)
{
return boost::apply_visitor(DescribeAddressVisitor(), dest);
}
+
+unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target)
+{
+ int target = value.get_int();
+ if (target < 1 || (unsigned int)target > max_target) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid conf_target, must be between %u - %u", 1, max_target));
+ }
+ return (unsigned int)target;
+}
+
+RPCErrorCode RPCErrorFromTransactionError(TransactionError terr)
+{
+ switch (terr) {
+ case TransactionError::MEMPOOL_REJECTED:
+ return RPC_TRANSACTION_REJECTED;
+ case TransactionError::ALREADY_IN_CHAIN:
+ return RPC_TRANSACTION_ALREADY_IN_CHAIN;
+ case TransactionError::P2P_DISABLED:
+ return RPC_CLIENT_P2P_DISABLED;
+ case TransactionError::INVALID_PSBT:
+ case TransactionError::PSBT_MISMATCH:
+ return RPC_INVALID_PARAMETER;
+ case TransactionError::SIGHASH_MISMATCH:
+ return RPC_DESERIALIZATION_ERROR;
+ default: break;
+ }
+ return RPC_TRANSACTION_ERROR;
+}
+
+UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_string)
+{
+ if (err_string.length() > 0) {
+ return JSONRPCError(RPCErrorFromTransactionError(terr), err_string);
+ } else {
+ return JSONRPCError(RPCErrorFromTransactionError(terr), TransactionErrorString(terr));
+ }
+}
+
+/**
+ * A pair of strings that can be aligned (through padding) with other Sections
+ * later on
+ */
+struct Section {
+ Section(const std::string& left, const std::string& right)
+ : m_left{left}, m_right{right} {}
+ const std::string m_left;
+ const std::string m_right;
+};
+
+/**
+ * Keeps track of RPCArgs by transforming them into sections for the purpose
+ * of serializing everything to a single string
+ */
+struct Sections {
+ std::vector<Section> m_sections;
+ size_t m_max_pad{0};
+
+ void PushSection(const Section& s)
+ {
+ m_max_pad = std::max(m_max_pad, s.m_left.size());
+ m_sections.push_back(s);
+ }
+
+ /**
+ * Serializing RPCArgs depends on the outer type. Only arrays and
+ * dictionaries can be nested in json. The top-level outer type is "named
+ * arguments", a mix between a dictionary and arrays.
+ */
+ enum class OuterType {
+ ARR,
+ OBJ,
+ NAMED_ARG, // Only set on first recursion
+ };
+
+ /**
+ * Recursive helper to translate an RPCArg into sections
+ */
+ void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NAMED_ARG)
+ {
+ 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
+
+ switch (arg.m_type) {
+ case RPCArg::Type::STR_HEX:
+ case RPCArg::Type::STR:
+ case RPCArg::Type::NUM:
+ case RPCArg::Type::AMOUNT:
+ case RPCArg::Type::RANGE:
+ case RPCArg::Type::BOOL: {
+ if (outer_type == OuterType::NAMED_ARG) return; // Nothing more to do for non-recursive types on first recursion
+ auto left = indent;
+ if (arg.m_type_str.size() != 0 && push_name) {
+ left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0);
+ } else {
+ left += push_name ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false);
+ }
+ left += ",";
+ PushSection({left, arg.ToDescriptionString()});
+ break;
+ }
+ case RPCArg::Type::OBJ:
+ case RPCArg::Type::OBJ_USER_KEYS: {
+ const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString();
+ PushSection({indent + (push_name ? "\"" + arg.m_name + "\": " : "") + "{", right});
+ for (const auto& arg_inner : arg.m_inner) {
+ Push(arg_inner, current_indent + 2, OuterType::OBJ);
+ }
+ if (arg.m_type != RPCArg::Type::OBJ) {
+ PushSection({indent_next + "...", ""});
+ }
+ PushSection({indent + "}" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""});
+ break;
+ }
+ case RPCArg::Type::ARR: {
+ auto left = indent;
+ left += push_name ? "\"" + arg.m_name + "\": " : "";
+ left += "[";
+ const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString();
+ 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::NAMED_ARG ? "," : ""), ""});
+ break;
+ }
+
+ // no default case, so the compiler can warn about missing cases
+ }
+ }
+
+ /**
+ * Concatenate all sections with proper padding
+ */
+ std::string ToString() const
+ {
+ std::string ret;
+ const size_t pad = m_max_pad + 4;
+ for (const auto& s : m_sections) {
+ if (s.m_right.empty()) {
+ ret += s.m_left;
+ ret += "\n";
+ continue;
+ }
+
+ std::string left = s.m_left;
+ left.resize(pad, ' ');
+ ret += left;
+
+ // Properly pad after newlines
+ std::string right;
+ size_t begin = 0;
+ size_t new_line_pos = s.m_right.find_first_of('\n');
+ while (true) {
+ right += s.m_right.substr(begin, new_line_pos - begin);
+ if (new_line_pos == std::string::npos) {
+ break; //No new line
+ }
+ right += "\n" + std::string(pad, ' ');
+ begin = s.m_right.find_first_not_of(' ', new_line_pos + 1);
+ if (begin == std::string::npos) {
+ break; // Empty line
+ }
+ new_line_pos = s.m_right.find_first_of('\n', begin + 1);
+ }
+ ret += right;
+ ret += "\n";
+ }
+ return ret;
+ }
+};
+
+RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples)
+ : m_name{std::move(name)},
+ m_description{std::move(description)},
+ m_args{std::move(args)},
+ m_results{std::move(results)},
+ m_examples{std::move(examples)}
+{
+ std::set<std::string> named_args;
+ for (const auto& arg : m_args) {
+ // Should have unique named arguments
+ assert(named_args.insert(arg.m_name).second);
+ }
+}
+
+std::string RPCResults::ToDescriptionString() const
+{
+ std::string result;
+ for (const auto& r : m_results) {
+ if (r.m_cond.empty()) {
+ result += "\nResult:\n";
+ } else {
+ result += "\nResult (" + r.m_cond + "):\n";
+ }
+ result += r.m_result;
+ }
+ return result;
+}
+
+std::string RPCExamples::ToDescriptionString() const
+{
+ return m_examples.empty() ? m_examples : "\nExamples:\n" + m_examples;
+}
+
+bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
+{
+ size_t num_required_args = 0;
+ for (size_t n = m_args.size(); n > 0; --n) {
+ if (!m_args.at(n - 1).IsOptional()) {
+ num_required_args = n;
+ break;
+ }
+ }
+ return num_required_args <= num_args && num_args <= m_args.size();
+}
+std::string RPCHelpMan::ToString() const
+{
+ std::string ret;
+
+ // Oneline summary
+ ret += m_name;
+ bool was_optional{false};
+ for (const auto& arg : m_args) {
+ const bool optional = arg.IsOptional();
+ ret += " ";
+ if (optional) {
+ if (!was_optional) ret += "( ";
+ was_optional = true;
+ } else {
+ if (was_optional) ret += ") ";
+ was_optional = false;
+ }
+ ret += arg.ToString(/* oneline */ true);
+ }
+ if (was_optional) ret += " )";
+ ret += "\n";
+
+ // Description
+ ret += m_description;
+
+ // Arguments
+ Sections sections;
+ for (size_t i{0}; i < m_args.size(); ++i) {
+ const auto& arg = m_args.at(i);
+
+ if (i == 0) ret += "\nArguments:\n";
+
+ // Push named argument name and description
+ sections.m_sections.emplace_back(std::to_string(i + 1) + ". " + arg.m_name, arg.ToDescriptionString());
+ sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size());
+
+ // Recursively push nested args
+ sections.Push(arg);
+ }
+ ret += sections.ToString();
+
+ // Result
+ ret += m_results.ToDescriptionString();
+
+ // Examples
+ ret += m_examples.ToDescriptionString();
+
+ return ret;
+}
+
+bool RPCArg::IsOptional() const
+{
+ if (m_fallback.which() == 1) {
+ return true;
+ } else {
+ return RPCArg::Optional::NO != boost::get<RPCArg::Optional>(m_fallback);
+ }
+}
+
+std::string RPCArg::ToDescriptionString() const
+{
+ std::string ret;
+ ret += "(";
+ if (m_type_str.size() != 0) {
+ ret += m_type_str.at(1);
+ } else {
+ switch (m_type) {
+ case Type::STR_HEX:
+ case Type::STR: {
+ ret += "string";
+ break;
+ }
+ case Type::NUM: {
+ ret += "numeric";
+ break;
+ }
+ case Type::AMOUNT: {
+ ret += "numeric or string";
+ break;
+ }
+ case Type::RANGE: {
+ ret += "numeric or array";
+ break;
+ }
+ case Type::BOOL: {
+ ret += "boolean";
+ break;
+ }
+ case Type::OBJ:
+ case Type::OBJ_USER_KEYS: {
+ ret += "json object";
+ break;
+ }
+ case Type::ARR: {
+ ret += "json array";
+ break;
+ }
+
+ // no default case, so the compiler can warn about missing cases
+ }
+ }
+ if (m_fallback.which() == 1) {
+ ret += ", optional, default=" + boost::get<std::string>(m_fallback);
+ } else {
+ switch (boost::get<RPCArg::Optional>(m_fallback)) {
+ case RPCArg::Optional::OMITTED: {
+ // nothing to do. Element is treated as if not present and has no default value
+ break;
+ }
+ case RPCArg::Optional::OMITTED_NAMED_ARG: {
+ ret += ", optional"; // Default value is "null"
+ break;
+ }
+ case RPCArg::Optional::NO: {
+ ret += ", required";
+ break;
+ }
+
+ // no default case, so the compiler can warn about missing cases
+ }
+ }
+ ret += ")";
+ ret += m_description.empty() ? "" : " " + m_description;
+ return ret;
+}
+
+std::string RPCArg::ToStringObj(const bool oneline) const
+{
+ std::string res;
+ res += "\"";
+ res += m_name;
+ if (oneline) {
+ res += "\":";
+ } else {
+ res += "\": ";
+ }
+ switch (m_type) {
+ case Type::STR:
+ return res + "\"str\"";
+ case Type::STR_HEX:
+ return res + "\"hex\"";
+ case Type::NUM:
+ return res + "n";
+ case Type::RANGE:
+ return res + "n or [n,n]";
+ case Type::AMOUNT:
+ return res + "amount";
+ case Type::BOOL:
+ return res + "bool";
+ case Type::ARR:
+ res += "[";
+ for (const auto& i : m_inner) {
+ res += i.ToString(oneline) + ",";
+ }
+ return res + "...]";
+ case Type::OBJ:
+ case Type::OBJ_USER_KEYS:
+ // Currently unused, so avoid writing dead code
+ assert(false);
+
+ // no default case, so the compiler can warn about missing cases
+ }
+ assert(false);
+}
+
+std::string RPCArg::ToString(const bool oneline) const
+{
+ if (oneline && !m_oneline_description.empty()) return m_oneline_description;
+
+ switch (m_type) {
+ case Type::STR_HEX:
+ case Type::STR: {
+ return "\"" + m_name + "\"";
+ }
+ case Type::NUM:
+ case Type::RANGE:
+ case Type::AMOUNT:
+ case Type::BOOL: {
+ return m_name;
+ }
+ case Type::OBJ:
+ case Type::OBJ_USER_KEYS: {
+ std::string res;
+ for (size_t i = 0; i < m_inner.size();) {
+ res += m_inner[i].ToStringObj(oneline);
+ if (++i < m_inner.size()) res += ",";
+ }
+ if (m_type == Type::OBJ) {
+ return "{" + res + "}";
+ } else {
+ return "{" + res + ",...}";
+ }
+ }
+ case Type::ARR: {
+ std::string res;
+ for (const auto& i : m_inner) {
+ res += i.ToString(oneline) + ",";
+ }
+ return "[" + res + "...]";
+ }
+
+ // no default case, so the compiler can warn about missing cases
+ }
+ assert(false);
+}
+
+static std::pair<int64_t, int64_t> ParseRange(const UniValue& value)
+{
+ if (value.isNum()) {
+ return {0, value.get_int64()};
+ }
+ if (value.isArray() && value.size() == 2 && value[0].isNum() && value[1].isNum()) {
+ int64_t low = value[0].get_int64();
+ int64_t high = value[1].get_int64();
+ if (low > high) throw JSONRPCError(RPC_INVALID_PARAMETER, "Range specified as [begin,end] must not have begin after end");
+ return {low, high};
+ }
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Range must be specified as end or as [begin,end]");
+}
+
+std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue& value)
+{
+ int64_t low, high;
+ std::tie(low, high) = ParseRange(value);
+ if (low < 0) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should be greater or equal than 0");
+ }
+ if ((high >> 31) != 0) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "End of range is too high");
+ }
+ if (high >= low + 1000000) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Range is too large");
+ }
+ return {low, high};
+}
diff --git a/src/rpc/util.h b/src/rpc/util.h
index c6a79d5cf9..e4fa8fc3d7 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -1,22 +1,72 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_RPC_UTIL_H
#define BITCOIN_RPC_UTIL_H
+#include <node/transaction.h>
#include <pubkey.h>
+#include <rpc/protocol.h>
#include <script/standard.h>
#include <univalue.h>
-#include <boost/variant/static_visitor.hpp>
-
#include <string>
#include <vector>
+#include <boost/variant.hpp>
+
class CKeyStore;
class CPubKey;
class CScript;
+struct InitInterfaces;
+
+//! Pointers to interfaces that need to be accessible from RPC methods. Due to
+//! limitations of the RPC framework, there's currently no direct way to pass in
+//! state to RPC method implementations.
+extern InitInterfaces* g_rpc_interfaces;
+
+/** Wrapper for UniValue::VType, which includes typeAny:
+ * Used to denote don't care type. */
+struct UniValueType {
+ UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {}
+ UniValueType() : typeAny(true) {}
+ bool typeAny;
+ 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.
+*/
+void RPCTypeCheckObj(const UniValue& o,
+ const std::map<std::string, UniValueType>& typesExpected,
+ bool fAllowNull = false,
+ bool fStrict = false);
+
+/**
+ * Utilities: convert hex-encoded Values
+ * (throws error if not hex).
+ */
+extern uint256 ParseHashV(const UniValue& v, std::string strName);
+extern uint256 ParseHashO(const UniValue& o, std::string strKey);
+extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
+extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
+
+extern CAmount AmountFromValue(const UniValue& value);
+extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
+extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
CPubKey HexToPubKey(const std::string& hex_in);
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
@@ -24,4 +74,175 @@ CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey
UniValue DescribeAddress(const CTxDestination& dest);
+//! Parse a confirm target option and raise an RPC error if it is invalid.
+unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target);
+
+RPCErrorCode RPCErrorFromTransactionError(TransactionError terr);
+UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_string = "");
+
+//! Parse a JSON range specified as int64, or [int64, int64]
+std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue& value);
+
+struct RPCArg {
+ enum class Type {
+ OBJ,
+ ARR,
+ STR,
+ NUM,
+ BOOL,
+ OBJ_USER_KEYS, //!< Special type where the user must set the keys e.g. to define multiple addresses; as opposed to e.g. an options object where the keys are predefined
+ AMOUNT, //!< Special type representing a floating point amount (can be either NUM or STR)
+ STR_HEX, //!< Special type that is a STR with only hex chars
+ RANGE, //!< Special type that is a NUM or [NUM,NUM]
+ };
+
+ enum class Optional {
+ /** 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.
+ * When possible, the default value should be specified.
+ */
+ OMITTED,
+ };
+ using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>;
+ const std::string m_name; //!< The name of the arg (can be empty for inner args)
+ const Type m_type;
+ const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
+ const Fallback m_fallback;
+ const std::string m_description;
+ const std::string m_oneline_description; //!< Should be empty unless it is supposed to override the auto-generated summary line
+ const std::vector<std::string> m_type_str; //!< Should be empty unless it is supposed to override the auto-generated type strings. Vector length is either 0 or 2, m_type_str.at(0) will override the type of the value in a key-value pair, m_type_str.at(1) will override the type in the argument description.
+
+ RPCArg(
+ const std::string& name,
+ const Type& type,
+ const Fallback& fallback,
+ const std::string& description,
+ const std::string& oneline_description = "",
+ const std::vector<std::string>& type_str = {})
+ : m_name{name},
+ m_type{type},
+ m_fallback{fallback},
+ m_description{description},
+ m_oneline_description{oneline_description},
+ m_type_str{type_str}
+ {
+ assert(type != Type::ARR && type != Type::OBJ);
+ }
+
+ RPCArg(
+ const std::string& name,
+ const Type& type,
+ const Fallback& fallback,
+ const std::string& description,
+ const std::vector<RPCArg>& inner,
+ const std::string& oneline_description = "",
+ const std::vector<std::string>& type_str = {})
+ : m_name{name},
+ m_type{type},
+ m_inner{inner},
+ m_fallback{fallback},
+ m_description{description},
+ m_oneline_description{oneline_description},
+ m_type_str{type_str}
+ {
+ assert(type == Type::ARR || type == Type::OBJ);
+ }
+
+ bool IsOptional() const;
+
+ /**
+ * Return the type string of the argument.
+ * Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description).
+ */
+ std::string ToString(bool oneline) const;
+ /**
+ * Return the type string of the argument when it is in an object (dict).
+ * Set oneline to get the oneline representation (less whitespace)
+ */
+ std::string ToStringObj(bool oneline) const;
+ /**
+ * Return the description string, including the argument type and whether
+ * the argument is required.
+ */
+ std::string ToDescriptionString() const;
+};
+
+struct RPCResult {
+ const std::string m_cond;
+ const std::string m_result;
+
+ explicit RPCResult(std::string result)
+ : m_cond{}, m_result{std::move(result)}
+ {
+ assert(!m_result.empty());
+ }
+
+ RPCResult(std::string cond, std::string result)
+ : m_cond{std::move(cond)}, m_result{std::move(result)}
+ {
+ assert(!m_cond.empty());
+ assert(!m_result.empty());
+ }
+};
+
+struct RPCResults {
+ const std::vector<RPCResult> m_results;
+
+ RPCResults()
+ : m_results{}
+ {
+ }
+
+ RPCResults(RPCResult result)
+ : m_results{{result}}
+ {
+ }
+
+ RPCResults(std::initializer_list<RPCResult> results)
+ : m_results{results}
+ {
+ }
+
+ /**
+ * Return the description string.
+ */
+ std::string ToDescriptionString() const;
+};
+
+struct RPCExamples {
+ const std::string m_examples;
+ RPCExamples(
+ std::string examples)
+ : m_examples(std::move(examples))
+ {
+ }
+ std::string ToDescriptionString() const;
+};
+
+class RPCHelpMan
+{
+public:
+ RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples);
+
+ std::string ToString() const;
+ /** If the supplied number of args is neither too small nor too high */
+ bool IsValidNumArgs(size_t num_args) const;
+
+private:
+ const std::string m_name;
+ const std::string m_description;
+ const std::vector<RPCArg> m_args;
+ const RPCResults m_results;
+ const RPCExamples m_examples;
+};
+
#endif // BITCOIN_RPC_UTIL_H
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
index a94f6b2a66..fdc859b3a0 100644
--- a/src/scheduler.cpp
+++ b/src/scheduler.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,6 @@
#include <reverselock.h>
#include <assert.h>
-#include <boost/bind.hpp>
#include <utility>
CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false)
@@ -42,7 +41,7 @@ void CScheduler::serviceQueue()
try {
if (!shouldStop() && taskQueue.empty()) {
reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
- // Use this chance to get a tiny bit more entropy
+ // Use this chance to get more entropy
RandAddSeedSleep();
}
while (!shouldStop() && taskQueue.empty()) {
@@ -120,12 +119,12 @@ void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaMilliSecon
static void Repeat(CScheduler* s, CScheduler::Function f, int64_t deltaMilliSeconds)
{
f();
- s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaMilliSeconds), deltaMilliSeconds);
+ s->scheduleFromNow(std::bind(&Repeat, s, f, deltaMilliSeconds), deltaMilliSeconds);
}
void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaMilliSeconds)
{
- scheduleFromNow(boost::bind(&Repeat, this, f, deltaMilliSeconds), deltaMilliSeconds);
+ scheduleFromNow(std::bind(&Repeat, this, f, deltaMilliSeconds), deltaMilliSeconds);
}
size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first,
@@ -159,7 +158,7 @@ void SingleThreadedSchedulerClient::MaybeScheduleProcessQueue() {
}
void SingleThreadedSchedulerClient::ProcessQueue() {
- std::function<void (void)> callback;
+ std::function<void ()> callback;
{
LOCK(m_cs_callbacks_pending);
if (m_are_callbacks_running) return;
@@ -187,7 +186,7 @@ void SingleThreadedSchedulerClient::ProcessQueue() {
callback();
}
-void SingleThreadedSchedulerClient::AddToProcessQueue(std::function<void (void)> func) {
+void SingleThreadedSchedulerClient::AddToProcessQueue(std::function<void ()> func) {
assert(m_pscheduler);
{
diff --git a/src/scheduler.h b/src/scheduler.h
index 421002ec17..436f661c59 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -25,7 +25,7 @@
// CScheduler* s = new CScheduler();
// s->scheduleFromNow(doSomething, 11); // Assuming a: void doSomething() { }
// s->scheduleFromNow(std::bind(Class::func, this, argument), 3);
-// boost::thread* t = new boost::thread(boost::bind(CScheduler::serviceQueue, s));
+// boost::thread* t = new boost::thread(std::bind(CScheduler::serviceQueue, s));
//
// ... then at program shutdown, clean up the thread running serviceQueue:
// t->interrupt();
@@ -40,18 +40,18 @@ public:
CScheduler();
~CScheduler();
- typedef std::function<void(void)> Function;
+ typedef std::function<void()> Function;
// Call func at/after time t
void schedule(Function f, boost::chrono::system_clock::time_point t=boost::chrono::system_clock::now());
- // Convenience method: call f once deltaSeconds from now
+ // Convenience method: call f once deltaMilliSeconds from now
void scheduleFromNow(Function f, int64_t deltaMilliSeconds);
// Another convenience method: call f approximately
- // every deltaSeconds forever, starting deltaSeconds from now.
+ // every deltaMilliSeconds forever, starting deltaMilliSeconds from now.
// To be more precise: every time f is finished, it
- // is rescheduled to run deltaSeconds later. If you
+ // is rescheduled to run deltaMilliSeconds later. If you
// need more accurate scheduling, don't use this method.
void scheduleEvery(Function f, int64_t deltaMilliSeconds);
@@ -99,7 +99,7 @@ private:
CScheduler *m_pscheduler;
CCriticalSection m_cs_callbacks_pending;
- std::list<std::function<void (void)>> m_callbacks_pending GUARDED_BY(m_cs_callbacks_pending);
+ std::list<std::function<void ()>> m_callbacks_pending GUARDED_BY(m_cs_callbacks_pending);
bool m_are_callbacks_running GUARDED_BY(m_cs_callbacks_pending) = false;
void MaybeScheduleProcessQueue();
@@ -110,11 +110,11 @@ public:
/**
* Add a callback to be executed. Callbacks are executed serially
- * and memory is sequentially consistent between callback executions.
- * Practially, this means that callbacks can behave as if they are executed
+ * and memory is release-acquire consistent between callback executions.
+ * Practically, this means that callbacks can behave as if they are executed
* in order by a single thread.
*/
- void AddToProcessQueue(std::function<void (void)> func);
+ void AddToProcessQueue(std::function<void ()> func);
// Processes all remaining queue members on the calling thread, blocking until queue is empty
// Must be called after the CScheduler has no remaining processing threads!
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index e2370c5e50..15e204062f 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -88,7 +88,7 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
CTransaction tx(deserialize, stream);
if (nIn >= tx.vin.size())
return set_error(err, bitcoinconsensus_ERR_TX_INDEX);
- if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen)
+ if (GetSerializeSize(tx, PROTOCOL_VERSION) != txToLen)
return set_error(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH);
// Regardless of the verification result, the tx did not error.
diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index 5973808fa5..c5dceac848 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index f366b99ec3..9be87fabb0 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -10,8 +10,9 @@
#include <script/standard.h>
#include <span.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/bip32.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <memory>
#include <string>
@@ -20,28 +21,137 @@
namespace {
////////////////////////////////////////////////////////////////////////////
-// Internal representation //
+// Checksum //
////////////////////////////////////////////////////////////////////////////
-typedef std::vector<uint32_t> KeyPath;
+// This section implements a checksum algorithm for descriptors with the
+// following properties:
+// * Mistakes in a descriptor string are measured in "symbol errors". The higher
+// the number of symbol errors, the harder it is to detect:
+// * An error substituting a character from 0123456789()[],'/*abcdefgh@:$%{} for
+// another in that set always counts as 1 symbol error.
+// * Note that hex encoded keys are covered by these characters. Xprvs and
+// xpubs use other characters too, but already have their own checksum
+// mechanism.
+// * Function names like "multi()" use other characters, but mistakes in
+// these would generally result in an unparseable descriptor.
+// * A case error always counts as 1 symbol error.
+// * Any other 1 character substitution error counts as 1 or 2 symbol errors.
+// * Any 1 symbol error is always detected.
+// * Any 2 or 3 symbol error in a descriptor of up to 49154 characters is always detected.
+// * Any 4 symbol error in a descriptor of up to 507 characters is always detected.
+// * Any 5 symbol error in a descriptor of up to 77 characters is always detected.
+// * Is optimized to minimize the chance a 5 symbol error in a descriptor up to 387 characters is undetected
+// * Random errors have a chance of 1 in 2**40 of being undetected.
+//
+// These properties are achieved by expanding every group of 3 (non checksum) characters into
+// 4 GF(32) symbols, over which a cyclic code is defined.
+
+/*
+ * Interprets c as 8 groups of 5 bits which are the coefficients of a degree 8 polynomial over GF(32),
+ * multiplies that polynomial by x, computes its remainder modulo a generator, and adds the constant term val.
+ *
+ * This generator is G(x) = x^8 + {30}x^7 + {23}x^6 + {15}x^5 + {14}x^4 + {10}x^3 + {6}x^2 + {12}x + {9}.
+ * It is chosen to define an cyclic error detecting code which is selected by:
+ * - Starting from all BCH codes over GF(32) of degree 8 and below, which by construction guarantee detecting
+ * 3 errors in windows up to 19000 symbols.
+ * - Taking all those generators, and for degree 7 ones, extend them to degree 8 by adding all degree-1 factors.
+ * - Selecting just the set of generators that guarantee detecting 4 errors in a window of length 512.
+ * - Selecting one of those with best worst-case behavior for 5 errors in windows of length up to 512.
+ *
+ * The generator and the constants to implement it can be verified using this Sage code:
+ * B = GF(2) # Binary field
+ * BP.<b> = B[] # Polynomials over the binary field
+ * F_mod = b**5 + b**3 + 1
+ * F.<f> = GF(32, modulus=F_mod, repr='int') # GF(32) definition
+ * FP.<x> = F[] # Polynomials over GF(32)
+ * E_mod = x**3 + x + F.fetch_int(8)
+ * E.<e> = F.extension(E_mod) # Extension field definition
+ * alpha = e**2743 # Choice of an element in extension field
+ * for p in divisors(E.order() - 1): # Verify alpha has order 32767.
+ * assert((alpha**p == 1) == (p % 32767 == 0))
+ * G = lcm([(alpha**i).minpoly() for i in [1056,1057,1058]] + [x + 1])
+ * print(G) # Print out the generator
+ * for i in [1,2,4,8,16]: # Print out {1,2,4,8,16}*(G mod x^8), packed in hex integers.
+ * v = 0
+ * for coef in reversed((F.fetch_int(i)*(G % x**8)).coefficients(sparse=True)):
+ * v = v*32 + coef.integer_representation()
+ * print("0x%x" % v)
+ */
+uint64_t PolyMod(uint64_t c, int val)
+{
+ uint8_t c0 = c >> 35;
+ c = ((c & 0x7ffffffff) << 5) ^ val;
+ if (c0 & 1) c ^= 0xf5dee51989;
+ if (c0 & 2) c ^= 0xa9fdca3312;
+ if (c0 & 4) c ^= 0x1bab10e32d;
+ if (c0 & 8) c ^= 0x3706b1677a;
+ if (c0 & 16) c ^= 0x644d626ffd;
+ return c;
+}
-std::string FormatKeyPath(const KeyPath& path)
+std::string DescriptorChecksum(const Span<const char>& span)
{
- std::string ret;
- for (auto i : path) {
- ret += strprintf("/%i", (i << 1) >> 1);
- if (i >> 31) ret += '\'';
+ /** A character set designed such that:
+ * - The most common 'unprotected' descriptor characters (hex, keypaths) are in the first group of 32.
+ * - Case errors cause an offset that's a multiple of 32.
+ * - As many alphabetic characters are in the same group (while following the above restrictions).
+ *
+ * If p(x) gives the position of a character c in this character set, every group of 3 characters
+ * (a,b,c) is encoded as the 4 symbols (p(a) & 31, p(b) & 31, p(c) & 31, (p(a) / 32) + 3 * (p(b) / 32) + 9 * (p(c) / 32).
+ * This means that changes that only affect the lower 5 bits of the position, or only the higher 2 bits, will just
+ * affect a single symbol.
+ *
+ * As a result, within-group-of-32 errors count as 1 symbol, as do cross-group errors that don't affect
+ * the position within the groups.
+ */
+ static std::string INPUT_CHARSET =
+ "0123456789()[],'/*abcdefgh@:$%{}"
+ "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
+ "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
+
+ /** The character set for the checksum itself (same as bech32). */
+ static std::string CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
+
+ uint64_t c = 1;
+ int cls = 0;
+ int clscount = 0;
+ for (auto ch : span) {
+ auto pos = INPUT_CHARSET.find(ch);
+ if (pos == std::string::npos) return "";
+ c = PolyMod(c, pos & 31); // Emit a symbol for the position inside the group, for every character.
+ cls = cls * 3 + (pos >> 5); // Accumulate the group numbers
+ if (++clscount == 3) {
+ // Emit an extra symbol representing the group numbers, for every 3 characters.
+ c = PolyMod(c, cls);
+ cls = 0;
+ clscount = 0;
+ }
}
+ if (clscount > 0) c = PolyMod(c, cls);
+ for (int j = 0; j < 8; ++j) c = PolyMod(c, 0); // Shift further to determine the checksum.
+ c ^= 1; // Prevent appending zeroes from not affecting the checksum.
+
+ std::string ret(8, ' ');
+ for (int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
return ret;
}
+std::string AddChecksum(const std::string& str) { return str + "#" + DescriptorChecksum(MakeSpan(str)); }
+
+////////////////////////////////////////////////////////////////////////////
+// Internal representation //
+////////////////////////////////////////////////////////////////////////////
+
+typedef std::vector<uint32_t> KeyPath;
+
/** Interface for public key objects in descriptors. */
struct PubkeyProvider
{
virtual ~PubkeyProvider() = default;
- /** Derive a public key. */
- virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const = 0;
+ /** Derive a public key. If key==nullptr, only info is desired. */
+ virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const = 0;
/** Whether this represent multiple public keys at different positions. */
virtual bool IsRange() const = 0;
@@ -56,6 +166,37 @@ struct PubkeyProvider
virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
};
+class OriginPubkeyProvider final : public PubkeyProvider
+{
+ KeyOriginInfo m_origin;
+ std::unique_ptr<PubkeyProvider> m_provider;
+
+ std::string OriginString() const
+ {
+ return HexStr(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint)) + FormatHDKeypath(m_origin.path);
+ }
+
+public:
+ OriginPubkeyProvider(KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : m_origin(std::move(info)), m_provider(std::move(provider)) {}
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
+ {
+ if (!m_provider->GetPubKey(pos, arg, key, info)) return false;
+ std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.fingerprint);
+ info.path.insert(info.path.begin(), m_origin.path.begin(), m_origin.path.end());
+ return true;
+ }
+ bool IsRange() const override { return m_provider->IsRange(); }
+ size_t GetSize() const override { return m_provider->GetSize(); }
+ std::string ToString() const override { return "[" + OriginString() + "]" + m_provider->ToString(); }
+ bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
+ {
+ std::string sub;
+ if (!m_provider->ToPrivateString(arg, sub)) return false;
+ ret = "[" + OriginString() + "]" + std::move(sub);
+ return true;
+ }
+};
+
/** An object representing a parsed constant public key in a descriptor. */
class ConstPubkeyProvider final : public PubkeyProvider
{
@@ -63,9 +204,12 @@ class ConstPubkeyProvider final : public PubkeyProvider
public:
ConstPubkeyProvider(const CPubKey& pubkey) : m_pubkey(pubkey) {}
- bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const override
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
{
- out = m_pubkey;
+ if (key) *key = m_pubkey;
+ info.path.clear();
+ CKeyID keyid = m_pubkey.GetID();
+ std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
return true;
}
bool IsRange() const override { return false; }
@@ -98,7 +242,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
CKey key;
if (!arg.GetKey(m_extkey.pubkey.GetID(), key)) return false;
ret.nDepth = m_extkey.nDepth;
- std::copy(m_extkey.vchFingerprint, m_extkey.vchFingerprint + 4, ret.vchFingerprint);
+ std::copy(m_extkey.vchFingerprint, m_extkey.vchFingerprint + sizeof(ret.vchFingerprint), ret.vchFingerprint);
ret.nChild = m_extkey.nChild;
ret.chaincode = m_extkey.chaincode;
ret.key = key;
@@ -118,32 +262,39 @@ public:
BIP32PubkeyProvider(const CExtPubKey& extkey, KeyPath path, DeriveType derive) : m_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
bool IsRange() const override { return m_derive != DeriveType::NO; }
size_t GetSize() const override { return 33; }
- bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const override
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey* key, KeyOriginInfo& info) const override
{
- if (IsHardened()) {
- CExtKey key;
- if (!GetExtKey(arg, key)) return false;
- for (auto entry : m_path) {
- key.Derive(key, entry);
- }
- if (m_derive == DeriveType::UNHARDENED) key.Derive(key, pos);
- if (m_derive == DeriveType::HARDENED) key.Derive(key, pos | 0x80000000UL);
- out = key.Neuter().pubkey;
- } else {
- // TODO: optimize by caching
- CExtPubKey key = m_extkey;
- for (auto entry : m_path) {
- key.Derive(key, entry);
+ if (key) {
+ if (IsHardened()) {
+ CExtKey extkey;
+ if (!GetExtKey(arg, extkey)) return false;
+ for (auto entry : m_path) {
+ extkey.Derive(extkey, entry);
+ }
+ if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
+ if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
+ *key = extkey.Neuter().pubkey;
+ } else {
+ // TODO: optimize by caching
+ CExtPubKey extkey = m_extkey;
+ for (auto entry : m_path) {
+ extkey.Derive(extkey, entry);
+ }
+ if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
+ assert(m_derive != DeriveType::HARDENED);
+ *key = extkey.pubkey;
}
- if (m_derive == DeriveType::UNHARDENED) key.Derive(key, pos);
- assert(m_derive != DeriveType::HARDENED);
- out = key.pubkey;
}
+ CKeyID keyid = m_extkey.pubkey.GetID();
+ std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
+ info.path = m_path;
+ if (m_derive == DeriveType::UNHARDENED) info.path.push_back((uint32_t)pos);
+ if (m_derive == DeriveType::HARDENED) info.path.push_back(((uint32_t)pos) | 0x80000000L);
return true;
}
std::string ToString() const override
{
- std::string ret = EncodeExtPubKey(m_extkey) + FormatKeyPath(m_path);
+ std::string ret = EncodeExtPubKey(m_extkey) + FormatHDKeypath(m_path);
if (IsRange()) {
ret += "/*";
if (m_derive == DeriveType::HARDENED) ret += '\'';
@@ -154,7 +305,7 @@ public:
{
CExtKey key;
if (!GetExtKey(arg, key)) return false;
- out = EncodeExtKey(key) + FormatKeyPath(m_path);
+ out = EncodeExtKey(key) + FormatHDKeypath(m_path);
if (IsRange()) {
out += "/*";
if (m_derive == DeriveType::HARDENED) out += '\'';
@@ -163,204 +314,276 @@ public:
}
};
-/** A parsed addr(A) descriptor. */
-class AddressDescriptor final : public Descriptor
+/** Base class for all Descriptor implementations. */
+class DescriptorImpl : public Descriptor
{
- CTxDestination m_destination;
+ //! Public key arguments for this descriptor (size 1 for PK, PKH, WPKH; any size of Multisig).
+ const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
+ //! The sub-descriptor argument (nullptr for everything but SH and WSH).
+ const std::unique_ptr<DescriptorImpl> m_script_arg;
+ //! The string name of the descriptor function.
+ const std::string m_name;
+
+protected:
+ //! Return a serialization of anything except pubkey and script arguments, to be prepended to those.
+ virtual std::string ToStringExtra() const { return ""; }
+
+ /** A helper function to construct the scripts for this descriptor.
+ *
+ * This function is invoked once for every CScript produced by evaluating
+ * m_script_arg, or just once in case m_script_arg is nullptr.
+
+ * @param pubkeys The evaluations of the m_pubkey_args field.
+ * @param script The evaluation of m_script_arg (or nullptr when m_script_arg is nullptr).
+ * @param out A FlatSigningProvider to put scripts or public keys in that are necessary to the solver.
+ * The script arguments to this function are automatically added, as is the origin info of the provided pubkeys.
+ * @return A vector with scriptPubKeys for this descriptor.
+ */
+ virtual std::vector<CScript> MakeScripts(const std::vector<CPubKey>& pubkeys, const CScript* script, FlatSigningProvider& out) const = 0;
public:
- AddressDescriptor(CTxDestination destination) : m_destination(std::move(destination)) {}
+ DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys, std::unique_ptr<DescriptorImpl> script, const std::string& name) : m_pubkey_args(std::move(pubkeys)), m_script_arg(std::move(script)), m_name(name) {}
- bool IsRange() const override { return false; }
- std::string ToString() const override { return "addr(" + EncodeDestination(m_destination) + ")"; }
- bool ToPrivateString(const SigningProvider& arg, std::string& out) const override { out = ToString(); return true; }
- bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ bool IsSolvable() const override
{
- output_scripts = std::vector<CScript>{GetScriptForDestination(m_destination)};
+ if (m_script_arg) {
+ if (!m_script_arg->IsSolvable()) return false;
+ }
return true;
}
-};
-
-/** A parsed raw(H) descriptor. */
-class RawDescriptor final : public Descriptor
-{
- CScript m_script;
-public:
- RawDescriptor(CScript script) : m_script(std::move(script)) {}
+ bool IsRange() const final
+ {
+ for (const auto& pubkey : m_pubkey_args) {
+ if (pubkey->IsRange()) return true;
+ }
+ if (m_script_arg) {
+ if (m_script_arg->IsRange()) return true;
+ }
+ return false;
+ }
- bool IsRange() const override { return false; }
- std::string ToString() const override { return "raw(" + HexStr(m_script.begin(), m_script.end()) + ")"; }
- bool ToPrivateString(const SigningProvider& arg, std::string& out) const override { out = ToString(); return true; }
- bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ bool ToStringHelper(const SigningProvider* arg, std::string& out, bool priv) const
{
- output_scripts = std::vector<CScript>{m_script};
+ std::string extra = ToStringExtra();
+ size_t pos = extra.size() > 0 ? 1 : 0;
+ std::string ret = m_name + "(" + extra;
+ for (const auto& pubkey : m_pubkey_args) {
+ if (pos++) ret += ",";
+ std::string tmp;
+ if (priv) {
+ if (!pubkey->ToPrivateString(*arg, tmp)) return false;
+ } else {
+ tmp = pubkey->ToString();
+ }
+ ret += std::move(tmp);
+ }
+ if (m_script_arg) {
+ if (pos++) ret += ",";
+ std::string tmp;
+ if (!m_script_arg->ToStringHelper(arg, tmp, priv)) return false;
+ ret += std::move(tmp);
+ }
+ out = std::move(ret) + ")";
return true;
}
-};
-
-/** A parsed pk(P), pkh(P), or wpkh(P) descriptor. */
-class SingleKeyDescriptor final : public Descriptor
-{
- const std::function<CScript(const CPubKey&)> m_script_fn;
- const std::string m_fn_name;
- std::unique_ptr<PubkeyProvider> m_provider;
-
-public:
- SingleKeyDescriptor(std::unique_ptr<PubkeyProvider> prov, const std::function<CScript(const CPubKey&)>& fn, const std::string& name) : m_script_fn(fn), m_fn_name(name), m_provider(std::move(prov)) {}
- bool IsRange() const override { return m_provider->IsRange(); }
- std::string ToString() const override { return m_fn_name + "(" + m_provider->ToString() + ")"; }
- bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
+ std::string ToString() const final
{
std::string ret;
- if (!m_provider->ToPrivateString(arg, ret)) return false;
- out = m_fn_name + "(" + std::move(ret) + ")";
- return true;
+ ToStringHelper(nullptr, ret, false);
+ return AddChecksum(ret);
}
- bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override final
{
- CPubKey key;
- if (!m_provider->GetPubKey(pos, arg, key)) return false;
- output_scripts = std::vector<CScript>{m_script_fn(key)};
- out.pubkeys.emplace(key.GetID(), std::move(key));
- return true;
+ bool ret = ToStringHelper(&arg, out, true);
+ out = AddChecksum(out);
+ return ret;
}
-};
-
-CScript P2PKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(pubkey.GetID()); }
-CScript P2PKGetScript(const CPubKey& pubkey) { return GetScriptForRawPubKey(pubkey); }
-CScript P2WPKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(WitnessV0KeyHash(pubkey.GetID())); }
-
-/** A parsed multi(...) descriptor. */
-class MultisigDescriptor : public Descriptor
-{
- int m_threshold;
- std::vector<std::unique_ptr<PubkeyProvider>> m_providers;
-public:
- MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers) : m_threshold(threshold), m_providers(std::move(providers)) {}
-
- bool IsRange() const override
+ bool ExpandHelper(int pos, const SigningProvider& arg, Span<const unsigned char>* cache_read, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache_write) const
{
- for (const auto& p : m_providers) {
- if (p->IsRange()) return true;
+ std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
+ entries.reserve(m_pubkey_args.size());
+
+ // Construct temporary data in `entries` and `subscripts`, to avoid producing output in case of failure.
+ for (const auto& p : m_pubkey_args) {
+ entries.emplace_back();
+ if (!p->GetPubKey(pos, arg, cache_read ? nullptr : &entries.back().first, entries.back().second)) return false;
+ if (cache_read) {
+ // Cached expanded public key exists, use it.
+ if (cache_read->size() == 0) return false;
+ bool compressed = ((*cache_read)[0] == 0x02 || (*cache_read)[0] == 0x03) && cache_read->size() >= 33;
+ bool uncompressed = ((*cache_read)[0] == 0x04) && cache_read->size() >= 65;
+ if (!(compressed || uncompressed)) return false;
+ CPubKey pubkey(cache_read->begin(), cache_read->begin() + (compressed ? 33 : 65));
+ entries.back().first = pubkey;
+ *cache_read = cache_read->subspan(compressed ? 33 : 65);
+ }
+ if (cache_write) {
+ cache_write->insert(cache_write->end(), entries.back().first.begin(), entries.back().first.end());
+ }
+ }
+ std::vector<CScript> subscripts;
+ if (m_script_arg) {
+ FlatSigningProvider subprovider;
+ if (!m_script_arg->ExpandHelper(pos, arg, cache_read, subscripts, subprovider, cache_write)) return false;
+ out = Merge(out, subprovider);
}
- return false;
- }
- std::string ToString() const override
- {
- std::string ret = strprintf("multi(%i", m_threshold);
- for (const auto& p : m_providers) {
- ret += "," + p->ToString();
+ std::vector<CPubKey> pubkeys;
+ pubkeys.reserve(entries.size());
+ for (auto& entry : entries) {
+ pubkeys.push_back(entry.first);
+ out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(CPubKey(entry.first), std::move(entry.second)));
+ }
+ if (m_script_arg) {
+ for (const auto& subscript : subscripts) {
+ out.scripts.emplace(CScriptID(subscript), subscript);
+ std::vector<CScript> addscripts = MakeScripts(pubkeys, &subscript, out);
+ for (auto& addscript : addscripts) {
+ output_scripts.push_back(std::move(addscript));
+ }
+ }
+ } else {
+ output_scripts = MakeScripts(pubkeys, nullptr, out);
}
- return std::move(ret) + ")";
+ return true;
}
- bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
+ bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache = nullptr) const final
{
- std::string ret = strprintf("multi(%i", m_threshold);
- for (const auto& p : m_providers) {
- std::string sub;
- if (!p->ToPrivateString(arg, sub)) return false;
- ret += "," + std::move(sub);
- }
- out = std::move(ret) + ")";
- return true;
+ return ExpandHelper(pos, provider, nullptr, output_scripts, out, cache);
}
- bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ bool ExpandFromCache(int pos, const std::vector<unsigned char>& cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const final
{
- std::vector<CPubKey> pubkeys;
- pubkeys.reserve(m_providers.size());
- for (const auto& p : m_providers) {
- CPubKey key;
- if (!p->GetPubKey(pos, arg, key)) return false;
- pubkeys.push_back(key);
- }
- for (const CPubKey& key : pubkeys) {
- out.pubkeys.emplace(key.GetID(), std::move(key));
- }
- output_scripts = std::vector<CScript>{GetScriptForMultisig(m_threshold, pubkeys)};
- return true;
+ Span<const unsigned char> span = MakeSpan(cache);
+ return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &span, output_scripts, out, nullptr) && span.size() == 0;
}
};
-/** A parsed sh(S) or wsh(S) descriptor. */
-class ConvertorDescriptor : public Descriptor
+/** Construct a vector with one element, which is moved into it. */
+template<typename T>
+std::vector<T> Singleton(T elem)
{
- const std::function<CScript(const CScript&)> m_convert_fn;
- const std::string m_fn_name;
- std::unique_ptr<Descriptor> m_descriptor;
+ std::vector<T> ret;
+ ret.emplace_back(std::move(elem));
+ return ret;
+}
+/** A parsed addr(A) descriptor. */
+class AddressDescriptor final : public DescriptorImpl
+{
+ const CTxDestination m_destination;
+protected:
+ std::string ToStringExtra() const override { return EncodeDestination(m_destination); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(m_destination)); }
public:
- ConvertorDescriptor(std::unique_ptr<Descriptor> descriptor, const std::function<CScript(const CScript&)>& fn, const std::string& name) : m_convert_fn(fn), m_fn_name(name), m_descriptor(std::move(descriptor)) {}
-
- bool IsRange() const override { return m_descriptor->IsRange(); }
- std::string ToString() const override { return m_fn_name + "(" + m_descriptor->ToString() + ")"; }
- bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
- {
- std::string ret;
- if (!m_descriptor->ToPrivateString(arg, ret)) return false;
- out = m_fn_name + "(" + std::move(ret) + ")";
- return true;
- }
- bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
- {
- std::vector<CScript> sub;
- if (!m_descriptor->Expand(pos, arg, sub, out)) return false;
- output_scripts.clear();
- for (const auto& script : sub) {
- CScriptID id(script);
- out.scripts.emplace(CScriptID(script), script);
- output_scripts.push_back(m_convert_fn(script));
- }
- return true;
- }
+ AddressDescriptor(CTxDestination destination) : DescriptorImpl({}, {}, "addr"), m_destination(std::move(destination)) {}
+ bool IsSolvable() const final { return false; }
};
-CScript ConvertP2SH(const CScript& script) { return GetScriptForDestination(CScriptID(script)); }
-CScript ConvertP2WSH(const CScript& script) { return GetScriptForDestination(WitnessV0ScriptHash(script)); }
+/** A parsed raw(H) descriptor. */
+class RawDescriptor final : public DescriptorImpl
+{
+ const CScript m_script;
+protected:
+ std::string ToStringExtra() const override { return HexStr(m_script.begin(), m_script.end()); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Singleton(m_script); }
+public:
+ RawDescriptor(CScript script) : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
+ bool IsSolvable() const final { return false; }
+};
-/** A parsed combo(P) descriptor. */
-class ComboDescriptor final : public Descriptor
+/** A parsed pk(P) descriptor. */
+class PKDescriptor final : public DescriptorImpl
{
- std::unique_ptr<PubkeyProvider> m_provider;
+protected:
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForRawPubKey(keys[0])); }
+public:
+ PKDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pk") {}
+};
+/** A parsed pkh(P) descriptor. */
+class PKHDescriptor final : public DescriptorImpl
+{
+protected:
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider& out) const override
+ {
+ CKeyID id = keys[0].GetID();
+ out.pubkeys.emplace(id, keys[0]);
+ return Singleton(GetScriptForDestination(PKHash(id)));
+ }
public:
- ComboDescriptor(std::unique_ptr<PubkeyProvider> provider) : m_provider(std::move(provider)) {}
+ PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "pkh") {}
+};
- bool IsRange() const override { return m_provider->IsRange(); }
- std::string ToString() const override { return "combo(" + m_provider->ToString() + ")"; }
- bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
+/** A parsed wpkh(P) descriptor. */
+class WPKHDescriptor final : public DescriptorImpl
+{
+protected:
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider& out) const override
{
- std::string ret;
- if (!m_provider->ToPrivateString(arg, ret)) return false;
- out = "combo(" + std::move(ret) + ")";
- return true;
+ CKeyID id = keys[0].GetID();
+ out.pubkeys.emplace(id, keys[0]);
+ return Singleton(GetScriptForDestination(WitnessV0KeyHash(id)));
}
- bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+public:
+ WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "wpkh") {}
+};
+
+/** A parsed combo(P) descriptor. */
+class ComboDescriptor final : public DescriptorImpl
+{
+protected:
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider& out) const override
{
- CPubKey key;
- if (!m_provider->GetPubKey(pos, arg, key)) return false;
- CKeyID keyid = key.GetID();
- {
- CScript p2pk = GetScriptForRawPubKey(key);
- CScript p2pkh = GetScriptForDestination(keyid);
- output_scripts = std::vector<CScript>{std::move(p2pk), std::move(p2pkh)};
- out.pubkeys.emplace(keyid, key);
- }
- if (key.IsCompressed()) {
- CScript p2wpkh = GetScriptForDestination(WitnessV0KeyHash(keyid));
- CScriptID p2wpkh_id(p2wpkh);
- CScript p2sh_p2wpkh = GetScriptForDestination(p2wpkh_id);
- out.scripts.emplace(p2wpkh_id, p2wpkh);
- output_scripts.push_back(std::move(p2wpkh));
- output_scripts.push_back(std::move(p2sh_p2wpkh));
+ std::vector<CScript> ret;
+ CKeyID id = keys[0].GetID();
+ out.pubkeys.emplace(id, keys[0]);
+ ret.emplace_back(GetScriptForRawPubKey(keys[0])); // P2PK
+ ret.emplace_back(GetScriptForDestination(PKHash(id))); // P2PKH
+ if (keys[0].IsCompressed()) {
+ CScript p2wpkh = GetScriptForDestination(WitnessV0KeyHash(id));
+ out.scripts.emplace(CScriptID(p2wpkh), p2wpkh);
+ ret.emplace_back(p2wpkh);
+ ret.emplace_back(GetScriptForDestination(ScriptHash(p2wpkh))); // P2SH-P2WPKH
}
- return true;
+ return ret;
}
+public:
+ ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "combo") {}
+};
+
+/** A parsed multi(...) descriptor. */
+class MultisigDescriptor final : public DescriptorImpl
+{
+ const int m_threshold;
+protected:
+ std::string ToStringExtra() const override { return strprintf("%i", m_threshold); }
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForMultisig(m_threshold, keys)); }
+public:
+ MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers) : DescriptorImpl(std::move(providers), {}, "multi"), m_threshold(threshold) {}
+};
+
+/** A parsed sh(...) descriptor. */
+class SHDescriptor final : public DescriptorImpl
+{
+protected:
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(ScriptHash(*script))); }
+public:
+ SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {}
+};
+
+/** A parsed wsh(...) descriptor. */
+class WSHDescriptor final : public DescriptorImpl
+{
+protected:
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript* script, FlatSigningProvider&) const override { return Singleton(GetScriptForDestination(WitnessV0ScriptHash(*script))); }
+public:
+ WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "wsh") {}
};
////////////////////////////////////////////////////////////////////////////
@@ -373,7 +596,7 @@ enum class ParseScriptContext {
P2WSH,
};
-/** Parse a constant. If succesful, sp is updated to skip the constant and return true. */
+/** Parse a constant. If successful, sp is updated to skip the constant and return true. */
bool Const(const std::string& str, Span<const char>& sp)
{
if ((size_t)sp.size() >= str.size() && std::equal(str.begin(), str.end(), sp.begin())) {
@@ -383,7 +606,7 @@ bool Const(const std::string& str, Span<const char>& sp)
return false;
}
-/** Parse a function call. If succesful, sp is updated to be the function's argument(s). */
+/** Parse a function call. If successful, sp is updated to be the function's argument(s). */
bool Func(const std::string& str, Span<const char>& sp)
{
if ((size_t)sp.size() >= str.size() + 2 && sp[str.size()] == '(' && sp[sp.size() - 1] == ')' && std::equal(str.begin(), str.end(), sp.begin())) {
@@ -431,7 +654,7 @@ std::vector<Span<const char>> Split(const Span<const char>& sp, char sep)
}
/** Parse a key path, being passed a split list of elements (the first element is ignored). */
-bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out)
+NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out)
{
for (size_t i = 1; i < split.size(); ++i) {
Span<const char> elem = split[i];
@@ -447,7 +670,8 @@ bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out)
return true;
}
-std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out)
+/** Parse a public key that excludes origin information. */
+std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out)
{
auto split = Split(sp, '/');
std::string str(split[0].begin(), split[0].end());
@@ -484,19 +708,41 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
return MakeUnique<BIP32PubkeyProvider>(extpubkey, std::move(path), type);
}
+/** Parse a public key including origin information (if enabled). */
+std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out)
+{
+ auto origin_split = Split(sp, ']');
+ if (origin_split.size() > 2) return nullptr;
+ if (origin_split.size() == 1) return ParsePubkeyInner(origin_split[0], permit_uncompressed, out);
+ if (origin_split[0].size() < 1 || origin_split[0][0] != '[') return nullptr;
+ auto slash_split = Split(origin_split[0].subspan(1), '/');
+ if (slash_split[0].size() != 8) return nullptr;
+ std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
+ if (!IsHex(fpr_hex)) return nullptr;
+ auto fpr_bytes = ParseHex(fpr_hex);
+ KeyOriginInfo info;
+ static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
+ assert(fpr_bytes.size() == 4);
+ std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
+ if (!ParseKeyPath(slash_split, info.path)) return nullptr;
+ auto provider = ParsePubkeyInner(origin_split[1], permit_uncompressed, out);
+ if (!provider) return nullptr;
+ return MakeUnique<OriginPubkeyProvider>(std::move(info), std::move(provider));
+}
+
/** Parse a script in a particular context. */
-std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out)
+std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out)
{
auto expr = Expr(sp);
if (Func("pk", expr)) {
auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out);
if (!pubkey) return nullptr;
- return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2PKGetScript, "pk");
+ return MakeUnique<PKDescriptor>(std::move(pubkey));
}
if (Func("pkh", expr)) {
auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out);
if (!pubkey) return nullptr;
- return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2PKHGetScript, "pkh");
+ return MakeUnique<PKHDescriptor>(std::move(pubkey));
}
if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
auto pubkey = ParsePubkey(expr, true, out);
@@ -529,17 +775,17 @@ std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext
if (ctx != ParseScriptContext::P2WSH && Func("wpkh", expr)) {
auto pubkey = ParsePubkey(expr, false, out);
if (!pubkey) return nullptr;
- return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2WPKHGetScript, "wpkh");
+ return MakeUnique<WPKHDescriptor>(std::move(pubkey));
}
if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
auto desc = ParseScript(expr, ParseScriptContext::P2SH, out);
if (!desc || expr.size()) return nullptr;
- return MakeUnique<ConvertorDescriptor>(std::move(desc), ConvertP2SH, "sh");
+ return MakeUnique<SHDescriptor>(std::move(desc));
}
if (ctx != ParseScriptContext::P2WSH && Func("wsh", expr)) {
auto desc = ParseScript(expr, ParseScriptContext::P2WSH, out);
if (!desc || expr.size()) return nullptr;
- return MakeUnique<ConvertorDescriptor>(std::move(desc), ConvertP2WSH, "wsh");
+ return MakeUnique<WSHDescriptor>(std::move(desc));
}
if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
CTxDestination dest = DecodeDestination(std::string(expr.begin(), expr.end()));
@@ -555,12 +801,105 @@ std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext
return nullptr;
}
+std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
+{
+ std::unique_ptr<PubkeyProvider> key_provider = MakeUnique<ConstPubkeyProvider>(pubkey);
+ KeyOriginInfo info;
+ if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
+ return MakeUnique<OriginPubkeyProvider>(std::move(info), std::move(key_provider));
+ }
+ return key_provider;
+}
+
+std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
+{
+ std::vector<std::vector<unsigned char>> data;
+ txnouttype txntype = Solver(script, data);
+
+ if (txntype == TX_PUBKEY) {
+ CPubKey pubkey(data[0].begin(), data[0].end());
+ if (pubkey.IsValid()) {
+ return MakeUnique<PKDescriptor>(InferPubkey(pubkey, ctx, provider));
+ }
+ }
+ if (txntype == TX_PUBKEYHASH) {
+ uint160 hash(data[0]);
+ CKeyID keyid(hash);
+ CPubKey pubkey;
+ if (provider.GetPubKey(keyid, pubkey)) {
+ return MakeUnique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider));
+ }
+ }
+ if (txntype == TX_WITNESS_V0_KEYHASH && ctx != ParseScriptContext::P2WSH) {
+ uint160 hash(data[0]);
+ CKeyID keyid(hash);
+ CPubKey pubkey;
+ if (provider.GetPubKey(keyid, pubkey)) {
+ return MakeUnique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider));
+ }
+ }
+ if (txntype == TX_MULTISIG) {
+ std::vector<std::unique_ptr<PubkeyProvider>> providers;
+ for (size_t i = 1; i + 1 < data.size(); ++i) {
+ CPubKey pubkey(data[i].begin(), data[i].end());
+ providers.push_back(InferPubkey(pubkey, ctx, provider));
+ }
+ return MakeUnique<MultisigDescriptor>((int)data[0][0], std::move(providers));
+ }
+ if (txntype == TX_SCRIPTHASH && ctx == ParseScriptContext::TOP) {
+ uint160 hash(data[0]);
+ CScriptID scriptid(hash);
+ CScript subscript;
+ if (provider.GetCScript(scriptid, subscript)) {
+ auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
+ if (sub) return MakeUnique<SHDescriptor>(std::move(sub));
+ }
+ }
+ if (txntype == TX_WITNESS_V0_SCRIPTHASH && ctx != ParseScriptContext::P2WSH) {
+ CScriptID scriptid;
+ CRIPEMD160().Write(data[0].data(), data[0].size()).Finalize(scriptid.begin());
+ CScript subscript;
+ if (provider.GetCScript(scriptid, subscript)) {
+ auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
+ if (sub) return MakeUnique<WSHDescriptor>(std::move(sub));
+ }
+ }
+
+ CTxDestination dest;
+ if (ExtractDestination(script, dest)) {
+ if (GetScriptForDestination(dest) == script) {
+ return MakeUnique<AddressDescriptor>(std::move(dest));
+ }
+ }
+
+ return MakeUnique<RawDescriptor>(script);
+}
+
+
} // namespace
-std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out)
+std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out, bool require_checksum)
{
Span<const char> sp(descriptor.data(), descriptor.size());
+
+ // Checksum checks
+ auto check_split = Split(sp, '#');
+ if (check_split.size() > 2) return nullptr; // Multiple '#' symbols
+ if (check_split.size() == 1 && require_checksum) return nullptr; // Missing checksum
+ if (check_split.size() == 2) {
+ if (check_split[1].size() != 8) return nullptr; // Unexpected length for checksum
+ auto checksum = DescriptorChecksum(check_split[0]);
+ if (checksum.empty()) return nullptr; // Invalid characters in payload
+ if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) return nullptr; // Checksum mismatch
+ }
+ sp = check_split[0];
+
auto ret = ParseScript(sp, ParseScriptContext::TOP, out);
- if (sp.size() == 0 && ret) return ret;
+ if (sp.size() == 0 && ret) return std::unique_ptr<Descriptor>(std::move(ret));
return nullptr;
}
+
+std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider)
+{
+ return InferScript(script, ParseScriptContext::TOP, provider);
+}
diff --git a/src/script/descriptor.h b/src/script/descriptor.h
index e079c72e92..907a102284 100644
--- a/src/script/descriptor.h
+++ b/src/script/descriptor.h
@@ -22,55 +22,8 @@
// they can be included inside by changing public keys to private keys (WIF
// format), and changing xpubs by xprvs.
//
-// 1. Examples
-//
-// A P2PK descriptor with a fixed public key:
-// - pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)
-//
-// A P2SH-P2WSH-P2PKH descriptor with a fixed public key:
-// - sh(wsh(pkh(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)))
-//
-// A bare 1-of-2 multisig descriptor:
-// - multi(1,022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)
-//
-// A chain of P2PKH outputs (this needs the corresponding private key to derive):
-// - pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1'/2/*)
-//
-// 2. Grammar description:
-//
-// X: xpub or xprv encoded extended key
-// I: decimal encoded integer
-// H: Hex encoded byte array
-// A: Address in P2PKH, P2SH, or Bech32 encoding
-//
-// S (Scripts):
-// * pk(P): Pay-to-pubkey (P2PK) output for public key P.
-// * pkh(P): Pay-to-pubkey-hash (P2PKH) output for public key P.
-// * wpkh(P): Pay-to-witness-pubkey-hash (P2WPKH) output for public key P.
-// * sh(S): Pay-to-script-hash (P2SH) output for script S
-// * wsh(S): Pay-to-witness-script-hash (P2WSH) output for script S
-// * combo(P): combination of P2PK, P2PKH, P2WPKH, and P2SH-P2WPKH for public key P.
-// * multi(I,L): k-of-n multisig for given public keys
-// * addr(A): Output to address
-// * raw(H): scriptPubKey with raw bytes
-//
-// P (Public keys):
-// * H: fixed public key (or WIF-encoded private key)
-// * E: extended public key
-// * E/*: (ranged) all unhardened direct children of an extended public key
-// * E/*': (ranged) all hardened direct children of an extended public key
-//
-// L (Comma-separated lists of public keys):
-// * P
-// * L,P
-//
-// E (Extended public keys):
-// * X
-// * E/I: unhardened child
-// * E/I': hardened child
-// * E/Ih: hardened child (alternative notation)
-//
-// The top level is S.
+// Reference documentation about the descriptor language can be found in
+// doc/descriptors.md.
/** Interface for parsed descriptor objects. */
struct Descriptor {
@@ -79,6 +32,10 @@ struct Descriptor {
/** Whether the expansion of this descriptor depends on the position. */
virtual bool IsRange() const = 0;
+ /** Whether this descriptor has all information about signing ignoring lack of private keys.
+ * This is true for all descriptors except ones that use `raw` or `addr` constructions. */
+ virtual bool IsSolvable() const = 0;
+
/** Convert the descriptor back to a string, undoing parsing. */
virtual std::string ToString() const = 0;
@@ -91,12 +48,44 @@ struct Descriptor {
* provider: the provider to query for private keys in case of hardened derivation.
* output_script: the expanded scriptPubKeys will be put here.
* out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider).
+ * cache: vector which will be overwritten with cache data necessary to-evaluate the descriptor at this point without access to private keys.
+ */
+ virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache = nullptr) const = 0;
+
+ /** Expand a descriptor at a specified position using cached expansion data.
+ *
+ * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored.
+ * cache: vector from which cached expansion data will be read.
+ * output_script: the expanded scriptPubKeys will be put here.
+ * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider).
*/
- virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0;
+ virtual bool ExpandFromCache(int pos, const std::vector<unsigned char>& cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0;
};
-/** Parse a descriptor string. Included private keys are put in out. Returns nullptr if parsing fails. */
-std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out);
+/** Parse a descriptor string. Included private keys are put in out.
+ *
+ * If the descriptor has a checksum, it must be valid. If require_checksum
+ * is set, the checksum is mandatory - otherwise it is optional.
+ *
+ * If a parse error occurs, or the checksum is missing/invalid, or anything
+ * else is wrong, nullptr is returned.
+ */
+std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out, bool require_checksum = false);
-#endif // BITCOIN_SCRIPT_DESCRIPTOR_H
+/** Find a descriptor for the specified script, using information from provider where possible.
+ *
+ * A non-ranged descriptor which only generates the specified script will be returned in all
+ * circumstances.
+ *
+ * For public keys with key origin information, this information will be preserved in the returned
+ * descriptor.
+ *
+ * - If all information for solving `script` is present in `provider`, a descriptor will be returned
+ * which is `IsSolvable()` and encapsulates said information.
+ * - Failing that, if `script` corresponds to a known address type, an "addr()" descriptor will be
+ * returned (which is not `IsSolvable()`).
+ * - Failing that, a "raw()" descriptor is returned.
+ */
+std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider);
+#endif // BITCOIN_SCRIPT_DESCRIPTOR_H
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index be2138d502..95b25b4911 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 2d21aa81df..276ff9a58a 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index 8c26866483..75fc2e84f1 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -23,9 +23,9 @@ namespace {
*/
enum class IsMineSigVersion
{
- TOP = 0, //! scriptPubKey execution
- P2SH = 1, //! P2SH redeemScript
- WITNESS_V0 = 2 //! P2WSH witness script execution
+ TOP = 0, //!< scriptPubKey execution
+ P2SH = 1, //!< P2SH redeemScript
+ WITNESS_V0 = 2, //!< P2WSH witness script execution
};
/**
@@ -35,10 +35,10 @@ enum class IsMineSigVersion
*/
enum class IsMineResult
{
- NO = 0, //! Not ours
- WATCH_ONLY = 1, //! Included in watch-only balance
- SPENDABLE = 2, //! Included in all balances
- INVALID = 3, //! Not spendable by anyone (uncompressed pubkey in segwit, P2SH inside P2SH or witness, witness inside witness)
+ NO = 0, //!< Not ours
+ WATCH_ONLY = 1, //!< Included in watch-only balance
+ SPENDABLE = 2, //!< Included in all balances
+ INVALID = 3, //!< Not spendable by anyone (uncompressed pubkey in segwit, P2SH inside P2SH or witness, witness inside witness)
};
bool PermitsUncompressed(IsMineSigVersion sigversion)
@@ -60,8 +60,7 @@ IsMineResult IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey,
IsMineResult ret = IsMineResult::NO;
std::vector<valtype> vSolutions;
- txnouttype whichType;
- Solver(scriptPubKey, whichType, vSolutions);
+ txnouttype whichType = Solver(scriptPubKey, vSolutions);
CKeyID keyID;
switch (whichType)
@@ -91,7 +90,7 @@ IsMineResult IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey,
// This also applies to the P2WSH case.
break;
}
- ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
+ ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(PKHash(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
break;
}
case TX_PUBKEYHASH:
diff --git a/src/script/ismine.h b/src/script/ismine.h
index 4246da49fe..55e28e225a 100644
--- a/src/script/ismine.h
+++ b/src/script/ismine.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,6 +9,7 @@
#include <script/standard.h>
#include <stdint.h>
+#include <bitset>
class CKeyStore;
class CScript;
@@ -16,10 +17,11 @@ class CScript;
/** IsMine() return codes */
enum isminetype
{
- ISMINE_NO = 0,
- ISMINE_WATCH_ONLY = 1,
- ISMINE_SPENDABLE = 2,
- ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
+ ISMINE_NO = 0,
+ ISMINE_WATCH_ONLY = 1 << 0,
+ ISMINE_SPENDABLE = 1 << 1,
+ ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE,
+ ISMINE_ENUM_ELEMENTS,
};
/** used for bitflags of isminetype */
typedef uint8_t isminefilter;
@@ -27,4 +29,23 @@ typedef uint8_t isminefilter;
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
+/**
+ * Cachable amount subdivided into watchonly and spendable parts.
+ */
+struct CachableAmount
+{
+ // NO and ALL are never (supposed to be) cached
+ std::bitset<ISMINE_ENUM_ELEMENTS> m_cached;
+ CAmount m_value[ISMINE_ENUM_ELEMENTS];
+ inline void Reset()
+ {
+ m_cached.reset();
+ }
+ void Set(isminefilter filter, CAmount value)
+ {
+ m_cached.set(filter);
+ m_value[filter] = value;
+ }
+};
+
#endif // BITCOIN_SCRIPT_ISMINE_H
diff --git a/src/script/script.cpp b/src/script/script.cpp
index c84c7b8ec1..982aa241e7 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -1,12 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <script/script.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
const char* GetOpName(opcodetype opcode)
{
diff --git a/src/script/script.h b/src/script/script.h
index a4f377dd94..11e8661a5b 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -38,6 +38,12 @@ static const int MAX_STACK_SIZE = 1000;
// otherwise as UNIX timestamp.
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
+// Maximum nLockTime. Since a lock time indicates the last invalid timestamp, a
+// transaction with this lock time will never be valid unless lock time
+// checking is disabled (by setting all input sequence numbers to
+// SEQUENCE_FINAL).
+static const uint32_t LOCKTIME_MAX = 0xFFFFFFFFU;
+
template <typename T>
std::vector<unsigned char> ToByteVector(const T& in)
{
@@ -575,13 +581,4 @@ struct CScriptWitness
std::string ToString() const;
};
-class CReserveScript
-{
-public:
- CScript reserveScript;
- virtual void KeepScript() {}
- CReserveScript() {}
- virtual ~CReserveScript() {}
-};
-
#endif // BITCOIN_SCRIPT_SCRIPT_H
diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp
index ceda740580..9d7deffc78 100644
--- a/src/script/script_error.cpp
+++ b/src/script/script_error.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/script_error.h b/src/script/script_error.h
index 6982a087f4..400f63ff0f 100644
--- a/src/script/script_error.h
+++ b/src/script/script_error.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2016 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index 9638b12f99..94005cf6f3 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <pubkey.h>
#include <random.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
#include <cuckoocache.h>
#include <boost/thread.hpp>
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index 1309d57cc6..807b61b542 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index fa09adbaf8..36dd68a3d8 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -48,12 +48,8 @@ static bool GetCScript(const SigningProvider& provider, const SignatureData& sig
return false;
}
-static bool GetPubKey(const SigningProvider& provider, SignatureData& sigdata, const CKeyID& address, CPubKey& pubkey)
+static bool GetPubKey(const SigningProvider& provider, const SignatureData& sigdata, const CKeyID& address, CPubKey& pubkey)
{
- if (provider.GetPubKey(address, pubkey)) {
- sigdata.misc_pubkeys.emplace(pubkey.GetID(), pubkey);
- return true;
- }
// Look for pubkey in all partial sigs
const auto it = sigdata.signatures.find(address);
if (it != sigdata.signatures.end()) {
@@ -63,26 +59,32 @@ static bool GetPubKey(const SigningProvider& provider, SignatureData& sigdata, c
// Look for pubkey in pubkey list
const auto& pk_it = sigdata.misc_pubkeys.find(address);
if (pk_it != sigdata.misc_pubkeys.end()) {
- pubkey = pk_it->second;
+ pubkey = pk_it->second.first;
return true;
}
- return false;
+ // Query the underlying provider
+ return provider.GetPubKey(address, pubkey);
}
-static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const CKeyID& keyid, const CScript& scriptcode, SigVersion sigversion)
+static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const CPubKey& pubkey, const CScript& scriptcode, SigVersion sigversion)
{
+ CKeyID keyid = pubkey.GetID();
const auto it = sigdata.signatures.find(keyid);
if (it != sigdata.signatures.end()) {
sig_out = it->second.second;
return true;
}
- CPubKey pubkey;
- GetPubKey(provider, sigdata, keyid, pubkey);
+ KeyOriginInfo info;
+ if (provider.GetKeyOrigin(keyid, info)) {
+ sigdata.misc_pubkeys.emplace(keyid, std::make_pair(pubkey, std::move(info)));
+ }
if (creator.CreateSig(provider, sig_out, keyid, scriptcode, sigversion)) {
auto i = sigdata.signatures.emplace(keyid, SigPair(pubkey, sig_out));
assert(i.second);
return true;
}
+ // Could not make signature or signature not found, add keyid to missing
+ sigdata.missing_sigs.push_back(keyid);
return false;
}
@@ -101,8 +103,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
std::vector<unsigned char> sig;
std::vector<valtype> vSolutions;
- if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
- return false;
+ whichTypeRet = Solver(scriptPubKey, vSolutions);
switch (whichTypeRet)
{
@@ -111,23 +112,30 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TX_WITNESS_UNKNOWN:
return false;
case TX_PUBKEY:
- if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]).GetID(), scriptPubKey, sigversion)) return false;
+ if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;
ret.push_back(std::move(sig));
return true;
case TX_PUBKEYHASH: {
CKeyID keyID = CKeyID(uint160(vSolutions[0]));
- if (!CreateSig(creator, sigdata, provider, sig, keyID, scriptPubKey, sigversion)) return false;
- ret.push_back(std::move(sig));
CPubKey pubkey;
- GetPubKey(provider, sigdata, keyID, pubkey);
+ if (!GetPubKey(provider, sigdata, keyID, pubkey)) {
+ // Pubkey could not be found, add to missing
+ sigdata.missing_pubkeys.push_back(keyID);
+ return false;
+ }
+ if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) return false;
+ ret.push_back(std::move(sig));
ret.push_back(ToByteVector(pubkey));
return true;
}
case TX_SCRIPTHASH:
- if (GetCScript(provider, sigdata, uint160(vSolutions[0]), scriptRet)) {
+ h160 = uint160(vSolutions[0]);
+ if (GetCScript(provider, sigdata, h160, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
+ // Could not find redeemScript, add to missing
+ sigdata.missing_redeem_script = h160;
return false;
case TX_MULTISIG: {
@@ -135,7 +143,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
CPubKey pubkey = CPubKey(vSolutions[i]);
- if (ret.size() < required + 1 && CreateSig(creator, sigdata, provider, sig, pubkey.GetID(), scriptPubKey, sigversion)) {
+ if (ret.size() < required + 1 && CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) {
ret.push_back(std::move(sig));
}
}
@@ -155,6 +163,8 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
+ // Could not find witnessScript, add to missing
+ sigdata.missing_witness_script = uint256(vSolutions[0]);
return false;
default:
@@ -233,32 +243,6 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
return sigdata.complete;
}
-bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& tx, PSBTInput& input, SignatureData& sigdata, int index, int sighash)
-{
- // if this input has a final scriptsig or scriptwitness, don't do anything with it
- if (!input.final_script_sig.empty() || !input.final_script_witness.IsNull()) {
- return true;
- }
-
- // Fill SignatureData with input info
- input.FillSignatureData(sigdata);
-
- // Get UTXO
- CTxOut utxo;
- if (input.non_witness_utxo) {
- utxo = input.non_witness_utxo->vout[tx.vin[index].prevout.n];
- } else if (!input.witness_utxo.IsNull()) {
- utxo = input.witness_utxo;
- } else {
- return false;
- }
-
- MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue, sighash);
- bool sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
- input.FromSignatureData(sigdata);
- return sig_complete;
-}
-
class SignatureExtractorChecker final : public BaseSignatureChecker
{
private:
@@ -313,9 +297,8 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
}
// Get scripts
- txnouttype script_type;
std::vector<std::vector<unsigned char>> solutions;
- Solver(txout.scriptPubKey, script_type, solutions);
+ txnouttype script_type = Solver(txout.scriptPubKey, solutions);
SigVersion sigversion = SigVersion::BASE;
CScript next_script = txout.scriptPubKey;
@@ -326,7 +309,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
next_script = std::move(redeem_script);
// Get redeemScript type
- Solver(next_script, script_type, solutions);
+ script_type = Solver(next_script, solutions);
stack.script.pop_back();
}
if (script_type == TX_WITNESS_V0_SCRIPTHASH && !stack.witness.empty() && !stack.witness.back().empty()) {
@@ -336,7 +319,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
next_script = std::move(witness_script);
// Get witnessScript type
- Solver(next_script, script_type, solutions);
+ script_type = Solver(next_script, solutions);
stack.witness.pop_back();
stack.script = std::move(stack.witness);
stack.witness.clear();
@@ -417,22 +400,25 @@ public:
const DummySignatureChecker DUMMY_CHECKER;
class DummySignatureCreator final : public BaseSignatureCreator {
+private:
+ char m_r_len = 32;
+ char m_s_len = 32;
public:
- DummySignatureCreator() {}
+ DummySignatureCreator(char r_len, char s_len) : m_r_len(r_len), m_s_len(s_len) {}
const BaseSignatureChecker& Checker() const override { return DUMMY_CHECKER; }
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override
{
// Create a dummy signature that is a valid DER-encoding
- vchSig.assign(72, '\000');
+ vchSig.assign(m_r_len + m_s_len + 7, '\000');
vchSig[0] = 0x30;
- vchSig[1] = 69;
+ vchSig[1] = m_r_len + m_s_len + 4;
vchSig[2] = 0x02;
- vchSig[3] = 33;
+ vchSig[3] = m_r_len;
vchSig[4] = 0x01;
- vchSig[4 + 33] = 0x02;
- vchSig[5 + 33] = 32;
- vchSig[6 + 33] = 0x01;
- vchSig[6 + 33 + 32] = SIGHASH_ALL;
+ vchSig[4 + m_r_len] = 0x02;
+ vchSig[5 + m_r_len] = m_s_len;
+ vchSig[6 + m_r_len] = 0x01;
+ vchSig[6 + m_r_len + m_s_len] = SIGHASH_ALL;
return true;
}
};
@@ -450,7 +436,8 @@ bool LookupHelper(const M& map, const K& key, V& value)
}
-const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator();
+const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator(32, 32);
+const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR = DummySignatureCreator(33, 32);
const SigningProvider& DUMMY_SIGNING_PROVIDER = SigningProvider();
bool IsSolvable(const SigningProvider& provider, const CScript& script)
@@ -465,172 +452,44 @@ bool IsSolvable(const SigningProvider& provider, const CScript& script)
static_assert(STANDARD_SCRIPT_VERIFY_FLAGS & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, "IsSolvable requires standard script flags to include WITNESS_PUBKEYTYPE");
if (ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, script, sigs)) {
// VerifyScript check is just defensive, and should never fail.
- assert(VerifyScript(sigs.scriptSig, script, &sigs.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, DUMMY_CHECKER));
+ bool verified = VerifyScript(sigs.scriptSig, script, &sigs.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, DUMMY_CHECKER);
+ assert(verified);
return true;
}
return false;
}
-bool PartiallySignedTransaction::IsNull() const
-{
- return !tx && inputs.empty() && outputs.empty() && unknown.empty();
-}
-
-void PartiallySignedTransaction::Merge(const PartiallySignedTransaction& psbt)
+bool HidingSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const
{
- for (unsigned int i = 0; i < inputs.size(); ++i) {
- inputs[i].Merge(psbt.inputs[i]);
- }
- for (unsigned int i = 0; i < outputs.size(); ++i) {
- outputs[i].Merge(psbt.outputs[i]);
- }
- unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
-}
-
-bool PartiallySignedTransaction::IsSane() const
-{
- for (PSBTInput input : inputs) {
- if (!input.IsSane()) return false;
- }
- return true;
-}
-
-bool PSBTInput::IsNull() const
-{
- return !non_witness_utxo && witness_utxo.IsNull() && partial_sigs.empty() && unknown.empty() && hd_keypaths.empty() && redeem_script.empty() && witness_script.empty();
-}
-
-void PSBTInput::FillSignatureData(SignatureData& sigdata) const
-{
- if (!final_script_sig.empty()) {
- sigdata.scriptSig = final_script_sig;
- sigdata.complete = true;
- }
- if (!final_script_witness.IsNull()) {
- sigdata.scriptWitness = final_script_witness;
- sigdata.complete = true;
- }
- if (sigdata.complete) {
- return;
- }
-
- sigdata.signatures.insert(partial_sigs.begin(), partial_sigs.end());
- if (!redeem_script.empty()) {
- sigdata.redeem_script = redeem_script;
- }
- if (!witness_script.empty()) {
- sigdata.witness_script = witness_script;
- }
- for (const auto& key_pair : hd_keypaths) {
- sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair.first);
- }
-}
-
-void PSBTInput::FromSignatureData(const SignatureData& sigdata)
-{
- if (sigdata.complete) {
- partial_sigs.clear();
- hd_keypaths.clear();
- redeem_script.clear();
- witness_script.clear();
-
- if (!sigdata.scriptSig.empty()) {
- final_script_sig = sigdata.scriptSig;
- }
- if (!sigdata.scriptWitness.IsNull()) {
- final_script_witness = sigdata.scriptWitness;
- }
- return;
- }
-
- partial_sigs.insert(sigdata.signatures.begin(), sigdata.signatures.end());
- if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
- redeem_script = sigdata.redeem_script;
- }
- if (witness_script.empty() && !sigdata.witness_script.empty()) {
- witness_script = sigdata.witness_script;
- }
-}
-
-void PSBTInput::Merge(const PSBTInput& input)
-{
- if (!non_witness_utxo && input.non_witness_utxo) non_witness_utxo = input.non_witness_utxo;
- if (witness_utxo.IsNull() && !input.witness_utxo.IsNull()) {
- witness_utxo = input.witness_utxo;
- non_witness_utxo = nullptr; // Clear out any non-witness utxo when we set a witness one.
- }
-
- partial_sigs.insert(input.partial_sigs.begin(), input.partial_sigs.end());
- hd_keypaths.insert(input.hd_keypaths.begin(), input.hd_keypaths.end());
- unknown.insert(input.unknown.begin(), input.unknown.end());
-
- if (redeem_script.empty() && !input.redeem_script.empty()) redeem_script = input.redeem_script;
- if (witness_script.empty() && !input.witness_script.empty()) witness_script = input.witness_script;
- if (final_script_sig.empty() && !input.final_script_sig.empty()) final_script_sig = input.final_script_sig;
- if (final_script_witness.IsNull() && !input.final_script_witness.IsNull()) final_script_witness = input.final_script_witness;
-}
-
-bool PSBTInput::IsSane() const
-{
- // Cannot have both witness and non-witness utxos
- if (!witness_utxo.IsNull() && non_witness_utxo) return false;
-
- // If we have a witness_script or a scriptWitness, we must also have a witness utxo
- if (!witness_script.empty() && witness_utxo.IsNull()) return false;
- if (!final_script_witness.IsNull() && witness_utxo.IsNull()) return false;
-
- return true;
-}
-
-void PSBTOutput::FillSignatureData(SignatureData& sigdata) const
-{
- if (!redeem_script.empty()) {
- sigdata.redeem_script = redeem_script;
- }
- if (!witness_script.empty()) {
- sigdata.witness_script = witness_script;
- }
- for (const auto& key_pair : hd_keypaths) {
- sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair.first);
- }
-}
-
-void PSBTOutput::FromSignatureData(const SignatureData& sigdata)
-{
- if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
- redeem_script = sigdata.redeem_script;
- }
- if (witness_script.empty() && !sigdata.witness_script.empty()) {
- witness_script = sigdata.witness_script;
- }
-}
-
-bool PSBTOutput::IsNull() const
-{
- return redeem_script.empty() && witness_script.empty() && hd_keypaths.empty() && unknown.empty();
+ return m_provider->GetCScript(scriptid, script);
}
-void PSBTOutput::Merge(const PSBTOutput& output)
+bool HidingSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const
{
- hd_keypaths.insert(output.hd_keypaths.begin(), output.hd_keypaths.end());
- unknown.insert(output.unknown.begin(), output.unknown.end());
-
- if (redeem_script.empty() && !output.redeem_script.empty()) redeem_script = output.redeem_script;
- if (witness_script.empty() && !output.witness_script.empty()) witness_script = output.witness_script;
+ return m_provider->GetPubKey(keyid, pubkey);
}
-bool PublicOnlySigningProvider::GetCScript(const CScriptID &scriptid, CScript& script) const
+bool HidingSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const
{
- return m_provider->GetCScript(scriptid, script);
+ if (m_hide_secret) return false;
+ return m_provider->GetKey(keyid, key);
}
-bool PublicOnlySigningProvider::GetPubKey(const CKeyID &address, CPubKey& pubkey) const
+bool HidingSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const
{
- return m_provider->GetPubKey(address, pubkey);
+ if (m_hide_origin) return false;
+ return m_provider->GetKeyOrigin(keyid, info);
}
bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
+bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const
+{
+ std::pair<CPubKey, KeyOriginInfo> out;
+ bool ret = LookupHelper(origins, keyid, out);
+ if (ret) info = std::move(out.second);
+ return ret;
+}
bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b)
@@ -642,5 +501,7 @@ FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvide
ret.pubkeys.insert(b.pubkeys.begin(), b.pubkeys.end());
ret.keys = a.keys;
ret.keys.insert(b.keys.begin(), b.keys.end());
+ ret.origins = a.origins;
+ ret.origins.insert(b.origins.begin(), b.origins.end());
return ret;
}
diff --git a/src/script/sign.h b/src/script/sign.h
index 96ef59fbe8..f746325b90 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -20,6 +20,31 @@ class CTransaction;
struct CMutableTransaction;
+struct KeyOriginInfo
+{
+ unsigned char fingerprint[4]; //!< First 32 bits of the Hash160 of the public key at the root of the path
+ std::vector<uint32_t> path;
+
+ friend bool operator==(const KeyOriginInfo& a, const KeyOriginInfo& b)
+ {
+ return std::equal(std::begin(a.fingerprint), std::end(a.fingerprint), std::begin(b.fingerprint)) && a.path == b.path;
+ }
+
+ ADD_SERIALIZE_METHODS;
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action)
+ {
+ READWRITE(fingerprint);
+ READWRITE(path);
+ }
+
+ void clear()
+ {
+ memset(fingerprint, 0, 4);
+ path.clear();
+ }
+};
+
/** An interface to be implemented by keystores that support signing. */
class SigningProvider
{
@@ -28,29 +53,36 @@ public:
virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const { return false; }
virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const { return false; }
virtual bool GetKey(const CKeyID &address, CKey& key) const { return false; }
+ virtual bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return false; }
};
extern const SigningProvider& DUMMY_SIGNING_PROVIDER;
-class PublicOnlySigningProvider : public SigningProvider
+class HidingSigningProvider : public SigningProvider
{
private:
+ const bool m_hide_secret;
+ const bool m_hide_origin;
const SigningProvider* m_provider;
public:
- PublicOnlySigningProvider(const SigningProvider* provider) : m_provider(provider) {}
- bool GetCScript(const CScriptID &scriptid, CScript& script) const;
- bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const;
+ HidingSigningProvider(const SigningProvider* provider, bool hide_secret, bool hide_origin) : m_hide_secret(hide_secret), m_hide_origin(hide_origin), m_provider(provider) {}
+ bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
+ bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
+ bool GetKey(const CKeyID& keyid, CKey& key) const override;
+ bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
};
struct FlatSigningProvider final : public SigningProvider
{
std::map<CScriptID, CScript> scripts;
std::map<CKeyID, CPubKey> pubkeys;
+ std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> origins;
std::map<CKeyID, CKey> keys;
bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
+ bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
bool GetKey(const CKeyID& keyid, CKey& key) const override;
};
@@ -80,8 +112,10 @@ public:
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
};
-/** A signature creator that just produces 72-byte empty signatures. */
+/** A signature creator that just produces 71-byte empty signatures. */
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
+/** A signature creator that just produces 72-byte empty signatures. */
+extern const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR;
typedef std::pair<CPubKey, std::vector<unsigned char>> SigPair;
@@ -96,45 +130,23 @@ struct SignatureData {
CScript witness_script; ///< The witnessScript (if any) for the input. witnessScripts are used in P2WSH outputs.
CScriptWitness scriptWitness; ///< The scriptWitness of an input. Contains complete signatures or the traditional partial signatures format. scriptWitness is part of a transaction input per BIP 144.
std::map<CKeyID, SigPair> signatures; ///< BIP 174 style partial signatures for the input. May contain all signatures necessary for producing a final scriptSig or scriptWitness.
- std::map<CKeyID, CPubKey> misc_pubkeys;
+ std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> misc_pubkeys;
+ std::vector<CKeyID> missing_pubkeys; ///< KeyIDs of pubkeys which could not be found
+ std::vector<CKeyID> missing_sigs; ///< KeyIDs of pubkeys for signatures which could not be found
+ uint160 missing_redeem_script; ///< ScriptID of the missing redeemScript (if any)
+ uint256 missing_witness_script; ///< SHA256 of the missing witnessScript (if any)
SignatureData() {}
explicit SignatureData(const CScript& script) : scriptSig(script) {}
void MergeSignatureData(SignatureData sigdata);
};
-// Magic bytes
-static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
-
-// Global types
-static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00;
-
-// Input types
-static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00;
-static constexpr uint8_t PSBT_IN_WITNESS_UTXO = 0x01;
-static constexpr uint8_t PSBT_IN_PARTIAL_SIG = 0x02;
-static constexpr uint8_t PSBT_IN_SIGHASH = 0x03;
-static constexpr uint8_t PSBT_IN_REDEEMSCRIPT = 0x04;
-static constexpr uint8_t PSBT_IN_WITNESSSCRIPT = 0x05;
-static constexpr uint8_t PSBT_IN_BIP32_DERIVATION = 0x06;
-static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07;
-static constexpr uint8_t PSBT_IN_SCRIPTWITNESS = 0x08;
-
-// Output types
-static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00;
-static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01;
-static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
-
-// The separator is 0x00. Reading this in means that the unserializer can interpret it
-// as a 0 length key which indicates that this is the separator. The separator has no value.
-static constexpr uint8_t PSBT_SEPARATOR = 0x00;
-
// Takes a stream and multiple arguments and serializes them as if first serialized into a vector and then into the stream
// The resulting output into the stream has the total serialized length of all of the objects followed by all objects concatenated with each other.
template<typename Stream, typename... X>
void SerializeToVector(Stream& s, const X&... args)
{
- WriteCompactSize(s, GetSerializeSizeMany(s, args...));
+ WriteCompactSize(s, GetSerializeSizeMany(s.GetVersion(), args...));
SerializeMany(s, args...);
}
@@ -153,7 +165,7 @@ void UnserializeFromVector(Stream& s, X&... args)
// Deserialize HD keypaths into a map
template<typename Stream>
-void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths)
+void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, KeyOriginInfo>& hd_keypaths)
{
// Make sure that the key is the size of pubkey + 1
if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) {
@@ -170,505 +182,39 @@ void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std
// Read in key path
uint64_t value_len = ReadCompactSize(s);
- std::vector<uint32_t> keypath;
- for (unsigned int i = 0; i < value_len; i += sizeof(uint32_t)) {
+ if (value_len % 4 || value_len == 0) {
+ throw std::ios_base::failure("Invalid length for HD key path");
+ }
+
+ KeyOriginInfo keypath;
+ s >> keypath.fingerprint;
+ for (unsigned int i = 4; i < value_len; i += sizeof(uint32_t)) {
uint32_t index;
s >> index;
- keypath.push_back(index);
+ keypath.path.push_back(index);
}
// Add to map
- hd_keypaths.emplace(pubkey, keypath);
+ hd_keypaths.emplace(pubkey, std::move(keypath));
}
// Serialize HD keypaths to a stream from a map
template<typename Stream>
-void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths, uint8_t type)
+void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, KeyOriginInfo>& hd_keypaths, uint8_t type)
{
for (auto keypath_pair : hd_keypaths) {
+ if (!keypath_pair.first.IsValid()) {
+ throw std::ios_base::failure("Invalid CPubKey being serialized");
+ }
SerializeToVector(s, type, MakeSpan(keypath_pair.first));
- WriteCompactSize(s, keypath_pair.second.size() * sizeof(uint32_t));
- for (auto& path : keypath_pair.second) {
+ WriteCompactSize(s, (keypath_pair.second.path.size() + 1) * sizeof(uint32_t));
+ s << keypath_pair.second.fingerprint;
+ for (const auto& path : keypath_pair.second.path) {
s << path;
}
}
}
-/** A structure for PSBTs which contain per-input information */
-struct PSBTInput
-{
- CTransactionRef non_witness_utxo;
- CTxOut witness_utxo;
- CScript redeem_script;
- CScript witness_script;
- CScript final_script_sig;
- CScriptWitness final_script_witness;
- std::map<CPubKey, std::vector<uint32_t>> hd_keypaths;
- std::map<CKeyID, SigPair> partial_sigs;
- std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
- int sighash_type = 0;
-
- bool IsNull() const;
- void FillSignatureData(SignatureData& sigdata) const;
- void FromSignatureData(const SignatureData& sigdata);
- void Merge(const PSBTInput& input);
- bool IsSane() const;
- PSBTInput() {}
-
- template <typename Stream>
- inline void Serialize(Stream& s) const {
- // Write the utxo
- // If there is a non-witness utxo, then don't add the witness one.
- if (non_witness_utxo) {
- SerializeToVector(s, PSBT_IN_NON_WITNESS_UTXO);
- SerializeToVector(s, non_witness_utxo);
- } else if (!witness_utxo.IsNull()) {
- SerializeToVector(s, PSBT_IN_WITNESS_UTXO);
- SerializeToVector(s, witness_utxo);
- }
-
- if (final_script_sig.empty() && final_script_witness.IsNull()) {
- // Write any partial signatures
- for (auto sig_pair : partial_sigs) {
- SerializeToVector(s, PSBT_IN_PARTIAL_SIG, MakeSpan(sig_pair.second.first));
- s << sig_pair.second.second;
- }
-
- // Write the sighash type
- if (sighash_type > 0) {
- SerializeToVector(s, PSBT_IN_SIGHASH);
- SerializeToVector(s, sighash_type);
- }
-
- // Write the redeem script
- if (!redeem_script.empty()) {
- SerializeToVector(s, PSBT_IN_REDEEMSCRIPT);
- s << redeem_script;
- }
-
- // Write the witness script
- if (!witness_script.empty()) {
- SerializeToVector(s, PSBT_IN_WITNESSSCRIPT);
- s << witness_script;
- }
-
- // Write any hd keypaths
- SerializeHDKeypaths(s, hd_keypaths, PSBT_IN_BIP32_DERIVATION);
- }
-
- // Write script sig
- if (!final_script_sig.empty()) {
- SerializeToVector(s, PSBT_IN_SCRIPTSIG);
- s << final_script_sig;
- }
- // write script witness
- if (!final_script_witness.IsNull()) {
- SerializeToVector(s, PSBT_IN_SCRIPTWITNESS);
- SerializeToVector(s, final_script_witness.stack);
- }
-
- // Write unknown things
- for (auto& entry : unknown) {
- s << entry.first;
- s << entry.second;
- }
-
- s << PSBT_SEPARATOR;
- }
-
-
- template <typename Stream>
- inline void Unserialize(Stream& s) {
- // Read loop
- while(!s.empty()) {
- // Read
- std::vector<unsigned char> key;
- s >> key;
-
- // the key is empty if that was actually a separator byte
- // This is a special case for key lengths 0 as those are not allowed (except for separator)
- if (key.empty()) return;
-
- // First byte of key is the type
- unsigned char type = key[0];
-
- // Do stuff based on type
- switch(type) {
- case PSBT_IN_NON_WITNESS_UTXO:
- if (non_witness_utxo) {
- throw std::ios_base::failure("Duplicate Key, input non-witness utxo already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Non-witness utxo key is more than one byte type");
- }
- UnserializeFromVector(s, non_witness_utxo);
- break;
- case PSBT_IN_WITNESS_UTXO:
- if (!witness_utxo.IsNull()) {
- throw std::ios_base::failure("Duplicate Key, input witness utxo already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Witness utxo key is more than one byte type");
- }
- UnserializeFromVector(s, witness_utxo);
- break;
- case PSBT_IN_PARTIAL_SIG:
- {
- // Make sure that the key is the size of pubkey + 1
- if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) {
- throw std::ios_base::failure("Size of key was not the expected size for the type partial signature pubkey");
- }
- // Read in the pubkey from key
- CPubKey pubkey(key.begin() + 1, key.end());
- if (!pubkey.IsFullyValid()) {
- throw std::ios_base::failure("Invalid pubkey");
- }
- if (partial_sigs.count(pubkey.GetID()) > 0) {
- throw std::ios_base::failure("Duplicate Key, input partial signature for pubkey already provided");
- }
-
- // Read in the signature from value
- std::vector<unsigned char> sig;
- s >> sig;
-
- // Add to list
- partial_sigs.emplace(pubkey.GetID(), SigPair(pubkey, std::move(sig)));
- break;
- }
- case PSBT_IN_SIGHASH:
- if (sighash_type > 0) {
- throw std::ios_base::failure("Duplicate Key, input sighash type already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Sighash type key is more than one byte type");
- }
- UnserializeFromVector(s, sighash_type);
- break;
- case PSBT_IN_REDEEMSCRIPT:
- {
- if (!redeem_script.empty()) {
- throw std::ios_base::failure("Duplicate Key, input redeemScript already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Input redeemScript key is more than one byte type");
- }
- s >> redeem_script;
- break;
- }
- case PSBT_IN_WITNESSSCRIPT:
- {
- if (!witness_script.empty()) {
- throw std::ios_base::failure("Duplicate Key, input witnessScript already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Input witnessScript key is more than one byte type");
- }
- s >> witness_script;
- break;
- }
- case PSBT_IN_BIP32_DERIVATION:
- {
- DeserializeHDKeypaths(s, key, hd_keypaths);
- break;
- }
- case PSBT_IN_SCRIPTSIG:
- {
- if (!final_script_sig.empty()) {
- throw std::ios_base::failure("Duplicate Key, input final scriptSig already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Final scriptSig key is more than one byte type");
- }
- s >> final_script_sig;
- break;
- }
- case PSBT_IN_SCRIPTWITNESS:
- {
- if (!final_script_witness.IsNull()) {
- throw std::ios_base::failure("Duplicate Key, input final scriptWitness already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Final scriptWitness key is more than one byte type");
- }
- UnserializeFromVector(s, final_script_witness.stack);
- break;
- }
- // Unknown stuff
- default:
- if (unknown.count(key) > 0) {
- throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
- }
- // Read in the value
- std::vector<unsigned char> val_bytes;
- s >> val_bytes;
- unknown.emplace(std::move(key), std::move(val_bytes));
- break;
- }
- }
- }
-
- template <typename Stream>
- PSBTInput(deserialize_type, Stream& s) {
- Unserialize(s);
- }
-};
-
-/** A structure for PSBTs which contains per output information */
-struct PSBTOutput
-{
- CScript redeem_script;
- CScript witness_script;
- std::map<CPubKey, std::vector<uint32_t>> hd_keypaths;
- std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
-
- bool IsNull() const;
- void FillSignatureData(SignatureData& sigdata) const;
- void FromSignatureData(const SignatureData& sigdata);
- void Merge(const PSBTOutput& output);
- bool IsSane() const;
- PSBTOutput() {}
-
- template <typename Stream>
- inline void Serialize(Stream& s) const {
- // Write the redeem script
- if (!redeem_script.empty()) {
- SerializeToVector(s, PSBT_OUT_REDEEMSCRIPT);
- s << redeem_script;
- }
-
- // Write the witness script
- if (!witness_script.empty()) {
- SerializeToVector(s, PSBT_OUT_WITNESSSCRIPT);
- s << witness_script;
- }
-
- // Write any hd keypaths
- SerializeHDKeypaths(s, hd_keypaths, PSBT_OUT_BIP32_DERIVATION);
-
- // Write unknown things
- for (auto& entry : unknown) {
- s << entry.first;
- s << entry.second;
- }
-
- s << PSBT_SEPARATOR;
- }
-
-
- template <typename Stream>
- inline void Unserialize(Stream& s) {
- // Read loop
- while(!s.empty()) {
- // Read
- std::vector<unsigned char> key;
- s >> key;
-
- // the key is empty if that was actually a separator byte
- // This is a special case for key lengths 0 as those are not allowed (except for separator)
- if (key.empty()) return;
-
- // First byte of key is the type
- unsigned char type = key[0];
-
- // Do stuff based on type
- switch(type) {
- case PSBT_OUT_REDEEMSCRIPT:
- {
- if (!redeem_script.empty()) {
- throw std::ios_base::failure("Duplicate Key, output redeemScript already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Output redeemScript key is more than one byte type");
- }
- s >> redeem_script;
- break;
- }
- case PSBT_OUT_WITNESSSCRIPT:
- {
- if (!witness_script.empty()) {
- throw std::ios_base::failure("Duplicate Key, output witnessScript already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Output witnessScript key is more than one byte type");
- }
- s >> witness_script;
- break;
- }
- case PSBT_OUT_BIP32_DERIVATION:
- {
- DeserializeHDKeypaths(s, key, hd_keypaths);
- break;
- }
- // Unknown stuff
- default: {
- if (unknown.count(key) > 0) {
- throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
- }
- // Read in the value
- std::vector<unsigned char> val_bytes;
- s >> val_bytes;
- unknown.emplace(std::move(key), std::move(val_bytes));
- break;
- }
- }
- }
- }
-
- template <typename Stream>
- PSBTOutput(deserialize_type, Stream& s) {
- Unserialize(s);
- }
-};
-
-/** A version of CTransaction with the PSBT format*/
-struct PartiallySignedTransaction
-{
- boost::optional<CMutableTransaction> tx;
- std::vector<PSBTInput> inputs;
- std::vector<PSBTOutput> outputs;
- std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
-
- bool IsNull() const;
- void Merge(const PartiallySignedTransaction& psbt);
- bool IsSane() const;
- PartiallySignedTransaction() {}
- PartiallySignedTransaction(const PartiallySignedTransaction& psbt_in) : tx(psbt_in.tx), inputs(psbt_in.inputs), outputs(psbt_in.outputs), unknown(psbt_in.unknown) {}
-
- // Only checks if they refer to the same transaction
- friend bool operator==(const PartiallySignedTransaction& a, const PartiallySignedTransaction &b)
- {
- return a.tx->GetHash() == b.tx->GetHash();
- }
- friend bool operator!=(const PartiallySignedTransaction& a, const PartiallySignedTransaction &b)
- {
- return !(a == b);
- }
-
- template <typename Stream>
- inline void Serialize(Stream& s) const {
-
- // magic bytes
- s << PSBT_MAGIC_BYTES;
-
- // unsigned tx flag
- SerializeToVector(s, PSBT_GLOBAL_UNSIGNED_TX);
-
- // Write serialized tx to a stream
- SerializeToVector(s, *tx);
-
- // Write the unknown things
- for (auto& entry : unknown) {
- s << entry.first;
- s << entry.second;
- }
-
- // Separator
- s << PSBT_SEPARATOR;
-
- // Write inputs
- for (const PSBTInput& input : inputs) {
- s << input;
- }
- // Write outputs
- for (const PSBTOutput& output : outputs) {
- s << output;
- }
- }
-
-
- template <typename Stream>
- inline void Unserialize(Stream& s) {
- // Read the magic bytes
- uint8_t magic[5];
- s >> magic;
- if (!std::equal(magic, magic + 5, PSBT_MAGIC_BYTES)) {
- throw std::ios_base::failure("Invalid PSBT magic bytes");
- }
-
- // Read global data
- while(!s.empty()) {
- // Read
- std::vector<unsigned char> key;
- s >> key;
-
- // the key is empty if that was actually a separator byte
- // This is a special case for key lengths 0 as those are not allowed (except for separator)
- if (key.empty()) break;
-
- // First byte of key is the type
- unsigned char type = key[0];
-
- // Do stuff based on type
- switch(type) {
- case PSBT_GLOBAL_UNSIGNED_TX:
- {
- if (tx) {
- throw std::ios_base::failure("Duplicate Key, unsigned tx already provided");
- } else if (key.size() != 1) {
- throw std::ios_base::failure("Global unsigned tx key is more than one byte type");
- }
- CMutableTransaction mtx;
- UnserializeFromVector(s, mtx);
- tx = std::move(mtx);
- // Make sure that all scriptSigs and scriptWitnesses are empty
- for (const CTxIn& txin : tx->vin) {
- if (!txin.scriptSig.empty() || !txin.scriptWitness.IsNull()) {
- throw std::ios_base::failure("Unsigned tx does not have empty scriptSigs and scriptWitnesses.");
- }
- }
- break;
- }
- // Unknown stuff
- default: {
- if (unknown.count(key) > 0) {
- throw std::ios_base::failure("Duplicate Key, key for unknown value already provided");
- }
- // Read in the value
- std::vector<unsigned char> val_bytes;
- s >> val_bytes;
- unknown.emplace(std::move(key), std::move(val_bytes));
- }
- }
- }
-
- // Make sure that we got an unsigned tx
- if (!tx) {
- throw std::ios_base::failure("No unsigned transcation was provided");
- }
-
- // Read input data
- unsigned int i = 0;
- while (!s.empty() && i < tx->vin.size()) {
- PSBTInput input;
- s >> input;
- inputs.push_back(input);
-
- // Make sure the non-witness utxo matches the outpoint
- if (input.non_witness_utxo && input.non_witness_utxo->GetHash() != tx->vin[i].prevout.hash) {
- throw std::ios_base::failure("Non-witness UTXO does not match outpoint hash");
- }
- ++i;
- }
- // Make sure that the number of inputs matches the number of inputs in the transaction
- if (inputs.size() != tx->vin.size()) {
- throw std::ios_base::failure("Inputs provided does not match the number of inputs in transaction.");
- }
-
- // Read output data
- i = 0;
- while (!s.empty() && i < tx->vout.size()) {
- PSBTOutput output;
- s >> output;
- outputs.push_back(output);
- ++i;
- }
- // Make sure that the number of outputs matches the number of outputs in the transaction
- if (outputs.size() != tx->vout.size()) {
- throw std::ios_base::failure("Outputs provided does not match the number of outputs in transaction.");
- }
- // Sanity check
- if (!IsSane()) {
- throw std::ios_base::failure("PSBT is not sane.");
- }
- }
-
- template <typename Stream>
- PartiallySignedTransaction(deserialize_type, Stream& s) {
- Unserialize(s);
- }
-};
-
/** Produce a script signature using a generic signature creator. */
bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);
@@ -676,9 +222,6 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
-/** Signs a PSBTInput */
-bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& tx, PSBTInput& input, SignatureData& sigdata, int index, int sighash = 1);
-
/** Extract signature data from a transaction input, and insert it. */
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout);
void UpdateInput(CTxIn& input, const SignatureData& data);
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index d7b1724790..91a301bcdf 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,8 +8,8 @@
#include <crypto/sha256.h>
#include <pubkey.h>
#include <script/script.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
typedef std::vector<unsigned char> valtype;
@@ -19,6 +19,10 @@ unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
+ScriptHash::ScriptHash(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
+
+PKHash::PKHash(const CPubKey& pubkey) : uint160(pubkey.GetID()) {}
+
WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
{
CSHA256().Write(in.data(), in.size()).Finalize(begin());
@@ -87,7 +91,7 @@ static bool MatchMultisig(const CScript& script, unsigned int& required, std::ve
return (it + 1 == script.end());
}
-bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
+txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
{
vSolutionsRet.clear();
@@ -95,33 +99,28 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
if (scriptPubKey.IsPayToScriptHash())
{
- typeRet = TX_SCRIPTHASH;
std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
vSolutionsRet.push_back(hashBytes);
- return true;
+ return TX_SCRIPTHASH;
}
int witnessversion;
std::vector<unsigned char> witnessprogram;
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
- typeRet = TX_WITNESS_V0_KEYHASH;
vSolutionsRet.push_back(witnessprogram);
- return true;
+ return TX_WITNESS_V0_KEYHASH;
}
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
- typeRet = TX_WITNESS_V0_SCRIPTHASH;
vSolutionsRet.push_back(witnessprogram);
- return true;
+ return TX_WITNESS_V0_SCRIPTHASH;
}
if (witnessversion != 0) {
- typeRet = TX_WITNESS_UNKNOWN;
vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
vSolutionsRet.push_back(std::move(witnessprogram));
- return true;
+ return TX_WITNESS_UNKNOWN;
}
- typeRet = TX_NONSTANDARD;
- return false;
+ return TX_NONSTANDARD;
}
// Provably prunable, data-carrying output
@@ -130,62 +129,54 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
// byte passes the IsPushOnly() test we don't care what exactly is in the
// script.
if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
- typeRet = TX_NULL_DATA;
- return true;
+ return TX_NULL_DATA;
}
std::vector<unsigned char> data;
if (MatchPayToPubkey(scriptPubKey, data)) {
- typeRet = TX_PUBKEY;
vSolutionsRet.push_back(std::move(data));
- return true;
+ return TX_PUBKEY;
}
if (MatchPayToPubkeyHash(scriptPubKey, data)) {
- typeRet = TX_PUBKEYHASH;
vSolutionsRet.push_back(std::move(data));
- return true;
+ return TX_PUBKEYHASH;
}
unsigned int required;
std::vector<std::vector<unsigned char>> keys;
if (MatchMultisig(scriptPubKey, required, keys)) {
- typeRet = TX_MULTISIG;
vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
- return true;
+ return TX_MULTISIG;
}
vSolutionsRet.clear();
- typeRet = TX_NONSTANDARD;
- return false;
+ return TX_NONSTANDARD;
}
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
std::vector<valtype> vSolutions;
- txnouttype whichType;
- if (!Solver(scriptPubKey, whichType, vSolutions))
- return false;
+ txnouttype whichType = Solver(scriptPubKey, vSolutions);
- if (whichType == TX_PUBKEY)
- {
+ if (whichType == TX_PUBKEY) {
CPubKey pubKey(vSolutions[0]);
if (!pubKey.IsValid())
return false;
- addressRet = pubKey.GetID();
+ addressRet = PKHash(pubKey);
return true;
}
else if (whichType == TX_PUBKEYHASH)
{
- addressRet = CKeyID(uint160(vSolutions[0]));
+ addressRet = PKHash(uint160(vSolutions[0]));
return true;
}
else if (whichType == TX_SCRIPTHASH)
{
- addressRet = CScriptID(uint160(vSolutions[0]));
+ addressRet = ScriptHash(uint160(vSolutions[0]));
return true;
} else if (whichType == TX_WITNESS_V0_KEYHASH) {
WitnessV0KeyHash hash;
@@ -212,11 +203,11 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
{
addressRet.clear();
- typeRet = TX_NONSTANDARD;
std::vector<valtype> vSolutions;
- if (!Solver(scriptPubKey, typeRet, vSolutions))
+ typeRet = Solver(scriptPubKey, vSolutions);
+ if (typeRet == TX_NONSTANDARD) {
return false;
- if (typeRet == TX_NULL_DATA){
+ } else if (typeRet == TX_NULL_DATA) {
// This is data, not addresses
return false;
}
@@ -230,7 +221,7 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::
if (!pubKey.IsValid())
continue;
- CTxDestination address = pubKey.GetID();
+ CTxDestination address = PKHash(pubKey);
addressRet.push_back(address);
}
@@ -263,13 +254,13 @@ public:
return false;
}
- bool operator()(const CKeyID &keyID) const {
+ bool operator()(const PKHash &keyID) const {
script->clear();
*script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
return true;
}
- bool operator()(const CScriptID &scriptID) const {
+ bool operator()(const ScriptHash &scriptID) const {
script->clear();
*script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
return true;
@@ -324,14 +315,12 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
CScript GetScriptForWitness(const CScript& redeemscript)
{
- txnouttype typ;
std::vector<std::vector<unsigned char> > vSolutions;
- if (Solver(redeemscript, typ, vSolutions)) {
- if (typ == TX_PUBKEY) {
- return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
- } else if (typ == TX_PUBKEYHASH) {
- return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
- }
+ txnouttype typ = Solver(redeemscript, vSolutions);
+ if (typ == TX_PUBKEY) {
+ return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
+ } else if (typ == TX_PUBKEYHASH) {
+ return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
}
return GetScriptForDestination(WitnessV0ScriptHash(redeemscript));
}
diff --git a/src/script/standard.h b/src/script/standard.h
index 1380030871..e45e2d92cc 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -73,6 +73,22 @@ public:
friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; }
};
+struct PKHash : public uint160
+{
+ PKHash() : uint160() {}
+ explicit PKHash(const uint160& hash) : uint160(hash) {}
+ explicit PKHash(const CPubKey& pubkey);
+ using uint160::uint160;
+};
+
+struct ScriptHash : public uint160
+{
+ ScriptHash() : uint160() {}
+ explicit ScriptHash(const uint160& hash) : uint160(hash) {}
+ explicit ScriptHash(const CScript& script);
+ using uint160::uint160;
+};
+
struct WitnessV0ScriptHash : public uint256
{
WitnessV0ScriptHash() : uint256() {}
@@ -113,14 +129,14 @@ struct WitnessUnknown
/**
* A txout script template with a specific destination. It is either:
* * CNoDestination: no destination set
- * * CKeyID: TX_PUBKEYHASH destination (P2PKH)
- * * CScriptID: TX_SCRIPTHASH destination (P2SH)
+ * * PKHash: TX_PUBKEYHASH destination (P2PKH)
+ * * ScriptHash: TX_SCRIPTHASH destination (P2SH)
* * WitnessV0ScriptHash: TX_WITNESS_V0_SCRIPTHASH destination (P2WSH)
* * WitnessV0KeyHash: TX_WITNESS_V0_KEYHASH destination (P2WPKH)
* * WitnessUnknown: TX_WITNESS_UNKNOWN destination (P2W???)
* A CTxDestination is the internal data type encoded in a bitcoin address
*/
-typedef boost::variant<CNoDestination, CKeyID, CScriptID, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> CTxDestination;
+typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> CTxDestination;
/** Check whether a CTxDestination is a CNoDestination. */
bool IsValidDestination(const CTxDestination& dest);
@@ -135,11 +151,10 @@ const char* GetTxnOutputType(txnouttype t);
* script hash, for P2PKH it will contain the key hash, etc.
*
* @param[in] scriptPubKey Script to parse
- * @param[out] typeRet The script type
* @param[out] vSolutionsRet Vector of parsed pubkeys and hashes
- * @return True if script matches standard template
+ * @return The script type. TX_NONSTANDARD represents a failed solve.
*/
-bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
+txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet);
/**
* Parse a standard scriptPubKey for the destination address. Assigns result to
@@ -154,8 +169,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
* multisig scripts, this populates the addressRet vector with the pubkey IDs
* and nRequiredRet with the n required to spend. For other destinations,
* addressRet is populated with a single value and nRequiredRet is set to 1.
- * Returns true if successful. Currently does not extract address from
- * pay-to-witness scripts.
+ * Returns true if successful.
*
* Note: this function confuses destinations (a subset of CScripts that are
* encodable as an address) with key identifiers (of keys involved in a
diff --git a/src/serialize.h b/src/serialize.h
index 99d4c893f2..b001ee1324 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -89,6 +89,11 @@ template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
obj = htole32(obj);
s.write((char*)&obj, 4);
}
+template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
+{
+ obj = htobe32(obj);
+ s.write((char*)&obj, 4);
+}
template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
{
obj = htole64(obj);
@@ -118,6 +123,12 @@ template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
s.read((char*)&obj, 4);
return le32toh(obj);
}
+template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
+{
+ uint32_t obj;
+ s.read((char*)&obj, 4);
+ return be32toh(obj);
+}
template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
{
uint64_t obj;
@@ -901,10 +912,9 @@ class CSizeComputer
protected:
size_t nSize;
- const int nType;
const int nVersion;
public:
- CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {}
+ explicit CSizeComputer(int nVersionIn) : nSize(0), nVersion(nVersionIn) {}
void write(const char *psz, size_t _nSize)
{
@@ -929,7 +939,6 @@ public:
}
int GetVersion() const { return nVersion; }
- int GetType() const { return nType; }
};
template<typename Stream>
@@ -980,21 +989,15 @@ inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
}
template <typename T>
-size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
-{
- return (CSizeComputer(nType, nVersion) << t).size();
-}
-
-template <typename S, typename T>
-size_t GetSerializeSize(const S& s, const T& t)
+size_t GetSerializeSize(const T& t, int nVersion = 0)
{
- return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size();
+ return (CSizeComputer(nVersion) << t).size();
}
-template <typename S, typename... T>
-size_t GetSerializeSizeMany(const S& s, const T&... t)
+template <typename... T>
+size_t GetSerializeSizeMany(int nVersion, const T&... t)
{
- CSizeComputer sc(s.GetType(), s.GetVersion());
+ CSizeComputer sc(nVersion);
SerializeMany(sc, t...);
return sc.size();
}
diff --git a/src/streams.h b/src/streams.h
index ed2e985d76..4e600f1826 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -61,14 +61,9 @@ public:
int GetVersion() const { return nVersion; }
int GetType() const { return nType; }
+ size_t size() const { return stream->size(); }
};
-template<typename S>
-OverrideStream<S> WithOrVersion(S* s, int nVersionFlag)
-{
- return OverrideStream<S>(s, s->GetType(), s->GetVersion() | nVersionFlag);
-}
-
/* Minimal stream for overwriting and/or appending to an existing byte vector
*
* The referenced vector will grow as necessary
@@ -125,12 +120,6 @@ class CVectorWriter
{
return nType;
}
- void seek(size_t nSize)
- {
- nPos += nSize;
- if(nPos > vchData.size())
- vchData.resize(nPos);
- }
private:
const int nType;
const int nVersion;
@@ -138,6 +127,74 @@ private:
size_t nPos;
};
+/** Minimal stream for reading from an existing vector by reference
+ */
+class VectorReader
+{
+private:
+ const int m_type;
+ const int m_version;
+ const std::vector<unsigned char>& m_data;
+ size_t m_pos = 0;
+
+public:
+
+ /**
+ * @param[in] type Serialization Type
+ * @param[in] version Serialization Version (including any flags)
+ * @param[in] data Referenced byte vector to overwrite/append
+ * @param[in] pos Starting position. Vector index where reads should start.
+ */
+ VectorReader(int type, int version, const std::vector<unsigned char>& data, size_t pos)
+ : m_type(type), m_version(version), m_data(data), m_pos(pos)
+ {
+ if (m_pos > m_data.size()) {
+ throw std::ios_base::failure("VectorReader(...): end of data (m_pos > m_data.size())");
+ }
+ }
+
+ /**
+ * (other params same as above)
+ * @param[in] args A list of items to deserialize starting at pos.
+ */
+ template <typename... Args>
+ VectorReader(int type, int version, const std::vector<unsigned char>& data, size_t pos,
+ Args&&... args)
+ : VectorReader(type, version, data, pos)
+ {
+ ::UnserializeMany(*this, std::forward<Args>(args)...);
+ }
+
+ template<typename T>
+ VectorReader& operator>>(T& obj)
+ {
+ // Unserialize from this stream
+ ::Unserialize(*this, obj);
+ return (*this);
+ }
+
+ int GetVersion() const { return m_version; }
+ int GetType() const { return m_type; }
+
+ size_t size() const { return m_data.size() - m_pos; }
+ bool empty() const { return m_data.size() == m_pos; }
+
+ void read(char* dst, size_t n)
+ {
+ if (n == 0) {
+ return;
+ }
+
+ // Read from the beginning of the buffer
+ size_t pos_next = m_pos + n;
+ if (pos_next > m_data.size()) {
+ throw std::ios_base::failure("VectorReader::read(): end of data");
+ }
+ memcpy(dst, m_data.data() + m_pos, n);
+ m_pos = pos_next;
+ }
+};
+
/** Double ended buffer combining vector and stream-like interfaces.
*
* >> and << read and write unformatted data using the above serialization templates.
@@ -435,12 +492,105 @@ public:
}
};
+template <typename IStream>
+class BitStreamReader
+{
+private:
+ IStream& m_istream;
+
+ /// Buffered byte read in from the input stream. A new byte is read into the
+ /// buffer when m_offset reaches 8.
+ uint8_t m_buffer{0};
+
+ /// Number of high order bits in m_buffer already returned by previous
+ /// Read() calls. The next bit to be returned is at this offset from the
+ /// most significant bit position.
+ int m_offset{8};
+
+public:
+ explicit BitStreamReader(IStream& istream) : m_istream(istream) {}
+
+ /** Read the specified number of bits from the stream. The data is returned
+ * in the nbits least significant bits of a 64-bit uint.
+ */
+ uint64_t Read(int nbits) {
+ if (nbits < 0 || nbits > 64) {
+ throw std::out_of_range("nbits must be between 0 and 64");
+ }
+
+ uint64_t data = 0;
+ while (nbits > 0) {
+ if (m_offset == 8) {
+ m_istream >> m_buffer;
+ m_offset = 0;
+ }
+
+ int bits = std::min(8 - m_offset, nbits);
+ data <<= bits;
+ data |= static_cast<uint8_t>(m_buffer << m_offset) >> (8 - bits);
+ m_offset += bits;
+ nbits -= bits;
+ }
+ return data;
+ }
+};
+
+template <typename OStream>
+class BitStreamWriter
+{
+private:
+ OStream& m_ostream;
+ /// Buffered byte waiting to be written to the output stream. The byte is
+ /// written buffer when m_offset reaches 8 or Flush() is called.
+ uint8_t m_buffer{0};
+ /// Number of high order bits in m_buffer already written by previous
+ /// Write() calls and not yet flushed to the stream. The next bit to be
+ /// written to is at this offset from the most significant bit position.
+ int m_offset{0};
+
+public:
+ explicit BitStreamWriter(OStream& ostream) : m_ostream(ostream) {}
+ ~BitStreamWriter()
+ {
+ Flush();
+ }
+ /** Write the nbits least significant bits of a 64-bit int to the output
+ * stream. Data is buffered until it completes an octet.
+ */
+ void Write(uint64_t data, int nbits) {
+ if (nbits < 0 || nbits > 64) {
+ throw std::out_of_range("nbits must be between 0 and 64");
+ }
+ while (nbits > 0) {
+ int bits = std::min(8 - m_offset, nbits);
+ m_buffer |= (data << (64 - nbits)) >> (64 - 8 + m_offset);
+ m_offset += bits;
+ nbits -= bits;
+ if (m_offset == 8) {
+ Flush();
+ }
+ }
+ }
+
+ /** Flush any unwritten bits to the output stream, padding with 0's to the
+ * next byte boundary.
+ */
+ void Flush() {
+ if (m_offset == 0) {
+ return;
+ }
+
+ m_ostream << m_buffer;
+ m_buffer = 0;
+ m_offset = 0;
+ }
+};
@@ -565,15 +715,15 @@ private:
const int nType;
const int nVersion;
- FILE *src; // source file
- uint64_t nSrcPos; // how many bytes have been read from source
- uint64_t nReadPos; // 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<char> vchBuf; // the buffer
+ FILE *src; //!< source file
+ uint64_t nSrcPos; //!< how many bytes have been read from source
+ uint64_t nReadPos; //!< 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<char> vchBuf; //!< the buffer
protected:
- // read data from the source to fill the buffer
+ //! read data from the source to fill the buffer
bool Fill() {
unsigned int pos = nSrcPos % vchBuf.size();
unsigned int readNow = vchBuf.size() - pos;
@@ -593,7 +743,7 @@ protected:
public:
CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
- nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0)
+ nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit(std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn), vchBuf(nBufSize, 0)
{
src = fileIn;
}
@@ -618,12 +768,12 @@ public:
}
}
- // check whether we're at the end of the source file
+ //! check whether we're at the end of the source file
bool eof() const {
return nReadPos == nSrcPos && feof(src);
}
- // read a number of bytes
+ //! read a number of bytes
void read(char *pch, size_t nSize) {
if (nSize + nReadPos > nReadLimit)
throw std::ios_base::failure("Read attempted past buffer limit");
@@ -645,12 +795,12 @@ public:
}
}
- // return the current reading position
+ //! return the current reading position
uint64_t GetPos() const {
return nReadPos;
}
- // rewind to a given reading position
+ //! rewind to a given reading position
bool SetPos(uint64_t nPos) {
nReadPos = nPos;
if (nReadPos + nRewind < nSrcPos) {
@@ -676,9 +826,9 @@ public:
return true;
}
- // prevent reading beyond a certain position
- // no argument removes the limit
- bool SetLimit(uint64_t nPos = (uint64_t)(-1)) {
+ //! prevent reading beyond a certain position
+ //! no argument removes the limit
+ bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
if (nPos < nReadPos)
return false;
nReadLimit = nPos;
@@ -692,7 +842,7 @@ public:
return (*this);
}
- // search for a given byte in the stream, and remain positioned on it
+ //! search for a given byte in the stream, and remain positioned on it
void FindByte(char ch) {
while (true) {
if (nReadPos == nSrcPos)
diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h
index 0249afa499..57f5b1f733 100644
--- a/src/support/allocators/secure.h
+++ b/src/support/allocators/secure.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -40,7 +40,11 @@ struct secure_allocator : public std::allocator<T> {
T* allocate(std::size_t n, const void* hint = 0)
{
- return static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
+ T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
+ if (!allocation) {
+ throw std::bad_alloc();
+ }
+ return allocation;
}
void deallocate(T* p, std::size_t n)
diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h
index 78ff1ad024..c7ed5ef308 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-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/support/cleanse.cpp b/src/support/cleanse.cpp
index 9bf7eda785..17a4a4c2b2 100644
--- a/src/support/cleanse.cpp
+++ b/src/support/cleanse.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/support/cleanse.h b/src/support/cleanse.h
index 69c27df519..5298214e44 100644
--- a/src/support/cleanse.h
+++ b/src/support/cleanse.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/support/events.h b/src/support/events.h
index 7ad51f319c..0a74d02368 100644
--- a/src/support/events.h
+++ b/src/support/events.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
index a273424b51..5c2050e4a2 100644
--- a/src/support/lockedpool.cpp
+++ b/src/support/lockedpool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,10 +10,6 @@
#endif
#ifdef WIN32
-#ifdef _WIN32_WINNT
-#undef _WIN32_WINNT
-#endif
-#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX
@@ -75,7 +71,7 @@ void* Arena::alloc(size_t size)
// Create the used-chunk, taking its space from the end of the free-chunk
const size_t size_remaining = size_ptr_it->first - size;
- auto alloced = chunks_used.emplace(size_ptr_it->second + size_remaining, size).first;
+ auto allocated = chunks_used.emplace(size_ptr_it->second + size_remaining, size).first;
chunks_free_end.erase(size_ptr_it->second + size_ptr_it->first);
if (size_ptr_it->first == size) {
// whole chunk is used up
@@ -88,7 +84,7 @@ void* Arena::alloc(size_t size)
}
size_to_free_chunk.erase(size_ptr_it);
- return reinterpret_cast<void*>(alloced->first);
+ return reinterpret_cast<void*>(allocated->first);
}
void Arena::free(void *ptr)
@@ -248,6 +244,9 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
void *addr;
len = align_up(len, page_size);
addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (addr == MAP_FAILED) {
+ return nullptr;
+ }
if (addr) {
*lockingSuccess = mlock(addr, len) == 0;
}
diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h
index ccfae16701..b420c909fc 100644
--- a/src/support/lockedpool.h
+++ b/src/support/lockedpool.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -22,7 +22,7 @@ public:
virtual ~LockedPageAllocator() {}
/** Allocate and lock memory pages.
* If len is not a multiple of the system page size, it is rounded up.
- * Returns 0 in case of allocation failure.
+ * Returns nullptr in case of allocation failure.
*
* If locking the memory pages could not be accomplished it will still
* return the memory, however the lockingSuccess flag will be false.
diff --git a/src/sync.cpp b/src/sync.cpp
index 28a4e37e68..c2767b200a 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -1,11 +1,17 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
#include <sync.h>
+#include <tinyformat.h>
#include <logging.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
+#include <util/threadnames.h>
#include <stdio.h>
@@ -37,23 +43,30 @@ void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
//
struct CLockLocation {
- CLockLocation(const char* pszName, const char* pszFile, int nLine, bool fTryIn)
- {
- mutexName = pszName;
- sourceFile = pszFile;
- sourceLine = nLine;
- fTry = fTryIn;
- }
+ CLockLocation(
+ const char* pszName,
+ const char* pszFile,
+ int nLine,
+ bool fTryIn,
+ const std::string& thread_name)
+ : fTry(fTryIn),
+ mutexName(pszName),
+ sourceFile(pszFile),
+ m_thread_name(thread_name),
+ sourceLine(nLine) {}
std::string ToString() const
{
- return mutexName + " " + sourceFile + ":" + itostr(sourceLine) + (fTry ? " (TRY)" : "");
+ return tfm::format(
+ "%s %s:%s%s (in thread %s)",
+ mutexName, sourceFile, itostr(sourceLine), (fTry ? " (TRY)" : ""), m_thread_name);
}
private:
bool fTry;
std::string mutexName;
std::string sourceFile;
+ const std::string& m_thread_name;
int sourceLine;
};
@@ -73,7 +86,11 @@ struct LockData {
LockOrders lockorders;
InvLockOrders invlockorders;
std::mutex dd_mutex;
-} static lockdata;
+};
+LockData& GetLockData() {
+ static LockData lockdata;
+ return lockdata;
+}
static thread_local LockStack g_lockstack;
@@ -100,11 +117,16 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
}
LogPrintf(" %s\n", i.second.ToString());
}
- assert(false);
+ if (g_debug_lockorder_abort) {
+ fprintf(stderr, "Assertion failed: detected inconsistent lock order at %s:%i, details in debug log.\n", __FILE__, __LINE__);
+ abort();
+ }
+ throw std::logic_error("potential deadlock detected");
}
static void push_lock(void* c, const CLockLocation& locklocation)
{
+ LockData& lockdata = GetLockData();
std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
g_lockstack.push_back(std::make_pair(c, locklocation));
@@ -116,7 +138,7 @@ static void push_lock(void* c, const CLockLocation& locklocation)
std::pair<void*, void*> p1 = std::make_pair(i.first, c);
if (lockdata.lockorders.count(p1))
continue;
- lockdata.lockorders[p1] = g_lockstack;
+ lockdata.lockorders.emplace(p1, g_lockstack);
std::pair<void*, void*> p2 = std::make_pair(c, i.first);
lockdata.invlockorders.insert(p2);
@@ -132,7 +154,7 @@ static void pop_lock()
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
{
- push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry));
+ push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry, util::ThreadGetInternalName()));
}
void LeaveCritical()
@@ -169,6 +191,7 @@ void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLi
void DeleteLock(void* cs)
{
+ LockData& lockdata = GetLockData();
if (!lockdata.available) {
// We're already shutting down.
return;
@@ -189,4 +212,6 @@ void DeleteLock(void* cs)
}
}
+bool g_debug_lockorder_abort = true;
+
#endif /* DEBUG_LOCKORDER */
diff --git a/src/sync.h b/src/sync.h
index 882ad5dc4c..2667fb52f9 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -20,7 +20,7 @@
////////////////////////////////////////////////
/*
-CCriticalSection mutex;
+RecursiveMutex mutex;
std::recursive_mutex mutex;
LOCK(mutex);
@@ -46,14 +46,42 @@ LEAVE_CRITICAL_SECTION(mutex); // no RAII
// //
///////////////////////////////
+#ifdef DEBUG_LOCKORDER
+void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
+void LeaveCritical();
+std::string LocksHeld();
+void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) ASSERT_EXCLUSIVE_LOCK(cs);
+void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
+void DeleteLock(void* cs);
+
+/**
+ * Call abort() if a potential lock order deadlock bug is detected, instead of
+ * just logging information and throwing a logic_error. Defaults to true, and
+ * set to false in DEBUG_LOCKORDER unit tests.
+ */
+extern bool g_debug_lockorder_abort;
+#else
+void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
+void static inline LeaveCritical() {}
+void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) ASSERT_EXCLUSIVE_LOCK(cs) {}
+void static inline AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
+void static inline DeleteLock(void* cs) {}
+#endif
+#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
+#define AssertLockNotHeld(cs) AssertLockNotHeldInternal(#cs, __FILE__, __LINE__, &cs)
+
/**
- * Template mixin that adds -Wthread-safety locking
- * annotations to a subset of the mutex API.
+ * Template mixin that adds -Wthread-safety locking annotations and lock order
+ * checking to a subset of the mutex API.
*/
template <typename PARENT>
class LOCKABLE AnnotatedMixin : public PARENT
{
public:
+ ~AnnotatedMixin() {
+ DeleteLock((void*)this);
+ }
+
void lock() EXCLUSIVE_LOCK_FUNCTION()
{
PARENT::lock();
@@ -68,64 +96,37 @@ public:
{
return PARENT::try_lock();
}
-};
-#ifdef DEBUG_LOCKORDER
-void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
-void LeaveCritical();
-std::string LocksHeld();
-void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) ASSERT_EXCLUSIVE_LOCK(cs);
-void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
-void DeleteLock(void* cs);
-#else
-void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
-void static inline LeaveCritical() {}
-void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) ASSERT_EXCLUSIVE_LOCK(cs) {}
-void static inline AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
-void static inline DeleteLock(void* cs) {}
-#endif
-#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
-#define AssertLockNotHeld(cs) AssertLockNotHeldInternal(#cs, __FILE__, __LINE__, &cs)
+ using UniqueLock = std::unique_lock<PARENT>;
+};
/**
* Wrapped mutex: supports recursive locking, but no waiting
* TODO: We should move away from using the recursive lock by default.
*/
-class CCriticalSection : public AnnotatedMixin<std::recursive_mutex>
-{
-public:
- ~CCriticalSection() {
- DeleteLock((void*)this);
- }
-};
+using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
+typedef AnnotatedMixin<std::recursive_mutex> CCriticalSection;
/** Wrapped mutex: supports waiting but not recursive locking */
-typedef AnnotatedMixin<std::mutex> CWaitableCriticalSection;
-
-/** Just a typedef for std::condition_variable, can be wrapped later if desired */
-typedef std::condition_variable CConditionVariable;
-
-/** Just a typedef for std::unique_lock, can be wrapped later if desired */
-typedef std::unique_lock<std::mutex> WaitableLock;
+typedef AnnotatedMixin<std::mutex> Mutex;
#ifdef DEBUG_LOCKCONTENTION
void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
#endif
-/** Wrapper around std::unique_lock<CCriticalSection> */
-class SCOPED_LOCKABLE CCriticalBlock
+/** Wrapper around std::unique_lock style lock for Mutex. */
+template <typename Mutex, typename Base = typename Mutex::UniqueLock>
+class SCOPED_LOCKABLE UniqueLock : public Base
{
private:
- std::unique_lock<CCriticalSection> lock;
-
void Enter(const char* pszName, const char* pszFile, int nLine)
{
- EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
+ EnterCritical(pszName, pszFile, nLine, (void*)(Base::mutex()));
#ifdef DEBUG_LOCKCONTENTION
- if (!lock.try_lock()) {
+ if (!Base::try_lock()) {
PrintLockContention(pszName, pszFile, nLine);
#endif
- lock.lock();
+ Base::lock();
#ifdef DEBUG_LOCKCONTENTION
}
#endif
@@ -133,15 +134,15 @@ private:
bool TryEnter(const char* pszName, const char* pszFile, int nLine)
{
- EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
- lock.try_lock();
- if (!lock.owns_lock())
+ EnterCritical(pszName, pszFile, nLine, (void*)(Base::mutex()), true);
+ Base::try_lock();
+ if (!Base::owns_lock())
LeaveCritical();
- return lock.owns_lock();
+ return Base::owns_lock();
}
public:
- CCriticalBlock(CCriticalSection& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, std::defer_lock)
+ UniqueLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
{
if (fTry)
TryEnter(pszName, pszFile, nLine);
@@ -149,35 +150,41 @@ public:
Enter(pszName, pszFile, nLine);
}
- CCriticalBlock(CCriticalSection* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
+ UniqueLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
{
if (!pmutexIn) return;
- lock = std::unique_lock<CCriticalSection>(*pmutexIn, std::defer_lock);
+ *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);
if (fTry)
TryEnter(pszName, pszFile, nLine);
else
Enter(pszName, pszFile, nLine);
}
- ~CCriticalBlock() UNLOCK_FUNCTION()
+ ~UniqueLock() UNLOCK_FUNCTION()
{
- if (lock.owns_lock())
+ if (Base::owns_lock())
LeaveCritical();
}
operator bool()
{
- return lock.owns_lock();
+ return Base::owns_lock();
}
};
+template<typename MutexArg>
+using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
+
#define PASTE(x, y) x ## y
#define PASTE2(x, y) PASTE(x, y)
-#define LOCK(cs) CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
-#define LOCK2(cs1, cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), criticalblock2(cs2, #cs2, __FILE__, __LINE__)
-#define TRY_LOCK(cs, name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
+#define LOCK(cs) DebugLock<decltype(cs)> PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
+#define LOCK2(cs1, cs2) \
+ DebugLock<decltype(cs1)> criticalblock1(cs1, #cs1, __FILE__, __LINE__); \
+ DebugLock<decltype(cs2)> criticalblock2(cs2, #cs2, __FILE__, __LINE__);
+#define TRY_LOCK(cs, name) DebugLock<decltype(cs)> name(cs, #cs, __FILE__, __LINE__, true)
+#define WAIT_LOCK(cs, name) DebugLock<decltype(cs)> name(cs, #cs, __FILE__, __LINE__)
#define ENTER_CRITICAL_SECTION(cs) \
{ \
@@ -191,6 +198,16 @@ public:
LeaveCritical(); \
}
+//! Run code while locking a mutex.
+//!
+//! Examples:
+//!
+//! WITH_LOCK(cs, shared_val = shared_val + 1);
+//!
+//! int val = WITH_LOCK(cs, return shared_val);
+//!
+#define WITH_LOCK(cs, code) [&] { LOCK(cs); code; }()
+
class CSemaphore
{
private:
diff --git a/src/test/README.md b/src/test/README.md
index f2a4cb1818..0017e3de26 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -42,7 +42,7 @@ unit tests as possible).
The build system is setup to compile an executable called `test_bitcoin`
that runs all of the unit tests. The main source file is called
-test_bitcoin.cpp. To add a new unit test file to our test suite you need
+setup_common.cpp. To add a new unit test file to our test suite you need
to add the file to `src/Makefile.test.include`. The pattern is to create
one test file for each class or source file for which you want to create
unit tests. The file naming convention is `<source_filename>_tests.cpp`
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index ee3650d148..eeb54b4cf0 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -1,8 +1,8 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <addrman.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <string>
#include <boost/test/unit_test.hpp>
@@ -12,13 +12,9 @@
class CAddrManTest : public CAddrMan
{
- uint64_t state;
-
public:
explicit CAddrManTest(bool makeDeterministic = true)
{
- state = 1;
-
if (makeDeterministic) {
// Set addrman addr placement to be deterministic.
MakeDeterministic();
@@ -32,30 +28,28 @@ public:
insecure_rand = FastRandomContext(true);
}
- int RandomInt(int nMax) override
- {
- state = (CHashWriter(SER_GETHASH, 0) << state).GetHash().GetCheapHash();
- return (unsigned int)(state % nMax);
- }
-
CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr)
{
+ LOCK(cs);
return CAddrMan::Find(addr, pnId);
}
CAddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr)
{
+ LOCK(cs);
return CAddrMan::Create(addr, addrSource, pnId);
}
void Delete(int nId)
{
+ LOCK(cs);
CAddrMan::Delete(nId);
}
// Simulates connection failure so that we can test eviction of offline nodes
void SimConnFail(CService& addr)
{
+ LOCK(cs);
int64_t nLastSuccess = 1;
Good_(addr, true, nLastSuccess); // Set last good connection in the deep past.
@@ -150,11 +144,11 @@ BOOST_AUTO_TEST_CASE(addrman_ports)
// Test 7; Addr with same IP but diff port does not replace existing addr.
CService addr1 = ResolveService("250.1.1.1", 8333);
- addrman.Add(CAddress(addr1, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source));
BOOST_CHECK_EQUAL(addrman.size(), 1U);
CService addr1_port = ResolveService("250.1.1.1", 8334);
- addrman.Add(CAddress(addr1_port, NODE_NONE), source);
+ BOOST_CHECK(!addrman.Add(CAddress(addr1_port, NODE_NONE), source));
BOOST_CHECK_EQUAL(addrman.size(), 1U);
CAddrInfo addr_ret2 = addrman.Select();
BOOST_CHECK_EQUAL(addr_ret2.ToString(), "250.1.1.1:8333");
@@ -177,7 +171,7 @@ BOOST_AUTO_TEST_CASE(addrman_select)
// Test: Select from new with 1 addr in new.
CService addr1 = ResolveService("250.1.1.1", 8333);
- addrman.Add(CAddress(addr1, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source));
BOOST_CHECK_EQUAL(addrman.size(), 1U);
bool newOnly = true;
@@ -201,20 +195,20 @@ BOOST_AUTO_TEST_CASE(addrman_select)
CService addr3 = ResolveService("250.3.2.2", 9999);
CService addr4 = ResolveService("250.3.3.3", 9999);
- addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333));
- addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333));
- addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333));
+ BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333)));
+ BOOST_CHECK(addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333)));
+ BOOST_CHECK(addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333)));
// Add three addresses to tried table.
CService addr5 = ResolveService("250.4.4.4", 8333);
CService addr6 = ResolveService("250.4.5.5", 7777);
CService addr7 = ResolveService("250.4.6.6", 8333);
- addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333));
+ BOOST_CHECK(addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333)));
addrman.Good(CAddress(addr5, NODE_NONE));
- addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333));
+ BOOST_CHECK(addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333)));
addrman.Good(CAddress(addr6, NODE_NONE));
- addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333));
+ BOOST_CHECK(addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333)));
addrman.Good(CAddress(addr7, NODE_NONE));
// Test: 6 addrs + 1 addr from last test = 7.
@@ -238,7 +232,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
for (unsigned int i = 1; i < 18; i++) {
CService addr = ResolveService("250.1.1." + std::to_string(i));
- addrman.Add(CAddress(addr, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
//Test: No collision in new table yet.
BOOST_CHECK_EQUAL(addrman.size(), i);
@@ -246,11 +240,11 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
//Test: new table collision!
CService addr1 = ResolveService("250.1.1.18");
- addrman.Add(CAddress(addr1, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source));
BOOST_CHECK_EQUAL(addrman.size(), 17U);
CService addr2 = ResolveService("250.1.1.19");
- addrman.Add(CAddress(addr2, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source));
BOOST_CHECK_EQUAL(addrman.size(), 18U);
}
@@ -264,7 +258,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
for (unsigned int i = 1; i < 80; i++) {
CService addr = ResolveService("250.1.1." + std::to_string(i));
- addrman.Add(CAddress(addr, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(CAddress(addr, NODE_NONE));
//Test: No collision in tried table yet.
@@ -273,11 +267,11 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
//Test: tried table collision!
CService addr1 = ResolveService("250.1.1.80");
- addrman.Add(CAddress(addr1, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source));
BOOST_CHECK_EQUAL(addrman.size(), 79U);
CService addr2 = ResolveService("250.1.1.81");
- addrman.Add(CAddress(addr2, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source));
BOOST_CHECK_EQUAL(addrman.size(), 80U);
}
@@ -294,9 +288,9 @@ BOOST_AUTO_TEST_CASE(addrman_find)
CNetAddr source1 = ResolveIP("250.1.2.1");
CNetAddr source2 = ResolveIP("250.1.2.2");
- addrman.Add(addr1, source1);
- addrman.Add(addr2, source2);
- addrman.Add(addr3, source1);
+ BOOST_CHECK(addrman.Add(addr1, source1));
+ BOOST_CHECK(!addrman.Add(addr2, source2));
+ BOOST_CHECK(addrman.Add(addr3, source1));
// Test: ensure Find returns an IP matching what we searched on.
CAddrInfo* info1 = addrman.Find(addr1);
@@ -378,11 +372,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
CNetAddr source2 = ResolveIP("250.2.3.3");
// Test: Ensure GetAddr works with new addresses.
- addrman.Add(addr1, source1);
- addrman.Add(addr2, source2);
- addrman.Add(addr3, source1);
- addrman.Add(addr4, source2);
- addrman.Add(addr5, source1);
+ BOOST_CHECK(addrman.Add(addr1, source1));
+ BOOST_CHECK(addrman.Add(addr2, source2));
+ BOOST_CHECK(addrman.Add(addr3, source1));
+ BOOST_CHECK(addrman.Add(addr4, source2));
+ BOOST_CHECK(addrman.Add(addr5, source1));
// GetAddr returns 23% of addresses, 23% of 5 is 1 rounded down.
BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1U);
@@ -551,7 +545,7 @@ BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
CNetAddr source = ResolveIP("252.2.2.2");
for (unsigned int i = 1; i < 23; i++) {
CService addr = ResolveService("250.1.1."+std::to_string(i));
- addrman.Add(CAddress(addr, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
// No collisions yet.
@@ -581,7 +575,7 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
CNetAddr source = ResolveIP("252.2.2.2");
for (unsigned int i = 1; i < 23; i++) {
CService addr = ResolveService("250.1.1."+std::to_string(i));
- addrman.Add(CAddress(addr, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
// No collision yet.
@@ -591,7 +585,7 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
// Collision between 23 and 19.
CService addr23 = ResolveService("250.1.1.23");
- addrman.Add(CAddress(addr23, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr23, NODE_NONE), source));
addrman.Good(addr23);
BOOST_CHECK(addrman.size() == 23);
@@ -604,7 +598,7 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
// Lets create two collisions.
for (unsigned int i = 24; i < 33; i++) {
CService addr = ResolveService("250.1.1."+std::to_string(i));
- addrman.Add(CAddress(addr, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
BOOST_CHECK(addrman.size() == i);
@@ -613,14 +607,14 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
// Cause a collision.
CService addr33 = ResolveService("250.1.1.33");
- addrman.Add(CAddress(addr33, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr33, NODE_NONE), source));
addrman.Good(addr33);
BOOST_CHECK(addrman.size() == 33);
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.27:0");
// Cause a second collision.
- addrman.Add(CAddress(addr23, NODE_NONE), source);
+ BOOST_CHECK(!addrman.Add(CAddress(addr23, NODE_NONE), source));
addrman.Good(addr23);
BOOST_CHECK(addrman.size() == 33);
@@ -645,7 +639,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
CNetAddr source = ResolveIP("252.2.2.2");
for (unsigned int i = 1; i < 23; i++) {
CService addr = ResolveService("250.1.1."+std::to_string(i));
- addrman.Add(CAddress(addr, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
// No collision yet.
@@ -655,7 +649,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
// Collision between 23 and 19.
CService addr = ResolveService("250.1.1.23");
- addrman.Add(CAddress(addr, NODE_NONE), source);
+ BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
BOOST_CHECK(addrman.size() == 23);
@@ -670,14 +664,14 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
// If 23 was swapped for 19, then this should cause no collisions.
- addrman.Add(CAddress(addr, NODE_NONE), source);
+ BOOST_CHECK(!addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
// If we insert 19 is should collide with 23.
CService addr19 = ResolveService("250.1.1.19");
- addrman.Add(CAddress(addr19, NODE_NONE), source);
+ BOOST_CHECK(!addrman.Add(CAddress(addr19, NODE_NONE), source));
addrman.Good(addr19);
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.23:0");
diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp
index 67d1229c70..f255691704 100644
--- a/src/test/allocator_tests.cpp
+++ b/src/test/allocator_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
+#include <util/system.h>
#include <support/allocators/secure.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <memory>
@@ -105,13 +105,13 @@ BOOST_AUTO_TEST_CASE(arena_tests)
// Go entirely wild: free and alloc interleaved,
// generate targets and sizes using pseudo-randomness.
for (int x=0; x<2048; ++x)
- addr.push_back(0);
+ addr.push_back(nullptr);
uint32_t s = 0x12345678;
for (int x=0; x<5000; ++x) {
int idx = s & (addr.size()-1);
if (s & 0x80000000) {
b.free(addr[idx]);
- addr[idx] = 0;
+ addr[idx] = nullptr;
} else if(!addr[idx]) {
addr[idx] = b.alloc((s >> 16) & 2047);
}
@@ -144,9 +144,9 @@ public:
*lockingSuccess = true;
}
- return reinterpret_cast<void*>(0x08000000 + (count<<24)); // Fake address, do not actually use this memory
+ return reinterpret_cast<void*>(uint64_t{static_cast<uint64_t>(0x08000000) + (count << 24)}); // Fake address, do not actually use this memory
}
- return 0;
+ return nullptr;
}
void FreeLocked(void* addr, size_t len) override
{
@@ -163,7 +163,7 @@ private:
BOOST_AUTO_TEST_CASE(lockedpool_tests_mock)
{
// Test over three virtual arenas, of which one will succeed being locked
- std::unique_ptr<LockedPageAllocator> x(new TestLockedPageAllocator(3, 1));
+ std::unique_ptr<LockedPageAllocator> x = MakeUnique<TestLockedPageAllocator>(3, 1);
LockedPool pool(std::move(x));
BOOST_CHECK(pool.stats().total == 0);
BOOST_CHECK(pool.stats().locked == 0);
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
index 854146102e..378fe285d5 100644
--- a/src/test/amount_tests.cpp
+++ b/src/test/amount_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <amount.h>
#include <policy/feerate.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -13,8 +13,10 @@ BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(MoneyRangeTest)
{
BOOST_CHECK_EQUAL(MoneyRange(CAmount(-1)), false);
- BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false);
+ BOOST_CHECK_EQUAL(MoneyRange(CAmount(0)), true);
BOOST_CHECK_EQUAL(MoneyRange(CAmount(1)), true);
+ BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY), true);
+ BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false);
}
BOOST_AUTO_TEST_CASE(GetFeeTest)
@@ -23,43 +25,43 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
feeRate = CFeeRate(0);
// Must always return 0
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), CAmount(0));
feeRate = CFeeRate(1000);
// Must always just return the arg
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1), 1);
- BOOST_CHECK_EQUAL(feeRate.GetFee(121), 121);
- BOOST_CHECK_EQUAL(feeRate.GetFee(999), 999);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 1e3);
- BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 9e3);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1), CAmount(1));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(121));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(999));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(1e3));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(9e3));
feeRate = CFeeRate(-1000);
// Must always just return -1 * arg
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1), -1);
- BOOST_CHECK_EQUAL(feeRate.GetFee(121), -121);
- BOOST_CHECK_EQUAL(feeRate.GetFee(999), -999);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), -1e3);
- BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), -9e3);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1), CAmount(-1));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(-121));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(-999));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(-1e3));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(-9e3));
feeRate = CFeeRate(123);
// Truncates the result, if not integer
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(8), 1); // Special case: returns 1 instead of 0
- BOOST_CHECK_EQUAL(feeRate.GetFee(9), 1);
- BOOST_CHECK_EQUAL(feeRate.GetFee(121), 14);
- BOOST_CHECK_EQUAL(feeRate.GetFee(122), 15);
- BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122);
- BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 123);
- BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 1107);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(8), CAmount(1)); // Special case: returns 1 instead of 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9), CAmount(1));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), CAmount(14));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(122), CAmount(15));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), CAmount(122));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), CAmount(123));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), CAmount(1107));
feeRate = CFeeRate(-123);
// Truncates the result, if not integer
- BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
- BOOST_CHECK_EQUAL(feeRate.GetFee(8), -1); // Special case: returns -1 instead of 0
- BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmount(0));
+ BOOST_CHECK_EQUAL(feeRate.GetFee(8), CAmount(-1)); // Special case: returns -1 instead of 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9), CAmount(-1));
// check alternate constructor
feeRate = CFeeRate(1000);
@@ -67,6 +69,9 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
BOOST_CHECK_EQUAL(feeRate.GetFee(100), altFeeRate.GetFee(100));
// Check full constructor
+ BOOST_CHECK(CFeeRate(CAmount(-1), 0) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(0), 0) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(1), 0) == CFeeRate(0));
// default value
BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1));
BOOST_CHECK(CFeeRate(CAmount(0), 1000) == CFeeRate(0));
diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp
index 8644aea371..809c627d27 100644
--- a/src/test/arith_uint256_tests.cpp
+++ b/src/test/arith_uint256_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <arith_uint256.h>
#include <string>
#include <version.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup)
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
index 1210c7a7ee..b3bed2434c 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index f90d4f90cb..cb376cddb6 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -1,12 +1,12 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/data/base58_encode_decode.json.h>
#include <base58.h>
-#include <test/test_bitcoin.h>
-#include <utilstrencodings.h>
+#include <test/setup_common.h>
+#include <util/strencodings.h>
#include <univalue.h>
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index f785cede81..9ffffb0b7d 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp
index 6ecc9ac705..0ba492c24e 100644
--- a/src/test/bech32_tests.cpp
+++ b/src/test/bech32_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bech32.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 2c625c089c..0c0423c0db 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2017 The Bitcoin Core developers
+// Copyright (c) 2013-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,9 +7,9 @@
#include <key.h>
#include <key_io.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
#include <string>
#include <vector>
diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp
index 7d8ae46fb8..13afcca375 100644
--- a/src/test/blockchain_tests.cpp
+++ b/src/test/blockchain_tests.cpp
@@ -3,7 +3,7 @@
#include <stdlib.h>
#include <rpc/blockchain.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
/* Equality between doubles is imprecise. Comparison should be done
* with a small threshold of tolerance, rather than exact equality.
@@ -68,11 +68,4 @@ BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target)
TestDifficulty(0x12345678, 5913134931067755359633408.0);
}
-// Verify that difficulty is 1.0 for an empty chain.
-BOOST_AUTO_TEST_CASE(get_difficulty_for_null_tip)
-{
- double difficulty = GetDifficulty(nullptr);
- RejectDifficultyMismatch(difficulty, 1.0);
-}
-
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index df839884fe..f57e1a0ebd 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <pow.h>
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -62,8 +62,8 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- LOCK(pool.cs);
- pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
+ LOCK2(cs_main, pool.cs);
+ pool.addUnchecked(entry.FromTx(block.vtx[2]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
// Do a simple ShortTxIDs RT
@@ -162,8 +162,8 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- LOCK(pool.cs);
- pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
+ LOCK2(cs_main, pool.cs);
+ pool.addUnchecked(entry.FromTx(block.vtx[2]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
uint256 txhash;
@@ -232,8 +232,8 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- LOCK(pool.cs);
- pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(block.vtx[1]));
+ LOCK2(cs_main, pool.cs);
+ pool.addUnchecked(entry.FromTx(block.vtx[1]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
uint256 txhash;
@@ -344,4 +344,50 @@ BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) {
BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]);
}
+BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationMaxTest) {
+ // Check that the highest legal index is decoded correctly
+ BlockTransactionsRequest req0;
+ req0.blockhash = InsecureRand256();
+ req0.indexes.resize(1);
+ req0.indexes[0] = 0xffff;
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << req0;
+
+ BlockTransactionsRequest req1;
+ stream >> req1;
+ BOOST_CHECK_EQUAL(req0.indexes.size(), req1.indexes.size());
+ BOOST_CHECK_EQUAL(req0.indexes[0], req1.indexes[0]);
+}
+
+BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationOverflowTest) {
+ // Any set of index deltas that starts with N values that sum to (0x10000 - N)
+ // causes the edge-case overflow that was originally not checked for. Such
+ // a request cannot be created by serializing a real BlockTransactionsRequest
+ // due to the overflow, so here we'll serialize from raw deltas.
+ BlockTransactionsRequest req0;
+ req0.blockhash = InsecureRand256();
+ req0.indexes.resize(3);
+ req0.indexes[0] = 0x7000;
+ req0.indexes[1] = 0x10000 - 0x7000 - 2;
+ req0.indexes[2] = 0;
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << req0.blockhash;
+ WriteCompactSize(stream, req0.indexes.size());
+ WriteCompactSize(stream, req0.indexes[0]);
+ WriteCompactSize(stream, req0.indexes[1]);
+ WriteCompactSize(stream, req0.indexes[2]);
+
+ BlockTransactionsRequest req1;
+ try {
+ stream >> req1;
+ // before patch: deserialize above succeeds and this check fails, demonstrating the overflow
+ BOOST_CHECK(req1.indexes[1] < req1.indexes[2]);
+ // this shouldn't be reachable before or after patch
+ BOOST_CHECK(0);
+ } catch(std::ios_base::failure &) {
+ // deserialize should fail
+ BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
new file mode 100644
index 0000000000..7ba483173c
--- /dev/null
+++ b/src/test/blockfilter_index_tests.cpp
@@ -0,0 +1,307 @@
+// Copyright (c) 2017-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <blockfilter.h>
+#include <chainparams.h>
+#include <consensus/validation.h>
+#include <index/blockfilterindex.h>
+#include <miner.h>
+#include <pow.h>
+#include <test/setup_common.h>
+#include <script/standard.h>
+#include <validation.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(blockfilter_index_tests)
+
+static bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index,
+ BlockFilter& filter)
+{
+ CBlock block;
+ if (!ReadBlockFromDisk(block, block_index->GetBlockPos(), Params().GetConsensus())) {
+ return false;
+ }
+
+ CBlockUndo block_undo;
+ if (block_index->nHeight > 0 && !UndoReadFromDisk(block_undo, block_index)) {
+ return false;
+ }
+
+ filter = BlockFilter(filter_type, block, block_undo);
+ return true;
+}
+
+static bool CheckFilterLookups(BlockFilterIndex& filter_index, const CBlockIndex* block_index,
+ uint256& last_header)
+{
+ BlockFilter expected_filter;
+ if (!ComputeFilter(filter_index.GetFilterType(), block_index, expected_filter)) {
+ BOOST_ERROR("ComputeFilter failed on block " << block_index->nHeight);
+ return false;
+ }
+
+ BlockFilter filter;
+ uint256 filter_header;
+ std::vector<BlockFilter> filters;
+ std::vector<uint256> filter_hashes;
+
+ BOOST_CHECK(filter_index.LookupFilter(block_index, filter));
+ BOOST_CHECK(filter_index.LookupFilterHeader(block_index, filter_header));
+ BOOST_CHECK(filter_index.LookupFilterRange(block_index->nHeight, block_index, filters));
+ BOOST_CHECK(filter_index.LookupFilterHashRange(block_index->nHeight, block_index,
+ filter_hashes));
+
+ BOOST_CHECK_EQUAL(filters.size(), 1);
+ BOOST_CHECK_EQUAL(filter_hashes.size(), 1);
+
+ BOOST_CHECK_EQUAL(filter.GetHash(), expected_filter.GetHash());
+ BOOST_CHECK_EQUAL(filter_header, expected_filter.ComputeHeader(last_header));
+ BOOST_CHECK_EQUAL(filters[0].GetHash(), expected_filter.GetHash());
+ BOOST_CHECK_EQUAL(filter_hashes[0], expected_filter.GetHash());
+
+ filters.clear();
+ filter_hashes.clear();
+ last_header = filter_header;
+ return true;
+}
+
+static CBlock CreateBlock(const CBlockIndex* prev,
+ const std::vector<CMutableTransaction>& txns,
+ const CScript& scriptPubKey)
+{
+ const CChainParams& chainparams = Params();
+ std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
+ CBlock& block = pblocktemplate->block;
+ block.hashPrevBlock = prev->GetBlockHash();
+ block.nTime = prev->nTime + 1;
+
+ // Replace mempool-selected txns with just coinbase plus passed-in txns:
+ block.vtx.resize(1);
+ for (const CMutableTransaction& tx : txns) {
+ block.vtx.push_back(MakeTransactionRef(tx));
+ }
+ // IncrementExtraNonce creates a valid coinbase and merkleRoot
+ unsigned int extraNonce = 0;
+ IncrementExtraNonce(&block, prev, extraNonce);
+
+ while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
+
+ return block;
+}
+
+static bool BuildChain(const CBlockIndex* pindex, const CScript& coinbase_script_pub_key,
+ size_t length, std::vector<std::shared_ptr<CBlock>>& chain)
+{
+ std::vector<CMutableTransaction> no_txns;
+
+ chain.resize(length);
+ for (auto& block : chain) {
+ block = std::make_shared<CBlock>(CreateBlock(pindex, no_txns, coinbase_script_pub_key));
+ CBlockHeader header = block->GetBlockHeader();
+
+ CValidationState state;
+ if (!ProcessNewBlockHeaders({header}, state, Params(), &pindex, nullptr)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup)
+{
+ BlockFilterIndex filter_index(BlockFilterType::BASIC, 1 << 20, true);
+
+ uint256 last_header;
+
+ // Filter should not be found in the index before it is started.
+ {
+ LOCK(cs_main);
+
+ BlockFilter filter;
+ uint256 filter_header;
+ std::vector<BlockFilter> filters;
+ std::vector<uint256> filter_hashes;
+
+ for (const CBlockIndex* block_index = ::ChainActive().Genesis();
+ block_index != nullptr;
+ block_index = ::ChainActive().Next(block_index)) {
+ BOOST_CHECK(!filter_index.LookupFilter(block_index, filter));
+ BOOST_CHECK(!filter_index.LookupFilterHeader(block_index, filter_header));
+ BOOST_CHECK(!filter_index.LookupFilterRange(block_index->nHeight, block_index, filters));
+ BOOST_CHECK(!filter_index.LookupFilterHashRange(block_index->nHeight, block_index,
+ filter_hashes));
+ }
+ }
+
+ // BlockUntilSyncedToCurrentChain should return false before index is started.
+ BOOST_CHECK(!filter_index.BlockUntilSyncedToCurrentChain());
+
+ filter_index.Start();
+
+ // Allow filter index to catch up with the block index.
+ constexpr int64_t timeout_ms = 10 * 1000;
+ int64_t time_start = GetTimeMillis();
+ while (!filter_index.BlockUntilSyncedToCurrentChain()) {
+ BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
+ MilliSleep(100);
+ }
+
+ // Check that filter index has all blocks that were in the chain before it started.
+ {
+ LOCK(cs_main);
+ const CBlockIndex* block_index;
+ for (block_index = ::ChainActive().Genesis();
+ block_index != nullptr;
+ block_index = ::ChainActive().Next(block_index)) {
+ CheckFilterLookups(filter_index, block_index, last_header);
+ }
+ }
+
+ // Create two forks.
+ const CBlockIndex* tip;
+ {
+ LOCK(cs_main);
+ tip = ::ChainActive().Tip();
+ }
+ CScript coinbase_script_pub_key = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));
+ std::vector<std::shared_ptr<CBlock>> chainA, chainB;
+ BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainA));
+ BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainB));
+
+ // Check that new blocks on chain A get indexed.
+ uint256 chainA_last_header = last_header;
+ for (size_t i = 0; i < 2; i++) {
+ const auto& block = chainA[i];
+ BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+
+ const CBlockIndex* block_index;
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(block->GetHash());
+ }
+
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainA_last_header);
+ }
+
+ // Reorg to chain B.
+ uint256 chainB_last_header = last_header;
+ for (size_t i = 0; i < 3; i++) {
+ const auto& block = chainB[i];
+ BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+
+ const CBlockIndex* block_index;
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(block->GetHash());
+ }
+
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainB_last_header);
+ }
+
+ // Check that filters for stale blocks on A can be retrieved.
+ chainA_last_header = last_header;
+ for (size_t i = 0; i < 2; i++) {
+ const auto& block = chainA[i];
+ const CBlockIndex* block_index;
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(block->GetHash());
+ }
+
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainA_last_header);
+ }
+
+ // Reorg back to chain A.
+ for (size_t i = 2; i < 4; i++) {
+ const auto& block = chainA[i];
+ BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+ }
+
+ // Check that chain A and B blocks can be retrieved.
+ chainA_last_header = last_header;
+ chainB_last_header = last_header;
+ for (size_t i = 0; i < 3; i++) {
+ const CBlockIndex* block_index;
+
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(chainA[i]->GetHash());
+ }
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainA_last_header);
+
+ {
+ LOCK(cs_main);
+ block_index = LookupBlockIndex(chainB[i]->GetHash());
+ }
+ BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
+ CheckFilterLookups(filter_index, block_index, chainB_last_header);
+ }
+
+ // Test lookups for a range of filters/hashes.
+ std::vector<BlockFilter> filters;
+ std::vector<uint256> filter_hashes;
+
+ {
+ LOCK(cs_main);
+ tip = ::ChainActive().Tip();
+ }
+ BOOST_CHECK(filter_index.LookupFilterRange(0, tip, filters));
+ BOOST_CHECK(filter_index.LookupFilterHashRange(0, tip, filter_hashes));
+
+ BOOST_CHECK_EQUAL(filters.size(), tip->nHeight + 1);
+ BOOST_CHECK_EQUAL(filter_hashes.size(), tip->nHeight + 1);
+
+ filters.clear();
+ filter_hashes.clear();
+
+ filter_index.Interrupt();
+ filter_index.Stop();
+}
+
+BOOST_FIXTURE_TEST_CASE(blockfilter_index_init_destroy, BasicTestingSetup)
+{
+ SetDataDir("tempdir");
+
+ BlockFilterIndex* filter_index;
+
+ filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
+ BOOST_CHECK(filter_index == nullptr);
+
+ BOOST_CHECK(InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+
+ filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
+ BOOST_CHECK(filter_index != nullptr);
+ BOOST_CHECK(filter_index->GetFilterType() == BlockFilterType::BASIC);
+
+ // Initialize returns false if index already exists.
+ BOOST_CHECK(!InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+
+ int iter_count = 0;
+ ForEachBlockFilterIndex([&iter_count](BlockFilterIndex& _index) { iter_count++; });
+ BOOST_CHECK_EQUAL(iter_count, 1);
+
+ BOOST_CHECK(DestroyBlockFilterIndex(BlockFilterType::BASIC));
+
+ // Destroy returns false because index was already destroyed.
+ BOOST_CHECK(!DestroyBlockFilterIndex(BlockFilterType::BASIC));
+
+ filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
+ BOOST_CHECK(filter_index == nullptr);
+
+ // Reinitialize index.
+ BOOST_CHECK(InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+
+ DestroyAllBlockFilterIndexes();
+
+ filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
+ BOOST_CHECK(filter_index == nullptr);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp
new file mode 100644
index 0000000000..df0a041e0e
--- /dev/null
+++ b/src/test/blockfilter_tests.cpp
@@ -0,0 +1,194 @@
+// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/data/blockfilters.json.h>
+#include <test/setup_common.h>
+
+#include <blockfilter.h>
+#include <core_io.h>
+#include <serialize.h>
+#include <streams.h>
+#include <univalue.h>
+#include <util/strencodings.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(blockfilter_tests)
+
+BOOST_AUTO_TEST_CASE(gcsfilter_test)
+{
+ GCSFilter::ElementSet included_elements, excluded_elements;
+ for (int i = 0; i < 100; ++i) {
+ GCSFilter::Element element1(32);
+ element1[0] = i;
+ included_elements.insert(std::move(element1));
+
+ GCSFilter::Element element2(32);
+ element2[1] = i;
+ excluded_elements.insert(std::move(element2));
+ }
+
+ GCSFilter filter({0, 0, 10, 1 << 10}, included_elements);
+ for (const auto& element : included_elements) {
+ BOOST_CHECK(filter.Match(element));
+
+ auto insertion = excluded_elements.insert(element);
+ BOOST_CHECK(filter.MatchAny(excluded_elements));
+ excluded_elements.erase(insertion.first);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(gcsfilter_default_constructor)
+{
+ GCSFilter filter;
+ BOOST_CHECK_EQUAL(filter.GetN(), 0);
+ BOOST_CHECK_EQUAL(filter.GetEncoded().size(), 1);
+
+ const GCSFilter::Params& params = filter.GetParams();
+ BOOST_CHECK_EQUAL(params.m_siphash_k0, 0);
+ BOOST_CHECK_EQUAL(params.m_siphash_k1, 0);
+ BOOST_CHECK_EQUAL(params.m_P, 0);
+ BOOST_CHECK_EQUAL(params.m_M, 1);
+}
+
+BOOST_AUTO_TEST_CASE(blockfilter_basic_test)
+{
+ CScript included_scripts[5], excluded_scripts[4];
+
+ // First two are outputs on a single transaction.
+ included_scripts[0] << std::vector<unsigned char>(0, 65) << OP_CHECKSIG;
+ included_scripts[1] << OP_DUP << OP_HASH160 << std::vector<unsigned char>(1, 20) << OP_EQUALVERIFY << OP_CHECKSIG;
+
+ // Third is an output on in a second transaction.
+ included_scripts[2] << OP_1 << std::vector<unsigned char>(2, 33) << OP_1 << OP_CHECKMULTISIG;
+
+ // Last two are spent by a single transaction.
+ included_scripts[3] << OP_0 << std::vector<unsigned char>(3, 32);
+ included_scripts[4] << OP_4 << OP_ADD << OP_8 << OP_EQUAL;
+
+ // OP_RETURN output is an output on the second transaction.
+ excluded_scripts[0] << OP_RETURN << std::vector<unsigned char>(4, 40);
+
+ // This script is not related to the block at all.
+ excluded_scripts[1] << std::vector<unsigned char>(5, 33) << OP_CHECKSIG;
+
+ // OP_RETURN is non-standard since it's not followed by a data push, but is still excluded from
+ // filter.
+ excluded_scripts[2] << OP_RETURN << OP_4 << OP_ADD << OP_8 << OP_EQUAL;
+
+ CMutableTransaction tx_1;
+ tx_1.vout.emplace_back(100, included_scripts[0]);
+ tx_1.vout.emplace_back(200, included_scripts[1]);
+ tx_1.vout.emplace_back(0, excluded_scripts[0]);
+
+ CMutableTransaction tx_2;
+ tx_2.vout.emplace_back(300, included_scripts[2]);
+ tx_2.vout.emplace_back(0, excluded_scripts[2]);
+ tx_2.vout.emplace_back(400, excluded_scripts[3]); // Script is empty
+
+ CBlock block;
+ block.vtx.push_back(MakeTransactionRef(tx_1));
+ block.vtx.push_back(MakeTransactionRef(tx_2));
+
+ CBlockUndo block_undo;
+ block_undo.vtxundo.emplace_back();
+ block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(500, included_scripts[3]), 1000, true);
+ block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(600, included_scripts[4]), 10000, false);
+ block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(700, excluded_scripts[3]), 100000, false);
+
+ BlockFilter block_filter(BlockFilterType::BASIC, block, block_undo);
+ const GCSFilter& filter = block_filter.GetFilter();
+
+ for (const CScript& script : included_scripts) {
+ BOOST_CHECK(filter.Match(GCSFilter::Element(script.begin(), script.end())));
+ }
+ for (const CScript& script : excluded_scripts) {
+ BOOST_CHECK(!filter.Match(GCSFilter::Element(script.begin(), script.end())));
+ }
+
+ // Test serialization/unserialization.
+ BlockFilter block_filter2;
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << block_filter;
+ stream >> block_filter2;
+
+ BOOST_CHECK_EQUAL(block_filter.GetFilterType(), block_filter2.GetFilterType());
+ BOOST_CHECK_EQUAL(block_filter.GetBlockHash(), block_filter2.GetBlockHash());
+ BOOST_CHECK(block_filter.GetEncodedFilter() == block_filter2.GetEncodedFilter());
+
+ BlockFilter default_ctor_block_filter_1;
+ BlockFilter default_ctor_block_filter_2;
+ BOOST_CHECK_EQUAL(default_ctor_block_filter_1.GetFilterType(), default_ctor_block_filter_2.GetFilterType());
+ BOOST_CHECK_EQUAL(default_ctor_block_filter_1.GetBlockHash(), default_ctor_block_filter_2.GetBlockHash());
+ BOOST_CHECK(default_ctor_block_filter_1.GetEncodedFilter() == default_ctor_block_filter_2.GetEncodedFilter());
+}
+
+BOOST_AUTO_TEST_CASE(blockfilters_json_test)
+{
+ UniValue json;
+ std::string json_data(json_tests::blockfilters,
+ json_tests::blockfilters + sizeof(json_tests::blockfilters));
+ if (!json.read(json_data) || !json.isArray()) {
+ BOOST_ERROR("Parse error.");
+ return;
+ }
+
+ const UniValue& tests = json.get_array();
+ for (unsigned int i = 0; i < tests.size(); i++) {
+ UniValue test = tests[i];
+ std::string strTest = test.write();
+
+ if (test.size() == 1) {
+ continue;
+ } else if (test.size() < 7) {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ unsigned int pos = 0;
+ /*int block_height =*/ test[pos++].get_int();
+ uint256 block_hash;
+ BOOST_CHECK(ParseHashStr(test[pos++].get_str(), block_hash));
+
+ CBlock block;
+ BOOST_REQUIRE(DecodeHexBlk(block, test[pos++].get_str()));
+
+ CBlockUndo block_undo;
+ block_undo.vtxundo.emplace_back();
+ CTxUndo& tx_undo = block_undo.vtxundo.back();
+ const UniValue& prev_scripts = test[pos++].get_array();
+ for (unsigned int ii = 0; ii < prev_scripts.size(); ii++) {
+ std::vector<unsigned char> raw_script = ParseHex(prev_scripts[ii].get_str());
+ CTxOut txout(0, CScript(raw_script.begin(), raw_script.end()));
+ tx_undo.vprevout.emplace_back(txout, 0, false);
+ }
+
+ uint256 prev_filter_header_basic;
+ BOOST_CHECK(ParseHashStr(test[pos++].get_str(), prev_filter_header_basic));
+ std::vector<unsigned char> filter_basic = ParseHex(test[pos++].get_str());
+ uint256 filter_header_basic;
+ BOOST_CHECK(ParseHashStr(test[pos++].get_str(), filter_header_basic));
+
+ BlockFilter computed_filter_basic(BlockFilterType::BASIC, block, block_undo);
+ BOOST_CHECK(computed_filter_basic.GetFilter().GetEncoded() == filter_basic);
+
+ uint256 computed_header_basic = computed_filter_basic.ComputeHeader(prev_filter_header_basic);
+ BOOST_CHECK(computed_header_basic == filter_header_basic);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(blockfilter_type_names)
+{
+ BOOST_CHECK_EQUAL(BlockFilterTypeName(BlockFilterType::BASIC), "basic");
+ BOOST_CHECK_EQUAL(BlockFilterTypeName(static_cast<BlockFilterType>(255)), "");
+
+ BlockFilterType filter_type;
+ BOOST_CHECK(BlockFilterTypeByName("basic", filter_type));
+ BOOST_CHECK_EQUAL(filter_type, BlockFilterType::BASIC);
+
+ BOOST_CHECK(!BlockFilterTypeByName("unknown", filter_type));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 17f3004ef3..4421494007 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,9 +13,9 @@
#include <serialize.h>
#include <streams.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
#include <vector>
@@ -461,6 +461,9 @@ static std::vector<unsigned char> RandomData()
BOOST_AUTO_TEST_CASE(rolling_bloom)
{
+ SeedInsecureRand(/* deterministic */ true);
+ g_mock_deterministic_tests = true;
+
// last-100-entry, 1% false positive:
CRollingBloomFilter rb1(100, 0.01);
@@ -485,12 +488,8 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
if (rb1.contains(RandomData()))
++nHits;
}
- // Run test_bitcoin with --log_level=message to see BOOST_TEST_MESSAGEs:
- BOOST_TEST_MESSAGE("RollingBloomFilter got " << nHits << " false positives (~100 expected)");
-
- // Insanely unlikely to get a fp count outside this range:
- BOOST_CHECK(nHits > 25);
- BOOST_CHECK(nHits < 175);
+ // Expect about 100 hits
+ BOOST_CHECK_EQUAL(nHits, 75);
BOOST_CHECK(rb1.contains(data[DATASIZE-1]));
rb1.reset();
@@ -517,10 +516,8 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
if (rb1.contains(data[i]))
++nHits;
}
- // Expect about 5 false positives, more than 100 means
- // something is definitely broken.
- BOOST_TEST_MESSAGE("RollingBloomFilter got " << nHits << " false positives (~5 expected)");
- BOOST_CHECK(nHits < 100);
+ // Expect about 5 false positives
+ BOOST_CHECK_EQUAL(nHits, 6);
// last-1000-entry, 0.01% false positive:
CRollingBloomFilter rb2(1000, 0.001);
@@ -531,6 +528,7 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
for (int i = 0; i < DATASIZE; i++) {
BOOST_CHECK(rb2.contains(data[i]));
}
+ g_mock_deterministic_tests = false;
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp
index f22f513e87..8fd4e5d5d6 100644
--- a/src/test/bswap_tests.cpp
+++ b/src/test/bswap_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <compat/byteswap.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index c8de7f4a7c..408a7fbda4 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -1,12 +1,12 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/time.h>
#include <validation.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <checkqueue.h>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
@@ -148,14 +148,14 @@ typedef CCheckQueue<FrozenCleanupCheck> FrozenCleanup_Queue;
*/
static void Correct_Queue_range(std::vector<size_t> range)
{
- auto small_queue = std::unique_ptr<Correct_Queue>(new Correct_Queue {QUEUE_BATCH_SIZE});
+ auto small_queue = MakeUnique<Correct_Queue>(QUEUE_BATCH_SIZE);
boost::thread_group tg;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
tg.create_thread([&]{small_queue->Thread();});
}
// Make vChecks here to save on malloc (this test can be slow...)
std::vector<FakeCheckCheckCompletion> vChecks;
- for (auto i : range) {
+ for (const size_t i : range) {
size_t total = i;
FakeCheckCheckCompletion::n_calls = 0;
CCheckQueueControl<FakeCheckCheckCompletion> control(small_queue.get());
@@ -167,7 +167,6 @@ static void Correct_Queue_range(std::vector<size_t> range)
BOOST_REQUIRE(control.Wait());
if (FakeCheckCheckCompletion::n_calls != i) {
BOOST_REQUIRE_EQUAL(FakeCheckCheckCompletion::n_calls, i);
- BOOST_TEST_MESSAGE("Failure on trial " << i << " expected, got " << FakeCheckCheckCompletion::n_calls);
}
}
tg.interrupt_all();
@@ -213,7 +212,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random)
/** Test that failing checks are caught */
BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure)
{
- auto fail_queue = std::unique_ptr<Failing_Queue>(new Failing_Queue {QUEUE_BATCH_SIZE});
+ auto fail_queue = MakeUnique<Failing_Queue>(QUEUE_BATCH_SIZE);
boost::thread_group tg;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
@@ -246,14 +245,14 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure)
// future blocks, ie, the bad state is cleared.
BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure)
{
- auto fail_queue = std::unique_ptr<Failing_Queue>(new Failing_Queue {QUEUE_BATCH_SIZE});
+ auto fail_queue = MakeUnique<Failing_Queue>(QUEUE_BATCH_SIZE);
boost::thread_group tg;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
tg.create_thread([&]{fail_queue->Thread();});
}
for (auto times = 0; times < 10; ++times) {
- for (bool end_fails : {true, false}) {
+ for (const bool end_fails : {true, false}) {
CCheckQueueControl<FailingCheck> control(fail_queue.get());
{
std::vector<FailingCheck> vChecks;
@@ -274,7 +273,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure)
// more than once as well
BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck)
{
- auto queue = std::unique_ptr<Unique_Queue>(new Unique_Queue {QUEUE_BATCH_SIZE});
+ auto queue = MakeUnique<Unique_Queue>(QUEUE_BATCH_SIZE);
boost::thread_group tg;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
tg.create_thread([&]{queue->Thread();});
@@ -310,7 +309,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck)
// time could leave the data hanging across a sequence of blocks.
BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory)
{
- auto queue = std::unique_ptr<Memory_Queue>(new Memory_Queue {QUEUE_BATCH_SIZE});
+ auto queue = MakeUnique<Memory_Queue>(QUEUE_BATCH_SIZE);
boost::thread_group tg;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
tg.create_thread([&]{queue->Thread();});
@@ -341,7 +340,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory)
// have been destructed
BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup)
{
- auto queue = std::unique_ptr<FrozenCleanup_Queue>(new FrozenCleanup_Queue {QUEUE_BATCH_SIZE});
+ auto queue = MakeUnique<FrozenCleanup_Queue>(QUEUE_BATCH_SIZE);
boost::thread_group tg;
bool fails = false;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
@@ -355,7 +354,8 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup)
// would get called twice).
vChecks[0].should_freeze = true;
control.Add(vChecks);
- control.Wait(); // Hangs here
+ bool waitResult = control.Wait(); // Hangs here
+ assert(waitResult);
});
{
std::unique_lock<std::mutex> l(FrozenCleanupCheck::m);
@@ -384,7 +384,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup)
/** Test that CCheckQueueControl is threadsafe */
BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks)
{
- auto queue = std::unique_ptr<Standard_Queue>(new Standard_Queue{QUEUE_BATCH_SIZE});
+ auto queue = MakeUnique<Standard_Queue>(QUEUE_BATCH_SIZE);
{
boost::thread_group tg;
std::atomic<int> nThreads {0};
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index b792ff8b45..665975ca67 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -1,18 +1,19 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <attributes.h>
#include <coins.h>
+#include <consensus/validation.h>
#include <script/standard.h>
+#include <test/setup_common.h>
#include <uint256.h>
#include <undo.h>
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/strencodings.h>
#include <validation.h>
-#include <consensus/validation.h>
-#include <vector>
#include <map>
+#include <vector>
#include <boost/test/unit_test.hpp>
@@ -36,7 +37,7 @@ class CCoinsViewTest : public CCoinsView
std::map<COutPoint, Coin> map_;
public:
- bool GetCoin(const COutPoint& outpoint, Coin& coin) const override
+ NODISCARD bool GetCoin(const COutPoint& outpoint, Coin& coin) const override
{
std::map<COutPoint, Coin>::const_iterator it = map_.find(outpoint);
if (it == map_.end()) {
@@ -175,7 +176,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
} else {
removed_an_entry = true;
coin.Clear();
- stack.back()->SpendCoin(COutPoint(txid, 0));
+ BOOST_CHECK(stack.back()->SpendCoin(COutPoint(txid, 0)));
}
}
@@ -210,14 +211,14 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
// Every 100 iterations, flush an intermediate cache
if (stack.size() > 1 && InsecureRandBool() == 0) {
unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
- stack[flushIndex]->Flush();
+ BOOST_CHECK(stack[flushIndex]->Flush());
}
}
if (InsecureRandRange(100) == 0) {
// Every 100 iterations, change the cache stack.
if (stack.size() > 0 && InsecureRandBool() == 0) {
//Remove the top cache
- stack.back()->Flush();
+ BOOST_CHECK(stack.back()->Flush());
delete stack.back();
stack.pop_back();
}
@@ -278,6 +279,8 @@ UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) {
// has the expected effect (the other duplicate is overwritten at all cache levels)
BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
{
+ SeedInsecureRand(/* deterministic */ true);
+
bool spent_a_duplicate_coinbase = false;
// A simple map to track what we expect the cache stack to represent.
std::map<COutPoint, Coin> result;
@@ -376,7 +379,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
// Call UpdateCoins on the top cache
CTxUndo undo;
- UpdateCoins(tx, *(stack.back()), undo, height);
+ UpdateCoins(CTransaction(tx), *(stack.back()), undo, height);
// Update the utxo set for future spends
utxoset.insert(outpoint);
@@ -402,7 +405,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
// Disconnect the tx from the current UTXO
// See code in DisconnectBlock
// remove outputs
- stack.back()->SpendCoin(utxod->first);
+ BOOST_CHECK(stack.back()->SpendCoin(utxod->first));
// restore inputs
if (!tx.IsCoinBase()) {
const COutPoint &out = tx.vin[0].prevout;
@@ -443,13 +446,13 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
// Every 100 iterations, flush an intermediate cache
if (stack.size() > 1 && InsecureRandBool() == 0) {
unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
- stack[flushIndex]->Flush();
+ BOOST_CHECK(stack[flushIndex]->Flush());
}
}
if (InsecureRandRange(100) == 0) {
// Every 100 iterations, change the cache stack.
if (stack.size() > 0 && InsecureRandBool() == 0) {
- stack.back()->Flush();
+ BOOST_CHECK(stack.back()->Flush());
delete stack.back();
stack.pop_back();
}
@@ -482,7 +485,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
BOOST_CHECK_EQUAL(cc1.fCoinBase, false);
BOOST_CHECK_EQUAL(cc1.nHeight, 203998U);
BOOST_CHECK_EQUAL(cc1.out.nValue, CAmount{60000000000});
- BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))))));
+ BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))))));
// Good example
CDataStream ss2(ParseHex("8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4"), SER_DISK, CLIENT_VERSION);
@@ -491,7 +494,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
BOOST_CHECK_EQUAL(cc2.fCoinBase, true);
BOOST_CHECK_EQUAL(cc2.nHeight, 120891U);
BOOST_CHECK_EQUAL(cc2.out.nValue, 110397);
- BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"))))));
+ BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"))))));
// Smallest possible example
CDataStream ss3(ParseHex("000006"), SER_DISK, CLIENT_VERSION);
@@ -508,7 +511,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
Coin cc4;
ss4 >> cc4;
BOOST_CHECK_MESSAGE(false, "We should have thrown");
- } catch (const std::ios_base::failure& e) {
+ } catch (const std::ios_base::failure&) {
}
// Very large scriptPubKey (3*10^9 bytes) past the end of the stream
@@ -521,7 +524,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
Coin cc5;
ss5 >> cc5;
BOOST_CHECK_MESSAGE(false, "We should have thrown");
- } catch (const std::ios_base::failure& e) {
+ } catch (const std::ios_base::failure&) {
}
}
@@ -588,7 +591,7 @@ void WriteCoinsViewEntry(CCoinsView& view, CAmount value, char flags)
{
CCoinsMap map;
InsertCoinsMapEntry(map, value, flags);
- view.BatchWrite(map, {});
+ BOOST_CHECK(view.BatchWrite(map, {}));
}
class SingleEntryCacheTest
@@ -719,7 +722,7 @@ static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount mo
test.cache.AddCoin(OUTPOINT, Coin(std::move(output), 1, coinbase), coinbase);
test.cache.SelfTest();
GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
- } catch (std::logic_error& e) {
+ } catch (std::logic_error&) {
result_value = FAIL;
result_flags = NO_ENTRY;
}
@@ -736,7 +739,7 @@ static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount mo
template <typename... Args>
static void CheckAddCoin(Args&&... args)
{
- for (CAmount base_value : {ABSENT, PRUNED, VALUE1})
+ for (const CAmount base_value : {ABSENT, PRUNED, VALUE1})
CheckAddCoinBase(base_value, std::forward<Args>(args)...);
}
@@ -780,7 +783,7 @@ void CheckWriteCoins(CAmount parent_value, CAmount child_value, CAmount expected
WriteCoinsViewEntry(test.cache, child_value, child_flags);
test.cache.SelfTest();
GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
- } catch (std::logic_error& e) {
+ } catch (std::logic_error&) {
result_value = FAIL;
result_flags = NO_ENTRY;
}
@@ -848,10 +851,10 @@ BOOST_AUTO_TEST_CASE(ccoins_write)
// they would be too repetitive (the parent cache is never updated in these
// cases). The loop below covers these cases and makes sure the parent cache
// is always left unchanged.
- for (CAmount parent_value : {ABSENT, PRUNED, VALUE1})
- for (CAmount child_value : {ABSENT, PRUNED, VALUE2})
- for (char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS)
- for (char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS)
+ for (const CAmount parent_value : {ABSENT, PRUNED, VALUE1})
+ for (const CAmount child_value : {ABSENT, PRUNED, VALUE2})
+ for (const char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS)
+ for (const char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS)
CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags);
}
diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp
index 127cc154df..6cef8cd8a8 100644
--- a/src/test/compress_tests.cpp
+++ b/src/test/compress_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <compressor.h>
-#include <util.h>
-#include <test/test_bitcoin.h>
+#include <util/system.h>
+#include <test/setup_common.h>
#include <stdint.h>
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index d701f3bc4e..35911e507f 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -1,24 +1,24 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <crypto/aes.h>
#include <crypto/chacha20.h>
+#include <crypto/poly1305.h>
+#include <crypto/hkdf_sha256_32.h>
+#include <crypto/hmac_sha256.h>
+#include <crypto/hmac_sha512.h>
#include <crypto/ripemd160.h>
#include <crypto/sha1.h>
#include <crypto/sha256.h>
#include <crypto/sha512.h>
-#include <crypto/hmac_sha256.h>
-#include <crypto/hmac_sha512.h>
#include <random.h>
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
#include <vector>
#include <boost/test/unit_test.hpp>
-#include <openssl/aes.h>
-#include <openssl/evp.h>
BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup)
@@ -66,26 +66,6 @@ static void TestHMACSHA512(const std::string &hexkey, const std::string &hexin,
TestVector(CHMAC_SHA512(key.data(), key.size()), ParseHex(hexin), ParseHex(hexout));
}
-static void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
-{
- std::vector<unsigned char> key = ParseHex(hexkey);
- std::vector<unsigned char> in = ParseHex(hexin);
- std::vector<unsigned char> correctout = ParseHex(hexout);
- std::vector<unsigned char> buf, buf2;
-
- assert(key.size() == 16);
- assert(in.size() == 16);
- assert(correctout.size() == 16);
- AES128Encrypt enc(key.data());
- buf.resize(correctout.size());
- buf2.resize(correctout.size());
- enc.Encrypt(buf.data(), in.data());
- BOOST_CHECK_EQUAL(HexStr(buf), HexStr(correctout));
- AES128Decrypt dec(key.data());
- dec.Decrypt(buf2.data(), buf.data());
- BOOST_CHECK_EQUAL(HexStr(buf2), HexStr(in));
-}
-
static void TestAES256(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
@@ -105,47 +85,6 @@ static void TestAES256(const std::string &hexkey, const std::string &hexin, cons
BOOST_CHECK(buf == in);
}
-static void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout)
-{
- std::vector<unsigned char> key = ParseHex(hexkey);
- std::vector<unsigned char> iv = ParseHex(hexiv);
- std::vector<unsigned char> in = ParseHex(hexin);
- std::vector<unsigned char> correctout = ParseHex(hexout);
- std::vector<unsigned char> realout(in.size() + AES_BLOCKSIZE);
-
- // Encrypt the plaintext and verify that it equals the cipher
- AES128CBCEncrypt enc(key.data(), iv.data(), pad);
- int size = enc.Encrypt(in.data(), in.size(), realout.data());
- realout.resize(size);
- BOOST_CHECK(realout.size() == correctout.size());
- BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout);
-
- // Decrypt the cipher and verify that it equals the plaintext
- std::vector<unsigned char> decrypted(correctout.size());
- AES128CBCDecrypt dec(key.data(), iv.data(), pad);
- size = dec.Decrypt(correctout.data(), correctout.size(), decrypted.data());
- decrypted.resize(size);
- BOOST_CHECK(decrypted.size() == in.size());
- BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin);
-
- // Encrypt and re-decrypt substrings of the plaintext and verify that they equal each-other
- for(std::vector<unsigned char>::iterator i(in.begin()); i != in.end(); ++i)
- {
- std::vector<unsigned char> sub(i, in.end());
- std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
- int _size = enc.Encrypt(sub.data(), sub.size(), subout.data());
- if (_size != 0)
- {
- subout.resize(_size);
- std::vector<unsigned char> subdecrypted(subout.size());
- _size = dec.Decrypt(subout.data(), subout.size(), subdecrypted.data());
- subdecrypted.resize(_size);
- BOOST_CHECK(decrypted.size() == in.size());
- BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
- }
- }
-}
-
static void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
@@ -187,20 +126,66 @@ static void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, b
}
}
-static void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout)
+static void TestChaCha20(const std::string &hex_message, const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
+ std::vector<unsigned char> m = ParseHex(hex_message);
ChaCha20 rng(key.data(), key.size());
rng.SetIV(nonce);
rng.Seek(seek);
std::vector<unsigned char> out = ParseHex(hexout);
std::vector<unsigned char> outres;
outres.resize(out.size());
- rng.Output(outres.data(), outres.size());
+ assert(hex_message.empty() || m.size() == out.size());
+
+ // perform the ChaCha20 round(s), if message is provided it will output the encrypted ciphertext otherwise the keystream
+ if (!hex_message.empty()) {
+ rng.Crypt(m.data(), outres.data(), outres.size());
+ } else {
+ rng.Keystream(outres.data(), outres.size());
+ }
BOOST_CHECK(out == outres);
+ if (!hex_message.empty()) {
+ // Manually XOR with the keystream and compare the output
+ rng.SetIV(nonce);
+ rng.Seek(seek);
+ std::vector<unsigned char> only_keystream(outres.size());
+ rng.Keystream(only_keystream.data(), only_keystream.size());
+ for (size_t i = 0; i != m.size(); i++) {
+ outres[i] = m[i] ^ only_keystream[i];
+ }
+ BOOST_CHECK(out == outres);
+ }
+}
+
+static void TestPoly1305(const std::string &hexmessage, const std::string &hexkey, const std::string& hextag)
+{
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ std::vector<unsigned char> m = ParseHex(hexmessage);
+ std::vector<unsigned char> tag = ParseHex(hextag);
+ std::vector<unsigned char> tagres;
+ tagres.resize(POLY1305_TAGLEN);
+ poly1305_auth(tagres.data(), m.data(), m.size(), key.data());
+ BOOST_CHECK(tag == tagres);
+}
+
+static void TestHKDF_SHA256_32(const std::string &ikm_hex, const std::string &salt_hex, const std::string &info_hex, const std::string &okm_check_hex) {
+ std::vector<unsigned char> initial_key_material = ParseHex(ikm_hex);
+ std::vector<unsigned char> salt = ParseHex(salt_hex);
+ std::vector<unsigned char> info = ParseHex(info_hex);
+
+
+ // our implementation only supports strings for the "info" and "salt", stringify them
+ std::string salt_stringified(reinterpret_cast<char*>(salt.data()), salt.size());
+ std::string info_stringified(reinterpret_cast<char*>(info.data()), info.size());
+
+ CHKDF_HMAC_SHA256_L32 hkdf32(initial_key_material.data(), initial_key_material.size(), salt_stringified);
+ unsigned char out[32];
+ hkdf32.Expand32(info_stringified, out);
+ BOOST_CHECK(HexStr(out, out + 32) == okm_check_hex);
}
-static std::string LongTestString(void) {
+static std::string LongTestString() {
std::string ret;
for (int i=0; i<200000; i++) {
ret += (unsigned char)(i);
@@ -428,14 +413,9 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
BOOST_AUTO_TEST_CASE(aes_testvectors) {
// AES test vectors from FIPS 197.
- TestAES128("000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a");
TestAES256("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089");
// AES-ECB test vectors from NIST sp800-38a.
- TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97");
- TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf");
- TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688");
- TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4");
TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8");
TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870");
TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d");
@@ -443,27 +423,6 @@ BOOST_AUTO_TEST_CASE(aes_testvectors) {
}
BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) {
-
- // NIST AES CBC 128-bit encryption test-vectors
- TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", false, \
- "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d");
- TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", false, \
- "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b2");
- TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", false, \
- "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516");
- TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", false, \
- "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a7");
-
- // The same vectors with padding enabled
- TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", true, \
- "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d8964e0b149c10b7b682e6e39aaeb731c");
- TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", true, \
- "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b255e21d7100b988ffec32feeafaf23538");
- TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", true, \
- "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516f6eccda327bf8e5ec43718b0039adceb");
- TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", true, \
- "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a78cb82807230e1321d3fae00d18cc2012");
-
// NIST AES CBC 256-bit encryption test-vectors
TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
"000102030405060708090A0B0C0D0E0F", false, "6bc1bee22e409f96e93d7e117393172a", \
@@ -497,25 +456,37 @@ BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) {
BOOST_AUTO_TEST_CASE(chacha20_testvector)
{
// Test vector from RFC 7539
- TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1,
+
+ // test encryption
+ TestChaCha20("4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756"
+ "c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e"
+ "20776f756c642062652069742e",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1,
+ "6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d"
+ "624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74"
+ "a35be6b40b8eedf2785e42874d"
+ );
+
+ // test keystream output
+ TestChaCha20("", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1,
"224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cb"
"a40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a"
"832c89c167eacd901d7e2bf363");
// Test vectors from https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
- TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0, 0,
+ TestChaCha20("", "0000000000000000000000000000000000000000000000000000000000000000", 0, 0,
"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b"
"8f41518a11cc387b669b2ee6586");
- TestChaCha20("0000000000000000000000000000000000000000000000000000000000000001", 0, 0,
+ TestChaCha20("", "0000000000000000000000000000000000000000000000000000000000000001", 0, 0,
"4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d79"
"2b1c43fea817e9ad275ae546963");
- TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0,
+ TestChaCha20("", "0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0,
"de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b52770"
"62eb7a0433e445f41e3");
- TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 1, 0,
+ TestChaCha20("", "0000000000000000000000000000000000000000000000000000000000000000", 1, 0,
"ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc4"
"97a0b466e7d6bbdb0041b2f586b");
- TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0,
+ TestChaCha20("", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0,
"f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3b"
"e59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc1"
"18be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5"
@@ -524,6 +495,96 @@ BOOST_AUTO_TEST_CASE(chacha20_testvector)
"fab78c9");
}
+BOOST_AUTO_TEST_CASE(poly1305_testvector)
+{
+ // RFC 7539, section 2.5.2.
+ TestPoly1305("43727970746f6772617068696320466f72756d2052657365617263682047726f7570",
+ "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b",
+ "a8061dc1305136c6c22b8baf0c0127a9");
+
+ // RFC 7539, section A.3.
+ TestPoly1305("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000");
+
+ TestPoly1305("416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e747269627"
+ "5746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465"
+ "726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686"
+ "520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e2022494554"
+ "4620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c20737461746"
+ "56d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c65"
+ "6374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207"
+ "768696368206172652061646472657373656420746f",
+ "0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e",
+ "36e5f6b5c5e06070f0efca96227a863e");
+
+ TestPoly1305("416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e747269627"
+ "5746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465"
+ "726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686"
+ "520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e2022494554"
+ "4620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c20737461746"
+ "56d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c65"
+ "6374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207"
+ "768696368206172652061646472657373656420746f",
+ "36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000",
+ "f3477e7cd95417af89a6b8794c310cf0");
+
+ TestPoly1305("2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e6420676"
+ "96d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e"
+ "6420746865206d6f6d65207261746873206f757467726162652e",
+ "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
+ "4541669a7eaaee61e708dc7cbcc5eb62");
+
+ TestPoly1305("ffffffffffffffffffffffffffffffff",
+ "0200000000000000000000000000000000000000000000000000000000000000",
+ "03000000000000000000000000000000");
+
+ TestPoly1305("02000000000000000000000000000000",
+ "02000000000000000000000000000000ffffffffffffffffffffffffffffffff",
+ "03000000000000000000000000000000");
+
+ TestPoly1305("fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000",
+ "0100000000000000000000000000000000000000000000000000000000000000",
+ "05000000000000000000000000000000");
+
+ TestPoly1305("fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101",
+ "0100000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000");
+
+ TestPoly1305("fdffffffffffffffffffffffffffffff",
+ "0200000000000000000000000000000000000000000000000000000000000000",
+ "faffffffffffffffffffffffffffffff");
+
+ TestPoly1305("e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000",
+ "0100000000000000040000000000000000000000000000000000000000000000",
+ "14000000000000005500000000000000");
+
+ TestPoly1305("e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000",
+ "0100000000000000040000000000000000000000000000000000000000000000",
+ "13000000000000000000000000000000");
+}
+
+BOOST_AUTO_TEST_CASE(hkdf_hmac_sha256_l32_tests)
+{
+ // Use rfc5869 test vectors but trucated to 32 bytes (our implementation only support length 32)
+ TestHKDF_SHA256_32(
+ /* IKM */ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ /* salt */ "000102030405060708090a0b0c",
+ /* info */ "f0f1f2f3f4f5f6f7f8f9",
+ /* expected OKM */ "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf");
+ TestHKDF_SHA256_32(
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f",
+ "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c");
+ TestHKDF_SHA256_32(
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "",
+ "",
+ "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d");
+}
+
BOOST_AUTO_TEST_CASE(countbits_tests)
{
FastRandomContext ctx;
@@ -532,7 +593,7 @@ BOOST_AUTO_TEST_CASE(countbits_tests)
// Check handling of zero.
BOOST_CHECK_EQUAL(CountBits(0), 0U);
} else if (i < 10) {
- for (uint64_t j = 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);
}
diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp
index 2edc7c16d4..d38ede691a 100644
--- a/src/test/cuckoocache_tests.cpp
+++ b/src/test/cuckoocache_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <boost/test/unit_test.hpp>
#include <cuckoocache.h>
#include <script/sigcache.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <random.h>
#include <thread>
@@ -21,40 +21,23 @@
* using BOOST_CHECK_CLOSE to fail.
*
*/
-FastRandomContext local_rand_ctx(true);
-
BOOST_AUTO_TEST_SUITE(cuckoocache_tests);
-
-/** insecure_GetRandHash fills in a uint256 from local_rand_ctx
- */
-static void insecure_GetRandHash(uint256& t)
-{
- uint32_t* ptr = (uint32_t*)t.begin();
- for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = local_rand_ctx.rand32();
-}
-
-
-
/* Test that no values not inserted into the cache are read out of it.
*
* There are no repeats in the first 200000 insecure_GetRandHash calls
*/
BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
{
- local_rand_ctx = FastRandomContext(true);
+ SeedInsecureRand(true);
CuckooCache::cache<uint256, SignatureCacheHasher> cc{};
size_t megabytes = 4;
cc.setup_bytes(megabytes << 20);
- uint256 v;
for (int x = 0; x < 100000; ++x) {
- insecure_GetRandHash(v);
- cc.insert(v);
+ cc.insert(InsecureRand256());
}
for (int x = 0; x < 100000; ++x) {
- insecure_GetRandHash(v);
- BOOST_CHECK(!cc.contains(v, false));
+ BOOST_CHECK(!cc.contains(InsecureRand256(), false));
}
};
@@ -64,7 +47,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
template <typename Cache>
static double test_cache(size_t megabytes, double load)
{
- local_rand_ctx = FastRandomContext(true);
+ SeedInsecureRand(true);
std::vector<uint256> hashes;
Cache set{};
size_t bytes = megabytes * (1 << 20);
@@ -74,7 +57,7 @@ static double test_cache(size_t megabytes, double load)
for (uint32_t i = 0; i < n_insert; ++i) {
uint32_t* ptr = (uint32_t*)hashes[i].begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = local_rand_ctx.rand32();
+ *(ptr++) = InsecureRand32();
}
/** We make a copy of the hashes because future optimizations of the
* cuckoocache may overwrite the inserted element, so the test is
@@ -82,11 +65,11 @@ static double test_cache(size_t megabytes, double load)
*/
std::vector<uint256> hashes_insert_copy = hashes;
/** Do the insert */
- for (uint256& h : hashes_insert_copy)
+ for (const uint256& h : hashes_insert_copy)
set.insert(h);
/** Count the hits */
uint32_t count = 0;
- for (uint256& h : hashes)
+ for (const uint256& h : hashes)
count += set.contains(h, false);
double hit_rate = ((double)count) / ((double)n_insert);
return hit_rate;
@@ -135,7 +118,7 @@ template <typename Cache>
static void test_cache_erase(size_t megabytes)
{
double load = 1;
- local_rand_ctx = FastRandomContext(true);
+ SeedInsecureRand(true);
std::vector<uint256> hashes;
Cache set{};
size_t bytes = megabytes * (1 << 20);
@@ -145,7 +128,7 @@ static void test_cache_erase(size_t megabytes)
for (uint32_t i = 0; i < n_insert; ++i) {
uint32_t* ptr = (uint32_t*)hashes[i].begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = local_rand_ctx.rand32();
+ *(ptr++) = InsecureRand32();
}
/** We make a copy of the hashes because future optimizations of the
* cuckoocache may overwrite the inserted element, so the test is
@@ -158,7 +141,7 @@ static void test_cache_erase(size_t megabytes)
set.insert(hashes_insert_copy[i]);
/** Erase the first quarter */
for (uint32_t i = 0; i < (n_insert / 4); ++i)
- set.contains(hashes[i], true);
+ BOOST_CHECK(set.contains(hashes[i], true));
/** Insert the second half */
for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
set.insert(hashes_insert_copy[i]);
@@ -198,7 +181,7 @@ template <typename Cache>
static void test_cache_erase_parallel(size_t megabytes)
{
double load = 1;
- local_rand_ctx = FastRandomContext(true);
+ SeedInsecureRand(true);
std::vector<uint256> hashes;
Cache set{};
size_t bytes = megabytes * (1 << 20);
@@ -208,7 +191,7 @@ static void test_cache_erase_parallel(size_t megabytes)
for (uint32_t i = 0; i < n_insert; ++i) {
uint32_t* ptr = (uint32_t*)hashes[i].begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = local_rand_ctx.rand32();
+ *(ptr++) = InsecureRand32();
}
/** We make a copy of the hashes because future optimizations of the
* cuckoocache may overwrite the inserted element, so the test is
@@ -237,8 +220,10 @@ static void test_cache_erase_parallel(size_t megabytes)
size_t ntodo = (n_insert/4)/3;
size_t start = ntodo*x;
size_t end = ntodo*(x+1);
- for (uint32_t i = start; i < end; ++i)
- set.contains(hashes[i], true);
+ for (uint32_t i = start; i < end; ++i) {
+ bool contains = set.contains(hashes[i], true);
+ assert(contains);
+ }
});
/** Wait for all threads to finish
@@ -300,7 +285,7 @@ static void test_cache_generations()
// iterations with non-deterministic values, so it isn't "overfit" to the
// specific entropy in FastRandomContext(true) and implementation of the
// cache.
- local_rand_ctx = FastRandomContext(true);
+ SeedInsecureRand(true);
// block_activity models a chunk of network activity. n_insert elements are
// added to the cache. The first and last n/4 are stored for removal later
@@ -317,13 +302,13 @@ static void test_cache_generations()
for (uint32_t i = 0; i < n_insert; ++i) {
uint32_t* ptr = (uint32_t*)inserts[i].begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = local_rand_ctx.rand32();
+ *(ptr++) = InsecureRand32();
}
for (uint32_t i = 0; i < n_insert / 4; ++i)
reads.push_back(inserts[i]);
for (uint32_t i = n_insert - (n_insert / 4); i < n_insert; ++i)
reads.push_back(inserts[i]);
- for (auto h : inserts)
+ for (const auto& h : inserts)
c.insert(h);
}
};
diff --git a/src/test/data/blockfilters.json b/src/test/data/blockfilters.json
new file mode 100644
index 0000000000..8945296a07
--- /dev/null
+++ b/src/test/data/blockfilters.json
@@ -0,0 +1,13 @@
+[
+["Block Height,Block Hash,Block,[Prev Output Scripts for Block],Previous Basic Header,Basic Filter,Basic Header,Notes"],
+[0,"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943","0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",[],"0000000000000000000000000000000000000000000000000000000000000000","019dfca8","21584579b7eb08997773e5aeff3a7f932700042d0ed2a6129012b7d7ae81b750","Genesis block"],
+[2,"000000006c02c8ea6e4ff69651f7fcde348fb9d557a06e6957b65552002a7820","0100000006128e87be8b1b4dea47a7247d5528d2702c96826c7a648497e773b800000000e241352e3bec0a95a6217e10c3abb54adfa05abb12c126695595580fb92e222032e7494dffff001d00d235340101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0432e7494d010e062f503253482fffffffff0100f2052a010000002321038a7f6ef1c8ca0c588aa53fa860128077c9e6c11e6830f4d7ee4e763a56b7718fac00000000",[],"d7bdac13a59d745b1add0d2ce852f1a0442e8945fc1bf3848d3cbffd88c24fe1","0174a170","186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0",""],
+[3,"000000008b896e272758da5297bcd98fdc6d97c9b765ecec401e286dc1fdbe10","0100000020782a005255b657696ea057d5b98f34defcf75196f64f6eeac8026c0000000041ba5afc532aae03151b8aa87b65e1594f97504a768e010c98c0add79216247186e7494dffff001d058dc2b60101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0486e7494d0151062f503253482fffffffff0100f2052a01000000232103f6d9ff4c12959445ca5549c811683bf9c88e637b222dd2e0311154c4c85cf423ac00000000",[],"186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0","016cf7a0","8d63aadf5ab7257cb6d2316a57b16f517bff1c6388f124ec4c04af1212729d2a",""],
+[15007,"0000000038c44c703bae0f98cdd6bf30922326340a5996cc692aaae8bacf47ad","0100000002394092aa378fe35d7e9ac79c869b975c4de4374cd75eb5484b0e1e00000000eb9b8670abd44ad6c55cee18e3020fb0c6519e7004b01a16e9164867531b67afc33bc94fffff001d123f10050101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e04c33bc94f0115062f503253482fffffffff0100f2052a01000000232103f268e9ae07e0f8cb2f6e901d87c510d650b97230c0365b021df8f467363cafb1ac00000000",[],"18b5c2b0146d2d09d24fb00ff5b52bd0742f36c9e65527abdb9de30c027a4748","013c3710","07384b01311867949e0c046607c66b7a766d338474bb67f66c8ae9dbd454b20e","Tx has non-standard OP_RETURN output followed by opcodes"],
+[49291,"0000000018b07dca1b28b4b5a119f6d6e71698ce1ed96f143f54179ce177a19c","02000000abfaf47274223ca2fea22797e44498240e482cb4c2f2baea088962f800000000604b5b52c32305b15d7542071d8b04e750a547500005d4010727694b6e72a776e55d0d51ffff001d211806480201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0d038bc0000102062f503253482fffffffff01a078072a01000000232102971dd6034ed0cf52450b608d196c07d6345184fcb14deb277a6b82d526a6163dac0000000001000000081cefd96060ecb1c4fbe675ad8a4f8bdc61d634c52b3a1c4116dee23749fe80ff000000009300493046022100866859c21f306538152e83f115bcfbf59ab4bb34887a88c03483a5dff9895f96022100a6dfd83caa609bf0516debc2bf65c3df91813a4842650a1858b3f61cfa8af249014730440220296d4b818bb037d0f83f9f7111665f49532dfdcbec1e6b784526e9ac4046eaa602204acf3a5cb2695e8404d80bf49ab04828bcbe6fc31d25a2844ced7a8d24afbdff01ffffffff1cefd96060ecb1c4fbe675ad8a4f8bdc61d634c52b3a1c4116dee23749fe80ff020000009400483045022100e87899175991aa008176cb553c6f2badbb5b741f328c9845fcab89f8b18cae2302200acce689896dc82933015e7230e5230d5cff8a1ffe82d334d60162ac2c5b0c9601493046022100994ad29d1e7b03e41731a4316e5f4992f0d9b6e2efc40a1ccd2c949b461175c502210099b69fdc2db00fbba214f16e286f6a49e2d8a0d5ffc6409d87796add475478d601ffffffff1e4a6d2d280ea06680d6cf8788ac90344a9c67cca9b06005bbd6d3f6945c8272010000009500493046022100a27400ba52fd842ce07398a1de102f710a10c5599545e6c95798934352c2e4df022100f6383b0b14c9f64b6718139f55b6b9494374755b86bae7d63f5d3e583b57255a01493046022100fdf543292f34e1eeb1703b264965339ec4a450ec47585009c606b3edbc5b617b022100a5fbb1c8de8aaaa582988cdb23622838e38de90bebcaab3928d949aa502a65d401ffffffff1e4a6d2d280ea06680d6cf8788ac90344a9c67cca9b06005bbd6d3f6945c8272020000009400493046022100ac626ac3051f875145b4fe4cfe089ea895aac73f65ab837b1ac30f5d875874fa022100bc03e79fa4b7eb707fb735b95ff6613ca33adeaf3a0607cdcead4cfd3b51729801483045022100b720b04a5c5e2f61b7df0fcf334ab6fea167b7aaede5695d3f7c6973496adbf1022043328c4cc1cdc3e5db7bb895ccc37133e960b2fd3ece98350f774596badb387201ffffffff23a8733e349c97d6cd90f520fdd084ba15ce0a395aad03cd51370602bb9e5db3010000004a00483045022100e8556b72c5e9c0da7371913a45861a61c5df434dfd962de7b23848e1a28c86ca02205d41ceda00136267281be0974be132ac4cda1459fe2090ce455619d8b91045e901ffffffff6856d609b881e875a5ee141c235e2a82f6b039f2b9babe82333677a5570285a6000000006a473044022040a1c631554b8b210fbdf2a73f191b2851afb51d5171fb53502a3a040a38d2c0022040d11cf6e7b41fe1b66c3d08f6ada1aee07a047cb77f242b8ecc63812c832c9a012102bcfad931b502761e452962a5976c79158a0f6d307ad31b739611dac6a297c256ffffffff6856d609b881e875a5ee141c235e2a82f6b039f2b9babe82333677a5570285a601000000930048304502205b109df098f7e932fbf71a45869c3f80323974a826ee2770789eae178a21bfc8022100c0e75615e53ee4b6e32b9bb5faa36ac539e9c05fa2ae6b6de5d09c08455c8b9601483045022009fb7d27375c47bea23b24818634df6a54ecf72d52e0c1268fb2a2c84f1885de022100e0ed4f15d62e7f537da0d0f1863498f9c7c0c0a4e00e4679588c8d1a9eb20bb801ffffffffa563c3722b7b39481836d5edfc1461f97335d5d1e9a23ade13680d0e2c1c371f030000006c493046022100ecc38ae2b1565643dc3c0dad5e961a5f0ea09cab28d024f92fa05c922924157e022100ebc166edf6fbe4004c72bfe8cf40130263f98ddff728c8e67b113dbd621906a601210211a4ed241174708c07206601b44a4c1c29e5ad8b1f731c50ca7e1d4b2a06dc1fffffffff02d0223a00000000001976a91445db0b779c0b9fa207f12a8218c94fc77aff504588ac80f0fa02000000000000000000",["5221033423007d8f263819a2e42becaaf5b06f34cb09919e06304349d950668209eaed21021d69e2b68c3960903b702af7829fadcd80bd89b158150c85c4a75b2c8cb9c39452ae","52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821021d69e2b68c3960903b702af7829fadcd80bd89b158150c85c4a75b2c8cb9c39452ae","522102a7ae1e0971fc1689bd66d2a7296da3a1662fd21a53c9e38979e0f090a375c12d21022adb62335f41eb4e27056ac37d462cda5ad783fa8e0e526ed79c752475db285d52ae","52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821022adb62335f41eb4e27056ac37d462cda5ad783fa8e0e526ed79c752475db285d52ae","512103b9d1d0e2b4355ec3cdef7c11a5c0beff9e8b8d8372ab4b4e0aaf30e80173001951ae","76a9149144761ebaccd5b4bbdc2a35453585b5637b2f8588ac","522103f1848b40621c5d48471d9784c8174ca060555891ace6d2b03c58eece946b1a9121020ee5d32b54d429c152fdc7b1db84f2074b0564d35400d89d11870f9273ec140c52ae","76a914f4fa1cc7de742d135ea82c17adf0bb9cf5f4fb8388ac"],"ed47705334f4643892ca46396eb3f4196a5e30880589e4009ef38eae895d4a13","0afbc2920af1b027f31f87b592276eb4c32094bb4d3697021b4c6380","b6d98692cec5145f67585f3434ec3c2b3030182e1cb3ec58b855c5c164dfaaa3","Tx pays to empty output script"],
+[180480,"00000000fd3ceb2404ff07a785c7fdcc76619edc8ed61bd25134eaa22084366a","020000006058aa080a655aa991a444bd7d1f2defd9a3bbe68aabb69030cf3b4e00000000d2e826bfd7ef0beaa891a7eedbc92cd6a544a6cb61c7bdaa436762eb2123ef9790f5f552ffff001d0002c90f0501000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0300c102024608062f503253482fffffffff01c0c6072a01000000232102e769e60137a4df6b0df8ebd387cca44c4c57ae74cc0114a8e8317c8f3bfd85e9ac00000000010000000381a0802911a01ffb025c4dea0bc77963e8c1bb46313b71164c53f72f37fe5248010000000151ffffffffc904b267833d215e2128bd9575242232ac2bc311550c7fc1f0ef6f264b40d14c010000000151ffffffffdf0915666649dba81886519c531649b7b02180b4af67d6885e871299e9d5f775000000000151ffffffff0180817dcb00000000232103bb52138972c48a132fc1f637858c5189607dd0f7fe40c4f20f6ad65f2d389ba4ac0000000001000000018da38b434fba82d66052af74fc5e4e94301b114d9bc03f819dc876398404c8b4010000006c493046022100fe738b7580dc5fb5168e51fc61b5aed211125eb71068031009a22d9bbad752c5022100be5086baa384d40bcab0fa586e4f728397388d86e18b66cc417dc4f7fa4f9878012103f233299455134caa2687bdf15cb0becdfb03bd0ff2ff38e65ec6b7834295c34fffffffff022ebc1400000000001976a9147779b7fba1c1e06b717069b80ca170e8b04458a488ac9879c40f000000001976a9142a0307cd925dbb66b534c4db33003dd18c57015788ac0000000001000000026139a62e3422a602de36c873a225c1d3ca5aeee598539ceecb9f0dc8d1ad0f83010000006b483045022100ad9f32b4a0a2ddc19b5a74eba78123e57616f1b3cfd72ce68c03ea35a3dda1f002200dbd22aa6da17213df5e70dfc3b2611d40f70c98ed9626aa5e2cde9d97461f0a012103ddb295d2f1e8319187738fb4b230fdd9aa29d0e01647f69f6d770b9ab24eea90ffffffff983c82c87cf020040d671956525014d5c2b28c6d948c85e1a522362c0059eeae010000006b4830450221009ca544274c786d30a5d5d25e17759201ea16d3aedddf0b9e9721246f7ef6b32e02202cfa5564b6e87dfd9fd98957820e4d4e6238baeb0f65fe305d91506bb13f5f4f012103c99113deac0d5d044e3ac0346abc02501542af8c8d3759f1382c72ff84e704f7ffffffff02c0c62d00000000001976a914ae19d27efe12f5a886dc79af37ad6805db6f922d88ac70ce2000000000001976a9143b8d051d37a07ea1042067e93efe63dbf73920b988ac000000000100000002be566e8cd9933f0c75c4a82c027f7d0c544d5c101d0607ef6ae5d07b98e7f1dc000000006b483045022036a8cdfd5ea7ebc06c2bfb6e4f942bbf9a1caeded41680d11a3a9f5d8284abad022100cacb92a5be3f39e8bc14db1710910ef7b395fa1e18f45d41c28d914fcdde33be012102bf59abf110b5131fae0a3ce1ec379329b4c896a6ae5d443edb68529cc2bc7816ffffffff96cf67645b76ceb23fe922874847456a15feee1655082ff32d25a6bf2c0dfc90000000006a47304402203471ca2001784a5ac0abab583581f2613523da47ec5f53df833c117b5abd81500220618a2847723d57324f2984678db556dbca1a72230fc7e39df04c2239942ba942012102925c9794fd7bb9f8b29e207d5fc491b1150135a21f505041858889fa4edf436fffffffff026c840f00000000001976a914797fb8777d7991d8284d88bfd421ce520f0f843188ac00ca9a3b000000001976a9146d10f3f592699265d10b106eda37c3ce793f7a8588ac00000000",["","","","76a9142903b138c24be9e070b3e73ec495d77a204615e788ac","76a91433a1941fd9a37b9821d376f5a51bd4b52fa50e2888ac","76a914e4374e8155d0865742ca12b8d4d14d41b57d682f88ac","76a914001fa7459a6cfc64bdc178ba7e7a21603bb2568f88ac","76a914f6039952bc2b307aeec5371bfb96b66078ec17f688ac"],"d34ef98386f413769502808d4bac5f20f8dfd5bffc9eedafaa71de0eb1f01489","0db414c859a07e8205876354a210a75042d0463404913d61a8e068e58a3ae2aa080026","c582d51c0ca365e3fcf36c51cb646d7f83a67e867cb4743fd2128e3e022b700c","Tx spends from empty output script"],
+[926485,"000000000000015d6077a411a8f5cc95caf775ccf11c54e27df75ce58d187313","0000002060bbab0edbf3ef8a49608ee326f8fd75c473b7e3982095e2d100000000000000c30134f8c9b6d2470488d7a67a888f6fa12f8692e0c3411fbfb92f0f68f67eedae03ca57ef13021acc22dc4105010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2f0315230e0004ae03ca57043e3d1e1d0c8796bf579aef0c0000000000122f4e696e6a61506f6f6c2f5345475749542fffffffff038427a112000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9ed5c748e121c0fe146d973a4ac26fa4a68b0549d46ee22d25f50a5e46fe1b377ee00000000000000002952534b424c4f434b3acd16772ad61a3c5f00287480b720f6035d5e54c9efc71be94bb5e3727f10909001200000000000000000000000000000000000000000000000000000000000000000000000000100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000010000000120925534261de4dcebb1ed5ab1b62bfe7a3ef968fb111dc2c910adfebc6e3bdf010000006b483045022100f50198f5ae66211a4f485190abe4dc7accdabe3bc214ebc9ea7069b97097d46e0220316a70a03014887086e335fc1b48358d46cd6bdc9af3b57c109c94af76fc915101210316cff587a01a2736d5e12e53551b18d73780b83c3bfb4fcf209c869b11b6415effffffff0220a10700000000001976a91450333046115eaa0ac9e0216565f945070e44573988ac2e7cd01a000000001976a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac00000000010000000203a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322010000006a47304402204efc3d70e4ca3049c2a425025edf22d5ca355f9ec899dbfbbeeb2268533a0f2b02204780d3739653035af4814ea52e1396d021953f948c29754edd0ee537364603dc012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff03a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322000000006a47304402202d96defdc5b4af71d6ba28c9a6042c2d5ee7bc6de565d4db84ef517445626e03022022da80320e9e489c8f41b74833dfb6a54a4eb5087cdb46eb663eef0b25caa526012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a914b7e6f7ff8658b2d1fb107e3d7be7af4742e6b1b3876f88fc00000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac0000000001000000043ffd60d3818431c495b89be84afac205d5d1ed663009291c560758bbd0a66df5010000006b483045022100f344607de9df42049688dcae8ff1db34c0c7cd25ec05516e30d2bc8f12ac9b2f022060b648f6a21745ea6d9782e17bcc4277b5808326488a1f40d41e125879723d3a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffffa5379401cce30f84731ef1ba65ce27edf2cc7ce57704507ebe8714aa16a96b92010000006a473044022020c37a63bf4d7f564c2192528709b6a38ab8271bd96898c6c2e335e5208661580220435c6f1ad4d9305d2c0a818b2feb5e45d443f2f162c0f61953a14d097fd07064012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff70e731e193235ff12c3184510895731a099112ffca4b00246c60003c40f843ce000000006a473044022053760f74c29a879e30a17b5f03a5bb057a5751a39f86fa6ecdedc36a1b7db04c022041d41c9b95f00d2d10a0373322a9025dba66c942196bc9d8adeb0e12d3024728012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff66b7a71b3e50379c8e85fc18fe3f1a408fc985f257036c34702ba205cef09f6f000000006a4730440220499bf9e2db3db6e930228d0661395f65431acae466634d098612fd80b08459ee022040e069fc9e3c60009f521cef54c38aadbd1251aee37940e6018aadb10f194d6a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a9148fc37ad460fdfbd2b44fe446f6e3071a4f64faa6878f447f0b000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac00000000",["a914feb8a29635c56d9cd913122f90678756bf23887687","76a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac"],"8f13b9a9c85611635b47906c3053ac53cfcec7211455d4cb0d63dc9acc13d472","09027acea61b6cc3fb33f5d52f7d088a6b2f75d234e89ca800","546c574a0472144bcaf9b6aeabf26372ad87c7af7d1ee0dbfae5e099abeae49c","Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb"],
+[987876,"0000000000000c00901f2049055e2a437c819d79a3d54fd63e6af796cd7b8a79","000000202694f74969fdb542090e95a56bc8aa2d646e27033850e32f1c5f000000000000f7e53676b3f12d5beb524ed617f2d25f5a93b5f4f52c1ba2678260d72712f8dd0a6dfe5740257e1a4b1768960101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1603e4120ff9c30a1c216900002f424d4920546573742fffffff0001205fa012000000001e76a914c486de584a735ec2f22da7cd9681614681f92173d83d0aa68688ac00000000",[],"fe4d230dbb0f4fec9bed23a5283e08baf996e3f32b93f52c7de1f641ddfd04ad","010c0b40","0965a544743bbfa36f254446e75630c09404b3d164a261892372977538928ed5","Coinbase tx has unparseable output script"],
+[1263442,"000000006f27ddfe1dd680044a34548f41bed47eba9e6f0b310da21423bc5f33","000000201c8d1a529c39a396db2db234d5ec152fa651a2872966daccbde028b400000000083f14492679151dbfaa1a825ef4c18518e780c1f91044180280a7d33f4a98ff5f45765aaddc001d38333b9a02010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230352471300fe5f45765afe94690a000963676d696e6572343208000000000000000000ffffffff024423a804000000001976a914f2c25ac3d59f3d674b1d1d0a25c27339aaac0ba688ac0000000000000000266a24aa21a9edcb26cb3052426b9ebb4d19c819ef87c19677bbf3a7c46ef0855bd1b2abe83491012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101d20978463906ba4ff5e7192494b88dd5eb0de85d900ab253af909106faa22cc5010000000004000000014777ff000000000016001446c29eabe8208a33aa1023c741fa79aa92e881ff0347304402207d7ca96134f2bcfdd6b536536fdd39ad17793632016936f777ebb32c22943fda02206014d2fb8a6aa58279797f861042ba604ebd2f8f61e5bddbd9d3be5a245047b201004b632103eeaeba7ce5dc2470221e9517fb498e8d6bd4e73b85b8be655196972eb9ccd5566754b2752103a40b74d43df244799d041f32ce1ad515a6cd99501701540e38750d883ae21d3a68ac00000000",["002027a5000c7917f785d8fc6e5a55adfca8717ecb973ebb7743849ff956d896a7ed"],"31d66d516a9eda7de865df29f6ef6cb8e4bf9309e5dac899968a9a62a5df61e3","0385acb4f0fe889ef0","4e6d564c2a2452065c205dd7eb2791124e0c4e0dbb064c410c24968572589dec","Includes witness data"],
+[1414221,"0000000000000027b2b3b3381f114f674f481544ff2be37ae3788d7e078383b1","000000204ea88307a7959d8207968f152bedca5a93aefab253f1fb2cfb032a400000000070cebb14ec6dbc27a9dfd066d9849a4d3bac5f674665f73a5fe1de01a022a0c851fda85bf05f4c19a779d1450102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff18034d94154d696e6572476174653030310d000000f238f401ffffffff01c817a804000000000000000000",[],"5e5e12d90693c8e936f01847859404c67482439681928353ca1296982042864e","00","021e8882ef5a0ed932edeebbecfeda1d7ce528ec7b3daa27641acf1189d7b5dc","Empty data"]
+]
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index 918df6d8d9..d22175d660 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -363,7 +363,7 @@
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
-["Using CHECKSIG with singatures in scriptSigs will trigger FindAndDelete, which is invalid"],
+["Using CHECKSIG with signatures in scriptSigs will trigger FindAndDelete, which is invalid"],
[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index 5ba54ef9b0..0bde92c18d 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <dbwrapper.h>
#include <uint256.h>
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <memory>
@@ -26,7 +26,7 @@ BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(dbwrapper)
{
// Perform tests both obfuscated and non-obfuscated.
- for (bool obfuscate : {false, true}) {
+ for (const bool obfuscate : {false, true}) {
fs::path ph = SetDataDir(std::string("dbwrapper").append(obfuscate ? "_true" : "_false"));
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
char key = 'k';
@@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper)
BOOST_AUTO_TEST_CASE(dbwrapper_batch)
{
// Perform tests both obfuscated and non-obfuscated.
- for (bool obfuscate : {false, true}) {
+ for (const bool obfuscate : {false, true}) {
fs::path ph = SetDataDir(std::string("dbwrapper_batch").append(obfuscate ? "_true" : "_false"));
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch)
// Remove key3 before it's even been written
batch.Erase(key3);
- dbw.WriteBatch(batch);
+ BOOST_CHECK(dbw.WriteBatch(batch));
BOOST_CHECK(dbw.Read(key, res));
BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
@@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch)
BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
{
// Perform tests both obfuscated and non-obfuscated.
- for (bool obfuscate : {false, true}) {
+ for (const bool obfuscate : {false, true}) {
fs::path ph = SetDataDir(std::string("dbwrapper_iterator").append(obfuscate ? "_true" : "_false"));
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
@@ -102,15 +102,15 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
char key_res;
uint256 val_res;
- it->GetKey(key_res);
- it->GetValue(val_res);
+ BOOST_REQUIRE(it->GetKey(key_res));
+ BOOST_REQUIRE(it->GetValue(val_res));
BOOST_CHECK_EQUAL(key_res, key);
BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString());
it->Next();
- it->GetKey(key_res);
- it->GetValue(val_res);
+ BOOST_REQUIRE(it->GetKey(key_res));
+ BOOST_REQUIRE(it->GetValue(val_res));
BOOST_CHECK_EQUAL(key_res, key2);
BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString());
@@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(iterator_ordering)
if (x & 1) BOOST_CHECK(dbw.Write(key, value));
}
- for (int seek_start : {0x00, 0x80}) {
+ for (const int seek_start : {0x00, 0x80}) {
it->Seek((uint8_t)seek_start);
for (unsigned int x=seek_start; x<255; ++x) {
uint8_t key;
@@ -262,7 +262,7 @@ struct StringContentsSerializer {
try {
READWRITE(c);
str.push_back(c);
- } catch (const std::ios_base::failure& e) {
+ } catch (const std::ios_base::failure&) {
break;
}
}
@@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering)
}
std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
- for (int seek_start : {0, 5}) {
+ for (const int seek_start : {0, 5}) {
snprintf(buf, sizeof(buf), "%d", seek_start);
StringContentsSerializer seek_key(buf);
it->Seek(seek_key);
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index 49037adb9a..d47f395c15 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -1,9 +1,10 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Unit tests for denial-of-service detection/prevention code
+#include <banman.h>
#include <chainparams.h>
#include <keystore.h>
#include <net.h>
@@ -11,15 +12,32 @@
#include <pow.h>
#include <script/sign.h>
#include <serialize.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <stdint.h>
#include <boost/test/unit_test.hpp>
+struct CConnmanTest : public CConnman {
+ using CConnman::CConnman;
+ void AddNode(CNode& node)
+ {
+ LOCK(cs_vNodes);
+ vNodes.push_back(&node);
+ }
+ void ClearNodes()
+ {
+ LOCK(cs_vNodes);
+ for (CNode* node : vNodes) {
+ delete node;
+ }
+ vNodes.clear();
+ }
+};
+
// Tests these internal-to-net_processing.cpp methods:
extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer);
extern void EraseOrphansFor(NodeId peer);
@@ -31,7 +49,8 @@ struct COrphanTx {
NodeId fromPeer;
int64_t nTimeExpire;
};
-extern std::map<uint256, COrphanTx> mapOrphanTransactions;
+extern CCriticalSection g_cs_orphans;
+extern std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans);
static CService ip(uint32_t i)
{
@@ -56,6 +75,8 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
// work.
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
+ auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false);
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -69,14 +90,14 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
// This test requires that we have a chain with non-zero work.
{
LOCK(cs_main);
- BOOST_CHECK(chainActive.Tip() != nullptr);
- BOOST_CHECK(chainActive.Tip()->nChainWork > 0);
+ BOOST_CHECK(::ChainActive().Tip() != nullptr);
+ BOOST_CHECK(::ChainActive().Tip()->nChainWork > 0);
}
// Test starts here
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1); // should result in getheaders
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
}
{
LOCK2(cs_main, dummyNode1.cs_vSend);
@@ -89,7 +110,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(nStartTime+21*60);
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1); // should result in getheaders
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
}
{
LOCK2(cs_main, dummyNode1.cs_vSend);
@@ -99,7 +120,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(nStartTime+24*60);
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1); // should result in disconnect
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in disconnect
}
BOOST_CHECK(dummyNode1.fDisconnect == true);
SetMockTime(0);
@@ -108,9 +129,9 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
}
-static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic)
+static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic, CConnmanTest* connman)
{
- CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE);
+ CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false));
CNode &node = *vNodes.back();
node.SetSendVersion(PROTOCOL_VERSION);
@@ -119,11 +140,14 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidat
node.nVersion = 1;
node.fSuccessfullyConnected = true;
- CConnmanTest::AddNode(node);
+ connman->AddNode(node);
}
BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
+ auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false);
+
const Consensus::Params& consensusParams = Params().GetConsensus();
constexpr int nMaxOutbound = 8;
CConnman::Options options;
@@ -136,7 +160,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
// Mock some outbound peers
for (int i=0; i<nMaxOutbound; ++i) {
- AddRandomOutboundPeer(vNodes, *peerLogic);
+ AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
}
peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
@@ -161,7 +185,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
// If we add one more peer, something should get marked for eviction
// on the next check (since we're mocking the time to be in the future, the
// required time connected check should be satisfied).
- AddRandomOutboundPeer(vNodes, *peerLogic);
+ AddRandomOutboundPeer(vNodes, *peerLogic, connman.get());
peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
for (int i=0; i<nMaxOutbound; ++i) {
@@ -188,13 +212,16 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
peerLogic->FinalizeNode(node->GetId(), dummy);
}
- CConnmanTest::ClearNodes();
+ connman->ClearNodes();
}
BOOST_AUTO_TEST_CASE(DoS_banning)
{
+ auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
- connman->ClearBanned();
+ banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true);
dummyNode1.SetSendVersion(PROTOCOL_VERSION);
@@ -207,10 +234,10 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
- BOOST_CHECK(connman->IsBanned(addr1));
- BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
+ BOOST_CHECK(banman->IsBanned(addr1));
+ BOOST_CHECK(!banman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
CAddress addr2(ip(0xa0b0c002), NODE_NONE);
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true);
@@ -224,19 +251,19 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
}
{
LOCK2(cs_main, dummyNode2.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode2);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
}
- BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet...
- BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be
+ BOOST_CHECK(!banman->IsBanned(addr2)); // 2 not banned yet...
+ BOOST_CHECK(banman->IsBanned(addr1)); // ... but 1 still should be
{
LOCK(cs_main);
Misbehaving(dummyNode2.GetId(), 50);
}
{
LOCK2(cs_main, dummyNode2.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode2);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
}
- BOOST_CHECK(connman->IsBanned(addr2));
+ BOOST_CHECK(banman->IsBanned(addr2));
bool dummy;
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
@@ -245,8 +272,11 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
BOOST_AUTO_TEST_CASE(DoS_banscore)
{
+ auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
- connman->ClearBanned();
+ banman->ClearBanned();
gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true);
@@ -260,27 +290,27 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
- BOOST_CHECK(!connman->IsBanned(addr1));
+ BOOST_CHECK(!banman->IsBanned(addr1));
{
LOCK(cs_main);
Misbehaving(dummyNode1.GetId(), 10);
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
- BOOST_CHECK(!connman->IsBanned(addr1));
+ BOOST_CHECK(!banman->IsBanned(addr1));
{
LOCK(cs_main);
Misbehaving(dummyNode1.GetId(), 1);
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
}
- BOOST_CHECK(connman->IsBanned(addr1));
+ BOOST_CHECK(banman->IsBanned(addr1));
gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
bool dummy;
@@ -289,8 +319,11 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
BOOST_AUTO_TEST_CASE(DoS_bantime)
{
+ auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false);
- connman->ClearBanned();
+ banman->ClearBanned();
int64_t nStartTime = GetTime();
SetMockTime(nStartTime); // Overrides future calls to GetTime()
@@ -307,15 +340,15 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
}
{
LOCK2(cs_main, dummyNode.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode);
+ BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
}
- BOOST_CHECK(connman->IsBanned(addr));
+ BOOST_CHECK(banman->IsBanned(addr));
SetMockTime(nStartTime+60*60);
- BOOST_CHECK(connman->IsBanned(addr));
+ BOOST_CHECK(banman->IsBanned(addr));
SetMockTime(nStartTime+60*60*24+1);
- BOOST_CHECK(!connman->IsBanned(addr));
+ BOOST_CHECK(!banman->IsBanned(addr));
bool dummy;
peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
@@ -324,7 +357,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
static CTransactionRef RandomOrphan()
{
std::map<uint256, COrphanTx>::iterator it;
- LOCK(cs_main);
+ LOCK2(cs_main, g_cs_orphans);
it = mapOrphanTransactions.lower_bound(InsecureRand256());
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
@@ -336,7 +369,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
CKey key;
key.MakeNewKey(true);
CBasicKeyStore keystore;
- keystore.AddKey(key);
+ BOOST_CHECK(keystore.AddKey(key));
// 50 orphan transactions:
for (int i = 0; i < 50; i++)
@@ -348,7 +381,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vin[0].scriptSig << OP_1;
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
- tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
+ tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
AddOrphanTx(MakeTransactionRef(tx), i);
}
@@ -364,8 +397,8 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vin[0].prevout.hash = txPrev->GetHash();
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
- tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
- SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);
+ tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
+ BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
AddOrphanTx(MakeTransactionRef(tx), i);
}
@@ -378,14 +411,14 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
CMutableTransaction tx;
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
- tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
+ tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
tx.vin.resize(2777);
for (unsigned int j = 0; j < tx.vin.size(); j++)
{
tx.vin[j].prevout.n = j;
tx.vin[j].prevout.hash = txPrev->GetHash();
}
- SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);
+ BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL));
// Re-use same signature for other inputs
// (they don't have to be valid for this test)
for (unsigned int j = 1; j < tx.vin.size(); j++)
@@ -394,7 +427,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i));
}
- LOCK(cs_main);
+ LOCK2(cs_main, g_cs_orphans);
// Test EraseOrphansFor:
for (NodeId i = 0; i < 3; i++)
{
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index f189222be8..f5bda7d5e6 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,10 +6,10 @@
#include <string>
#include <script/sign.h>
#include <script/standard.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <script/descriptor.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
namespace {
@@ -18,8 +18,8 @@ void CheckUnparsable(const std::string& prv, const std::string& pub)
FlatSigningProvider keys_priv, keys_pub;
auto parse_priv = Parse(prv, keys_priv);
auto parse_pub = Parse(pub, keys_pub);
- BOOST_CHECK(!parse_priv);
- BOOST_CHECK(!parse_pub);
+ BOOST_CHECK_MESSAGE(!parse_priv, prv);
+ BOOST_CHECK_MESSAGE(!parse_pub, pub);
}
constexpr int DEFAULT = 0;
@@ -28,6 +28,18 @@ constexpr int HARDENED = 2; // Derivation needs access to private keys
constexpr int UNSOLVABLE = 4; // This descriptor is not expected to be solvable
constexpr int SIGNABLE = 8; // We can sign with this descriptor (this is not true when actual BIP32 derivation is used, as that's not integrated in our signing code)
+/** Compare two descriptors. If only one of them has a checksum, the checksum is ignored. */
+bool EqualDescriptor(std::string a, std::string b)
+{
+ bool a_check = (a.size() > 9 && a[a.size() - 9] == '#');
+ bool b_check = (b.size() > 9 && b[b.size() - 9] == '#');
+ if (a_check != b_check) {
+ if (a_check) a = a.substr(0, a.size() - 9);
+ if (b_check) b = b.substr(0, b.size() - 9);
+ }
+ return a == b;
+}
+
std::string MaybeUseHInsteadOfApostrophy(std::string ret)
{
if (InsecureRandBool()) {
@@ -35,6 +47,7 @@ std::string MaybeUseHInsteadOfApostrophy(std::string ret)
auto it = ret.find("'");
if (it != std::string::npos) {
ret[it] = 'h';
+ if (ret.size() > 9 && ret[ret.size() - 9] == '#') ret = ret.substr(0, ret.size() - 9); // Changing apostrophe to h breaks the checksum
} else {
break;
}
@@ -43,9 +56,12 @@ std::string MaybeUseHInsteadOfApostrophy(std::string ret)
return ret;
}
-void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts)
+const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}};
+
+void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
{
FlatSigningProvider keys_priv, keys_pub;
+ std::set<std::vector<uint32_t>> left_paths = paths;
// Check that parsing succeeds.
auto parse_priv = Parse(MaybeUseHInsteadOfApostrophy(prv), keys_priv);
@@ -59,36 +75,59 @@ void Check(const std::string& prv, const std::string& pub, int flags, const std:
// Check that both versions serialize back to the public version.
std::string pub1 = parse_priv->ToString();
- std::string pub2 = parse_priv->ToString();
- BOOST_CHECK_EQUAL(pub, pub1);
- BOOST_CHECK_EQUAL(pub, pub2);
+ std::string pub2 = parse_pub->ToString();
+ BOOST_CHECK(EqualDescriptor(pub, pub1));
+ BOOST_CHECK(EqualDescriptor(pub, pub2));
// Check that both can be serialized with private key back to the private version, but not without private key.
- std::string prv1, prv2;
+ std::string prv1;
BOOST_CHECK(parse_priv->ToPrivateString(keys_priv, prv1));
- BOOST_CHECK_EQUAL(prv, prv1);
+ BOOST_CHECK(EqualDescriptor(prv, prv1));
BOOST_CHECK(!parse_priv->ToPrivateString(keys_pub, prv1));
BOOST_CHECK(parse_pub->ToPrivateString(keys_priv, prv1));
- BOOST_CHECK_EQUAL(prv, prv1);
+ BOOST_CHECK(EqualDescriptor(prv, prv1));
BOOST_CHECK(!parse_pub->ToPrivateString(keys_pub, prv1));
// Check whether IsRange on both returns the expected result
BOOST_CHECK_EQUAL(parse_pub->IsRange(), (flags & RANGE) != 0);
BOOST_CHECK_EQUAL(parse_priv->IsRange(), (flags & RANGE) != 0);
-
- // Is not ranged descriptor, only a single result is expected.
+ // * For ranged descriptors, the `scripts` parameter is a list of expected result outputs, for subsequent
+ // positions to evaluate the descriptors on (so the first element of `scripts` is for evaluating the
+ // descriptor at 0; the second at 1; and so on). To verify this, we evaluate the descriptors once for
+ // each element in `scripts`.
+ // * For non-ranged descriptors, we evaluate the descriptors at positions 0, 1, and 2, but expect the
+ // same result in each case, namely the first element of `scripts`. Because of that, the size of
+ // `scripts` must be one in that case.
if (!(flags & RANGE)) assert(scripts.size() == 1);
-
size_t max = (flags & RANGE) ? scripts.size() : 3;
+
+ // Iterate over the position we'll evaluate the descriptors in.
for (size_t i = 0; i < max; ++i) {
+ // Call the expected result scripts `ref`.
const auto& ref = scripts[(flags & RANGE) ? i : 0];
+ // When t=0, evaluate the `prv` descriptor; when t=1, evaluate the `pub` descriptor.
for (int t = 0; t < 2; ++t) {
- FlatSigningProvider key_provider = (flags & HARDENED) ? keys_priv : keys_pub;
- FlatSigningProvider script_provider;
- std::vector<CScript> spks;
- BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider));
+ // When the descriptor is hardened, evaluate with access to the private keys inside.
+ const FlatSigningProvider& key_provider = (flags & HARDENED) ? keys_priv : keys_pub;
+
+ // Evaluate the descriptor selected by `t` in poisition `i`.
+ FlatSigningProvider script_provider, script_provider_cached;
+ std::vector<CScript> spks, spks_cached;
+ std::vector<unsigned char> cache;
+ BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider, &cache));
+
+ // Compare the output with the expected result.
BOOST_CHECK_EQUAL(spks.size(), ref.size());
+
+ // Try to expand again using cached data, and compare.
+ BOOST_CHECK(parse_pub->ExpandFromCache(i, cache, spks_cached, script_provider_cached));
+ BOOST_CHECK(spks == spks_cached);
+ BOOST_CHECK(script_provider.pubkeys == script_provider_cached.pubkeys);
+ BOOST_CHECK(script_provider.scripts == script_provider_cached.scripts);
+ BOOST_CHECK(script_provider.origins == script_provider_cached.origins);
+
+ // For each of the produced scripts, verify solvability, and when possible, try to sign a transaction spending it.
for (size_t n = 0; n < spks.size(); ++n) {
BOOST_CHECK_EQUAL(ref[n], HexStr(spks[n].begin(), spks[n].end()));
BOOST_CHECK_EQUAL(IsSolvable(Merge(key_provider, script_provider), spks[n]), (flags & UNSOLVABLE) == 0);
@@ -99,10 +138,30 @@ void Check(const std::string& prv, const std::string& pub, int flags, const std:
spend.vout.resize(1);
BOOST_CHECK_MESSAGE(SignSignature(Merge(keys_priv, script_provider), spks[n], spend, 0, 1, SIGHASH_ALL), prv);
}
+
+ /* Infer a descriptor from the generated script, and verify its solvability and that it roundtrips. */
+ auto inferred = InferDescriptor(spks[n], script_provider);
+ BOOST_CHECK_EQUAL(inferred->IsSolvable(), !(flags & UNSOLVABLE));
+ std::vector<CScript> spks_inferred;
+ FlatSigningProvider provider_inferred;
+ BOOST_CHECK(inferred->Expand(0, provider_inferred, spks_inferred, provider_inferred));
+ BOOST_CHECK_EQUAL(spks_inferred.size(), 1);
+ BOOST_CHECK(spks_inferred[0] == spks[n]);
+ BOOST_CHECK_EQUAL(IsSolvable(provider_inferred, spks_inferred[0]), !(flags & UNSOLVABLE));
+ BOOST_CHECK(provider_inferred.origins == script_provider.origins);
}
+ // Test whether the observed key path is present in the 'paths' variable (which contains expected, unobserved paths),
+ // and then remove it from that set.
+ for (const auto& origin : script_provider.origins) {
+ BOOST_CHECK_MESSAGE(paths.count(origin.second.second.path), "Unexpected key path: " + prv);
+ left_paths.erase(origin.second.second.path);
+ }
}
}
+
+ // Verify no expected paths remain that were not observed.
+ BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv);
}
}
@@ -114,7 +173,7 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
// Basic single-key compressed
Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}});
- Check("pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}});
+ Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, {{1,0x80000002UL,3,0x80000004UL}});
Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}});
Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
@@ -135,20 +194,26 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}});
// Versions with BIP32 derivations
- Check("combo(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}});
- Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}});
- Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}});
- Check("wpkh(xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}});
- Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}});
- Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}});
+ Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}});
+ Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, {{0}});
+ Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, {{0xFFFFFFFFUL,0}});
+ Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
+ Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
+ Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, {{0}, {1}});
+ CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)"); // Too long key fingerprint
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)"); // BIP 32 path element overflow
// Multisig constructions
Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
- Check("sh(multi(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}});
- Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}});
+ Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}});
CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
+ CheckUnparsable("wsh(multi(2,[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa][aaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Double key origin descriptor
+ CheckUnparsable("wsh(multi(2,[aaaagaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaagaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Non hex fingerprint
+ CheckUnparsable("wsh(multi(2,[aaaaaaaa],xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa],xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // No public key with origin
+ CheckUnparsable("wsh(multi(2,[aaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Too short fingerprint
+ CheckUnparsable("wsh(multi(2,[aaaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))"); // Too long fingerprint
// Check for invalid nesting of structures
CheckUnparsable("sh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)"); // P2SH needs a script, not a key
@@ -158,6 +223,15 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
CheckUnparsable("wsh(sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2SH inside P2WSH
CheckUnparsable("sh(sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2SH inside P2SH
CheckUnparsable("wsh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2WSH inside P2WSH
+
+ // Checksums
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}});
+ CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#"); // Empty checksum
+ CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq"); // Too long checksum
+ CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5"); // Too short checksum
+ CheckUnparsable("sh(multi(3,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t"); // Error in payload
+ CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggssrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjq09x4t"); // Error in checksum
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp
new file mode 100644
index 0000000000..1db2f8054c
--- /dev/null
+++ b/src/test/flatfile_tests.cpp
@@ -0,0 +1,123 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <flatfile.h>
+#include <test/setup_common.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(flatfile_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(flatfile_filename)
+{
+ auto data_dir = SetDataDir("flatfile_test");
+
+ FlatFilePos pos(456, 789);
+
+ FlatFileSeq seq1(data_dir, "a", 16 * 1024);
+ BOOST_CHECK_EQUAL(seq1.FileName(pos), data_dir / "a00456.dat");
+
+ FlatFileSeq seq2(data_dir / "a", "b", 16 * 1024);
+ BOOST_CHECK_EQUAL(seq2.FileName(pos), data_dir / "a" / "b00456.dat");
+}
+
+BOOST_AUTO_TEST_CASE(flatfile_open)
+{
+ auto data_dir = SetDataDir("flatfile_test");
+ FlatFileSeq seq(data_dir, "a", 16 * 1024);
+
+ std::string line1("A purely peer-to-peer version of electronic cash would allow online "
+ "payments to be sent directly from one party to another without going "
+ "through a financial institution.");
+ std::string line2("Digital signatures provide part of the solution, but the main benefits are "
+ "lost if a trusted third party is still required to prevent double-spending.");
+
+ size_t pos1 = 0;
+ size_t pos2 = pos1 + GetSerializeSize(line1, CLIENT_VERSION);
+
+ // Write first line to file.
+ {
+ CAutoFile file(seq.Open(FlatFilePos(0, pos1)), SER_DISK, CLIENT_VERSION);
+ file << LIMITED_STRING(line1, 256);
+ }
+
+ // Attempt to append to file opened in read-only mode.
+ {
+ CAutoFile file(seq.Open(FlatFilePos(0, pos2), true), SER_DISK, CLIENT_VERSION);
+ BOOST_CHECK_THROW(file << LIMITED_STRING(line2, 256), std::ios_base::failure);
+ }
+
+ // Append second line to file.
+ {
+ CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION);
+ file << LIMITED_STRING(line2, 256);
+ }
+
+ // Read text from file in read-only mode.
+ {
+ std::string text;
+ CAutoFile file(seq.Open(FlatFilePos(0, pos1), true), SER_DISK, CLIENT_VERSION);
+
+ file >> LIMITED_STRING(text, 256);
+ BOOST_CHECK_EQUAL(text, line1);
+
+ file >> LIMITED_STRING(text, 256);
+ BOOST_CHECK_EQUAL(text, line2);
+ }
+
+ // Read text from file with position offset.
+ {
+ std::string text;
+ CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION);
+
+ file >> LIMITED_STRING(text, 256);
+ BOOST_CHECK_EQUAL(text, line2);
+ }
+
+ // Ensure another file in the sequence has no data.
+ {
+ std::string text;
+ CAutoFile file(seq.Open(FlatFilePos(1, pos2)), SER_DISK, CLIENT_VERSION);
+ BOOST_CHECK_THROW(file >> LIMITED_STRING(text, 256), std::ios_base::failure);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(flatfile_allocate)
+{
+ auto data_dir = SetDataDir("flatfile_test");
+ FlatFileSeq seq(data_dir, "a", 100);
+
+ bool out_of_space;
+
+ BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 0), 1, out_of_space), 100);
+ BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 0))), 100);
+ BOOST_CHECK(!out_of_space);
+
+ BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 1, out_of_space), 0);
+ BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 100);
+ BOOST_CHECK(!out_of_space);
+
+ BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 2, out_of_space), 101);
+ BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 200);
+ BOOST_CHECK(!out_of_space);
+}
+
+BOOST_AUTO_TEST_CASE(flatfile_flush)
+{
+ auto data_dir = SetDataDir("flatfile_test");
+ FlatFileSeq seq(data_dir, "a", 100);
+
+ bool out_of_space;
+ seq.Allocate(FlatFilePos(0, 0), 1, out_of_space);
+
+ // Flush without finalize should not truncate file.
+ seq.Flush(FlatFilePos(0, 1));
+ BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 100);
+
+ // Flush with finalize should truncate file.
+ seq.Flush(FlatFilePos(0, 1), true);
+ BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 1);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp
new file mode 100644
index 0000000000..6bd6bb1be3
--- /dev/null
+++ b/src/test/fs_tests.cpp
@@ -0,0 +1,56 @@
+// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+//
+#include <fs.h>
+#include <test/setup_common.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(fsbridge_fstream)
+{
+ fs::path tmpfolder = SetDataDir("fsbridge_fstream");
+ // tmpfile1 should be the same as tmpfile2
+ fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃";
+ fs::path tmpfile2 = tmpfolder / L"fs_tests_₿_🏃";
+ {
+ fsbridge::ofstream file(tmpfile1);
+ file << "bitcoin";
+ }
+ {
+ fsbridge::ifstream file(tmpfile2);
+ std::string input_buffer;
+ file >> input_buffer;
+ BOOST_CHECK_EQUAL(input_buffer, "bitcoin");
+ }
+ {
+ fsbridge::ifstream file(tmpfile1, std::ios_base::in | std::ios_base::ate);
+ std::string input_buffer;
+ file >> input_buffer;
+ BOOST_CHECK_EQUAL(input_buffer, "");
+ }
+ {
+ fsbridge::ofstream file(tmpfile2, std::ios_base::out | std::ios_base::app);
+ file << "tests";
+ }
+ {
+ fsbridge::ifstream file(tmpfile1);
+ std::string input_buffer;
+ file >> input_buffer;
+ BOOST_CHECK_EQUAL(input_buffer, "bitcointests");
+ }
+ {
+ fsbridge::ofstream file(tmpfile2, std::ios_base::out | std::ios_base::trunc);
+ file << "bitcoin";
+ }
+ {
+ fsbridge::ifstream file(tmpfile1);
+ std::string input_buffer;
+ file >> input_buffer;
+ BOOST_CHECK_EQUAL(input_buffer, "bitcoin");
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
new file mode 100644
index 0000000000..97d7633715
--- /dev/null
+++ b/src/test/fuzz/deserialize.cpp
@@ -0,0 +1,167 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <addrman.h>
+#include <blockencodings.h>
+#include <chain.h>
+#include <coins.h>
+#include <compressor.h>
+#include <consensus/merkle.h>
+#include <net.h>
+#include <primitives/block.h>
+#include <protocol.h>
+#include <pubkey.h>
+#include <script/script.h>
+#include <streams.h>
+#include <undo.h>
+#include <version.h>
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+#include <test/fuzz/fuzz.h>
+
+void test_one_input(std::vector<uint8_t> buffer)
+{
+ CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ try {
+ int nVersion;
+ ds >> nVersion;
+ ds.SetVersion(nVersion);
+ } catch (const std::ios_base::failure& e) {
+ return;
+ }
+
+#if BLOCK_DESERIALIZE
+ try
+ {
+ CBlock block;
+ ds >> block;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif TRANSACTION_DESERIALIZE
+ try
+ {
+ CTransaction tx(deserialize, ds);
+ } catch (const std::ios_base::failure& e) {return;}
+#elif BLOCKLOCATOR_DESERIALIZE
+ try
+ {
+ CBlockLocator bl;
+ ds >> bl;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif BLOCKMERKLEROOT
+ try
+ {
+ CBlock block;
+ ds >> block;
+ bool mutated;
+ BlockMerkleRoot(block, &mutated);
+ } catch (const std::ios_base::failure& e) {return;}
+#elif ADDRMAN_DESERIALIZE
+ try
+ {
+ CAddrMan am;
+ ds >> am;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif BLOCKHEADER_DESERIALIZE
+ try
+ {
+ CBlockHeader bh;
+ ds >> bh;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif BANENTRY_DESERIALIZE
+ try
+ {
+ CBanEntry be;
+ ds >> be;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif TXUNDO_DESERIALIZE
+ try
+ {
+ CTxUndo tu;
+ ds >> tu;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif BLOCKUNDO_DESERIALIZE
+ try
+ {
+ CBlockUndo bu;
+ ds >> bu;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif COINS_DESERIALIZE
+ try
+ {
+ Coin coin;
+ ds >> coin;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif NETADDR_DESERIALIZE
+ try
+ {
+ CNetAddr na;
+ ds >> na;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif SERVICE_DESERIALIZE
+ try
+ {
+ CService s;
+ ds >> s;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif MESSAGEHEADER_DESERIALIZE
+ CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
+ try
+ {
+ CMessageHeader mh(pchMessageStart);
+ ds >> mh;
+ if (!mh.IsValid(pchMessageStart)) {return;}
+ } catch (const std::ios_base::failure& e) {return;}
+#elif ADDRESS_DESERIALIZE
+ try
+ {
+ CAddress a;
+ ds >> a;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif INV_DESERIALIZE
+ try
+ {
+ CInv i;
+ ds >> i;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif BLOOMFILTER_DESERIALIZE
+ try
+ {
+ CBloomFilter bf;
+ ds >> bf;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif DISKBLOCKINDEX_DESERIALIZE
+ try
+ {
+ CDiskBlockIndex dbi;
+ ds >> dbi;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif TXOUTCOMPRESSOR_DESERIALIZE
+ CTxOut to;
+ CTxOutCompressor toc(to);
+ try
+ {
+ ds >> toc;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif BLOCKTRANSACTIONS_DESERIALIZE
+ try
+ {
+ BlockTransactions bt;
+ ds >> bt;
+ } catch (const std::ios_base::failure& e) {return;}
+#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
+ try
+ {
+ BlockTransactionsRequest btr;
+ ds >> btr;
+ } catch (const std::ios_base::failure& e) {return;}
+#else
+#error Need at least one fuzz target to compile
+#endif
+}
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
new file mode 100644
index 0000000000..0709da5563
--- /dev/null
+++ b/src/test/fuzz/fuzz.cpp
@@ -0,0 +1,77 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/fuzz/fuzz.h>
+
+#include <unistd.h>
+
+#include <pubkey.h>
+#include <util/memory.h>
+
+
+static bool read_stdin(std::vector<uint8_t>& data)
+{
+ uint8_t buffer[1024];
+ ssize_t length = 0;
+ while ((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
+ data.insert(data.end(), buffer, buffer + length);
+
+ if (data.size() > (1 << 20)) return false;
+ }
+ return length == 0;
+}
+
+static void initialize()
+{
+ const static auto verify_handle = MakeUnique<ECCVerifyHandle>();
+}
+
+// This function is used by libFuzzer
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ test_one_input(std::vector<uint8_t>(data, data + size));
+ return 0;
+}
+
+// This function is used by libFuzzer
+extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
+{
+ initialize();
+ return 0;
+}
+
+// Disabled under WIN32 due to clash with Cygwin's WinMain.
+#ifndef WIN32
+// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
+// the main(...) function.
+__attribute__((weak))
+#endif
+int main(int argc, char **argv)
+{
+ initialize();
+#ifdef __AFL_INIT
+ // Enable AFL deferred forkserver mode. Requires compilation using
+ // afl-clang-fast++. See fuzzing.md for details.
+ __AFL_INIT();
+#endif
+
+#ifdef __AFL_LOOP
+ // Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
+ // See fuzzing.md for details.
+ while (__AFL_LOOP(1000)) {
+ std::vector<uint8_t> buffer;
+ if (!read_stdin(buffer)) {
+ continue;
+ }
+ test_one_input(buffer);
+ }
+#else
+ std::vector<uint8_t> buffer;
+ if (!read_stdin(buffer)) {
+ return 0;
+ }
+ test_one_input(buffer);
+#endif
+ return 0;
+}
diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h
new file mode 100644
index 0000000000..8b03a7e46e
--- /dev/null
+++ b/src/test/fuzz/fuzz.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_FUZZ_FUZZ_H
+#define BITCOIN_TEST_FUZZ_FUZZ_H
+
+#include <functional>
+#include <stdint.h>
+#include <vector>
+
+
+void test_one_input(std::vector<uint8_t> buffer);
+
+#endif // BITCOIN_TEST_FUZZ_FUZZ_H
diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp
new file mode 100644
index 0000000000..2c0bfa360c
--- /dev/null
+++ b/src/test/fuzz/script_flags.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <script/interpreter.h>
+#include <script/script.h>
+#include <streams.h>
+#include <version.h>
+
+#include <test/fuzz/fuzz.h>
+
+/** Flags that are not forbidden by an assert */
+static bool IsValidFlagCombination(unsigned flags);
+
+void test_one_input(std::vector<uint8_t> buffer)
+{
+ CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ try {
+ int nVersion;
+ ds >> nVersion;
+ ds.SetVersion(nVersion);
+ } catch (const std::ios_base::failure&) {
+ return;
+ }
+
+ try {
+ const CTransaction tx(deserialize, ds);
+ const PrecomputedTransactionData txdata(tx);
+
+ unsigned int verify_flags;
+ ds >> verify_flags;
+
+ if (!IsValidFlagCombination(verify_flags)) return;
+
+ unsigned int fuzzed_flags;
+ ds >> fuzzed_flags;
+
+ for (unsigned i = 0; i < tx.vin.size(); ++i) {
+ CTxOut prevout;
+ ds >> prevout;
+
+ const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata};
+
+ ScriptError serror;
+ const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror);
+ assert(ret == (serror == SCRIPT_ERR_OK));
+
+ // Verify that removing flags from a passing test or adding flags to a failing test does not change the result
+ if (ret) {
+ verify_flags &= ~fuzzed_flags;
+ } else {
+ verify_flags |= fuzzed_flags;
+ }
+ if (!IsValidFlagCombination(verify_flags)) return;
+
+ ScriptError serror_fuzzed;
+ const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed);
+ assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK));
+
+ assert(ret_fuzzed == ret);
+ }
+ } catch (const std::ios_base::failure&) {
+ return;
+ }
+}
+
+static bool IsValidFlagCombination(unsigned flags)
+{
+ if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false;
+ if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false;
+ return true;
+}
diff --git a/src/test/gen/crypto_gen.cpp b/src/test/gen/crypto_gen.cpp
new file mode 100644
index 0000000000..ca8c65806f
--- /dev/null
+++ b/src/test/gen/crypto_gen.cpp
@@ -0,0 +1,19 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <test/gen/crypto_gen.h>
+
+#include <key.h>
+
+#include <rapidcheck/gen/Arbitrary.h>
+#include <rapidcheck/Gen.h>
+#include <rapidcheck/gen/Predicate.h>
+#include <rapidcheck/gen/Container.h>
+
+/** Generates 1 to 20 keys for OP_CHECKMULTISIG */
+rc::Gen<std::vector<CKey>> MultisigKeys()
+{
+ return rc::gen::suchThat(rc::gen::arbitrary<std::vector<CKey>>(), [](const std::vector<CKey>& keys) {
+ return keys.size() >= 1 && keys.size() <= 15;
+ });
+};
diff --git a/src/test/gen/crypto_gen.h b/src/test/gen/crypto_gen.h
new file mode 100644
index 0000000000..7c2fb0350f
--- /dev/null
+++ b/src/test/gen/crypto_gen.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_TEST_GEN_CRYPTO_GEN_H
+#define BITCOIN_TEST_GEN_CRYPTO_GEN_H
+
+#include <key.h>
+#include <random.h>
+#include <uint256.h>
+#include <rapidcheck/gen/Arbitrary.h>
+#include <rapidcheck/Gen.h>
+#include <rapidcheck/gen/Create.h>
+#include <rapidcheck/gen/Numeric.h>
+
+/** Generates 1 to 15 keys for OP_CHECKMULTISIG */
+rc::Gen<std::vector<CKey>> MultisigKeys();
+
+namespace rc
+{
+/** Generator for a new CKey */
+template <>
+struct Arbitrary<CKey> {
+ static Gen<CKey> arbitrary()
+ {
+ return rc::gen::map<int>([](int x) {
+ CKey key;
+ key.MakeNewKey(true);
+ return key;
+ });
+ };
+};
+
+/** Generator for a CPrivKey */
+template <>
+struct Arbitrary<CPrivKey> {
+ static Gen<CPrivKey> arbitrary()
+ {
+ return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) {
+ return key.GetPrivKey();
+ });
+ };
+};
+
+/** Generator for a new CPubKey */
+template <>
+struct Arbitrary<CPubKey> {
+ static Gen<CPubKey> arbitrary()
+ {
+ return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) {
+ return key.GetPubKey();
+ });
+ };
+};
+/** Generates a arbitrary uint256 */
+template <>
+struct Arbitrary<uint256> {
+ static Gen<uint256> arbitrary()
+ {
+ return rc::gen::just(GetRandHash());
+ };
+};
+} //namespace rc
+#endif
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index c065e25676..8a42344642 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -1,9 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
-#include <test/test_bitcoin.h>
+#include <util/strencodings.h>
+#include <util/system.h>
+#include <test/setup_common.h>
#include <string>
#include <vector>
@@ -17,18 +18,18 @@ static void ResetArgs(const std::string& strArg)
{
std::vector<std::string> vecArg;
if (strArg.size())
- boost::split(vecArg, strArg, boost::is_space(), boost::token_compress_on);
+ boost::split(vecArg, strArg, IsSpace, boost::token_compress_on);
// Insert dummy executable name:
vecArg.insert(vecArg.begin(), "testbitcoin");
// Convert to char*:
std::vector<const char*> vecChar;
- for (std::string& s : vecArg)
+ for (const std::string& s : vecArg)
vecChar.push_back(s.c_str());
std::string error;
- gArgs.ParseParameters(vecChar.size(), vecChar.data(), error);
+ BOOST_CHECK(gArgs.ParseParameters(vecChar.size(), vecChar.data(), error));
}
static void SetupArgs(const std::vector<std::string>& args)
diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp
index d7d6c9b5a3..325b7002f2 100644
--- a/src/test/hash_tests.cpp
+++ b/src/test/hash_tests.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2013-2017 The Bitcoin Core developers
+// Copyright (c) 2013-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <crypto/siphash.h>
#include <hash.h>
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp
index 1ac1e0015b..e924f27d1b 100644
--- a/src/test/key_io_tests.cpp
+++ b/src/test/key_io_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2016 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,8 +8,8 @@
#include <key.h>
#include <key_io.h>
#include <script/script.h>
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(key_io_valid_gen)
} else {
CTxDestination dest;
CScript exp_script(exp_payload.begin(), exp_payload.end());
- ExtractDestination(exp_script, dest);
+ BOOST_CHECK(ExtractDestination(exp_script, dest));
std::string address = EncodeDestination(dest);
BOOST_CHECK_EQUAL(address, exp_base58string);
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(key_io_invalid)
std::string exp_base58string = test[0].get_str();
// must be invalid as public and as private key
- for (auto chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) {
+ for (const auto& chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) {
SelectParams(chain);
destination = DecodeDestination(exp_base58string);
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest);
diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp
new file mode 100644
index 0000000000..8b508ed7f7
--- /dev/null
+++ b/src/test/key_properties.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <key.h>
+
+#include <base58.h>
+#include <script/script.h>
+#include <uint256.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
+#include <string>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+#include <rapidcheck/boost_test.h>
+#include <rapidcheck/gen/Arbitrary.h>
+#include <rapidcheck/Gen.h>
+
+#include <test/gen/crypto_gen.h>
+
+BOOST_FIXTURE_TEST_SUITE(key_properties, BasicTestingSetup)
+
+/** Check CKey uniqueness */
+RC_BOOST_PROP(key_uniqueness, (const CKey& key1, const CKey& key2))
+{
+ RC_ASSERT(!(key1 == key2));
+}
+
+/** Verify that a private key generates the correct public key */
+RC_BOOST_PROP(key_generates_correct_pubkey, (const CKey& key))
+{
+ CPubKey pubKey = key.GetPubKey();
+ RC_ASSERT(key.VerifyPubKey(pubKey));
+}
+
+/** Create a CKey using the 'Set' function must give us the same key */
+RC_BOOST_PROP(key_set_symmetry, (const CKey& key))
+{
+ CKey key1;
+ key1.Set(key.begin(), key.end(), key.IsCompressed());
+ RC_ASSERT(key1 == key);
+}
+
+/** Create a CKey, sign a piece of data, then verify it with the public key */
+RC_BOOST_PROP(key_sign_symmetry, (const CKey& key, const uint256& hash))
+{
+ std::vector<unsigned char> vchSig;
+ key.Sign(hash, vchSig, 0);
+ const CPubKey& pubKey = key.GetPubKey();
+ RC_ASSERT(pubKey.Verify(hash, vchSig));
+}
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 64c57f0705..1b95105eab 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,9 +7,9 @@
#include <key_io.h>
#include <script/script.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
#include <string>
#include <vector>
@@ -68,10 +68,10 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));
- BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(pubkey1.GetID()));
- BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(pubkey2.GetID()));
- BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID()));
- BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID()));
+ BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(PKHash(pubkey1)));
+ BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(PKHash(pubkey2)));
+ BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(PKHash(pubkey1C)));
+ BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(PKHash(pubkey2C)));
for (int n=0; n<16; n++)
{
@@ -152,4 +152,72 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
}
+BOOST_AUTO_TEST_CASE(key_signature_tests)
+{
+ // When entropy is specified, we should see at least one high R signature within 20 signatures
+ CKey key = DecodeSecret(strSecret1);
+ std::string msg = "A message to be signed";
+ uint256 msg_hash = Hash(msg.begin(), msg.end());
+ std::vector<unsigned char> sig;
+ bool found = false;
+
+ for (int i = 1; i <=20; ++i) {
+ sig.clear();
+ BOOST_CHECK(key.Sign(msg_hash, sig, false, i));
+ found = sig[3] == 0x21 && sig[4] == 0x00;
+ if (found) {
+ break;
+ }
+ }
+ BOOST_CHECK(found);
+
+ // When entropy is not specified, we should always see low R signatures that are less than 70 bytes in 256 tries
+ // We should see at least one signature that is less than 70 bytes.
+ found = true;
+ bool found_small = false;
+ for (int i = 0; i < 256; ++i) {
+ sig.clear();
+ std::string msg = "A message to be signed" + std::to_string(i);
+ msg_hash = Hash(msg.begin(), msg.end());
+ BOOST_CHECK(key.Sign(msg_hash, sig));
+ found = sig[3] == 0x20;
+ BOOST_CHECK(sig.size() <= 70);
+ found_small |= sig.size() < 70;
+ }
+ BOOST_CHECK(found);
+ BOOST_CHECK(found_small);
+}
+
+BOOST_AUTO_TEST_CASE(key_key_negation)
+{
+ // create a dummy hash for signature comparison
+ unsigned char rnd[8];
+ std::string str = "Bitcoin key verification\n";
+ GetRandBytes(rnd, sizeof(rnd));
+ uint256 hash;
+ CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin());
+
+ // import the static test key
+ CKey key = DecodeSecret(strSecret1C);
+
+ // create a signature
+ std::vector<unsigned char> vch_sig;
+ std::vector<unsigned char> vch_sig_cmp;
+ key.Sign(hash, vch_sig);
+
+ // negate the key twice
+ BOOST_CHECK(key.GetPubKey().data()[0] == 0x03);
+ key.Negate();
+ // after the first negation, the signature must be different
+ key.Sign(hash, vch_sig_cmp);
+ BOOST_CHECK(vch_sig_cmp != vch_sig);
+ BOOST_CHECK(key.GetPubKey().data()[0] == 0x02);
+ key.Negate();
+ // after the second negation, we should have the original key and thus the
+ // same signature
+ key.Sign(hash, vch_sig_cmp);
+ BOOST_CHECK(vch_sig_cmp == vch_sig);
+ BOOST_CHECK(key.GetPubKey().data()[0] == 0x03);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp
index 7871ff6f74..00b36f51fb 100644
--- a/src/test/limitedmap_tests.cpp
+++ b/src/test/limitedmap_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <limitedmap.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/main.cpp b/src/test/main.cpp
new file mode 100644
index 0000000000..ff3f36b561
--- /dev/null
+++ b/src/test/main.cpp
@@ -0,0 +1,7 @@
+// Copyright (c) 2011-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#define BOOST_TEST_MODULE Bitcoin Core Test Suite
+
+#include <boost/test/unit_test.hpp>
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index fb80599af7..0f74b379c0 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -1,12 +1,12 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <policy/policy.h>
#include <txmempool.h>
-#include <util.h>
+#include <util/system.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <list>
@@ -55,53 +55,53 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
CTxMemPool testPool;
- LOCK(testPool.cs);
+ LOCK2(cs_main, testPool.cs);
// Nothing in pool, remove should do nothing:
unsigned int poolSize = testPool.size();
- testPool.removeRecursive(txParent);
+ testPool.removeRecursive(CTransaction(txParent));
BOOST_CHECK_EQUAL(testPool.size(), poolSize);
// Just the parent:
- testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent));
+ testPool.addUnchecked(entry.FromTx(txParent));
poolSize = testPool.size();
- testPool.removeRecursive(txParent);
+ testPool.removeRecursive(CTransaction(txParent));
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 1);
// Parent, children, grandchildren:
- testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent));
+ testPool.addUnchecked(entry.FromTx(txParent));
for (int i = 0; i < 3; i++)
{
- testPool.addUnchecked(txChild[i].GetHash(), entry.FromTx(txChild[i]));
- testPool.addUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i]));
+ testPool.addUnchecked(entry.FromTx(txChild[i]));
+ testPool.addUnchecked(entry.FromTx(txGrandChild[i]));
}
// Remove Child[0], GrandChild[0] should be removed:
poolSize = testPool.size();
- testPool.removeRecursive(txChild[0]);
+ testPool.removeRecursive(CTransaction(txChild[0]));
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 2);
// ... make sure grandchild and child are gone:
poolSize = testPool.size();
- testPool.removeRecursive(txGrandChild[0]);
+ testPool.removeRecursive(CTransaction(txGrandChild[0]));
BOOST_CHECK_EQUAL(testPool.size(), poolSize);
poolSize = testPool.size();
- testPool.removeRecursive(txChild[0]);
+ testPool.removeRecursive(CTransaction(txChild[0]));
BOOST_CHECK_EQUAL(testPool.size(), poolSize);
// Remove parent, all children/grandchildren should go:
poolSize = testPool.size();
- testPool.removeRecursive(txParent);
+ testPool.removeRecursive(CTransaction(txParent));
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 5);
BOOST_CHECK_EQUAL(testPool.size(), 0U);
// Add children and grandchildren, but NOT the parent (simulate the parent being in a block)
for (int i = 0; i < 3; i++)
{
- testPool.addUnchecked(txChild[i].GetHash(), entry.FromTx(txChild[i]));
- testPool.addUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i]));
+ testPool.addUnchecked(entry.FromTx(txChild[i]));
+ testPool.addUnchecked(entry.FromTx(txGrandChild[i]));
}
// Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
// put into the mempool (maybe because it is non-standard):
poolSize = testPool.size();
- testPool.removeRecursive(txParent);
+ testPool.removeRecursive(CTransaction(txParent));
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 6);
BOOST_CHECK_EQUAL(testPool.size(), 0U);
}
@@ -120,7 +120,7 @@ static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder) E
BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
{
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
/* 3rd highest fee */
@@ -128,28 +128,28 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx1.vout.resize(1);
tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx1.vout[0].nValue = 10 * COIN;
- pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1));
/* highest fee */
CMutableTransaction tx2 = CMutableTransaction();
tx2.vout.resize(1);
tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx2.vout[0].nValue = 2 * COIN;
- pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).FromTx(tx2));
+ pool.addUnchecked(entry.Fee(20000LL).FromTx(tx2));
/* lowest fee */
CMutableTransaction tx3 = CMutableTransaction();
tx3.vout.resize(1);
tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx3.vout[0].nValue = 5 * COIN;
- pool.addUnchecked(tx3.GetHash(), entry.Fee(0LL).FromTx(tx3));
+ pool.addUnchecked(entry.Fee(0LL).FromTx(tx3));
/* 2nd highest fee */
CMutableTransaction tx4 = CMutableTransaction();
tx4.vout.resize(1);
tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx4.vout[0].nValue = 6 * COIN;
- pool.addUnchecked(tx4.GetHash(), entry.Fee(15000LL).FromTx(tx4));
+ pool.addUnchecked(entry.Fee(15000LL).FromTx(tx4));
/* equal fee rate to tx1, but newer */
CMutableTransaction tx5 = CMutableTransaction();
@@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx5.vout[0].nValue = 11 * COIN;
entry.nTime = 1;
- pool.addUnchecked(tx5.GetHash(), entry.Fee(10000LL).FromTx(tx5));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx5));
BOOST_CHECK_EQUAL(pool.size(), 5U);
std::vector<std::string> sortedOrder;
@@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx6.vout.resize(1);
tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx6.vout[0].nValue = 20 * COIN;
- pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6));
+ pool.addUnchecked(entry.Fee(0LL).FromTx(tx6));
BOOST_CHECK_EQUAL(pool.size(), 6U);
// Check that at this point, tx6 is sorted low
sortedOrder.insert(sortedOrder.begin(), tx6.GetHash().ToString());
@@ -198,7 +198,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(2000000LL).FromTx(tx7), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
BOOST_CHECK(setAncestorsCalculated == setAncestors);
- pool.addUnchecked(tx7.GetHash(), entry.FromTx(tx7), setAncestors);
+ pool.addUnchecked(entry.FromTx(tx7), setAncestors);
BOOST_CHECK_EQUAL(pool.size(), 7U);
// Now tx6 should be sorted higher (high fee child): tx7, tx6, tx2, ...
@@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx8.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx8.vout[0].nValue = 10 * COIN;
setAncestors.insert(pool.mapTx.find(tx7.GetHash()));
- pool.addUnchecked(tx8.GetHash(), entry.Fee(0LL).Time(2).FromTx(tx8), setAncestors);
+ pool.addUnchecked(entry.Fee(0LL).Time(2).FromTx(tx8), setAncestors);
// Now tx8 should be sorted low, but tx6/tx both high
sortedOrder.insert(sortedOrder.begin(), tx8.GetHash().ToString());
@@ -230,7 +230,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx9.vout.resize(1);
tx9.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx9.vout[0].nValue = 1 * COIN;
- pool.addUnchecked(tx9.GetHash(), entry.Fee(0LL).Time(3).FromTx(tx9), setAncestors);
+ pool.addUnchecked(entry.Fee(0LL).Time(3).FromTx(tx9), setAncestors);
// tx9 should be sorted low
BOOST_CHECK_EQUAL(pool.size(), 9U);
@@ -256,7 +256,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(200000LL).Time(4).FromTx(tx10), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
BOOST_CHECK(setAncestorsCalculated == setAncestors);
- pool.addUnchecked(tx10.GetHash(), entry.FromTx(tx10), setAncestors);
+ pool.addUnchecked(entry.FromTx(tx10), setAncestors);
/**
* tx8 and tx9 should both now be sorted higher
@@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
{
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
/* 3rd highest fee */
@@ -301,36 +301,36 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
tx1.vout.resize(1);
tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx1.vout[0].nValue = 10 * COIN;
- pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1));
/* highest fee */
CMutableTransaction tx2 = CMutableTransaction();
tx2.vout.resize(1);
tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx2.vout[0].nValue = 2 * COIN;
- pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).FromTx(tx2));
- uint64_t tx2Size = GetVirtualTransactionSize(tx2);
+ pool.addUnchecked(entry.Fee(20000LL).FromTx(tx2));
+ uint64_t tx2Size = GetVirtualTransactionSize(CTransaction(tx2));
/* lowest fee */
CMutableTransaction tx3 = CMutableTransaction();
tx3.vout.resize(1);
tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx3.vout[0].nValue = 5 * COIN;
- pool.addUnchecked(tx3.GetHash(), entry.Fee(0LL).FromTx(tx3));
+ pool.addUnchecked(entry.Fee(0LL).FromTx(tx3));
/* 2nd highest fee */
CMutableTransaction tx4 = CMutableTransaction();
tx4.vout.resize(1);
tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx4.vout[0].nValue = 6 * COIN;
- pool.addUnchecked(tx4.GetHash(), entry.Fee(15000LL).FromTx(tx4));
+ pool.addUnchecked(entry.Fee(15000LL).FromTx(tx4));
/* equal fee rate to tx1, but newer */
CMutableTransaction tx5 = CMutableTransaction();
tx5.vout.resize(1);
tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx5.vout[0].nValue = 11 * COIN;
- pool.addUnchecked(tx5.GetHash(), entry.Fee(10000LL).FromTx(tx5));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx5));
BOOST_CHECK_EQUAL(pool.size(), 5U);
std::vector<std::string> sortedOrder;
@@ -357,9 +357,9 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
tx6.vout.resize(1);
tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx6.vout[0].nValue = 20 * COIN;
- uint64_t tx6Size = GetVirtualTransactionSize(tx6);
+ uint64_t tx6Size = GetVirtualTransactionSize(CTransaction(tx6));
- pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6));
+ pool.addUnchecked(entry.Fee(0LL).FromTx(tx6));
BOOST_CHECK_EQUAL(pool.size(), 6U);
// Ties are broken by hash
if (tx3.GetHash() < tx6.GetHash())
@@ -376,12 +376,12 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
tx7.vout.resize(1);
tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx7.vout[0].nValue = 10 * COIN;
- uint64_t tx7Size = GetVirtualTransactionSize(tx7);
+ uint64_t tx7Size = GetVirtualTransactionSize(CTransaction(tx7));
/* set the fee to just below tx2's feerate when including ancestor */
CAmount fee = (20000/tx2Size)*(tx7Size + tx6Size) - 1;
- pool.addUnchecked(tx7.GetHash(), entry.Fee(fee).FromTx(tx7));
+ pool.addUnchecked(entry.Fee(fee).FromTx(tx7));
BOOST_CHECK_EQUAL(pool.size(), 7U);
sortedOrder.insert(sortedOrder.begin()+1, tx7.GetHash().ToString());
CheckSort<ancestor_score>(pool, sortedOrder);
@@ -413,7 +413,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
// Check that we sort by min(feerate, ancestor_feerate):
// set the fee so that the ancestor feerate is above tx1/5,
// but the transaction's own feerate is lower
- pool.addUnchecked(tx8.GetHash(), entry.Fee(5000LL).FromTx(tx8));
+ pool.addUnchecked(entry.Fee(5000LL).FromTx(tx8));
sortedOrder.insert(sortedOrder.end()-1, tx8.GetHash().ToString());
CheckSort<ancestor_score>(pool, sortedOrder);
}
@@ -422,7 +422,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
{
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
CMutableTransaction tx1 = CMutableTransaction();
@@ -431,7 +431,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
tx1.vout.resize(1);
tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
tx1.vout[0].nValue = 10 * COIN;
- pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1));
CMutableTransaction tx2 = CMutableTransaction();
tx2.vin.resize(1);
@@ -439,7 +439,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
tx2.vout.resize(1);
tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
tx2.vout[0].nValue = 10 * COIN;
- pool.addUnchecked(tx2.GetHash(), entry.Fee(5000LL).FromTx(tx2));
+ pool.addUnchecked(entry.Fee(5000LL).FromTx(tx2));
pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
BOOST_CHECK(pool.exists(tx1.GetHash()));
@@ -449,7 +449,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
BOOST_CHECK(pool.exists(tx1.GetHash()));
BOOST_CHECK(!pool.exists(tx2.GetHash()));
- pool.addUnchecked(tx2.GetHash(), entry.FromTx(tx2));
+ pool.addUnchecked(entry.FromTx(tx2));
CMutableTransaction tx3 = CMutableTransaction();
tx3.vin.resize(1);
tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
@@ -457,19 +457,19 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
tx3.vout.resize(1);
tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
tx3.vout[0].nValue = 10 * COIN;
- pool.addUnchecked(tx3.GetHash(), entry.Fee(20000LL).FromTx(tx3));
+ pool.addUnchecked(entry.Fee(20000LL).FromTx(tx3));
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
BOOST_CHECK(!pool.exists(tx1.GetHash()));
BOOST_CHECK(pool.exists(tx2.GetHash()));
BOOST_CHECK(pool.exists(tx3.GetHash()));
- pool.TrimToSize(GetVirtualTransactionSize(tx1)); // mempool is limited to tx1's size in memory usage, so nothing fits
+ pool.TrimToSize(GetVirtualTransactionSize(CTransaction(tx1))); // mempool is limited to tx1's size in memory usage, so nothing fits
BOOST_CHECK(!pool.exists(tx1.GetHash()));
BOOST_CHECK(!pool.exists(tx2.GetHash()));
BOOST_CHECK(!pool.exists(tx3.GetHash()));
- CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(tx3) + GetVirtualTransactionSize(tx2));
+ CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2)));
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
CMutableTransaction tx4 = CMutableTransaction();
@@ -520,10 +520,10 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
tx7.vout[1].nValue = 10 * COIN;
- pool.addUnchecked(tx4.GetHash(), entry.Fee(7000LL).FromTx(tx4));
- pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5));
- pool.addUnchecked(tx6.GetHash(), entry.Fee(1100LL).FromTx(tx6));
- pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7));
+ pool.addUnchecked(entry.Fee(7000LL).FromTx(tx4));
+ pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5));
+ pool.addUnchecked(entry.Fee(1100LL).FromTx(tx6));
+ pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7));
// we only require this to remove, at max, 2 txn, because it's not clear what we're really optimizing for aside from that
pool.TrimToSize(pool.DynamicMemoryUsage() - 1);
@@ -532,8 +532,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
BOOST_CHECK(!pool.exists(tx7.GetHash()));
if (!pool.exists(tx5.GetHash()))
- pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5));
- pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7));
+ pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5));
+ pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7));
pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7
BOOST_CHECK(pool.exists(tx4.GetHash()));
@@ -541,8 +541,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
BOOST_CHECK(pool.exists(tx6.GetHash()));
BOOST_CHECK(!pool.exists(tx7.GetHash()));
- pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5));
- pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7));
+ pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5));
+ pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7));
std::vector<CTransactionRef> vtx;
SetMockTime(42);
@@ -595,7 +595,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
size_t ancestors, descendants;
CTxMemPool pool;
- LOCK(pool.cs);
+ LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
/* Base transaction */
@@ -603,7 +603,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
// [tx1]
//
CTransactionRef tx1 = make_tx(/* output_values */ {10 * COIN});
- pool.addUnchecked(tx1->GetHash(), entry.Fee(10000LL).FromTx(tx1));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1));
// Ancestors / descendants should be 1 / 1 (itself / itself)
pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants);
@@ -615,7 +615,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
// [tx1].0 <- [tx2]
//
CTransactionRef tx2 = make_tx(/* output_values */ {495 * CENT, 5 * COIN}, /* inputs */ {tx1});
- pool.addUnchecked(tx2->GetHash(), entry.Fee(10000LL).FromTx(tx2));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx2));
// Ancestors / descendants should be:
// transaction ancestors descendants
@@ -634,7 +634,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
// [tx1].0 <- [tx2].0 <- [tx3]
//
CTransactionRef tx3 = make_tx(/* output_values */ {290 * CENT, 200 * CENT}, /* inputs */ {tx2});
- pool.addUnchecked(tx3->GetHash(), entry.Fee(10000LL).FromTx(tx3));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx3));
// Ancestors / descendants should be:
// transaction ancestors descendants
@@ -659,7 +659,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
// \---1 <- [tx4]
//
CTransactionRef tx4 = make_tx(/* output_values */ {290 * CENT, 250 * CENT}, /* inputs */ {tx2}, /* input_indices */ {1});
- pool.addUnchecked(tx4->GetHash(), entry.Fee(10000LL).FromTx(tx4));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tx4));
// Ancestors / descendants should be:
// transaction ancestors descendants
@@ -696,13 +696,13 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
CTransactionRef& tyi = *ty[i];
tyi = make_tx(/* output_values */ {v}, /* inputs */ i > 0 ? std::vector<CTransactionRef>{*ty[i - 1]} : std::vector<CTransactionRef>{});
v -= 50 * CENT;
- pool.addUnchecked(tyi->GetHash(), entry.Fee(10000LL).FromTx(tyi));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(tyi));
pool.GetTransactionAncestry(tyi->GetHash(), ancestors, descendants);
BOOST_CHECK_EQUAL(ancestors, i+1);
BOOST_CHECK_EQUAL(descendants, i+1);
}
CTransactionRef ty6 = make_tx(/* output_values */ {5 * COIN}, /* inputs */ {tx3, ty5});
- pool.addUnchecked(ty6->GetHash(), entry.Fee(10000LL).FromTx(ty6));
+ pool.addUnchecked(entry.Fee(10000LL).FromTx(ty6));
// Ancestors / descendants should be:
// transaction ancestors descendants
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 259e45dacf..1684258c9f 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <consensus/merkle.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -13,9 +13,9 @@ static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vecto
uint256 hash = leaf;
for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
if (nIndex & 1) {
- hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
+ hash = Hash(it->begin(), it->end(), hash.begin(), hash.end());
} else {
- hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
+ hash = Hash(hash.begin(), hash.end(), it->begin(), it->end());
}
nIndex >>= 1;
}
diff --git a/src/test/merkleblock_tests.cpp b/src/test/merkleblock_tests.cpp
index 2472ea9950..eac43471c7 100644
--- a/src/test/merkleblock_tests.cpp
+++ b/src/test/merkleblock_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <merkleblock.h>
#include <uint256.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index e2424f012d..4321d7d16e 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,17 +8,17 @@
#include <consensus/merkle.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
-#include <validation.h>
#include <miner.h>
#include <policy/policy.h>
#include <pubkey.h>
#include <script/standard.h>
#include <txmempool.h>
#include <uint256.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
+#include <util/system.h>
+#include <validation.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <memory>
@@ -29,7 +29,7 @@ BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup)
// BOOST_CHECK_EXCEPTION predicates to check the specific validation error
class HasReason {
public:
- HasReason(const std::string& reason) : m_reason(reason) {}
+ explicit HasReason(const std::string& reason) : m_reason(reason) {}
bool operator() (const std::runtime_error& e) const {
return std::string(e.what()).find(m_reason) != std::string::npos;
};
@@ -82,24 +82,24 @@ struct {
{2, 0xbbbeb305}, {2, 0xfe1c810a},
};
-static CBlockIndex CreateBlockIndex(int nHeight)
+static CBlockIndex CreateBlockIndex(int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
CBlockIndex index;
index.nHeight = nHeight;
- index.pprev = chainActive.Tip();
+ index.pprev = ::ChainActive().Tip();
return index;
}
-static bool TestSequenceLocks(const CTransaction &tx, int flags)
+static bool TestSequenceLocks(const CTransaction &tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- LOCK(mempool.cs);
- return CheckSequenceLocks(tx, flags);
+ LOCK(::mempool.cs);
+ return CheckSequenceLocks(::mempool, tx, flags);
}
// Test suite for ancestor feerate transaction selection.
// Implemented as an additional function, rather than a separate test case,
// to allow reusing the blockchain created in CreateNewBlock_validity.
-static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs)
+static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::mempool.cs)
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
@@ -115,19 +115,19 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
tx.vout[0].nValue = 5000000000LL - 1000;
// This tx has a low fee: 1000 satoshis
uint256 hashParentTx = tx.GetHash(); // save this txid for later use
- mempool.addUnchecked(hashParentTx, entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
// This tx has a medium fee: 10000 satoshis
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
tx.vout[0].nValue = 5000000000LL - 10000;
uint256 hashMediumFeeTx = tx.GetHash();
- mempool.addUnchecked(hashMediumFeeTx, entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
// This tx has a high fee, but depends on the first transaction
tx.vin[0].prevout.hash = hashParentTx;
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
uint256 hashHighFeeTx = tx.GetHash();
- mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
@@ -138,8 +138,8 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
tx.vin[0].prevout.hash = hashHighFeeTx;
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
uint256 hashFreeTx = tx.GetHash();
- mempool.addUnchecked(hashFreeTx, entry.Fee(0).FromTx(tx));
- size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
+ mempool.addUnchecked(entry.Fee(0).FromTx(tx));
+ size_t freeTxSize = ::GetSerializeSize(tx, PROTOCOL_VERSION);
// Calculate a fee on child transaction that will put the package just
// below the block min tx fee (assuming 1 child tx of the same size).
@@ -148,7 +148,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
tx.vin[0].prevout.hash = hashFreeTx;
tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
uint256 hashLowFeeTx = tx.GetHash();
- mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(feeToUse).FromTx(tx));
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
// Verify that the free tx and the low fee tx didn't get selected
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
@@ -159,10 +159,10 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
// Test that packages above the min relay fee do get included, even if one
// of the transactions is below the min relay fee
// Remove the low fee transaction and replace with a higher fee transaction
- mempool.removeRecursive(tx);
+ mempool.removeRecursive(CTransaction(tx));
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
hashLowFeeTx = tx.GetHash();
- mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(feeToUse+2).FromTx(tx));
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
@@ -175,7 +175,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
tx.vout[0].nValue = 5000000000LL - 100000000;
tx.vout[1].nValue = 100000000; // 1BTC output
uint256 hashFreeTx2 = tx.GetHash();
- mempool.addUnchecked(hashFreeTx2, entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
// This tx can't be mined by itself
tx.vin[0].prevout.hash = hashFreeTx2;
@@ -183,7 +183,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
feeToUse = blockMinFeeRate.GetFee(freeTxSize);
tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
uint256 hashLowFeeTx2 = tx.GetHash();
- mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
// Verify that this tx isn't selected.
@@ -196,7 +196,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
// as well.
tx.vin[0].prevout.n = 1;
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
- mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(10000).FromTx(tx));
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
}
@@ -231,17 +231,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
LOCK(cs_main);
pblock->nVersion = 1;
- pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
+ pblock->nTime = ::ChainActive().Tip()->GetMedianTimePast()+1;
CMutableTransaction txCoinbase(*pblock->vtx[0]);
txCoinbase.nVersion = 1;
txCoinbase.vin[0].scriptSig = CScript();
txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
- txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
+ txCoinbase.vin[0].scriptSig.push_back(::ChainActive().Height());
txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
txCoinbase.vout[0].scriptPubKey = CScript();
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
if (txFirst.size() == 0)
- baseheight = chainActive.Height();
+ baseheight = ::ChainActive().Height();
if (txFirst.size() < 4)
txFirst.push_back(pblock->vtx[0]);
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
@@ -277,7 +277,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
hash = tx.GetHash();
bool spendsCoinbase = i == 0; // only first tx spends coinbase
// If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
- mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
tx.vin[0].prevout.hash = hash;
}
@@ -292,7 +292,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
hash = tx.GetHash();
bool spendsCoinbase = i == 0; // only first tx spends coinbase
// If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
- mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
tx.vin[0].prevout.hash = hash;
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
@@ -312,7 +312,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue -= LOWFEE;
hash = tx.GetHash();
bool spendsCoinbase = i == 0; // only first tx spends coinbase
- mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
tx.vin[0].prevout.hash = hash;
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
@@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// orphan in mempool, template creation fails
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
mempool.clear();
@@ -329,7 +329,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
tx.vin[0].prevout.hash = hash;
tx.vin.resize(2);
tx.vin[1].scriptSig = CScript() << OP_1;
@@ -337,7 +337,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vin[1].prevout.n = 0;
tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
mempool.clear();
@@ -348,7 +348,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue = 0;
hash = tx.GetHash();
// give it a fee so it'll get mined
- mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
// Should throw bad-cb-multiple
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
mempool.clear();
@@ -359,37 +359,37 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
tx.vout[0].scriptPubKey = CScript() << OP_1;
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
tx.vout[0].scriptPubKey = CScript() << OP_2;
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
mempool.clear();
// subsidy changing
- int nHeight = chainActive.Height();
+ int nHeight = ::ChainActive().Height();
// Create an actual 209999-long block chain (without valid blocks).
- while (chainActive.Tip()->nHeight < 209999) {
- CBlockIndex* prev = chainActive.Tip();
+ while (::ChainActive().Tip()->nHeight < 209999) {
+ CBlockIndex* prev = ::ChainActive().Tip();
CBlockIndex* next = new CBlockIndex();
next->phashBlock = new uint256(InsecureRand256());
pcoinsTip->SetBestBlock(next->GetBlockHash());
next->pprev = prev;
next->nHeight = prev->nHeight + 1;
next->BuildSkip();
- chainActive.SetTip(next);
+ ::ChainActive().SetTip(next);
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
// Extend to a 210000-long block chain.
- while (chainActive.Tip()->nHeight < 210000) {
- CBlockIndex* prev = chainActive.Tip();
+ while (::ChainActive().Tip()->nHeight < 210000) {
+ CBlockIndex* prev = ::ChainActive().Tip();
CBlockIndex* next = new CBlockIndex();
next->phashBlock = new uint256(InsecureRand256());
pcoinsTip->SetBestBlock(next->GetBlockHash());
next->pprev = prev;
next->nHeight = prev->nHeight + 1;
next->BuildSkip();
- chainActive.SetTip(next);
+ ::ChainActive().SetTip(next);
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
@@ -399,29 +399,29 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vin[0].scriptSig = CScript() << OP_1;
tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE;
script = CScript() << OP_0;
- tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script));
+ tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script));
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
tx.vin[0].prevout.hash = hash;
tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
tx.vout[0].nValue -= LOWFEE;
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
+ mempool.addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
// Should throw block-validation-failed
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
mempool.clear();
// Delete the dummy blocks again.
- while (chainActive.Tip()->nHeight > nHeight) {
- CBlockIndex* del = chainActive.Tip();
- chainActive.SetTip(del->pprev);
+ while (::ChainActive().Tip()->nHeight > nHeight) {
+ CBlockIndex* del = ::ChainActive().Tip();
+ ::ChainActive().SetTip(del->pprev);
pcoinsTip->SetBestBlock(del->pprev->GetBlockHash());
delete del->phashBlock;
delete del;
}
// non-final txs in mempool
- SetMockTime(chainActive.Tip()->GetMedianTimePast()+1);
+ SetMockTime(::ChainActive().Tip()->GetMedianTimePast()+1);
int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST;
// height map
std::vector<int> prevheights;
@@ -433,68 +433,68 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction
tx.vin[0].prevout.n = 0;
tx.vin[0].scriptSig = CScript() << OP_1;
- tx.vin[0].nSequence = chainActive.Tip()->nHeight + 1; // txFirst[0] is the 2nd block
+ tx.vin[0].nSequence = ::ChainActive().Tip()->nHeight + 1; // txFirst[0] is the 2nd block
prevheights[0] = baseheight + 1;
tx.vout.resize(1);
tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
tx.vout[0].scriptPubKey = CScript() << OP_1;
tx.nLockTime = 0;
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
- BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
- BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
- BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
+ mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
+ BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
// relative time locked
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
- tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((chainActive.Tip()->GetMedianTimePast()+1-chainActive[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((::ChainActive().Tip()->GetMedianTimePast()+1-::ChainActive()[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
prevheights[0] = baseheight + 2;
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
- BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+ mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
- chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
- BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later
+ ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
+ BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(::ChainActive().Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
- chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP
+ ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP
// absolute height locked
tx.vin[0].prevout.hash = txFirst[2]->GetHash();
tx.vin[0].nSequence = CTxIn::SEQUENCE_FINAL - 1;
prevheights[0] = baseheight + 3;
- tx.nLockTime = chainActive.Tip()->nHeight + 1;
+ tx.nLockTime = ::ChainActive().Tip()->nHeight + 1;
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails
- BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
- BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
+ mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails
+ BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
// absolute time locked
tx.vin[0].prevout.hash = txFirst[3]->GetHash();
- tx.nLockTime = chainActive.Tip()->GetMedianTimePast();
+ tx.nLockTime = ::ChainActive().Tip()->GetMedianTimePast();
prevheights.resize(1);
prevheights[0] = baseheight + 4;
hash = tx.GetHash();
- mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails
- BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
- BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
+ mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails
+ BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(IsFinalTx(CTransaction(tx), ::ChainActive().Tip()->nHeight + 2, ::ChainActive().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
// mempool-dependent transactions (not added)
tx.vin[0].prevout.hash = hash;
- prevheights[0] = chainActive.Tip()->nHeight + 1;
+ prevheights[0] = ::ChainActive().Tip()->nHeight + 1;
tx.nLockTime = 0;
tx.vin[0].nSequence = 0;
- BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
- BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
+ BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
tx.vin[0].nSequence = 1;
- BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+ BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
- BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
- BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+ BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
@@ -505,14 +505,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U);
// However if we advance height by 1 and time by 512, all of them should be mined
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
- chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
- chainActive.Tip()->nHeight++;
- SetMockTime(chainActive.Tip()->GetMedianTimePast() + 1);
+ ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
+ ::ChainActive().Tip()->nHeight++;
+ SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1);
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
- chainActive.Tip()->nHeight--;
+ ::ChainActive().Tip()->nHeight--;
SetMockTime(0);
mempool.clear();
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 77db9f5c57..682f1bee26 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,7 @@
#include <script/sign.h>
#include <script/ismine.h>
#include <uint256.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -76,20 +76,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
// Test a AND b:
keys.assign(1,key[0]);
keys.push_back(key[1]);
- s = sign_multisig(a_and_b, keys, txTo[0], 0);
+ s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
BOOST_CHECK(VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
for (int i = 0; i < 4; i++)
{
keys.assign(1,key[i]);
- s = sign_multisig(a_and_b, keys, txTo[0], 0);
+ s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
keys.assign(1,key[1]);
keys.push_back(key[i]);
- s = sign_multisig(a_and_b, keys, txTo[0], 0);
+ s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
@@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
for (int i = 0; i < 4; i++)
{
keys.assign(1,key[i]);
- s = sign_multisig(a_or_b, keys, txTo[1], 0);
+ s = sign_multisig(a_or_b, keys, CTransaction(txTo[1]), 0);
if (i == 0 || i == 1)
{
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
@@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
{
keys.assign(1,key[i]);
keys.push_back(key[j]);
- s = sign_multisig(escrow, keys, txTo[2], 0);
+ s = sign_multisig(escrow, keys, CTransaction(txTo[2]), 0);
if (i < j && i < 3 && j < 3)
{
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j));
@@ -179,7 +179,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
for (int i = 0; i < 4; i++)
{
key[i].MakeNewKey(true);
- keystore.AddKey(key[i]);
+ BOOST_CHECK(keystore.AddKey(key[i]));
}
CScript a_and_b;
@@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
for (int i = 0; i < 3; i++)
{
- BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
}
}
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index f7861d9b8a..54d18c0a1c 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -1,8 +1,8 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <addrman.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <string>
#include <boost/test/unit_test.hpp>
#include <hash.h>
@@ -11,7 +11,7 @@
#include <net.h>
#include <netbase.h>
#include <chainparams.h>
-#include <util.h>
+#include <util/system.h>
#include <memory>
@@ -54,10 +54,10 @@ public:
s << nUBuckets;
CService serv;
- Lookup("252.1.1.1", serv, 7777, false);
+ BOOST_CHECK(Lookup("252.1.1.1", serv, 7777, false));
CAddress addr = CAddress(serv, NODE_NONE);
CNetAddr resolved;
- LookupHost("252.2.2.2", resolved, false);
+ BOOST_CHECK(LookupHost("252.2.2.2", resolved, false));
CAddrInfo info = CAddrInfo(addr, resolved);
s << info;
}
@@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(cnode_listen_port)
BOOST_CHECK(port == Params().GetDefaultPort());
// test set port
unsigned short altPort = 12345;
- gArgs.SoftSetArg("-port", std::to_string(altPort));
+ BOOST_CHECK(gArgs.SoftSetArg("-port", std::to_string(altPort)));
port = GetListenPort();
BOOST_CHECK(port == altPort);
}
@@ -94,16 +94,16 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
addrmanUncorrupted.MakeDeterministic();
CService addr1, addr2, addr3;
- Lookup("250.7.1.1", addr1, 8333, false);
- Lookup("250.7.2.2", addr2, 9999, false);
- Lookup("250.7.3.3", addr3, 9999, false);
+ BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
+ BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false));
+ BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false));
// Add three addresses to new table.
CService source;
- Lookup("252.5.1.1", source, 8333, false);
- addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source);
- addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source);
- addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source);
+ BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false));
+ BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source));
+ BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source));
+ BOOST_CHECK(addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source));
// Test that the de-serialization does not throw an exception.
CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
@@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
unsigned char pchMsgTmp[4];
ssPeers1 >> pchMsgTmp;
ssPeers1 >> addrman1;
- } catch (const std::exception& e) {
+ } catch (const std::exception&) {
exceptionThrown = true;
}
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
CAddrMan addrman2;
CAddrDB adb;
BOOST_CHECK(addrman2.size() == 0);
- adb.Read(addrman2, ssPeers2);
+ BOOST_CHECK(adb.Read(addrman2, ssPeers2));
BOOST_CHECK(addrman2.size() == 3);
}
@@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
unsigned char pchMsgTmp[4];
ssPeers1 >> pchMsgTmp;
ssPeers1 >> addrman1;
- } catch (const std::exception& e) {
+ } catch (const std::exception&) {
exceptionThrown = true;
}
// Even through de-serialization failed addrman is not left in a clean state.
@@ -161,7 +161,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
CAddrMan addrman2;
CAddrDB adb;
BOOST_CHECK(addrman2.size() == 0);
- adb.Read(addrman2, ssPeers2);
+ BOOST_CHECK(!adb.Read(addrman2, ssPeers2));
BOOST_CHECK(addrman2.size() == 0);
}
@@ -179,14 +179,128 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
bool fInboundIn = false;
// Test that fFeeler is false by default.
- std::unique_ptr<CNode> pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn));
+ std::unique_ptr<CNode> pnode1 = MakeUnique<CNode>(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn);
BOOST_CHECK(pnode1->fInbound == false);
BOOST_CHECK(pnode1->fFeeler == false);
fInboundIn = true;
- std::unique_ptr<CNode> pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn));
+ std::unique_ptr<CNode> pnode2 = MakeUnique<CNode>(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn);
BOOST_CHECK(pnode2->fInbound == true);
BOOST_CHECK(pnode2->fFeeler == false);
}
+// prior to PR #14728, this test triggers an undefined behavior
+BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
+{
+ // set up local addresses; all that's necessary to reproduce the bug is
+ // that a normal IPv4 address is among the entries, but if this address is
+ // !IsRoutable the undefined behavior is easier to trigger deterministically
+ {
+ LOCK(cs_mapLocalHost);
+ in_addr ipv4AddrLocal;
+ ipv4AddrLocal.s_addr = 0x0100007f;
+ CNetAddr addr = CNetAddr(ipv4AddrLocal);
+ LocalServiceInfo lsi;
+ lsi.nScore = 23;
+ lsi.nPort = 42;
+ mapLocalHost[addr] = lsi;
+ }
+
+ // create a peer with an IPv4 address
+ in_addr ipv4AddrPeer;
+ ipv4AddrPeer.s_addr = 0xa0b0c001;
+ CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
+ std::unique_ptr<CNode> pnode = MakeUnique<CNode>(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, CAddress{}, std::string{}, false);
+ pnode->fSuccessfullyConnected.store(true);
+
+ // the peer claims to be reaching us via IPv6
+ in6_addr ipv6AddrLocal;
+ memset(ipv6AddrLocal.s6_addr, 0, 16);
+ ipv6AddrLocal.s6_addr[0] = 0xcc;
+ CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK);
+ pnode->SetAddrLocal(addrLocal);
+
+ // before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
+ AdvertiseLocal(&*pnode);
+
+ // suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
+ BOOST_CHECK(1);
+}
+
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
+{
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
+
+ SetReachable(NET_IPV4, false);
+ SetReachable(NET_IPV6, false);
+ SetReachable(NET_ONION, false);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false);
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false);
+ BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false);
+
+ SetReachable(NET_IPV4, true);
+ SetReachable(NET_IPV6, true);
+ SetReachable(NET_ONION, true);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
+}
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
+{
+ BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
+ BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
+
+ SetReachable(NET_UNROUTABLE, false);
+ SetReachable(NET_INTERNAL, false);
+
+ BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true); // Ignored for both networks
+ BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
+}
+
+CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
+{
+ unsigned char ip[] = {p1, p2, p3, p4};
+
+ struct sockaddr_in sa;
+ memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
+ memcpy(&(sa.sin_addr), &ip, sizeof(ip));
+ return CNetAddr(sa.sin_addr);
+}
+
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
+{
+ CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
+
+ SetReachable(NET_IPV4, true);
+ BOOST_CHECK_EQUAL(IsReachable(addr), true);
+
+ SetReachable(NET_IPV4, false);
+ BOOST_CHECK_EQUAL(IsReachable(addr), false);
+
+ SetReachable(NET_IPV4, true); // have to reset this, because this is stateful.
+}
+
+
+BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
+{
+ CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
+
+ SetReachable(NET_IPV4, true);
+
+ BOOST_CHECK_EQUAL(IsLocal(addr), false);
+ BOOST_CHECK_EQUAL(AddLocal(addr, 1000), true);
+ BOOST_CHECK_EQUAL(IsLocal(addr), true);
+
+ RemoveLocal(addr);
+ BOOST_CHECK_EQUAL(IsLocal(addr), false);
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 67f7c37f3b..dd5e3eb6d5 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <netbase.h>
-#include <test/test_bitcoin.h>
-#include <utilstrencodings.h>
+#include <test/setup_common.h>
+#include <util/strencodings.h>
#include <string>
@@ -302,4 +302,22 @@ BOOST_AUTO_TEST_CASE(netbase_getgroup)
BOOST_CHECK(CreateInternal("baz.net").GetGroup() == internal_group);
}
+BOOST_AUTO_TEST_CASE(netbase_parsenetwork)
+{
+ BOOST_CHECK_EQUAL(ParseNetwork("ipv4"), NET_IPV4);
+ BOOST_CHECK_EQUAL(ParseNetwork("ipv6"), NET_IPV6);
+ BOOST_CHECK_EQUAL(ParseNetwork("onion"), NET_ONION);
+ BOOST_CHECK_EQUAL(ParseNetwork("tor"), NET_ONION);
+
+ BOOST_CHECK_EQUAL(ParseNetwork("IPv4"), NET_IPV4);
+ BOOST_CHECK_EQUAL(ParseNetwork("IPv6"), NET_IPV6);
+ BOOST_CHECK_EQUAL(ParseNetwork("ONION"), NET_ONION);
+ BOOST_CHECK_EQUAL(ParseNetwork("TOR"), NET_ONION);
+
+ BOOST_CHECK_EQUAL(ParseNetwork(":)"), NET_UNROUTABLE);
+ BOOST_CHECK_EQUAL(ParseNetwork("tÖr"), NET_UNROUTABLE);
+ BOOST_CHECK_EQUAL(ParseNetwork("\xfe\xff"), NET_UNROUTABLE);
+ BOOST_CHECK_EQUAL(ParseNetwork(""), NET_UNROUTABLE);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index 4825c92296..c5513ae9fa 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <uint256.h>
#include <arith_uint256.h>
#include <version.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index e45fb6d17e..149094fc00 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,9 +6,9 @@
#include <policy/fees.h>
#include <txmempool.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
{
CBlockPolicyEstimator feeEst;
CTxMemPool mpool(&feeEst);
- LOCK(mpool.cs);
+ LOCK2(cs_main, mpool.cs);
TestMemPoolEntryHelper entry;
CAmount basefee(2000);
CAmount deltaFee(100);
@@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
tx.vin[0].scriptSig = garbage;
tx.vout.resize(1);
tx.vout[0].nValue=0LL;
- CFeeRate baseRate(basefee, GetVirtualTransactionSize(tx));
+ CFeeRate baseRate(basefee, GetVirtualTransactionSize(CTransaction(tx)));
// Create a fake block
std::vector<CTransactionRef> block;
@@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
for (int k = 0; k < 4; k++) { // add 4 fee txs
tx.vin[0].prevout.n = 10000*blocknum+100*j+k; // make transaction unique
uint256 hash = tx.GetHash();
- mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
+ mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
txHashes[j].push_back(hash);
}
}
@@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
for (int k = 0; k < 4; k++) { // add 4 fee txs
tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
uint256 hash = tx.GetHash();
- mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
+ mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
txHashes[j].push_back(hash);
}
}
@@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
for (int k = 0; k < 4; k++) { // add 4 fee txs
tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
uint256 hash = tx.GetHash();
- mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
+ mpool.addUnchecked(entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
CTransactionRef ptx = mpool.get(hash);
if (ptx)
block.push_back(ptx);
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 9abfd5ebd8..653433bfce 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -1,13 +1,13 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Copyright (c) 2015-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
#include <chainparams.h>
#include <pow.h>
#include <random.h>
-#include <util.h>
-#include <test/test_bitcoin.h>
+#include <util/system.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp
index 5f00009354..141be50f50 100644
--- a/src/test/prevector_tests.cpp
+++ b/src/test/prevector_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <serialize.h>
#include <streams.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -189,8 +189,8 @@ public:
prevector_tester() {
SeedInsecureRand();
- rand_seed = insecure_rand_seed;
- rand_cache = insecure_rand_ctx;
+ rand_seed = InsecureRand256();
+ rand_cache = FastRandomContext(rand_seed);
}
};
diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp
index 3dfa09e09e..2b01acf7fa 100644
--- a/src/test/raii_event_tests.cpp
+++ b/src/test/raii_event_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@
#include <support/events.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp
index 80a294d129..e6fbe2355d 100644
--- a/src/test/random_tests.cpp
+++ b/src/test/random_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -21,9 +21,14 @@ BOOST_AUTO_TEST_CASE(osrandom_tests)
BOOST_AUTO_TEST_CASE(fastrandom_tests)
{
// Check that deterministic FastRandomContexts are deterministic
+ g_mock_deterministic_tests = true;
FastRandomContext ctx1(true);
FastRandomContext ctx2(true);
+ for (int i = 10; i > 0; --i) {
+ BOOST_CHECK_EQUAL(GetRand(std::numeric_limits<uint64_t>::max()), uint64_t{10393729187455219830U});
+ BOOST_CHECK_EQUAL(GetRandInt(std::numeric_limits<int>::max()), int{769702006});
+ }
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64());
@@ -38,11 +43,23 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50));
// Check that a nondeterministic ones are not
- FastRandomContext ctx3;
- FastRandomContext ctx4;
- BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal
- BOOST_CHECK(ctx3.rand256() != ctx4.rand256());
- BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7));
+ g_mock_deterministic_tests = false;
+ for (int i = 10; i > 0; --i) {
+ BOOST_CHECK(GetRand(std::numeric_limits<uint64_t>::max()) != uint64_t{10393729187455219830U});
+ BOOST_CHECK(GetRandInt(std::numeric_limits<int>::max()) != int{769702006});
+ }
+ {
+ FastRandomContext ctx3, ctx4;
+ BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal
+ }
+ {
+ FastRandomContext ctx3, ctx4;
+ BOOST_CHECK(ctx3.rand256() != ctx4.rand256());
+ }
+ {
+ FastRandomContext ctx3, ctx4;
+ BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7));
+ }
}
BOOST_AUTO_TEST_CASE(fastrandom_randbits)
@@ -75,8 +92,42 @@ BOOST_AUTO_TEST_CASE(stdrandom_test)
for (int j = 1; j <= 10; ++j) {
BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
}
+ Shuffle(test.begin(), test.end(), ctx);
+ for (int j = 1; j <= 10; ++j) {
+ BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
+ }
}
}
+/** Test that Shuffle reaches every permutation with equal probability. */
+BOOST_AUTO_TEST_CASE(shuffle_stat_test)
+{
+ FastRandomContext ctx(true);
+ uint32_t counts[5 * 5 * 5 * 5 * 5] = {0};
+ for (int i = 0; i < 12000; ++i) {
+ int data[5] = {0, 1, 2, 3, 4};
+ Shuffle(std::begin(data), std::end(data), ctx);
+ int pos = data[0] + data[1] * 5 + data[2] * 25 + data[3] * 125 + data[4] * 625;
+ ++counts[pos];
+ }
+ unsigned int sum = 0;
+ double chi_score = 0.0;
+ for (int i = 0; i < 5 * 5 * 5 * 5 * 5; ++i) {
+ int i1 = i % 5, i2 = (i / 5) % 5, i3 = (i / 25) % 5, i4 = (i / 125) % 5, i5 = i / 625;
+ uint32_t count = counts[i];
+ if (i1 == i2 || i1 == i3 || i1 == i4 || i1 == i5 || i2 == i3 || i2 == i4 || i2 == i5 || i3 == i4 || i3 == i5 || i4 == i5) {
+ BOOST_CHECK(count == 0);
+ } else {
+ chi_score += ((count - 100.0) * (count - 100.0)) / 100.0;
+ BOOST_CHECK(count > 50);
+ BOOST_CHECK(count < 150);
+ sum += count;
+ }
+ }
+ BOOST_CHECK(chi_score > 58.1411); // 99.9999% confidence interval
+ BOOST_CHECK(chi_score < 210.275);
+ BOOST_CHECK_EQUAL(sum, 12000);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp
index 0a91c65afa..69db9dcf4e 100644
--- a/src/test/reverselock_tests.cpp
+++ b/src/test/reverselock_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <reverselock.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index da591547d7..07d1326bcb 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -1,21 +1,26 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <rpc/server.h>
#include <rpc/client.h>
+#include <rpc/util.h>
#include <core_io.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <key_io.h>
#include <netbase.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
+#include <rpc/blockchain.h>
+
UniValue CallRPC(std::string args)
{
std::vector<std::string> vArgs;
@@ -26,10 +31,9 @@ UniValue CallRPC(std::string args)
request.strMethod = strMethod;
request.params = RPCConvertValues(strMethod, vArgs);
request.fHelp = false;
- BOOST_CHECK(tableRPC[strMethod]);
- rpcfn_type method = tableRPC[strMethod]->actor;
+ if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
try {
- UniValue result = (*method)(request);
+ UniValue result = tableRPC.execute(request);
return result;
}
catch (const UniValue& objError) {
@@ -110,19 +114,20 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign)
std::string notsigned = r.get_str();
std::string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
std::string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
+ InitInterfaces interfaces;
+ interfaces.chain = interfaces::MakeChain();
+ g_rpc_interfaces = &interfaces;
r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" [] "+prevout);
BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" ["+privkey1+","+privkey2+"] "+prevout);
BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
+ g_rpc_interfaces = nullptr;
}
BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)
{
BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\"}"));
- // Allow more than one data transaction output
- BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\",\"data\":\"68656c6c6f776f726c64\"}"));
-
// Key not "data" (bad address)
BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"somedata\":\"68656c6c6f776f726c64\"}"), std::runtime_error);
@@ -336,4 +341,82 @@ BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)
BOOST_CHECK_EQUAL(result[2].get_int(), 9);
}
+BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
+{
+ int64_t total_weight = 200;
+ std::vector<std::pair<CAmount, int64_t>> feerates;
+ CAmount result[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
+
+ for (int64_t i = 0; i < 100; i++) {
+ feerates.emplace_back(std::make_pair(1 ,1));
+ }
+
+ for (int64_t i = 0; i < 100; i++) {
+ feerates.emplace_back(std::make_pair(2 ,1));
+ }
+
+ CalculatePercentilesByWeight(result, feerates, total_weight);
+ BOOST_CHECK_EQUAL(result[0], 1);
+ BOOST_CHECK_EQUAL(result[1], 1);
+ BOOST_CHECK_EQUAL(result[2], 1);
+ BOOST_CHECK_EQUAL(result[3], 2);
+ BOOST_CHECK_EQUAL(result[4], 2);
+
+ // Test with more pairs, and two pairs overlapping 2 percentiles.
+ total_weight = 100;
+ CAmount result2[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
+ feerates.clear();
+
+ feerates.emplace_back(std::make_pair(1, 9));
+ feerates.emplace_back(std::make_pair(2 , 16)); //10th + 25th percentile
+ feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile
+ feerates.emplace_back(std::make_pair(5 ,10));
+ feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile
+
+ CalculatePercentilesByWeight(result2, feerates, total_weight);
+
+ BOOST_CHECK_EQUAL(result2[0], 2);
+ BOOST_CHECK_EQUAL(result2[1], 2);
+ BOOST_CHECK_EQUAL(result2[2], 4);
+ BOOST_CHECK_EQUAL(result2[3], 4);
+ BOOST_CHECK_EQUAL(result2[4], 9);
+
+ // Same test as above, but one of the percentile-overlapping pairs is split in 2.
+ total_weight = 100;
+ CAmount result3[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
+ feerates.clear();
+
+ feerates.emplace_back(std::make_pair(1, 9));
+ feerates.emplace_back(std::make_pair(2 , 11)); // 10th percentile
+ feerates.emplace_back(std::make_pair(2 , 5)); // 25th percentile
+ feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile
+ feerates.emplace_back(std::make_pair(5 ,10));
+ feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile
+
+ CalculatePercentilesByWeight(result3, feerates, total_weight);
+
+ BOOST_CHECK_EQUAL(result3[0], 2);
+ BOOST_CHECK_EQUAL(result3[1], 2);
+ BOOST_CHECK_EQUAL(result3[2], 4);
+ BOOST_CHECK_EQUAL(result3[3], 4);
+ BOOST_CHECK_EQUAL(result3[4], 9);
+
+ // Test with one transaction spanning all percentiles.
+ total_weight = 104;
+ CAmount result4[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
+ feerates.clear();
+
+ feerates.emplace_back(std::make_pair(1, 100));
+ feerates.emplace_back(std::make_pair(2, 1));
+ feerates.emplace_back(std::make_pair(3, 1));
+ feerates.emplace_back(std::make_pair(3, 1));
+ feerates.emplace_back(std::make_pair(999999, 1));
+
+ CalculatePercentilesByWeight(result4, feerates, total_weight);
+
+ for (int64_t i = 0; i < NUM_GETBLOCKSTATS_PERCENTILES; i++) {
+ BOOST_CHECK_EQUAL(result4[i], 1);
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp
index e97ad2ee6a..891aa8e5c3 100644
--- a/src/test/sanity_tests.cpp
+++ b/src/test/sanity_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <compat/sanity.h>
#include <key.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index b1ea4b6fab..42242b962b 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -1,13 +1,12 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <random.h>
#include <scheduler.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
-#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/test/unit_test.hpp>
@@ -21,7 +20,7 @@ static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delt
}
boost::chrono::system_clock::time_point noTime = boost::chrono::system_clock::time_point::min();
if (rescheduleTime != noTime) {
- CScheduler::Function f = boost::bind(&microTask, boost::ref(s), boost::ref(mutex), boost::ref(counter), -delta + 1, noTime);
+ CScheduler::Function f = std::bind(&microTask, std::ref(s), std::ref(mutex), std::ref(counter), -delta + 1, noTime);
s.schedule(f, rescheduleTime);
}
}
@@ -54,7 +53,7 @@ BOOST_AUTO_TEST_CASE(manythreads)
boost::mutex counterMutex[10];
int counter[10] = { 0 };
- FastRandomContext rng(42);
+ FastRandomContext rng{/* fDeterministic */ true};
auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9]
auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + (int)rc.randrange(1012); }; // [-11, 1000]
auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + (int)rc.randrange(2001); }; // [-1000, 1000]
@@ -69,8 +68,8 @@ BOOST_AUTO_TEST_CASE(manythreads)
boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng));
boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng));
int whichCounter = zeroToNine(rng);
- CScheduler::Function f = boost::bind(&microTask, boost::ref(microTasks),
- boost::ref(counterMutex[whichCounter]), boost::ref(counter[whichCounter]),
+ CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
+ std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
randomDelta(rng), tReschedule);
microTasks.schedule(f, t);
}
@@ -82,20 +81,20 @@ BOOST_AUTO_TEST_CASE(manythreads)
// As soon as these are created they will start running and servicing the queue
boost::thread_group microThreads;
for (int i = 0; i < 5; i++)
- microThreads.create_thread(boost::bind(&CScheduler::serviceQueue, &microTasks));
+ microThreads.create_thread(std::bind(&CScheduler::serviceQueue, &microTasks));
MicroSleep(600);
now = boost::chrono::system_clock::now();
// More threads and more tasks:
for (int i = 0; i < 5; i++)
- microThreads.create_thread(boost::bind(&CScheduler::serviceQueue, &microTasks));
+ microThreads.create_thread(std::bind(&CScheduler::serviceQueue, &microTasks));
for (int i = 0; i < 100; i++) {
boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng));
boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng));
int whichCounter = zeroToNine(rng);
- CScheduler::Function f = boost::bind(&microTask, boost::ref(microTasks),
- boost::ref(counterMutex[whichCounter]), boost::ref(counter[whichCounter]),
+ CScheduler::Function f = std::bind(&microTask, std::ref(microTasks),
+ std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
randomDelta(rng), tReschedule);
microTasks.schedule(f, t);
}
@@ -126,7 +125,7 @@ BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
// if they don't we'll get out of order behaviour
boost::thread_group threads;
for (int i = 0; i < 5; ++i) {
- threads.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
+ threads.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
}
// these are not atomic, if SinglethreadedSchedulerClient prevents
@@ -138,11 +137,13 @@ BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
// the callbacks should run in exactly the order in which they were enqueued
for (int i = 0; i < 100; ++i) {
queue1.AddToProcessQueue([i, &counter1]() {
- BOOST_CHECK_EQUAL(i, counter1++);
+ bool expectation = i == counter1++;
+ assert(expectation);
});
queue2.AddToProcessQueue([i, &counter2]() {
- BOOST_CHECK_EQUAL(i, counter2++);
+ bool expectation = i == counter2++;
+ assert(expectation);
});
}
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index e224df6704..9c4606f1b3 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,9 +10,10 @@
#include <policy/policy.h>
#include <script/script.h>
#include <script/script_error.h>
+#include <policy/settings.h>
#include <script/sign.h>
#include <script/ismine.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
@@ -61,21 +62,21 @@ BOOST_AUTO_TEST_CASE(sign)
for (int i = 0; i < 4; i++)
{
key[i].MakeNewKey(true);
- keystore.AddKey(key[i]);
+ BOOST_CHECK(keystore.AddKey(key[i]));
}
// 8 Scripts: checking all combinations of
// different keys, straight/P2SH, pubkey/pubkeyhash
CScript standardScripts[4];
standardScripts[0] << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
- standardScripts[1] = GetScriptForDestination(key[1].GetPubKey().GetID());
+ standardScripts[1] = GetScriptForDestination(PKHash(key[1].GetPubKey()));
standardScripts[2] << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
- standardScripts[3] = GetScriptForDestination(key[2].GetPubKey().GetID());
+ standardScripts[3] = GetScriptForDestination(PKHash(key[2].GetPubKey()));
CScript evalScripts[4];
for (int i = 0; i < 4; i++)
{
- keystore.AddCScript(standardScripts[i]);
- evalScripts[i] = GetScriptForDestination(CScriptID(standardScripts[i]));
+ BOOST_CHECK(keystore.AddCScript(standardScripts[i]));
+ evalScripts[i] = GetScriptForDestination(ScriptHash(standardScripts[i]));
}
CMutableTransaction txFrom; // Funding transaction:
@@ -88,7 +89,7 @@ BOOST_AUTO_TEST_CASE(sign)
txFrom.vout[i+4].scriptPubKey = standardScripts[i];
txFrom.vout[i+4].nValue = COIN;
}
- BOOST_CHECK(IsStandardTx(txFrom, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(txFrom), reason));
CMutableTransaction txTo[8]; // Spending transactions
for (int i = 0; i < 8; i++)
@@ -102,7 +103,7 @@ BOOST_AUTO_TEST_CASE(sign)
}
for (int i = 0; i < 8; i++)
{
- BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
}
// All of the above should be OK, and the txTos have valid signatures
// Check to make sure signature verification fails if we use the wrong ScriptSig:
@@ -112,7 +113,7 @@ BOOST_AUTO_TEST_CASE(sign)
{
CScript sigSave = txTo[i].vin[0].scriptSig;
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
- bool sigOK = CScriptCheck(txFrom.vout[txTo[i].vin[0].prevout.n], txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
+ bool sigOK = CScriptCheck(txFrom.vout[txTo[i].vin[0].prevout.n], CTransaction(txTo[i]), 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
if (i == j)
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
else
@@ -130,7 +131,7 @@ BOOST_AUTO_TEST_CASE(norecurse)
CScript invalidAsScript;
invalidAsScript << OP_INVALIDOPCODE << OP_INVALIDOPCODE;
- CScript p2sh = GetScriptForDestination(CScriptID(invalidAsScript));
+ CScript p2sh = GetScriptForDestination(ScriptHash(invalidAsScript));
CScript scriptSig;
scriptSig << Serialize(invalidAsScript);
@@ -141,7 +142,7 @@ BOOST_AUTO_TEST_CASE(norecurse)
// Try to recur, and verification should succeed because
// the inner HASH160 <> EQUAL should only check the hash:
- CScript p2sh2 = GetScriptForDestination(CScriptID(p2sh));
+ CScript p2sh2 = GetScriptForDestination(ScriptHash(p2sh));
CScript scriptSig2;
scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh);
@@ -159,12 +160,12 @@ BOOST_AUTO_TEST_CASE(set)
for (int i = 0; i < 4; i++)
{
key[i].MakeNewKey(true);
- keystore.AddKey(key[i]);
+ BOOST_CHECK(keystore.AddKey(key[i]));
keys.push_back(key[i].GetPubKey());
}
CScript inner[4];
- inner[0] = GetScriptForDestination(key[0].GetPubKey().GetID());
+ inner[0] = GetScriptForDestination(PKHash(key[0].GetPubKey()));
inner[1] = GetScriptForMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+2));
inner[2] = GetScriptForMultisig(1, std::vector<CPubKey>(keys.begin(), keys.begin()+2));
inner[3] = GetScriptForMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+3));
@@ -172,8 +173,8 @@ BOOST_AUTO_TEST_CASE(set)
CScript outer[4];
for (int i = 0; i < 4; i++)
{
- outer[i] = GetScriptForDestination(CScriptID(inner[i]));
- keystore.AddCScript(inner[i]);
+ outer[i] = GetScriptForDestination(ScriptHash(inner[i]));
+ BOOST_CHECK(keystore.AddCScript(inner[i]));
}
CMutableTransaction txFrom; // Funding transaction:
@@ -184,7 +185,7 @@ BOOST_AUTO_TEST_CASE(set)
txFrom.vout[i].scriptPubKey = outer[i];
txFrom.vout[i].nValue = CENT;
}
- BOOST_CHECK(IsStandardTx(txFrom, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(txFrom), reason));
CMutableTransaction txTo[4]; // Spending transactions
for (int i = 0; i < 4; i++)
@@ -199,8 +200,8 @@ BOOST_AUTO_TEST_CASE(set)
}
for (int i = 0; i < 4; i++)
{
- BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
- BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i));
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
+ BOOST_CHECK_MESSAGE(IsStandardTx(CTransaction(txTo[i]), reason), strprintf("txTo[%d].IsStandard", i));
}
}
@@ -213,14 +214,22 @@ BOOST_AUTO_TEST_CASE(is)
BOOST_CHECK(p2sh.IsPayToScriptHash());
// Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes:
- static const unsigned char direct[] = { OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
- BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash());
- static const unsigned char pushdata1[] = { OP_HASH160, OP_PUSHDATA1, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
- BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash());
- static const unsigned char pushdata2[] = { OP_HASH160, OP_PUSHDATA2, 20,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
- BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash());
- static const unsigned char pushdata4[] = { OP_HASH160, OP_PUSHDATA4, 20,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
- BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash());
+ std::vector<unsigned char> direct = {OP_HASH160, 20};
+ direct.insert(direct.end(), 20, 0);
+ direct.push_back(OP_EQUAL);
+ BOOST_CHECK(CScript(direct.begin(), direct.end()).IsPayToScriptHash());
+ std::vector<unsigned char> pushdata1 = {OP_HASH160, OP_PUSHDATA1, 20};
+ pushdata1.insert(pushdata1.end(), 20, 0);
+ pushdata1.push_back(OP_EQUAL);
+ BOOST_CHECK(!CScript(pushdata1.begin(), pushdata1.end()).IsPayToScriptHash());
+ std::vector<unsigned char> pushdata2 = {OP_HASH160, 20, 0};
+ pushdata2.insert(pushdata2.end(), 20, 0);
+ pushdata2.push_back(OP_EQUAL);
+ BOOST_CHECK(!CScript(pushdata2.begin(), pushdata2.end()).IsPayToScriptHash());
+ std::vector<unsigned char> pushdata4 = {OP_HASH160, 20, 0, 0, 0};
+ pushdata4.insert(pushdata4.end(), 20, 0);
+ pushdata4.push_back(OP_EQUAL);
+ BOOST_CHECK(!CScript(pushdata4.begin(), pushdata4.end()).IsPayToScriptHash());
CScript not_p2sh;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
@@ -244,7 +253,7 @@ BOOST_AUTO_TEST_CASE(switchover)
CScript scriptSig;
scriptSig << Serialize(notValid);
- CScript fund = GetScriptForDestination(CScriptID(notValid));
+ CScript fund = GetScriptForDestination(ScriptHash(notValid));
// Validation should succeed under old rules (hash is correct):
@@ -266,7 +275,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
for (int i = 0; i < 6; i++)
{
key[i].MakeNewKey(true);
- keystore.AddKey(key[i]);
+ BOOST_CHECK(keystore.AddKey(key[i]));
}
for (int i = 0; i < 3; i++)
keys.push_back(key[i].GetPubKey());
@@ -275,11 +284,11 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txFrom.vout.resize(7);
// First three are standard:
- CScript pay1 = GetScriptForDestination(key[0].GetPubKey().GetID());
- keystore.AddCScript(pay1);
+ CScript pay1 = GetScriptForDestination(PKHash(key[0].GetPubKey()));
+ BOOST_CHECK(keystore.AddCScript(pay1));
CScript pay1of3 = GetScriptForMultisig(1, keys);
- txFrom.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(pay1)); // P2SH (OP_CHECKSIG)
+ txFrom.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(pay1)); // P2SH (OP_CHECKSIG)
txFrom.vout[0].nValue = 1000;
txFrom.vout[1].scriptPubKey = pay1; // ordinary OP_CHECKSIG
txFrom.vout[1].nValue = 2000;
@@ -293,8 +302,8 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
oneAndTwo << OP_3 << OP_CHECKMULTISIGVERIFY;
oneAndTwo << OP_2 << ToByteVector(key[3].GetPubKey()) << ToByteVector(key[4].GetPubKey()) << ToByteVector(key[5].GetPubKey());
oneAndTwo << OP_3 << OP_CHECKMULTISIG;
- keystore.AddCScript(oneAndTwo);
- txFrom.vout[3].scriptPubKey = GetScriptForDestination(CScriptID(oneAndTwo));
+ BOOST_CHECK(keystore.AddCScript(oneAndTwo));
+ txFrom.vout[3].scriptPubKey = GetScriptForDestination(ScriptHash(oneAndTwo));
txFrom.vout[3].nValue = 4000;
// vout[4] is max sigops:
@@ -302,25 +311,25 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
for (unsigned i = 0; i < MAX_P2SH_SIGOPS; i++)
fifteenSigops << ToByteVector(key[i%3].GetPubKey());
fifteenSigops << OP_15 << OP_CHECKMULTISIG;
- keystore.AddCScript(fifteenSigops);
- txFrom.vout[4].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops));
+ BOOST_CHECK(keystore.AddCScript(fifteenSigops));
+ txFrom.vout[4].scriptPubKey = GetScriptForDestination(ScriptHash(fifteenSigops));
txFrom.vout[4].nValue = 5000;
// vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS
CScript sixteenSigops; sixteenSigops << OP_16 << OP_CHECKMULTISIG;
- keystore.AddCScript(sixteenSigops);
- txFrom.vout[5].scriptPubKey = GetScriptForDestination(CScriptID(sixteenSigops));
+ BOOST_CHECK(keystore.AddCScript(sixteenSigops));
+ txFrom.vout[5].scriptPubKey = GetScriptForDestination(ScriptHash(sixteenSigops));
txFrom.vout[5].nValue = 5000;
CScript twentySigops; twentySigops << OP_CHECKMULTISIG;
- keystore.AddCScript(twentySigops);
- txFrom.vout[6].scriptPubKey = GetScriptForDestination(CScriptID(twentySigops));
+ BOOST_CHECK(keystore.AddCScript(twentySigops));
+ txFrom.vout[6].scriptPubKey = GetScriptForDestination(ScriptHash(twentySigops));
txFrom.vout[6].nValue = 6000;
- AddCoins(coins, txFrom, 0);
+ AddCoins(coins, CTransaction(txFrom), 0);
CMutableTransaction txTo;
txTo.vout.resize(1);
- txTo.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
+ txTo.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));
txTo.vin.resize(5);
for (int i = 0; i < 5; i++)
@@ -328,42 +337,42 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[i].prevout.n = i;
txTo.vin[i].prevout.hash = txFrom.GetHash();
}
- BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL));
- BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL));
- BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL));
+ BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL));
+ BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 1, SIGHASH_ALL));
+ BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 2, SIGHASH_ALL));
// SignSignature doesn't know how to sign these. We're
// not testing validating signatures, so just create
// dummy signatures that DO include the correct P2SH scripts:
txTo.vin[3].scriptSig << OP_11 << OP_11 << std::vector<unsigned char>(oneAndTwo.begin(), oneAndTwo.end());
txTo.vin[4].scriptSig << std::vector<unsigned char>(fifteenSigops.begin(), fifteenSigops.end());
- BOOST_CHECK(::AreInputsStandard(txTo, coins));
+ BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins));
// 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]
- BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U);
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins), 22U);
CMutableTransaction txToNonStd1;
txToNonStd1.vout.resize(1);
- txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
+ txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));
txToNonStd1.vout[0].nValue = 1000;
txToNonStd1.vin.resize(1);
txToNonStd1.vin[0].prevout.n = 5;
txToNonStd1.vin[0].prevout.hash = txFrom.GetHash();
txToNonStd1.vin[0].scriptSig << std::vector<unsigned char>(sixteenSigops.begin(), sixteenSigops.end());
- BOOST_CHECK(!::AreInputsStandard(txToNonStd1, coins));
- BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd1, coins), 16U);
+ BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins));
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins), 16U);
CMutableTransaction txToNonStd2;
txToNonStd2.vout.resize(1);
- txToNonStd2.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
+ txToNonStd2.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));
txToNonStd2.vout[0].nValue = 1000;
txToNonStd2.vin.resize(1);
txToNonStd2.vin[0].prevout.n = 6;
txToNonStd2.vin[0].prevout.hash = txFrom.GetHash();
txToNonStd2.vin[0].scriptSig << std::vector<unsigned char>(twentySigops.begin(), twentySigops.end());
- BOOST_CHECK(!::AreInputsStandard(txToNonStd2, coins));
- BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd2, coins), 20U);
+ BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins));
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins), 20U);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
index 7d4734986a..9f50083335 100644
--- a/src/test/script_standard_tests.cpp
+++ b/src/test/script_standard_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <script/script.h>
#include <script/script_error.h>
#include <script/standard.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -25,22 +25,19 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
}
CScript s;
- txnouttype whichType;
std::vector<std::vector<unsigned char> > solutions;
// TX_PUBKEY
s.clear();
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_PUBKEY);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_PUBKEY);
BOOST_CHECK_EQUAL(solutions.size(), 1U);
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
// TX_PUBKEYHASH
s.clear();
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_PUBKEYHASH);
BOOST_CHECK_EQUAL(solutions.size(), 1U);
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
@@ -48,8 +45,7 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
CScript redeemScript(s); // initialize with leftover P2PKH script
s.clear();
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_SCRIPTHASH);
BOOST_CHECK_EQUAL(solutions.size(), 1U);
BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
@@ -59,8 +55,7 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
ToByteVector(pubkeys[0]) <<
ToByteVector(pubkeys[1]) <<
OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_MULTISIG);
BOOST_CHECK_EQUAL(solutions.size(), 4U);
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
@@ -73,8 +68,7 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
ToByteVector(pubkeys[1]) <<
ToByteVector(pubkeys[2]) <<
OP_3 << OP_CHECKMULTISIG;
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_MULTISIG);
BOOST_CHECK_EQUAL(solutions.size(), 5U);
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
@@ -88,15 +82,13 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
std::vector<unsigned char>({0}) <<
std::vector<unsigned char>({75}) <<
std::vector<unsigned char>({255});
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_NULL_DATA);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NULL_DATA);
BOOST_CHECK_EQUAL(solutions.size(), 0U);
// TX_WITNESS_V0_KEYHASH
s.clear();
s << OP_0 << ToByteVector(pubkeys[0].GetID());
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_KEYHASH);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_WITNESS_V0_KEYHASH);
BOOST_CHECK_EQUAL(solutions.size(), 1U);
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
@@ -107,16 +99,14 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
s.clear();
s << OP_0 << ToByteVector(scriptHash);
- BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_SCRIPTHASH);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_WITNESS_V0_SCRIPTHASH);
BOOST_CHECK_EQUAL(solutions.size(), 1U);
BOOST_CHECK(solutions[0] == ToByteVector(scriptHash));
// TX_NONSTANDARD
s.clear();
s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
- BOOST_CHECK(!Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(whichType, TX_NONSTANDARD);
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
}
BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
@@ -127,53 +117,52 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
pubkey = key.GetPubKey();
CScript s;
- txnouttype whichType;
std::vector<std::vector<unsigned char> > solutions;
// TX_PUBKEY with incorrectly sized pubkey
s.clear();
s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
// TX_PUBKEYHASH with incorrectly sized key hash
s.clear();
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG;
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
// TX_SCRIPTHASH with incorrectly sized script hash
s.clear();
s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
// TX_MULTISIG 0/2
s.clear();
s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
// TX_MULTISIG 2/1
s.clear();
s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
// TX_MULTISIG n = 2 with 1 pubkey
s.clear();
s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
// TX_MULTISIG n = 1 with 0 pubkeys
s.clear();
s << OP_1 << OP_1 << OP_CHECKMULTISIG;
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
// TX_NULL_DATA with other opcodes
s.clear();
s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
// TX_WITNESS with incorrect program size
s.clear();
s << OP_0 << std::vector<unsigned char>(19, 0x01);
- BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
}
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
@@ -190,23 +179,23 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
s.clear();
s << ToByteVector(pubkey) << OP_CHECKSIG;
BOOST_CHECK(ExtractDestination(s, address));
- BOOST_CHECK(boost::get<CKeyID>(&address) &&
- *boost::get<CKeyID>(&address) == pubkey.GetID());
+ BOOST_CHECK(boost::get<PKHash>(&address) &&
+ *boost::get<PKHash>(&address) == PKHash(pubkey));
// TX_PUBKEYHASH
s.clear();
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
BOOST_CHECK(ExtractDestination(s, address));
- BOOST_CHECK(boost::get<CKeyID>(&address) &&
- *boost::get<CKeyID>(&address) == pubkey.GetID());
+ BOOST_CHECK(boost::get<PKHash>(&address) &&
+ *boost::get<PKHash>(&address) == PKHash(pubkey));
// TX_SCRIPTHASH
CScript redeemScript(s); // initialize with leftover P2PKH script
s.clear();
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
BOOST_CHECK(ExtractDestination(s, address));
- BOOST_CHECK(boost::get<CScriptID>(&address) &&
- *boost::get<CScriptID>(&address) == CScriptID(redeemScript));
+ BOOST_CHECK(boost::get<ScriptHash>(&address) &&
+ *boost::get<ScriptHash>(&address) == ScriptHash(redeemScript));
// TX_MULTISIG
s.clear();
@@ -266,8 +255,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
BOOST_CHECK_EQUAL(whichType, TX_PUBKEY);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
- BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
- *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
+ BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
+ *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
// TX_PUBKEYHASH
s.clear();
@@ -276,8 +265,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
- BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
- *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
+ BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
+ *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
// TX_SCRIPTHASH
CScript redeemScript(s); // initialize with leftover P2PKH script
@@ -287,8 +276,8 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
- BOOST_CHECK(boost::get<CScriptID>(&addresses[0]) &&
- *boost::get<CScriptID>(&addresses[0]) == CScriptID(redeemScript));
+ BOOST_CHECK(boost::get<ScriptHash>(&addresses[0]) &&
+ *boost::get<ScriptHash>(&addresses[0]) == ScriptHash(redeemScript));
// TX_MULTISIG
s.clear();
@@ -300,10 +289,10 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
BOOST_CHECK_EQUAL(addresses.size(), 2U);
BOOST_CHECK_EQUAL(nRequired, 2);
- BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
- *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
- BOOST_CHECK(boost::get<CKeyID>(&addresses[1]) &&
- *boost::get<CKeyID>(&addresses[1]) == pubkeys[1].GetID());
+ BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
+ *boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
+ BOOST_CHECK(boost::get<PKHash>(&addresses[1]) &&
+ *boost::get<PKHash>(&addresses[1]) == PKHash(pubkeys[1]));
// TX_NULL_DATA
s.clear();
@@ -322,17 +311,17 @@ BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_)
CScript expected, result;
- // CKeyID
+ // PKHash
expected.clear();
expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
- result = GetScriptForDestination(pubkeys[0].GetID());
+ result = GetScriptForDestination(PKHash(pubkeys[0]));
BOOST_CHECK(result == expected);
// CScriptID
CScript redeemScript(result);
expected.clear();
expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
- result = GetScriptForDestination(CScriptID(redeemScript));
+ result = GetScriptForDestination(ScriptHash(redeemScript));
BOOST_CHECK(result == expected);
// CNoDestination
@@ -409,7 +398,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -424,7 +413,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key
- keystore.AddKey(uncompressedKey);
+ BOOST_CHECK(keystore.AddKey(uncompressedKey));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -432,14 +421,14 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// P2PKH compressed
{
CBasicKeyStore keystore;
- scriptPubKey = GetScriptForDestination(pubkeys[0].GetID());
+ scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
// Keystore does not have key
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -447,14 +436,14 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// P2PKH uncompressed
{
CBasicKeyStore keystore;
- scriptPubKey = GetScriptForDestination(uncompressedPubkey.GetID());
+ scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
// Keystore does not have key
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key
- keystore.AddKey(uncompressedKey);
+ BOOST_CHECK(keystore.AddKey(uncompressedKey));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -463,20 +452,20 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
{
CBasicKeyStore keystore;
- CScript redeemScript = GetScriptForDestination(pubkeys[0].GetID());
- scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
+ scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
// Keystore does not have redeemScript or key
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has redeemScript but no key
- keystore.AddCScript(redeemScript);
+ BOOST_CHECK(keystore.AddCScript(redeemScript));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has redeemScript and key
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -485,14 +474,14 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
{
CBasicKeyStore keystore;
- CScript redeemscript_inner = GetScriptForDestination(pubkeys[0].GetID());
- CScript redeemscript = GetScriptForDestination(CScriptID(redeemscript_inner));
- scriptPubKey = GetScriptForDestination(CScriptID(redeemscript));
+ CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
+ CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner));
+ scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript));
- keystore.AddCScript(redeemscript);
- keystore.AddCScript(redeemscript_inner);
- keystore.AddCScript(scriptPubKey);
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddCScript(redeemscript));
+ BOOST_CHECK(keystore.AddCScript(redeemscript_inner));
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
+ BOOST_CHECK(keystore.AddKey(keys[0]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -501,14 +490,14 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
{
CBasicKeyStore keystore;
- CScript redeemscript = GetScriptForDestination(pubkeys[0].GetID());
- CScript witnessscript = GetScriptForDestination(CScriptID(redeemscript));
+ CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0]));
+ CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript));
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
- keystore.AddCScript(witnessscript);
- keystore.AddCScript(redeemscript);
- keystore.AddCScript(scriptPubKey);
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddCScript(witnessscript));
+ BOOST_CHECK(keystore.AddCScript(redeemscript));
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
+ BOOST_CHECK(keystore.AddKey(keys[0]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -517,12 +506,12 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
{
CBasicKeyStore keystore;
- CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
+ CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(PKHash(pubkeys[0])));
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
- keystore.AddCScript(witnessscript);
- keystore.AddCScript(scriptPubKey);
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddCScript(witnessscript));
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
+ BOOST_CHECK(keystore.AddKey(keys[0]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -531,14 +520,14 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
{
CBasicKeyStore keystore;
- CScript witnessscript_inner = GetScriptForDestination(pubkeys[0].GetID());
+ CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
- keystore.AddCScript(witnessscript_inner);
- keystore.AddCScript(witnessscript);
- keystore.AddCScript(scriptPubKey);
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddCScript(witnessscript_inner));
+ BOOST_CHECK(keystore.AddCScript(witnessscript));
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
+ BOOST_CHECK(keystore.AddKey(keys[0]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -546,12 +535,12 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// P2WPKH compressed
{
CBasicKeyStore keystore;
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
- scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
+ scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(PKHash(pubkeys[0])));
// Keystore implicitly has key and P2SH redeemScript
- keystore.AddCScript(scriptPubKey);
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -559,16 +548,16 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// P2WPKH uncompressed
{
CBasicKeyStore keystore;
- keystore.AddKey(uncompressedKey);
+ BOOST_CHECK(keystore.AddKey(uncompressedKey));
- scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey.GetID()));
+ scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(PKHash(uncompressedPubkey)));
// Keystore has key, but no P2SH redeemScript
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has key and P2SH redeemScript
- keystore.AddCScript(scriptPubKey);
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -584,19 +573,19 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has 1/2 keys
- keystore.AddKey(uncompressedKey);
+ BOOST_CHECK(keystore.AddKey(uncompressedKey));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has 2/2 keys
- keystore.AddKey(keys[1]);
+ BOOST_CHECK(keystore.AddKey(keys[1]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has 2/2 keys and the script
- keystore.AddCScript(scriptPubKey);
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
@@ -605,18 +594,18 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// P2SH multisig
{
CBasicKeyStore keystore;
- keystore.AddKey(uncompressedKey);
- keystore.AddKey(keys[1]);
+ BOOST_CHECK(keystore.AddKey(uncompressedKey));
+ BOOST_CHECK(keystore.AddKey(keys[1]));
CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
- scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
// Keystore has no redeemScript
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has redeemScript
- keystore.AddCScript(redeemScript);
+ BOOST_CHECK(keystore.AddCScript(redeemScript));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -624,8 +613,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// P2WSH multisig with compressed keys
{
CBasicKeyStore keystore;
- keystore.AddKey(keys[0]);
- keystore.AddKey(keys[1]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
+ BOOST_CHECK(keystore.AddKey(keys[1]));
CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
@@ -635,12 +624,12 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has keys and witnessScript, but no P2SH redeemScript
- keystore.AddCScript(witnessScript);
+ BOOST_CHECK(keystore.AddCScript(witnessScript));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has keys, witnessScript, P2SH redeemScript
- keystore.AddCScript(scriptPubKey);
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -648,8 +637,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// P2WSH multisig with uncompressed key
{
CBasicKeyStore keystore;
- keystore.AddKey(uncompressedKey);
- keystore.AddKey(keys[1]);
+ BOOST_CHECK(keystore.AddKey(uncompressedKey));
+ BOOST_CHECK(keystore.AddKey(keys[1]));
CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
@@ -659,12 +648,12 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has keys and witnessScript, but no P2SH redeemScript
- keystore.AddCScript(witnessScript);
+ BOOST_CHECK(keystore.AddCScript(witnessScript));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has keys, witnessScript, P2SH redeemScript
- keystore.AddCScript(scriptPubKey);
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
@@ -675,21 +664,21 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
- scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
// Keystore has no witnessScript, P2SH redeemScript, or keys
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has witnessScript and P2SH redeemScript, but no keys
- keystore.AddCScript(redeemScript);
- keystore.AddCScript(witnessScript);
+ BOOST_CHECK(keystore.AddCScript(redeemScript));
+ BOOST_CHECK(keystore.AddCScript(witnessScript));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
// Keystore has keys, witnessScript, P2SH redeemScript
- keystore.AddKey(keys[0]);
- keystore.AddKey(keys[1]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
+ BOOST_CHECK(keystore.AddKey(keys[1]));
result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
}
@@ -697,7 +686,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// OP_RETURN
{
CBasicKeyStore keystore;
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
scriptPubKey.clear();
scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
@@ -709,7 +698,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// witness unspendable
{
CBasicKeyStore keystore;
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
scriptPubKey.clear();
scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb"));
@@ -721,7 +710,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// witness unknown
{
CBasicKeyStore keystore;
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
scriptPubKey.clear();
scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb"));
@@ -733,7 +722,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
// Nonstandard
{
CBasicKeyStore keystore;
- keystore.AddKey(keys[0]);
+ BOOST_CHECK(keystore.AddKey(keys[0]));
scriptPubKey.clear();
scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 510910e149..4798909e2f 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,10 +10,10 @@
#include <script/script.h>
#include <script/script_error.h>
#include <script/sign.h>
-#include <util.h>
-#include <utilstrencodings.h>
-#include <test/test_bitcoin.h>
-#include <rpc/server.h>
+#include <util/system.h>
+#include <util/strencodings.h>
+#include <test/setup_common.h>
+#include <rpc/util.h>
#if defined(HAVE_CONSENSUS_LIB)
#include <script/bitcoinconsensus.h>
@@ -184,11 +184,12 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript
stream << tx2;
int libconsensus_flags = flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL;
if (libconsensus_flags == flags) {
+ int expectedSuccessCode = expect ? 1 : 0;
if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) {
- BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect, message);
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expectedSuccessCode, message);
} else {
- BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect, message);
- BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect,message);
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expectedSuccessCode, message);
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expectedSuccessCode, message);
}
}
#endif
@@ -369,7 +370,7 @@ public:
std::vector<unsigned char> vchSig, r, s;
uint32_t iter = 0;
do {
- key.Sign(hash, vchSig, iter++);
+ key.Sign(hash, vchSig, false, iter++);
if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) {
NegateSignatureS(vchSig);
}
@@ -937,17 +938,19 @@ BOOST_AUTO_TEST_CASE(script_build)
}
}
+#ifdef UPDATE_JSON_TESTS
std::string strGen;
-
+#endif
for (TestBuilder& test : tests) {
test.Test();
std::string str = JSONPrettyPrint(test.GetJSON());
-#ifndef UPDATE_JSON_TESTS
+#ifdef UPDATE_JSON_TESTS
+ strGen += str + ",\n";
+#else
if (tests_set.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment());
}
#endif
- strGen += str + ",\n";
}
#ifdef UPDATE_JSON_TESTS
@@ -1011,23 +1014,45 @@ BOOST_AUTO_TEST_CASE(script_PushData)
ScriptError err;
std::vector<std::vector<unsigned char> > directStack;
- BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(EvalScript(directStack, CScript(direct, direct + sizeof(direct)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata1Stack;
- BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata1Stack, CScript(pushdata1, pushdata1 + sizeof(pushdata1)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata1Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata2Stack;
- BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata2Stack, CScript(pushdata2, pushdata2 + sizeof(pushdata2)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata2Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
std::vector<std::vector<unsigned char> > pushdata4Stack;
- BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(EvalScript(pushdata4Stack, CScript(pushdata4, pushdata4 + sizeof(pushdata4)), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
BOOST_CHECK(pushdata4Stack == directStack);
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ const std::vector<unsigned char> pushdata1_trunc{OP_PUSHDATA1, 1};
+ const std::vector<unsigned char> pushdata2_trunc{OP_PUSHDATA2, 1, 0};
+ const std::vector<unsigned char> pushdata4_trunc{OP_PUSHDATA4, 1, 0, 0, 0};
+
+ std::vector<std::vector<unsigned char>> stack_ignore;
+ BOOST_CHECK(!EvalScript(stack_ignore, CScript(pushdata1_trunc.begin(), pushdata1_trunc.end()), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE);
+ BOOST_CHECK(!EvalScript(stack_ignore, CScript(pushdata2_trunc.begin(), pushdata2_trunc.end()), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE);
+ BOOST_CHECK(!EvalScript(stack_ignore, CScript(pushdata4_trunc.begin(), pushdata4_trunc.end()), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE);
+}
+
+BOOST_AUTO_TEST_CASE(script_cltv_truncated)
+{
+ const auto script_cltv_trunc = CScript() << OP_CHECKLOCKTIMEVERIFY;
+
+ std::vector<std::vector<unsigned char>> stack_ignore;
+ ScriptError err;
+ BOOST_CHECK(!EvalScript(stack_ignore, script_cltv_trunc, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK_EQUAL(err, SCRIPT_ERR_INVALID_STACK_OPERATION);
}
static CScript
@@ -1076,18 +1101,18 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
const CTransaction txFrom12{BuildCreditingTransaction(scriptPubKey12)};
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom12);
- CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
+ CScript goodsig1 = sign_multisig(scriptPubKey12, key1, CTransaction(txTo12));
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
txTo12.vout[0].nValue = 2;
BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
- CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
+ CScript goodsig2 = sign_multisig(scriptPubKey12, key2, CTransaction(txTo12));
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
- CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
+ CScript badsig1 = sign_multisig(scriptPubKey12, key3, CTransaction(txTo12));
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
@@ -1109,54 +1134,54 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
std::vector<CKey> keys;
keys.push_back(key1); keys.push_back(key2);
- CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript goodsig1 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key3);
- CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript goodsig2 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key3);
- CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript goodsig3 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
- CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript badsig1 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
- CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript badsig2 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
- CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript badsig3 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
- CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript badsig4 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
- CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript badsig5 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear(); // Must have signatures
- CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
+ CScript badsig6 = sign_multisig(scriptPubKey23, keys, CTransaction(txTo23));
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
}
@@ -1183,11 +1208,11 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
key.MakeNewKey(i%2 == 1);
keys.push_back(key);
pubkeys.push_back(key.GetPubKey());
- keystore.AddKey(key);
+ BOOST_CHECK(keystore.AddKey(key));
}
- CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID()));
- CMutableTransaction txTo = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom);
+ CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(PKHash(keys[0].GetPubKey())));
+ CMutableTransaction txTo = BuildSpendingTransaction(CScript(), CScriptWitness(), CTransaction(txFrom));
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
SignatureData scriptSig;
@@ -1196,7 +1221,7 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
BOOST_CHECK(combined.scriptSig.empty());
// Single signature case:
- SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig
+ BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL)); // changes scriptSig
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
@@ -1204,31 +1229,31 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
SignatureData scriptSigCopy = scriptSig;
// Signing again will give a different, valid signature:
- SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL));
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined = CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig);
BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || combined.scriptSig == scriptSig.scriptSig);
// P2SH, single-signature case:
CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG;
- keystore.AddCScript(pkSingle);
- scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
- SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ BOOST_CHECK(keystore.AddCScript(pkSingle));
+ scriptPubKey = GetScriptForDestination(ScriptHash(pkSingle));
+ BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL));
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
scriptSigCopy = scriptSig;
- SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL));
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined = CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig);
BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || combined.scriptSig == scriptSig.scriptSig);
// Hardest case: Multisig 2-of-3
scriptPubKey = GetScriptForMultisig(2, pubkeys);
- keystore.AddCScript(scriptPubKey);
- SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ BOOST_CHECK(keystore.AddCScript(scriptPubKey));
+ BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL));
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h
index 9e88866cb0..e763b64275 100644
--- a/src/test/scriptnum10.h
+++ b/src/test/scriptnum10.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp
index cd6e27d248..e7916f5000 100644
--- a/src/test/scriptnum_tests.cpp
+++ b/src/test/scriptnum_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/scriptnum10.h>
#include <script/script.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <limits.h>
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index a0dafaaf5c..2fab309aa4 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <serialize.h>
#include <streams.h>
#include <hash.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <stdint.h>
@@ -182,13 +182,13 @@ BOOST_AUTO_TEST_CASE(varints)
CDataStream::size_type size = 0;
for (int i = 0; i < 100000; i++) {
ss << VARINT(i, VarIntMode::NONNEGATIVE_SIGNED);
- size += ::GetSerializeSize(VARINT(i, VarIntMode::NONNEGATIVE_SIGNED), 0, 0);
+ size += ::GetSerializeSize(VARINT(i, VarIntMode::NONNEGATIVE_SIGNED), 0);
BOOST_CHECK(size == ss.size());
}
for (uint64_t i = 0; i < 100000000000ULL; i += 999999937) {
ss << VARINT(i);
- size += ::GetSerializeSize(VARINT(i), 0, 0);
+ size += ::GetSerializeSize(VARINT(i), 0);
BOOST_CHECK(size == ss.size());
}
@@ -200,7 +200,7 @@ BOOST_AUTO_TEST_CASE(varints)
}
for (uint64_t i = 0; i < 100000000000ULL; i += 999999937) {
- uint64_t j = -1;
+ uint64_t j = std::numeric_limits<uint64_t>::max();
ss >> VARINT(j);
BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
}
diff --git a/src/test/test_bitcoin.cpp b/src/test/setup_common.cpp
index b35b21335e..5b454da52b 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/setup_common.cpp
@@ -1,43 +1,30 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
+#include <banman.h>
#include <chainparams.h>
#include <consensus/consensus.h>
+#include <consensus/params.h>
#include <consensus/validation.h>
#include <crypto/sha256.h>
-#include <validation.h>
#include <miner.h>
#include <net_processing.h>
+#include <noui.h>
#include <pow.h>
-#include <ui_interface.h>
-#include <streams.h>
-#include <rpc/server.h>
#include <rpc/register.h>
+#include <rpc/server.h>
#include <script/sigcache.h>
+#include <streams.h>
+#include <ui_interface.h>
+#include <util/validation.h>
+#include <validation.h>
-void CConnmanTest::AddNode(CNode& node)
-{
- LOCK(g_connman->cs_vNodes);
- g_connman->vNodes.push_back(&node);
-}
-
-void CConnmanTest::ClearNodes()
-{
- LOCK(g_connman->cs_vNodes);
- for (CNode* node : g_connman->vNodes) {
- delete node;
- }
- g_connman->vNodes.clear();
-}
-
-uint256 insecure_rand_seed = GetRandHash();
-FastRandomContext insecure_rand_ctx(insecure_rand_seed);
+const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
-extern bool fPrintToConsole;
-extern void noui_connect();
+FastRandomContext g_insecure_rand_ctx;
std::ostream& operator<<(std::ostream& os, const uint256& num)
{
@@ -46,10 +33,9 @@ std::ostream& operator<<(std::ostream& os, const uint256& num)
}
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
- : m_path_root(fs::temp_directory_path() / "test_bitcoin" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))))
+ : m_path_root(fs::temp_directory_path() / "test_common_" PACKAGE_NAME / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))))
{
SHA256AutoDetect();
- RandomInit();
ECC_Start();
SetupEnvironment();
SetupNetworking();
@@ -57,7 +43,11 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
InitScriptExecutionCache();
fCheckBlockIndex = true;
SelectParams(chainName);
- noui_connect();
+ static bool noui_connected = false;
+ if (!noui_connected) {
+ noui_connect();
+ noui_connected = true;
+ }
}
BasicTestingSetup::~BasicTestingSetup()
@@ -78,57 +68,59 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
{
SetDataDir("tempdir");
const CChainParams& chainparams = Params();
- // Ideally we'd move all the RPC tests to the functional testing framework
- // instead of unit tests, but for now we need these here.
-
- RegisterAllCoreRPCCommands(tableRPC);
- ClearDatadirCache();
-
- // We have to run a scheduler thread to prevent ActivateBestChain
- // from blocking due to queue overrun.
- threadGroup.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
- GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
-
- mempool.setSanityCheck(1.0);
- pblocktree.reset(new CBlockTreeDB(1 << 20, true));
- pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
- pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
- if (!LoadGenesisBlock(chainparams)) {
- throw std::runtime_error("LoadGenesisBlock failed.");
- }
- {
- CValidationState state;
- if (!ActivateBestChain(state, chainparams)) {
- throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
- }
- }
- nScriptCheckThreads = 3;
- for (int i=0; i < nScriptCheckThreads-1; i++)
- threadGroup.create_thread(&ThreadScriptCheck);
- g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests.
- connman = g_connman.get();
- peerLogic.reset(new PeerLogicValidation(connman, scheduler, /*enable_bip61=*/true));
+ // Ideally we'd move all the RPC tests to the functional testing framework
+ // instead of unit tests, but for now we need these here.
+
+ RegisterAllCoreRPCCommands(tableRPC);
+ ClearDatadirCache();
+
+ // We have to run a scheduler thread to prevent ActivateBestChain
+ // from blocking due to queue overrun.
+ threadGroup.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
+ GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
+
+ mempool.setSanityCheck(1.0);
+ pblocktree.reset(new CBlockTreeDB(1 << 20, true));
+ pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
+ pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
+ if (!LoadGenesisBlock(chainparams)) {
+ throw std::runtime_error("LoadGenesisBlock failed.");
+ }
+
+ CValidationState state;
+ if (!ActivateBestChain(state, chainparams)) {
+ throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
+ }
+
+ nScriptCheckThreads = 3;
+ for (int i = 0; i < nScriptCheckThreads - 1; i++)
+ threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
+
+ g_banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ g_connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
}
TestingSetup::~TestingSetup()
{
- threadGroup.interrupt_all();
- threadGroup.join_all();
- GetMainSignals().FlushBackgroundCallbacks();
- GetMainSignals().UnregisterBackgroundSignalScheduler();
- g_connman.reset();
- peerLogic.reset();
- UnloadBlockIndex();
- pcoinsTip.reset();
- pcoinsdbview.reset();
- pblocktree.reset();
+ threadGroup.interrupt_all();
+ threadGroup.join_all();
+ GetMainSignals().FlushBackgroundCallbacks();
+ GetMainSignals().UnregisterBackgroundSignalScheduler();
+ g_connman.reset();
+ g_banman.reset();
+ UnloadBlockIndex();
+ pcoinsTip.reset();
+ pcoinsdbview.reset();
+ pblocktree.reset();
}
TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
{
// CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests.
// TODO: fix the code to support SegWit blocks.
- UpdateVersionBitsParameters(Consensus::DEPLOYMENT_SEGWIT, 0, Consensus::BIP9Deployment::NO_TIMEOUT);
+ gArgs.ForceSetArg("-vbparams", strprintf("segwit:0:%d", (int64_t)Consensus::BIP9Deployment::NO_TIMEOUT));
+ SelectParams(CBaseChainParams::REGTEST);
+
// Generate a 100-block chain:
coinbaseKey.MakeNewKey(true);
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
@@ -159,7 +151,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
{
LOCK(cs_main);
unsigned int extraNonce = 0;
- IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
+ IncrementExtraNonce(&block, ::ChainActive().Tip(), extraNonce);
}
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
diff --git a/src/test/test_bitcoin.h b/src/test/setup_common.h
index 88b2d37e87..893eca216d 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/setup_common.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_TEST_TEST_BITCOIN_H
-#define BITCOIN_TEST_TEST_BITCOIN_H
+#ifndef BITCOIN_TEST_SETUP_COMMON_H
+#define BITCOIN_TEST_SETUP_COMMON_H
#include <chainparamsbase.h>
#include <fs.h>
@@ -15,27 +15,43 @@
#include <txmempool.h>
#include <memory>
+#include <type_traits>
#include <boost/thread.hpp>
-extern uint256 insecure_rand_seed;
-extern FastRandomContext insecure_rand_ctx;
+// Enable BOOST_CHECK_EQUAL for enum class types
+template <typename T>
+std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e)
+{
+ return stream << static_cast<typename std::underlying_type<T>::type>(e);
+}
-static inline void SeedInsecureRand(bool fDeterministic = false)
+/**
+ * This global and the helpers that use it are not thread-safe.
+ *
+ * If thread-safety is needed, the global could be made thread_local (given
+ * that thread_local is supported on all architectures we support) or a
+ * per-thread instance could be used in the multi-threaded test.
+ */
+extern FastRandomContext g_insecure_rand_ctx;
+
+/**
+ * Flag to make GetRand in random.h return the same number
+ */
+extern bool g_mock_deterministic_tests;
+
+static inline void SeedInsecureRand(bool deterministic = false)
{
- if (fDeterministic) {
- insecure_rand_seed = uint256();
- } else {
- insecure_rand_seed = GetRandHash();
- }
- insecure_rand_ctx = FastRandomContext(insecure_rand_seed);
+ g_insecure_rand_ctx = FastRandomContext(deterministic);
}
-static inline uint32_t InsecureRand32() { return insecure_rand_ctx.rand32(); }
-static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); }
-static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); }
-static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); }
-static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); }
+static inline uint32_t InsecureRand32() { return g_insecure_rand_ctx.rand32(); }
+static inline uint256 InsecureRand256() { return g_insecure_rand_ctx.rand256(); }
+static inline uint64_t InsecureRandBits(int bits) { return g_insecure_rand_ctx.randbits(bits); }
+static inline uint64_t InsecureRandRange(uint64_t range) { return g_insecure_rand_ctx.randrange(range); }
+static inline bool InsecureRandBool() { return g_insecure_rand_ctx.randbool(); }
+
+static constexpr CAmount CENT{1000000};
/** Basic testing setup.
* This just configures logging and chain parameters.
@@ -55,19 +71,9 @@ private:
/** Testing setup that configures a complete environment.
* Included are data directory, coins database, script check threads setup.
*/
-class CConnman;
-class CNode;
-struct CConnmanTest {
- static void AddNode(CNode& node);
- static void ClearNodes();
-};
-
-class PeerLogicValidation;
-struct TestingSetup: public BasicTestingSetup {
+struct TestingSetup : public BasicTestingSetup {
boost::thread_group threadGroup;
- CConnman* connman;
CScheduler scheduler;
- std::unique_ptr<PeerLogicValidation> peerLogic;
explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
~TestingSetup();
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 6b8856ef47..15f8db899b 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -1,8 +1,8 @@
-// Copyright (c) 2013-2017 The Bitcoin Core developers
+// Copyright (c) 2013-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <consensus/tx_verify.h>
+#include <consensus/tx_check.h>
#include <consensus/validation.h>
#include <test/data/sighash.json.h>
#include <hash.h>
@@ -10,9 +10,9 @@
#include <script/script.h>
#include <serialize.h>
#include <streams.h>
-#include <test/test_bitcoin.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <test/setup_common.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <version.h>
#include <iostream>
@@ -105,7 +105,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
txin.prevout.hash = InsecureRand256();
txin.prevout.n = InsecureRandBits(2);
RandomScript(txin.scriptSig);
- txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : (unsigned int)-1;
+ txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : std::numeric_limits<uint32_t>::max();
}
for (int out = 0; out < outs; out++) {
tx.vout.push_back(CTxOut());
@@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(sighash_test)
int nIn = InsecureRandRange(txTo.vin.size());
uint256 sh, sho;
- sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
+ sho = SignatureHashOld(scriptCode, CTransaction(txTo), nIn, nHashType);
sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SigVersion::BASE);
#if defined(PRINT_SIGHASH_JSON)
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 86647e72eb..5c12ec13d2 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,7 @@
#include <script/script.h>
#include <script/standard.h>
#include <uint256.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <vector>
@@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3U);
BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21U);
- CScript p2sh = GetScriptForDestination(CScriptID(s1));
+ CScript p2sh = GetScriptForDestination(ScriptHash(s1));
CScript scriptSig;
scriptSig << OP_0 << Serialize(s1);
BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U);
@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3U);
BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20U);
- p2sh = GetScriptForDestination(CScriptID(s2));
+ p2sh = GetScriptForDestination(ScriptHash(s2));
BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0U);
BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0U);
CScript scriptSig2;
@@ -102,7 +102,7 @@ static void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CM
spendingTx.vout[0].nValue = 1;
spendingTx.vout[0].scriptPubKey = CScript();
- AddCoins(coins, creationTx, 0);
+ AddCoins(coins, CTransaction(creationTx), 0);
}
BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
@@ -138,18 +138,18 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
// is not accurate.
assert(GetTransactionSigOpCost(CTransaction(creationTx), coins, flags) == MAX_PUBKEYS_PER_MULTISIG * WITNESS_SCALE_FACTOR);
// Sanity check: script verification fails because of an invalid signature.
- assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
}
// Multisig nested in P2SH
{
CScript redeemScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
- CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ CScript scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript);
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CScriptWitness());
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2 * WITNESS_SCALE_FACTOR);
- assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
}
// P2WPKH witness program
@@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
// No signature operations if we don't verify the witness.
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0);
- assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
+ assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
// The sig op cost for witness version != 0 is zero.
assert(scriptPubKey[0] == 0x00);
@@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
{
CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
CScript scriptSig = GetScriptForWitness(p2pk);
- CScript scriptPubKey = GetScriptForDestination(CScriptID(scriptSig));
+ CScript scriptPubKey = GetScriptForDestination(ScriptHash(scriptSig));
scriptSig = CScript() << ToByteVector(scriptSig);
CScriptWitness scriptWitness;
scriptWitness.stack.push_back(std::vector<unsigned char>(0));
@@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
- assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
+ assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
}
// P2WSH witness program
@@ -209,14 +209,14 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0);
- assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
}
// P2WSH nested in P2SH
{
CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
CScript redeemScript = GetScriptForWitness(witnessScript);
- CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ CScript scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
CScript scriptSig = CScript() << ToByteVector(redeemScript);
CScriptWitness scriptWitness;
scriptWitness.stack.push_back(std::vector<unsigned char>(0));
@@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
- assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
}
}
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index 25c7e54808..3d39dfdb75 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
-#include <util.h>
-#include <test/test_bitcoin.h>
+#include <util/system.h>
+#include <test/setup_common.h>
#include <vector>
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
// Pick a random element in vBlocksMain.
int r = InsecureRandRange(vBlocksMain.size());
int64_t test_time = vBlocksMain[r].nTime;
- CBlockIndex *ret = chain.FindEarliestAtLeast(test_time);
+ CBlockIndex* ret = chain.FindEarliestAtLeast(test_time, 0);
BOOST_CHECK(ret->nTimeMax >= test_time);
BOOST_CHECK((ret->pprev==nullptr) || ret->pprev->nTimeMax < test_time);
BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret);
@@ -146,7 +146,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
{
std::list<CBlockIndex> blocks;
- for (unsigned int timeMax : {100, 100, 100, 200, 200, 200, 300, 300, 300}) {
+ for (const unsigned int timeMax : {100, 100, 100, 200, 200, 200, 300, 300, 300}) {
CBlockIndex* prev = blocks.empty() ? nullptr : &blocks.back();
blocks.emplace_back();
blocks.back().nHeight = prev ? prev->nHeight + 1 : 0;
@@ -158,23 +158,34 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
CChain chain;
chain.SetTip(&blocks.back());
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50)->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100)->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150)->nHeight, 3);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200)->nHeight, 3);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250)->nHeight, 6);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300)->nHeight, 6);
- BOOST_CHECK(!chain.FindEarliestAtLeast(350));
-
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0)->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1)->nHeight, 0);
-
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min())->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::min())->nHeight, 0);
- BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1)->nHeight, 0);
- BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max()));
- BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max()));
- BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1));
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50, 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100, 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150, 0)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200, 0)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250, 0)->nHeight, 6);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300, 0)->nHeight, 6);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(350, 0));
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1, 0)->nHeight, 0);
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min(), 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1, 0)->nHeight, 0);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max(), 0));
+ BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max(), 0));
+ BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1, 0));
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, -1)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 3)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 8)->nHeight, 8);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(0, 9));
+
+ CBlockIndex* ret1 = chain.FindEarliestAtLeast(100, 2);
+ BOOST_CHECK(ret1->nTimeMax >= 100 && ret1->nHeight == 2);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(300, 9));
+ CBlockIndex* ret2 = chain.FindEarliestAtLeast(200, 4);
+ BOOST_CHECK(ret2->nTimeMax >= 200 && ret2->nHeight == 4);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index 8ca668ba01..4e37199c63 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <streams.h>
#include <support/allocators/zeroafterfree.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -68,6 +68,86 @@ BOOST_AUTO_TEST_CASE(streams_vector_writer)
vch.clear();
}
+BOOST_AUTO_TEST_CASE(streams_vector_reader)
+{
+ std::vector<unsigned char> vch = {1, 255, 3, 4, 5, 6};
+
+ VectorReader reader(SER_NETWORK, INIT_PROTO_VERSION, vch, 0);
+ BOOST_CHECK_EQUAL(reader.size(), 6);
+ BOOST_CHECK(!reader.empty());
+
+ // Read a single byte as an unsigned char.
+ unsigned char a;
+ reader >> a;
+ BOOST_CHECK_EQUAL(a, 1);
+ BOOST_CHECK_EQUAL(reader.size(), 5);
+ BOOST_CHECK(!reader.empty());
+
+ // Read a single byte as a signed char.
+ signed char b;
+ reader >> b;
+ BOOST_CHECK_EQUAL(b, -1);
+ BOOST_CHECK_EQUAL(reader.size(), 4);
+ BOOST_CHECK(!reader.empty());
+
+ // Read a 4 bytes as an unsigned int.
+ unsigned int c;
+ reader >> c;
+ BOOST_CHECK_EQUAL(c, 100992003); // 3,4,5,6 in little-endian base-256
+ BOOST_CHECK_EQUAL(reader.size(), 0);
+ BOOST_CHECK(reader.empty());
+
+ // Reading after end of byte vector throws an error.
+ signed int d;
+ BOOST_CHECK_THROW(reader >> d, std::ios_base::failure);
+
+ // Read a 4 bytes as a signed int from the beginning of the buffer.
+ VectorReader new_reader(SER_NETWORK, INIT_PROTO_VERSION, vch, 0);
+ new_reader >> d;
+ BOOST_CHECK_EQUAL(d, 67370753); // 1,255,3,4 in little-endian base-256
+ BOOST_CHECK_EQUAL(new_reader.size(), 2);
+ BOOST_CHECK(!new_reader.empty());
+
+ // Reading after end of byte vector throws an error even if the reader is
+ // not totally empty.
+ BOOST_CHECK_THROW(new_reader >> d, std::ios_base::failure);
+}
+
+BOOST_AUTO_TEST_CASE(bitstream_reader_writer)
+{
+ CDataStream data(SER_NETWORK, INIT_PROTO_VERSION);
+
+ BitStreamWriter<CDataStream> bit_writer(data);
+ bit_writer.Write(0, 1);
+ bit_writer.Write(2, 2);
+ bit_writer.Write(6, 3);
+ bit_writer.Write(11, 4);
+ bit_writer.Write(1, 5);
+ bit_writer.Write(32, 6);
+ bit_writer.Write(7, 7);
+ bit_writer.Write(30497, 16);
+ bit_writer.Flush();
+
+ CDataStream data_copy(data);
+ uint32_t serialized_int1;
+ data >> serialized_int1;
+ 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
+
+ BitStreamReader<CDataStream> bit_reader(data_copy);
+ BOOST_CHECK_EQUAL(bit_reader.Read(1), 0);
+ BOOST_CHECK_EQUAL(bit_reader.Read(2), 2);
+ BOOST_CHECK_EQUAL(bit_reader.Read(3), 6);
+ BOOST_CHECK_EQUAL(bit_reader.Read(4), 11);
+ BOOST_CHECK_EQUAL(bit_reader.Read(5), 1);
+ BOOST_CHECK_EQUAL(bit_reader.Read(6), 32);
+ BOOST_CHECK_EQUAL(bit_reader.Read(7), 7);
+ BOOST_CHECK_EQUAL(bit_reader.Read(16), 30497);
+ BOOST_CHECK_THROW(bit_reader.Read(8), std::ios_base::failure);
+}
+
BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
{
std::vector<char> in;
diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp
new file mode 100644
index 0000000000..c1399d2dbe
--- /dev/null
+++ b/src/test/sync_tests.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2012-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <sync.h>
+#include <test/setup_common.h>
+
+#include <boost/test/unit_test.hpp>
+
+namespace {
+template <typename MutexType>
+void TestPotentialDeadLockDetected(MutexType& mutex1, MutexType& mutex2)
+{
+ {
+ LOCK2(mutex1, mutex2);
+ }
+ bool error_thrown = false;
+ try {
+ LOCK2(mutex2, mutex1);
+ } catch (const std::logic_error& e) {
+ BOOST_CHECK_EQUAL(e.what(), "potential deadlock detected");
+ error_thrown = true;
+ }
+ #ifdef DEBUG_LOCKORDER
+ BOOST_CHECK(error_thrown);
+ #else
+ BOOST_CHECK(!error_thrown);
+ #endif
+}
+} // namespace
+
+BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(potential_deadlock_detected)
+{
+ #ifdef DEBUG_LOCKORDER
+ bool prev = g_debug_lockorder_abort;
+ g_debug_lockorder_abort = false;
+ #endif
+
+ CCriticalSection rmutex1, rmutex2;
+ TestPotentialDeadLockDetected(rmutex1, rmutex2);
+
+ Mutex mutex1, mutex2;
+ TestPotentialDeadLockDetected(mutex1, mutex2);
+
+ #ifdef DEBUG_LOCKORDER
+ g_debug_lockorder_abort = prev;
+ #endif
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp
deleted file mode 100644
index b2daa2adb5..0000000000
--- a/src/test/test_bitcoin_fuzzy.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
-
-#include <consensus/merkle.h>
-#include <primitives/block.h>
-#include <script/script.h>
-#include <addrman.h>
-#include <chain.h>
-#include <coins.h>
-#include <compressor.h>
-#include <net.h>
-#include <protocol.h>
-#include <streams.h>
-#include <undo.h>
-#include <version.h>
-#include <pubkey.h>
-#include <blockencodings.h>
-
-#include <stdint.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-
-enum TEST_ID {
- CBLOCK_DESERIALIZE=0,
- CTRANSACTION_DESERIALIZE,
- CBLOCKLOCATOR_DESERIALIZE,
- CBLOCKMERKLEROOT,
- CADDRMAN_DESERIALIZE,
- CBLOCKHEADER_DESERIALIZE,
- CBANENTRY_DESERIALIZE,
- CTXUNDO_DESERIALIZE,
- CBLOCKUNDO_DESERIALIZE,
- CCOINS_DESERIALIZE,
- CNETADDR_DESERIALIZE,
- CSERVICE_DESERIALIZE,
- CMESSAGEHEADER_DESERIALIZE,
- CADDRESS_DESERIALIZE,
- CINV_DESERIALIZE,
- CBLOOMFILTER_DESERIALIZE,
- CDISKBLOCKINDEX_DESERIALIZE,
- CTXOUTCOMPRESSOR_DESERIALIZE,
- BLOCKTRANSACTIONS_DESERIALIZE,
- BLOCKTRANSACTIONSREQUEST_DESERIALIZE,
- TEST_ID_END
-};
-
-static bool read_stdin(std::vector<uint8_t> &data) {
- uint8_t buffer[1024];
- ssize_t length=0;
- while((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
- data.insert(data.end(), buffer, buffer+length);
-
- if (data.size() > (1<<20)) return false;
- }
- return length==0;
-}
-
-static int test_one_input(std::vector<uint8_t> buffer) {
- if (buffer.size() < sizeof(uint32_t)) return 0;
-
- uint32_t test_id = 0xffffffff;
- memcpy(&test_id, buffer.data(), sizeof(uint32_t));
- buffer.erase(buffer.begin(), buffer.begin() + sizeof(uint32_t));
-
- if (test_id >= TEST_ID_END) return 0;
-
- CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
- try {
- int nVersion;
- ds >> nVersion;
- ds.SetVersion(nVersion);
- } catch (const std::ios_base::failure& e) {
- return 0;
- }
-
- switch(test_id) {
- case CBLOCK_DESERIALIZE:
- {
- try
- {
- CBlock block;
- ds >> block;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CTRANSACTION_DESERIALIZE:
- {
- try
- {
- CTransaction tx(deserialize, ds);
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CBLOCKLOCATOR_DESERIALIZE:
- {
- try
- {
- CBlockLocator bl;
- ds >> bl;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CBLOCKMERKLEROOT:
- {
- try
- {
- CBlock block;
- ds >> block;
- bool mutated;
- BlockMerkleRoot(block, &mutated);
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CADDRMAN_DESERIALIZE:
- {
- try
- {
- CAddrMan am;
- ds >> am;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CBLOCKHEADER_DESERIALIZE:
- {
- try
- {
- CBlockHeader bh;
- ds >> bh;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CBANENTRY_DESERIALIZE:
- {
- try
- {
- CBanEntry be;
- ds >> be;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CTXUNDO_DESERIALIZE:
- {
- try
- {
- CTxUndo tu;
- ds >> tu;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CBLOCKUNDO_DESERIALIZE:
- {
- try
- {
- CBlockUndo bu;
- ds >> bu;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CCOINS_DESERIALIZE:
- {
- try
- {
- Coin coin;
- ds >> coin;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CNETADDR_DESERIALIZE:
- {
- try
- {
- CNetAddr na;
- ds >> na;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CSERVICE_DESERIALIZE:
- {
- try
- {
- CService s;
- ds >> s;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CMESSAGEHEADER_DESERIALIZE:
- {
- CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
- try
- {
- CMessageHeader mh(pchMessageStart);
- ds >> mh;
- if (!mh.IsValid(pchMessageStart)) {return 0;}
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CADDRESS_DESERIALIZE:
- {
- try
- {
- CAddress a;
- ds >> a;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CINV_DESERIALIZE:
- {
- try
- {
- CInv i;
- ds >> i;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CBLOOMFILTER_DESERIALIZE:
- {
- try
- {
- CBloomFilter bf;
- ds >> bf;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CDISKBLOCKINDEX_DESERIALIZE:
- {
- try
- {
- CDiskBlockIndex dbi;
- ds >> dbi;
- } catch (const std::ios_base::failure& e) {return 0;}
- break;
- }
- case CTXOUTCOMPRESSOR_DESERIALIZE:
- {
- CTxOut to;
- CTxOutCompressor toc(to);
- try
- {
- ds >> toc;
- } catch (const std::ios_base::failure& e) {return 0;}
-
- break;
- }
- case BLOCKTRANSACTIONS_DESERIALIZE:
- {
- try
- {
- BlockTransactions bt;
- ds >> bt;
- } catch (const std::ios_base::failure& e) {return 0;}
-
- break;
- }
- case BLOCKTRANSACTIONSREQUEST_DESERIALIZE:
- {
- try
- {
- BlockTransactionsRequest btr;
- ds >> btr;
- } catch (const std::ios_base::failure& e) {return 0;}
-
- break;
- }
- default:
- return 0;
- }
- return 0;
-}
-
-static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
-void initialize() {
- globalVerifyHandle = std::unique_ptr<ECCVerifyHandle>(new ECCVerifyHandle());
-}
-
-// This function is used by libFuzzer
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- test_one_input(std::vector<uint8_t>(data, data + size));
- return 0;
-}
-
-// This function is used by libFuzzer
-extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
- initialize();
- return 0;
-}
-
-// Disabled under WIN32 due to clash with Cygwin's WinMain.
-#ifndef WIN32
-// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
-// the main(...) function.
-__attribute__((weak))
-#endif
-int main(int argc, char **argv)
-{
- initialize();
-#ifdef __AFL_INIT
- // Enable AFL deferred forkserver mode. Requires compilation using
- // afl-clang-fast++. See fuzzing.md for details.
- __AFL_INIT();
-#endif
-
-#ifdef __AFL_LOOP
- // Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
- // See fuzzing.md for details.
- int ret = 0;
- while (__AFL_LOOP(1000)) {
- std::vector<uint8_t> buffer;
- if (!read_stdin(buffer)) {
- continue;
- }
- ret = test_one_input(buffer);
- }
- return ret;
-#else
- std::vector<uint8_t> buffer;
- if (!read_stdin(buffer)) {
- return 0;
- }
- return test_one_input(buffer);
-#endif
-}
diff --git a/src/test/test_bitcoin_main.cpp b/src/test/test_bitcoin_main.cpp
deleted file mode 100644
index e48c685b6b..0000000000
--- a/src/test/test_bitcoin_main.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#define BOOST_TEST_MODULE Bitcoin Test Suite
-
-#include <net.h>
-
-#include <memory>
-
-#include <boost/test/unit_test.hpp>
-
-std::unique_ptr<CConnman> g_connman;
-
-[[noreturn]] void Shutdown(void* parg)
-{
- std::exit(EXIT_SUCCESS);
-}
-
-[[noreturn]] void StartShutdown()
-{
- std::exit(EXIT_SUCCESS);
-}
-
-bool ShutdownRequested()
-{
- return false;
-}
diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp
index 5d93bc1efe..b4c0e6a0f4 100644
--- a/src/test/timedata_tests.cpp
+++ b/src/test/timedata_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#include <timedata.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp
index c7ceb2f1e9..6d8459f5b1 100644
--- a/src/test/torcontrol_tests.cpp
+++ b/src/test/torcontrol_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <torcontrol.h>
#include <boost/test/unit_test.hpp>
@@ -20,7 +20,6 @@ BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup)
static void CheckSplitTorReplyLine(std::string input, std::string command, std::string args)
{
- BOOST_TEST_MESSAGE(std::string("CheckSplitTorReplyLine(") + input + ")");
auto ret = SplitTorReplyLine(input);
BOOST_CHECK_EQUAL(ret.first, command);
BOOST_CHECK_EQUAL(ret.second, args);
@@ -61,7 +60,6 @@ BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine)
static void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected)
{
- BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(") + input + ")");
auto ret = ParseTorReplyMapping(input);
BOOST_CHECK_EQUAL(ret.size(), expected.size());
auto r_it = ret.begin();
@@ -173,7 +171,6 @@ BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping)
// Special handling for null case
// (needed because string comparison reads the null as end-of-string)
- BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(Null=\"\\0\")"));
auto ret = ParseTorReplyMapping("Null=\"\\0\"");
BOOST_CHECK_EQUAL(ret.size(), 1U);
auto r_it = ret.begin();
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index aff270942e..f5ff18c055 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -1,25 +1,26 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/data/tx_invalid.json.h>
#include <test/data/tx_valid.json.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <clientversion.h>
#include <checkqueue.h>
-#include <consensus/tx_verify.h>
+#include <consensus/tx_check.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <key.h>
#include <keystore.h>
#include <validation.h>
#include <policy/policy.h>
+#include <policy/settings.h>
#include <script/script.h>
#include <script/sign.h>
#include <script/script_error.h>
#include <script/standard.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <map>
#include <string>
@@ -65,7 +66,7 @@ unsigned int ParseScriptFlags(std::string strFlags)
std::vector<std::string> words;
boost::algorithm::split(words, strFlags, boost::algorithm::is_any_of(","));
- for (std::string word : words)
+ for (const std::string& word : words)
{
if (!mapFlagNames.count(word))
BOOST_ERROR("Bad test: unknown verification flag '" << word << "'");
@@ -273,11 +274,11 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
CMutableTransaction tx;
stream >> tx;
CValidationState state;
- BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid.");
+ BOOST_CHECK_MESSAGE(CheckTransaction(CTransaction(tx), state) && state.IsValid(), "Simple deserialized transaction should be valid.");
// Check that duplicate txins fail
tx.vin.push_back(tx.vin[0]);
- BOOST_CHECK_MESSAGE(!CheckTransaction(tx, state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
+ BOOST_CHECK_MESSAGE(!CheckTransaction(CTransaction(tx), state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
}
//
@@ -306,14 +307,14 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet)
dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
dummyTransactions[0].vout[1].nValue = 50*CENT;
dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
- AddCoins(coinsRet, dummyTransactions[0], 0);
+ AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
dummyTransactions[1].vout.resize(2);
dummyTransactions[1].vout[0].nValue = 21*CENT;
- dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID());
+ dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey()));
dummyTransactions[1].vout[1].nValue = 22*CENT;
- dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID());
- AddCoins(coinsRet, dummyTransactions[1], 0);
+ dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey()));
+ AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
return dummyTransactions;
}
@@ -340,8 +341,8 @@ BOOST_AUTO_TEST_CASE(test_Get)
t1.vout[0].nValue = 90*CENT;
t1.vout[0].scriptPubKey << OP_1;
- BOOST_CHECK(AreInputsStandard(t1, coins));
- BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
+ BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins));
+ BOOST_CHECK_EQUAL(coins.GetValueIn(CTransaction(t1)), (50+21+22)*CENT);
}
static void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, CTransactionRef& output, CMutableTransaction& input, bool success = true)
@@ -414,14 +415,15 @@ static void ReplaceRedeemScript(CScript& script, const CScript& redeemScript)
script = PushAll(stack);
}
-BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
+BOOST_AUTO_TEST_CASE(test_big_witness_transaction)
+{
CMutableTransaction mtx;
mtx.nVersion = 1;
CKey key;
key.MakeNewKey(true); // Need to use compressed keys in segwit or the signing will fail
CBasicKeyStore keystore;
- keystore.AddKeyPubKey(key, key.GetPubKey());
+ BOOST_CHECK(keystore.AddKeyPubKey(key, key.GetPubKey()));
CKeyID hash = key.GetPubKey().GetID();
CScript scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(hash.begin(), hash.end());
@@ -456,9 +458,8 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
}
CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION);
- auto vstream = WithOrVersion(&ssout, 0);
- vstream << mtx;
- CTransaction tx(deserialize, vstream);
+ ssout << mtx;
+ CTransaction tx(deserialize, ssout);
// check all inputs concurrently, with the cache
PrecomputedTransactionData txdata(tx);
@@ -467,7 +468,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
CCheckQueueControl<CScriptCheck> control(&scriptcheckqueue);
for (int i=0; i<20; i++)
- threadGroup.create_thread(boost::bind(&CCheckQueue<CScriptCheck>::Thread, boost::ref(scriptcheckqueue)));
+ threadGroup.create_thread(std::bind(&CCheckQueue<CScriptCheck>::Thread, std::ref(scriptcheckqueue)));
std::vector<Coin> coins;
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
@@ -518,10 +519,10 @@ BOOST_AUTO_TEST_CASE(test_witness)
pubkey3 = key3.GetPubKey();
pubkey1L = key1L.GetPubKey();
pubkey2L = key2L.GetPubKey();
- keystore.AddKeyPubKey(key1, pubkey1);
- keystore.AddKeyPubKey(key2, pubkey2);
- keystore.AddKeyPubKey(key1L, pubkey1L);
- keystore.AddKeyPubKey(key2L, pubkey2L);
+ BOOST_CHECK(keystore.AddKeyPubKey(key1, pubkey1));
+ BOOST_CHECK(keystore.AddKeyPubKey(key2, pubkey2));
+ BOOST_CHECK(keystore.AddKeyPubKey(key1L, pubkey1L));
+ BOOST_CHECK(keystore.AddKeyPubKey(key2L, pubkey2L));
CScript scriptPubkey1, scriptPubkey2, scriptPubkey1L, scriptPubkey2L, scriptMulti;
scriptPubkey1 << ToByteVector(pubkey1) << OP_CHECKSIG;
scriptPubkey2 << ToByteVector(pubkey2) << OP_CHECKSIG;
@@ -531,19 +532,19 @@ BOOST_AUTO_TEST_CASE(test_witness)
oneandthree.push_back(pubkey1);
oneandthree.push_back(pubkey3);
scriptMulti = GetScriptForMultisig(2, oneandthree);
- keystore.AddCScript(scriptPubkey1);
- keystore.AddCScript(scriptPubkey2);
- keystore.AddCScript(scriptPubkey1L);
- keystore.AddCScript(scriptPubkey2L);
- keystore.AddCScript(scriptMulti);
- keystore.AddCScript(GetScriptForWitness(scriptPubkey1));
- keystore.AddCScript(GetScriptForWitness(scriptPubkey2));
- keystore.AddCScript(GetScriptForWitness(scriptPubkey1L));
- keystore.AddCScript(GetScriptForWitness(scriptPubkey2L));
- keystore.AddCScript(GetScriptForWitness(scriptMulti));
- keystore2.AddCScript(scriptMulti);
- keystore2.AddCScript(GetScriptForWitness(scriptMulti));
- keystore2.AddKeyPubKey(key3, pubkey3);
+ BOOST_CHECK(keystore.AddCScript(scriptPubkey1));
+ BOOST_CHECK(keystore.AddCScript(scriptPubkey2));
+ BOOST_CHECK(keystore.AddCScript(scriptPubkey1L));
+ BOOST_CHECK(keystore.AddCScript(scriptPubkey2L));
+ BOOST_CHECK(keystore.AddCScript(scriptMulti));
+ BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptPubkey1)));
+ BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptPubkey2)));
+ BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptPubkey1L)));
+ BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptPubkey2L)));
+ BOOST_CHECK(keystore.AddCScript(GetScriptForWitness(scriptMulti)));
+ BOOST_CHECK(keystore2.AddCScript(scriptMulti));
+ BOOST_CHECK(keystore2.AddCScript(GetScriptForWitness(scriptMulti)));
+ BOOST_CHECK(keystore2.AddKeyPubKey(key3, pubkey3));
CTransactionRef output1, output2;
CMutableTransaction input1, input2;
@@ -561,8 +562,8 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
// P2SH pay-to-compressed-pubkey.
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1)), output1, input1);
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2)), output2, input2);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey1)), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey2)), output2, input2);
ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1);
CheckWithFlag(output1, input1, 0, true);
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
@@ -586,8 +587,8 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
// P2SH witness pay-to-compressed-pubkey (v0).
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1))), output1, input1);
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2))), output2, input2);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptPubkey1))), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptPubkey2))), output2, input2);
ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1));
CheckWithFlag(output1, input1, 0, true);
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
@@ -611,8 +612,8 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
// P2SH pay-to-uncompressed-pubkey.
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1L)), output1, input1);
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2L)), output2, input2);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey1L)), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptPubkey2L)), output2, input2);
ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1L);
CheckWithFlag(output1, input1, 0, true);
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
@@ -628,8 +629,8 @@ BOOST_AUTO_TEST_CASE(test_witness)
CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2, false);
// Signing disabled for P2SH witness pay-to-uncompressed-pubkey (v1).
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1, false);
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2, false);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptPubkey1L))), output1, input1, false);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptPubkey2L))), output2, input2, false);
// Normal 2-of-2 multisig
CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false);
@@ -641,10 +642,10 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
// P2SH 2-of-2 multisig
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptMulti)), output1, input1, false);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(scriptMulti)), output1, input1, false);
CheckWithFlag(output1, input1, 0, true);
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, false);
- CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(scriptMulti)), output2, input2, false);
+ CreateCreditAndSpend(keystore2, GetScriptForDestination(ScriptHash(scriptMulti)), output2, input2, false);
CheckWithFlag(output2, input2, 0, true);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false);
BOOST_CHECK(*output1 == *output2);
@@ -665,10 +666,10 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
// P2SH witness 2-of-2 multisig
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output1, input1, false);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptMulti))), output1, input1, false);
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
- CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output2, input2, false);
+ CreateCreditAndSpend(keystore2, GetScriptForDestination(ScriptHash(GetScriptForWitness(scriptMulti))), output2, input2, false);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
BOOST_CHECK(*output1 == *output2);
@@ -694,78 +695,78 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
t.vout[0].nValue = 90*CENT;
CKey key;
key.MakeNewKey(true);
- t.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
+ t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
std::string reason;
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
// Check dust with default relay fee:
CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000;
BOOST_CHECK_EQUAL(nDustThreshold, 546);
// dust:
t.vout[0].nValue = nDustThreshold - 1;
- BOOST_CHECK(!IsStandardTx(t, reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
// not dust:
t.vout[0].nValue = nDustThreshold;
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
// Check dust with odd relay fee to verify rounding:
// nDustThreshold = 182 * 3702 / 1000
dustRelayFee = CFeeRate(3702);
// dust:
t.vout[0].nValue = 673 - 1;
- BOOST_CHECK(!IsStandardTx(t, reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
// not dust:
t.vout[0].nValue = 673;
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
t.vout[0].scriptPubKey = CScript() << OP_1;
- BOOST_CHECK(!IsStandardTx(t, reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
// MAX_OP_RETURN_RELAY-byte TX_NULL_DATA (standard)
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
// MAX_OP_RETURN_RELAY+1-byte TX_NULL_DATA (non-standard)
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
- BOOST_CHECK(!IsStandardTx(t, reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
// Data payload can be encoded in any way...
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("");
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("00") << ParseHex("01");
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
// OP_RESERVED *is* considered to be a PUSHDATA type opcode by IsPushOnly()!
t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RESERVED << -1 << 0 << ParseHex("01") << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16;
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
t.vout[0].scriptPubKey = CScript() << OP_RETURN << 0 << ParseHex("01") << 2 << ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
// ...so long as it only contains PUSHDATA's
t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN;
- BOOST_CHECK(!IsStandardTx(t, reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
// TX_NULL_DATA w/o PUSHDATA
t.vout.resize(1);
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
- BOOST_CHECK(IsStandardTx(t, reason));
+ BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
// Only one TX_NULL_DATA permitted in all cases
t.vout.resize(2);
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
- BOOST_CHECK(!IsStandardTx(t, reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
t.vout[1].scriptPubKey = CScript() << OP_RETURN;
- BOOST_CHECK(!IsStandardTx(t, reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
t.vout[1].scriptPubKey = CScript() << OP_RETURN;
- BOOST_CHECK(!IsStandardTx(t, reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
index be7ee2428b..19561d4f67 100644
--- a/src/test/txindex_tests.cpp
+++ b/src/test/txindex_tests.cpp
@@ -1,12 +1,13 @@
-// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <chainparams.h>
#include <index/txindex.h>
#include <script/standard.h>
-#include <test/test_bitcoin.h>
-#include <util.h>
-#include <utiltime.h>
+#include <test/setup_common.h>
+#include <util/system.h>
+#include <util/time.h>
#include <validation.h>
#include <boost/test/unit_test.hpp>
@@ -38,6 +39,12 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
MilliSleep(100);
}
+ // Check that txindex excludes genesis block transactions.
+ const CBlock& genesis_block = Params().GenesisBlock();
+ for (const auto& txn : genesis_block.vtx) {
+ BOOST_CHECK(!txindex.FindTx(txn->GetHash(), block_hash, tx_disk));
+ }
+
// Check that txindex has all txs that were in the chain before it started.
for (const auto& txn : m_coinbase_txns) {
if (!txindex.FindTx(txn->GetHash(), block_hash, tx_disk)) {
@@ -49,7 +56,7 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
// Check that new transactions in new blocks make it into the index.
for (int i = 0; i < 10; i++) {
- CScript coinbase_script_pub_key = GetScriptForDestination(coinbaseKey.GetPubKey().GetID());
+ CScript coinbase_script_pub_key = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));
std::vector<CMutableTransaction> no_txns;
const CBlock& block = CreateAndProcessBlock(no_txns, coinbase_script_pub_key);
const CTransaction& txn = *block.vtx[0];
@@ -61,6 +68,14 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
BOOST_ERROR("Read incorrect tx");
}
}
+
+ // shutdown sequence (c.f. Shutdown() in init.cpp)
+ txindex.Stop();
+
+ threadGroup.interrupt_all();
+ threadGroup.join_all();
+
+ // Rest of shutdown sequence and destructors happen in ~TestingSetup()
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp
index 2d1eb7b772..26ae7be202 100644
--- a/src/test/txvalidation_tests.cpp
+++ b/src/test/txvalidation_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <consensus/validation.h>
#include <primitives/transaction.h>
#include <script/script.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
@@ -30,7 +30,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
coinbaseTx.vout[0].nValue = 1 * CENT;
coinbaseTx.vout[0].scriptPubKey = scriptPubKey;
- assert(CTransaction(coinbaseTx).IsCoinBase());
+ BOOST_CHECK(CTransaction(coinbaseTx).IsCoinBase());
CValidationState state;
@@ -52,10 +52,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
// Check that the validation state reflects the unsuccessful attempt.
BOOST_CHECK(state.IsInvalid());
BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase");
-
- int nDoS;
- BOOST_CHECK_EQUAL(state.IsInvalid(nDoS), true);
- BOOST_CHECK_EQUAL(nDoS, 100);
+ BOOST_CHECK(state.GetReason() == ValidationInvalidReason::CONSENSUS);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index d32d4b267c..fe30d5f3a7 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,8 +11,8 @@
#include <random.h>
#include <script/standard.h>
#include <script/sign.h>
-#include <test/test_bitcoin.h>
-#include <utiltime.h>
+#include <test/setup_common.h>
+#include <util/time.h>
#include <core_io.h>
#include <keystore.h>
#include <policy/policy.h>
@@ -66,18 +66,27 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
// Test 1: block with both of those transactions should be rejected.
block = CreateAndProcessBlock(spends, scriptPubKey);
- BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash());
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ }
// Test 2: ... and should be rejected if spend1 is in the memory pool
BOOST_CHECK(ToMemPool(spends[0]));
block = CreateAndProcessBlock(spends, scriptPubKey);
- BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash());
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ }
mempool.clear();
// Test 3: ... and should be rejected if spend2 is in the memory pool
BOOST_CHECK(ToMemPool(spends[1]));
block = CreateAndProcessBlock(spends, scriptPubKey);
- BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash());
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
+ }
mempool.clear();
// Final sanity test: first spend in mempool, second in block, that's OK:
@@ -85,7 +94,10 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
oneSpend.push_back(spends[0]);
BOOST_CHECK(ToMemPool(spends[1]));
block = CreateAndProcessBlock(oneSpend, scriptPubKey);
- BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash());
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() == block.GetHash());
+ }
// spends[1] should have been removed from the mempool when the
// block with spends[0] is accepted:
BOOST_CHECK_EQUAL(mempool.size(), 0U);
@@ -102,7 +114,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
// 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)
+static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
PrecomputedTransactionData txdata(tx);
// If we add many more flags, this loop can get too expensive, but we can
@@ -151,13 +163,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
}
CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
- CScript p2sh_scriptPubKey = GetScriptForDestination(CScriptID(p2pk_scriptPubKey));
- CScript p2pkh_scriptPubKey = GetScriptForDestination(coinbaseKey.GetPubKey().GetID());
+ CScript p2sh_scriptPubKey = GetScriptForDestination(ScriptHash(p2pk_scriptPubKey));
+ CScript p2pkh_scriptPubKey = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));
CScript p2wpkh_scriptPubKey = GetScriptForWitness(p2pkh_scriptPubKey);
CBasicKeyStore keystore;
- keystore.AddKey(coinbaseKey);
- keystore.AddCScript(p2pk_scriptPubKey);
+ BOOST_CHECK(keystore.AddKey(coinbaseKey));
+ BOOST_CHECK(keystore.AddCScript(p2pk_scriptPubKey));
// flags to test: SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, SCRIPT_VERIFY_CHECKSEQUENCE_VERIFY, SCRIPT_VERIFY_NULLDUMMY, uncompressed pubkey thing
@@ -198,20 +210,20 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
CValidationState state;
PrecomputedTransactionData ptd_spend_tx(spend_tx);
- BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
+ BOOST_CHECK(!CheckInputs(CTransaction(spend_tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
// If we call again asking for scriptchecks (as happens in
// ConnectBlock), we should add a script check object for this -- we're
// not caching invalidity (if that changes, delete this test case).
std::vector<CScriptCheck> scriptchecks;
- BOOST_CHECK(CheckInputs(spend_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks));
+ BOOST_CHECK(CheckInputs(CTransaction(spend_tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks));
BOOST_CHECK_EQUAL(scriptchecks.size(), 1U);
// Test that CheckInputs returns true iff DERSIG-enforcing flags are
// not present. Don't add these checks to the cache, so that we can
// test later that block validation works fine in the absence of cached
// successes.
- ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false);
+ ValidateCheckInputsForAllFlags(CTransaction(spend_tx), SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false);
}
// And if we produce a block with this tx, it should be valid (DERSIG not
@@ -219,10 +231,9 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
CBlock block;
block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey);
- BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash());
- BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash());
-
LOCK(cs_main);
+ BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() == block.GetHash());
+ BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash());
// Test P2SH: construct a transaction that is valid without P2SH, and
// then test validity with P2SH.
@@ -238,7 +249,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
std::vector<unsigned char> vchSig2(p2pk_scriptPubKey.begin(), p2pk_scriptPubKey.end());
invalid_under_p2sh_tx.vin[0].scriptSig << vchSig2;
- ValidateCheckInputsForAllFlags(invalid_under_p2sh_tx, SCRIPT_VERIFY_P2SH, true);
+ ValidateCheckInputsForAllFlags(CTransaction(invalid_under_p2sh_tx), SCRIPT_VERIFY_P2SH, true);
}
// Test CHECKLOCKTIMEVERIFY
@@ -261,13 +272,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
vchSig.push_back((unsigned char)SIGHASH_ALL);
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
- ValidateCheckInputsForAllFlags(invalid_with_cltv_tx, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true);
+ ValidateCheckInputsForAllFlags(CTransaction(invalid_with_cltv_tx), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true);
// Make it valid, and check again
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
CValidationState state;
PrecomputedTransactionData txdata(invalid_with_cltv_tx);
- BOOST_CHECK(CheckInputs(invalid_with_cltv_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
+ BOOST_CHECK(CheckInputs(CTransaction(invalid_with_cltv_tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
}
// TEST CHECKSEQUENCEVERIFY
@@ -289,13 +300,13 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
vchSig.push_back((unsigned char)SIGHASH_ALL);
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
- ValidateCheckInputsForAllFlags(invalid_with_csv_tx, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true);
+ ValidateCheckInputsForAllFlags(CTransaction(invalid_with_csv_tx), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true);
// Make it valid, and check again
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
CValidationState state;
PrecomputedTransactionData txdata(invalid_with_csv_tx);
- BOOST_CHECK(CheckInputs(invalid_with_csv_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
+ BOOST_CHECK(CheckInputs(CTransaction(invalid_with_csv_tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
}
// TODO: add tests for remaining script flags
@@ -314,15 +325,15 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Sign
SignatureData sigdata;
- ProduceSignature(keystore, MutableTransactionSignatureCreator(&valid_with_witness_tx, 0, 11*CENT, SIGHASH_ALL), spend_tx.vout[1].scriptPubKey, sigdata);
+ BOOST_CHECK(ProduceSignature(keystore, MutableTransactionSignatureCreator(&valid_with_witness_tx, 0, 11*CENT, SIGHASH_ALL), spend_tx.vout[1].scriptPubKey, sigdata));
UpdateInput(valid_with_witness_tx.vin[0], sigdata);
// This should be valid under all script flags.
- ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true);
+ ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), 0, true);
// Remove the witness, and check that it is now invalid.
valid_with_witness_tx.vin[0].scriptWitness.SetNull();
- ValidateCheckInputsForAllFlags(valid_with_witness_tx, SCRIPT_VERIFY_WITNESS, true);
+ ValidateCheckInputsForAllFlags(CTransaction(valid_with_witness_tx), SCRIPT_VERIFY_WITNESS, true);
}
{
@@ -342,12 +353,12 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Sign
for (int i=0; i<2; ++i) {
SignatureData sigdata;
- ProduceSignature(keystore, MutableTransactionSignatureCreator(&tx, i, 11*CENT, SIGHASH_ALL), spend_tx.vout[i].scriptPubKey, sigdata);
+ BOOST_CHECK(ProduceSignature(keystore, MutableTransactionSignatureCreator(&tx, i, 11*CENT, SIGHASH_ALL), spend_tx.vout[i].scriptPubKey, sigdata));
UpdateInput(tx.vin[i], sigdata);
}
// This should be valid under all script flags
- ValidateCheckInputsForAllFlags(tx, 0, true);
+ ValidateCheckInputsForAllFlags(CTransaction(tx), 0, true);
// Check that if the second input is invalid, but the first input is
// valid, the transaction is not cached.
@@ -357,12 +368,12 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
CValidationState state;
PrecomputedTransactionData txdata(tx);
// This transaction is now invalid under segwit, because of the second input.
- BOOST_CHECK(!CheckInputs(tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
+ BOOST_CHECK(!CheckInputs(CTransaction(tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
std::vector<CScriptCheck> scriptchecks;
// Make sure this transaction was not cached (ie because the first
// input was valid)
- BOOST_CHECK(CheckInputs(tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks));
+ BOOST_CHECK(CheckInputs(CTransaction(tx), state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks));
// Should get 2 script checks back -- caching is on a whole-transaction basis.
BOOST_CHECK_EQUAL(scriptchecks.size(), 2U);
}
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
index 79217fa430..c1749fb856 100644
--- a/src/test/uint256_tests.cpp
+++ b/src/test/uint256_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <arith_uint256.h>
#include <uint256.h>
#include <version.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <stdint.h>
@@ -184,8 +184,8 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G
BOOST_CHECK(OneL.begin() + 32 == OneL.end());
BOOST_CHECK(MaxL.begin() + 32 == MaxL.end());
BOOST_CHECK(TmpL.begin() + 32 == TmpL.end());
- BOOST_CHECK(GetSerializeSize(R1L, 0, PROTOCOL_VERSION) == 32);
- BOOST_CHECK(GetSerializeSize(ZeroL, 0, PROTOCOL_VERSION) == 32);
+ BOOST_CHECK(GetSerializeSize(R1L, PROTOCOL_VERSION) == 32);
+ BOOST_CHECK(GetSerializeSize(ZeroL, PROTOCOL_VERSION) == 32);
CDataStream ss(0, PROTOCOL_VERSION);
ss << R1L;
@@ -230,8 +230,8 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G
BOOST_CHECK(OneS.begin() + 20 == OneS.end());
BOOST_CHECK(MaxS.begin() + 20 == MaxS.end());
BOOST_CHECK(TmpS.begin() + 20 == TmpS.end());
- BOOST_CHECK(GetSerializeSize(R1S, 0, PROTOCOL_VERSION) == 20);
- BOOST_CHECK(GetSerializeSize(ZeroS, 0, PROTOCOL_VERSION) == 20);
+ BOOST_CHECK(GetSerializeSize(R1S, PROTOCOL_VERSION) == 20);
+ BOOST_CHECK(GetSerializeSize(ZeroS, PROTOCOL_VERSION) == 20);
ss << R1S;
BOOST_CHECK(ss.str() == std::string(R1Array,R1Array+20));
diff --git a/src/test/util.cpp b/src/test/util.cpp
new file mode 100644
index 0000000000..64ecc6623a
--- /dev/null
+++ b/src/test/util.cpp
@@ -0,0 +1,92 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/util.h>
+
+#include <chainparams.h>
+#include <consensus/merkle.h>
+#include <consensus/validation.h>
+#include <key_io.h>
+#include <miner.h>
+#include <outputtype.h>
+#include <pow.h>
+#include <scheduler.h>
+#include <script/standard.h>
+#include <txdb.h>
+#include <validation.h>
+#include <validationinterface.h>
+#ifdef ENABLE_WALLET
+#include <wallet/wallet.h>
+#endif
+
+#include <boost/thread.hpp>
+
+const std::string ADDRESS_BCRT1_UNSPENDABLE = "bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj";
+
+#ifdef ENABLE_WALLET
+std::string getnewaddress(CWallet& w)
+{
+ constexpr auto output_type = OutputType::BECH32;
+
+ CPubKey new_key;
+ if (!w.GetKeyFromPool(new_key)) assert(false);
+
+ w.LearnRelatedScripts(new_key, output_type);
+ const auto dest = GetDestinationForKey(new_key, output_type);
+
+ w.SetAddressBook(dest, /* label */ "", "receive");
+
+ return EncodeDestination(dest);
+}
+
+void importaddress(CWallet& wallet, const std::string& address)
+{
+ LOCK(wallet.cs_wallet);
+ const auto dest = DecodeDestination(address);
+ assert(IsValidDestination(dest));
+ const auto script = GetScriptForDestination(dest);
+ wallet.MarkDirty();
+ assert(!wallet.HaveWatchOnly(script));
+ if (!wallet.AddWatchOnly(script, 0 /* nCreateTime */)) assert(false);
+ wallet.SetAddressBook(dest, /* label */ "", "receive");
+}
+#endif // ENABLE_WALLET
+
+CTxIn generatetoaddress(const std::string& address)
+{
+ const auto dest = DecodeDestination(address);
+ assert(IsValidDestination(dest));
+ const auto coinbase_script = GetScriptForDestination(dest);
+
+ return MineBlock(coinbase_script);
+}
+
+CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = PrepareBlock(coinbase_scriptPubKey);
+
+ while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
+ ++block->nNonce;
+ assert(block->nNonce);
+ }
+
+ bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
+ assert(processed);
+
+ return CTxIn{block->vtx[0]->GetHash(), 0};
+}
+
+std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
+{
+ auto block = std::make_shared<CBlock>(
+ BlockAssembler{Params()}
+ .CreateNewBlock(coinbase_scriptPubKey)
+ ->block);
+
+ LOCK(cs_main);
+ block->nTime = ::ChainActive().Tip()->GetMedianTimePast() + 1;
+ block->hashMerkleRoot = BlockMerkleRoot(*block);
+
+ return block;
+}
diff --git a/src/test/util.h b/src/test/util.h
new file mode 100644
index 0000000000..f90cb0d623
--- /dev/null
+++ b/src/test/util.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_UTIL_H
+#define BITCOIN_TEST_UTIL_H
+
+#include <memory>
+#include <string>
+
+class CBlock;
+class CScript;
+class CTxIn;
+class CWallet;
+
+// Constants //
+
+extern const std::string ADDRESS_BCRT1_UNSPENDABLE;
+
+// Lower-level utils //
+
+/** Returns the generated coin */
+CTxIn MineBlock(const CScript& coinbase_scriptPubKey);
+/** Prepare a block to be mined */
+std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey);
+
+
+// RPC-like //
+
+/** Import the address to the wallet */
+void importaddress(CWallet& wallet, const std::string& address);
+/** Returns a new address from the wallet */
+std::string getnewaddress(CWallet& w);
+/** Returns the generated coin */
+CTxIn generatetoaddress(const std::string& address);
+
+/**
+ * Increment a string. Useful to enumerate all fixed length strings with
+ * characters in [min_char, max_char].
+ */
+template <typename CharType, size_t StringLength>
+bool NextString(CharType (&string)[StringLength], CharType min_char, CharType max_char)
+{
+ for (CharType& elem : string) {
+ bool has_next = elem != max_char;
+ elem = elem < min_char || elem >= max_char ? min_char : CharType(elem + 1);
+ if (has_next) return true;
+ }
+ return false;
+}
+
+/**
+ * Iterate over string values and call function for each string without
+ * successive duplicate characters.
+ */
+template <typename CharType, size_t StringLength, typename Fn>
+void ForEachNoDup(CharType (&string)[StringLength], CharType min_char, CharType max_char, Fn&& fn) {
+ for (bool has_next = true; has_next; has_next = NextString(string, min_char, max_char)) {
+ int prev = -1;
+ bool skip_string = false;
+ for (CharType c : string) {
+ if (c == prev) skip_string = true;
+ if (skip_string || c < min_char || c > max_char) break;
+ prev = c;
+ }
+ if (!skip_string) fn();
+ }
+}
+
+#endif // BITCOIN_TEST_UTIL_H
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 3661c762fc..51dd25ed1c 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1,15 +1,16 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
+#include <util/system.h>
#include <clientversion.h>
#include <primitives/transaction.h>
#include <sync.h>
-#include <utilstrencodings.h>
-#include <utilmoneystr.h>
-#include <test/test_bitcoin.h>
+#include <test/util.h>
+#include <util/strencodings.h>
+#include <util/moneystr.h>
+#include <test/setup_common.h>
#include <stdint.h>
#include <vector>
@@ -36,8 +37,10 @@ BOOST_AUTO_TEST_CASE(util_criticalsection)
do {
TRY_LOCK(cs, lockTest);
- if (lockTest)
+ if (lockTest) {
+ BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
break;
+ }
BOOST_ERROR("break was swallowed!");
} while(0);
@@ -78,80 +81,40 @@ BOOST_AUTO_TEST_CASE(util_HexStr)
"04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
BOOST_CHECK_EQUAL(
- HexStr(ParseHex_expected, ParseHex_expected + 5, true),
- "04 67 8a fd b0");
-
- BOOST_CHECK_EQUAL(
HexStr(ParseHex_expected + sizeof(ParseHex_expected),
ParseHex_expected + sizeof(ParseHex_expected)),
"");
BOOST_CHECK_EQUAL(
- HexStr(ParseHex_expected + sizeof(ParseHex_expected),
- ParseHex_expected + sizeof(ParseHex_expected), true),
- "");
-
- BOOST_CHECK_EQUAL(
HexStr(ParseHex_expected, ParseHex_expected),
"");
- BOOST_CHECK_EQUAL(
- HexStr(ParseHex_expected, ParseHex_expected, true),
- "");
-
std::vector<unsigned char> ParseHex_vec(ParseHex_expected, ParseHex_expected + 5);
BOOST_CHECK_EQUAL(
- HexStr(ParseHex_vec, true),
- "04 67 8a fd b0");
-
- BOOST_CHECK_EQUAL(
HexStr(ParseHex_vec.rbegin(), ParseHex_vec.rend()),
"b0fd8a6704"
);
BOOST_CHECK_EQUAL(
- HexStr(ParseHex_vec.rbegin(), ParseHex_vec.rend(), true),
- "b0 fd 8a 67 04"
- );
-
- BOOST_CHECK_EQUAL(
HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected),
std::reverse_iterator<const uint8_t *>(ParseHex_expected)),
""
);
BOOST_CHECK_EQUAL(
- HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected),
- std::reverse_iterator<const uint8_t *>(ParseHex_expected), true),
- ""
- );
-
- BOOST_CHECK_EQUAL(
HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 1),
std::reverse_iterator<const uint8_t *>(ParseHex_expected)),
"04"
);
BOOST_CHECK_EQUAL(
- HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 1),
- std::reverse_iterator<const uint8_t *>(ParseHex_expected), true),
- "04"
- );
-
- BOOST_CHECK_EQUAL(
HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 5),
std::reverse_iterator<const uint8_t *>(ParseHex_expected)),
"b0fd8a6704"
);
BOOST_CHECK_EQUAL(
- HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 5),
- std::reverse_iterator<const uint8_t *>(ParseHex_expected), true),
- "b0 fd 8a 67 04"
- );
-
- BOOST_CHECK_EQUAL(
HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 65),
std::reverse_iterator<const uint8_t *>(ParseHex_expected)),
"5f1df16b2b704c8a578d0bbaf74d385cde12c11ee50455f3c438ef4c3fbcf649b6de611feae06279a60939e028a8d65c10b73071a6f16719274855feb0fd8a6704"
@@ -169,11 +132,6 @@ BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
}
-BOOST_AUTO_TEST_CASE(util_FormatISO8601Time)
-{
- BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z");
-}
-
struct TestArgsManager : public ArgsManager
{
TestArgsManager() { m_network_only_args.clear(); }
@@ -185,9 +143,10 @@ struct TestArgsManager : public ArgsManager
{
LOCK(cs_args);
m_config_args.clear();
+ m_config_sections.clear();
}
std::string error;
- ReadConfigStream(streamConfig, error);
+ BOOST_REQUIRE(ReadConfigStream(streamConfig, "", error));
}
void SetNetworkOnlyArg(const std::string arg)
{
@@ -200,6 +159,9 @@ struct TestArgsManager : public ArgsManager
AddArg(args[i], "", false, OptionsCategory::OPTIONS);
}
}
+ using ArgsManager::ReadConfigStream;
+ using ArgsManager::cs_args;
+ using ArgsManager::m_network;
};
BOOST_AUTO_TEST_CASE(util_ParseParameters)
@@ -210,13 +172,13 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters)
std::string error;
testArgs.SetupArgs(4, avail_args);
- testArgs.ParseParameters(0, (char**)argv_test, error);
+ BOOST_CHECK(testArgs.ParseParameters(0, (char**)argv_test, error));
BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
- testArgs.ParseParameters(1, (char**)argv_test, error);
+ BOOST_CHECK(testArgs.ParseParameters(1, (char**)argv_test, error));
BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
- testArgs.ParseParameters(7, (char**)argv_test, error);
+ BOOST_CHECK(testArgs.ParseParameters(7, (char**)argv_test, error));
// expectation: -ignored is ignored (program name argument),
// -a, -b and -ccc end up in map, -d ignored because it is after
// a non-option argument (non-GNU option parsing)
@@ -242,10 +204,10 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArg)
"ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
std::string error;
testArgs.SetupArgs(6, avail_args);
- testArgs.ParseParameters(7, (char**)argv_test, error);
+ BOOST_CHECK(testArgs.ParseParameters(7, (char**)argv_test, error));
// Each letter should be set.
- for (char opt : "abcdef")
+ for (const char opt : "abcdef")
BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt);
// Nothing else should be in the map
@@ -278,7 +240,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
testArgs.SetupArgs(2, avail_args);
std::string error;
- testArgs.ParseParameters(4, (char**)argv_test, error);
+ BOOST_CHECK(testArgs.ParseParameters(4, (char**)argv_test, error));
// This was passed twice, second one overrides the negative setting.
BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
@@ -290,7 +252,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
// Config test
const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
- testArgs.ParseParameters(1, (char**)argv_test, error);
+ BOOST_CHECK(testArgs.ParseParameters(1, (char**)argv_test, error));
testArgs.ReadConfigString(conf_test);
// This was passed twice, second one overrides the negative setting,
@@ -305,7 +267,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
// Combined test
const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
const char *combo_test_conf = "foo=1\nnobar=1\n";
- testArgs.ParseParameters(3, (char**)combo_test_args, error);
+ BOOST_CHECK(testArgs.ParseParameters(3, (char**)combo_test_args, error));
testArgs.ReadConfigString(combo_test_conf);
// Command line overrides, but doesn't erase old setting
@@ -394,7 +356,7 @@ BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
&& test_args.GetArg("-iii", "xxx") == "xxx"
);
- for (bool def : {false, true}) {
+ for (const bool def : {false, true}) {
BOOST_CHECK(test_args.GetBoolArg("-a", def)
&& test_args.GetBoolArg("-b", def)
&& !test_args.GetBoolArg("-ccc", def)
@@ -557,38 +519,38 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
const char* testnetconf = "testnet=1\nregtest=0\n[test]\nregtest=1";
std::string error;
- test_args.ParseParameters(0, (char**)argv_testnet, error);
+ BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
- test_args.ParseParameters(2, (char**)argv_testnet, error);
+ BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_regtest, error);
+ BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
- test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
+ BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error));
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(3, (char**)argv_both, error);
+ BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
- test_args.ParseParameters(0, (char**)argv_testnet, error);
+ BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_testnet, error);
+ BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_regtest, error);
+ BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
- test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
+ BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(3, (char**)argv_both, error);
+ BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
@@ -596,27 +558,327 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
// [test] regtest=1 potentially relevant) doesn't break things
test_args.SelectConfigNetwork("test");
- test_args.ParseParameters(0, (char**)argv_testnet, error);
+ BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_testnet, error);
+ BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_regtest, error);
+ BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
- test_args.ParseParameters(2, (char**)argv_test_no_reg, error);
+ BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_test_no_reg, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(3, (char**)argv_both, error);
+ BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
}
+// Test different ways settings can be merged, and verify results. This test can
+// be used to confirm that updates to settings code don't change behavior
+// unintentionally.
+//
+// The test covers:
+//
+// - Combining different setting actions. Possible actions are: configuring a
+// setting, negating a setting (adding "-no" prefix), and configuring/negating
+// settings in a network section (adding "main." or "test." prefixes).
+//
+// - Combining settings from command line arguments and a config file.
+//
+// - Combining SoftSet and ForceSet calls.
+//
+// - Testing "main" and "test" network values to make sure settings from network
+// sections are applied and to check for mainnet-specific behaviors like
+// inheriting settings from the default section.
+//
+// - Testing network-specific settings like "-wallet", that may be ignored
+// outside a network section, and non-network specific settings like "-server"
+// that aren't sensitive to the network.
+//
+struct ArgsMergeTestingSetup : public BasicTestingSetup {
+ //! Max number of actions to sequence together. Can decrease this when
+ //! debugging to make test results easier to understand.
+ static constexpr int MAX_ACTIONS = 3;
+
+ enum Action { NONE, SET, NEGATE, SECTION_SET, SECTION_NEGATE };
+ using ActionList = Action[MAX_ACTIONS];
+
+ //! Enumerate all possible test configurations.
+ template <typename Fn>
+ void ForEachMergeSetup(Fn&& fn)
+ {
+ ActionList arg_actions = {};
+ ForEachNoDup(arg_actions, SET, SECTION_NEGATE, [&] {
+ ActionList conf_actions = {};
+ ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] {
+ for (bool soft_set : {false, true}) {
+ for (bool force_set : {false, true}) {
+ for (const std::string& section : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET}) {
+ for (const std::string& network : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET}) {
+ for (bool net_specific : {false, true}) {
+ fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);
+ }
+ }
+ }
+ }
+ }
+ });
+ });
+ }
+
+ //! Translate actions into a list of <key>=<value> setting strings.
+ std::vector<std::string> GetValues(const ActionList& actions,
+ const std::string& section,
+ const std::string& name,
+ const std::string& value_prefix)
+ {
+ std::vector<std::string> values;
+ int suffix = 0;
+ for (Action action : actions) {
+ if (action == NONE) break;
+ std::string prefix;
+ if (action == SECTION_SET || action == SECTION_NEGATE) prefix = section + ".";
+ if (action == SET || action == SECTION_SET) {
+ for (int i = 0; i < 2; ++i) {
+ values.push_back(prefix + name + "=" + value_prefix + std::to_string(++suffix));
+ }
+ }
+ if (action == NEGATE || action == SECTION_NEGATE) {
+ values.push_back(prefix + "no" + name + "=1");
+ }
+ }
+ return values;
+ }
+};
+
+// Regression test covering different ways config settings can be merged. The
+// test parses and merges settings, representing the results as strings that get
+// compared against an expected hash. To debug, the result strings can be dumped
+// to a file (see comments below).
+BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup)
+{
+ CHash256 out_sha;
+ FILE* out_file = nullptr;
+ if (const char* out_path = getenv("ARGS_MERGE_TEST_OUT")) {
+ out_file = fsbridge::fopen(out_path, "w");
+ if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
+ }
+
+ ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions, bool soft_set, bool force_set,
+ const std::string& section, const std::string& network, bool net_specific) {
+ TestArgsManager parser;
+ LOCK(parser.cs_args);
+
+ std::string desc = "net=";
+ desc += network;
+ parser.m_network = network;
+
+ const std::string& name = net_specific ? "wallet" : "server";
+ const std::string key = "-" + name;
+ parser.AddArg(key, name, false, OptionsCategory::OPTIONS);
+ if (net_specific) parser.SetNetworkOnlyArg(key);
+
+ auto args = GetValues(arg_actions, section, name, "a");
+ std::vector<const char*> argv = {"ignored"};
+ for (auto& arg : args) {
+ arg.insert(0, "-");
+ desc += " ";
+ desc += arg;
+ argv.push_back(arg.c_str());
+ }
+ std::string error;
+ BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));
+ BOOST_CHECK_EQUAL(error, "");
+
+ std::string conf;
+ for (auto& conf_val : GetValues(conf_actions, section, name, "c")) {
+ desc += " ";
+ desc += conf_val;
+ conf += conf_val;
+ conf += "\n";
+ }
+ std::istringstream conf_stream(conf);
+ BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));
+ BOOST_CHECK_EQUAL(error, "");
+
+ if (soft_set) {
+ desc += " soft";
+ parser.SoftSetArg(key, "soft1");
+ parser.SoftSetArg(key, "soft2");
+ }
+
+ if (force_set) {
+ desc += " force";
+ parser.ForceSetArg(key, "force1");
+ parser.ForceSetArg(key, "force2");
+ }
+
+ desc += " || ";
+
+ if (!parser.IsArgSet(key)) {
+ desc += "unset";
+ BOOST_CHECK(!parser.IsArgNegated(key));
+ BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "default");
+ BOOST_CHECK(parser.GetArgs(key).empty());
+ } else if (parser.IsArgNegated(key)) {
+ desc += "negated";
+ BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "0");
+ BOOST_CHECK(parser.GetArgs(key).empty());
+ } else {
+ desc += parser.GetArg(key, "default");
+ desc += " |";
+ for (const auto& arg : parser.GetArgs(key)) {
+ desc += " ";
+ desc += arg;
+ }
+ }
+
+ std::set<std::string> ignored = parser.GetUnsuitableSectionOnlyArgs();
+ if (!ignored.empty()) {
+ desc += " | ignored";
+ for (const auto& arg : ignored) {
+ desc += " ";
+ desc += arg;
+ }
+ }
+
+ desc += "\n";
+
+ out_sha.Write((const unsigned char*)desc.data(), desc.size());
+ if (out_file) {
+ BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
+ }
+ });
+
+ if (out_file) {
+ if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");
+ out_file = nullptr;
+ }
+
+ unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];
+ out_sha.Finalize(out_sha_bytes);
+ std::string out_sha_hex = HexStr(std::begin(out_sha_bytes), std::end(out_sha_bytes));
+
+ // If check below fails, should manually dump the results with:
+ //
+ // ARGS_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=util_tests/util_ArgsMerge
+ //
+ // And verify diff against previous results to make sure the changes are expected.
+ //
+ // Results file is formatted like:
+ //
+ // <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output>
+ BOOST_CHECK_EQUAL(out_sha_hex, "b835eef5977d69114eb039a976201f8c7121f34fe2b7ea2b73cafb516e5c9dc8");
+}
+
+// Similar test as above, but for ArgsManager::GetChainName function.
+struct ChainMergeTestingSetup : public BasicTestingSetup {
+ static constexpr int MAX_ACTIONS = 2;
+
+ enum Action { NONE, ENABLE_TEST, DISABLE_TEST, NEGATE_TEST, ENABLE_REG, DISABLE_REG, NEGATE_REG };
+ using ActionList = Action[MAX_ACTIONS];
+
+ //! Enumerate all possible test configurations.
+ template <typename Fn>
+ void ForEachMergeSetup(Fn&& fn)
+ {
+ ActionList arg_actions = {};
+ ForEachNoDup(arg_actions, ENABLE_TEST, NEGATE_REG, [&] {
+ ActionList conf_actions = {};
+ ForEachNoDup(conf_actions, ENABLE_TEST, NEGATE_REG, [&] { fn(arg_actions, conf_actions); });
+ });
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup)
+{
+ CHash256 out_sha;
+ FILE* out_file = nullptr;
+ if (const char* out_path = getenv("CHAIN_MERGE_TEST_OUT")) {
+ out_file = fsbridge::fopen(out_path, "w");
+ if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
+ }
+
+ ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions) {
+ TestArgsManager parser;
+ LOCK(parser.cs_args);
+ parser.AddArg("-regtest", "regtest", false, OptionsCategory::OPTIONS);
+ parser.AddArg("-testnet", "testnet", false, OptionsCategory::OPTIONS);
+
+ auto arg = [](Action action) { return action == ENABLE_TEST ? "-testnet=1" :
+ action == DISABLE_TEST ? "-testnet=0" :
+ action == NEGATE_TEST ? "-notestnet=1" :
+ action == ENABLE_REG ? "-regtest=1" :
+ action == DISABLE_REG ? "-regtest=0" :
+ action == NEGATE_REG ? "-noregtest=1" : nullptr; };
+
+ std::string desc;
+ std::vector<const char*> argv = {"ignored"};
+ for (Action action : arg_actions) {
+ const char* argstr = arg(action);
+ if (!argstr) break;
+ argv.push_back(argstr);
+ desc += " ";
+ desc += argv.back();
+ }
+ std::string error;
+ BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));
+ BOOST_CHECK_EQUAL(error, "");
+
+ std::string conf;
+ for (Action action : conf_actions) {
+ const char* argstr = arg(action);
+ if (!argstr) break;
+ desc += " ";
+ desc += argstr + 1;
+ conf += argstr + 1;
+ }
+ std::istringstream conf_stream(conf);
+ BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));
+ BOOST_CHECK_EQUAL(error, "");
+
+ desc += " || ";
+ try {
+ desc += parser.GetChainName();
+ } catch (const std::runtime_error& e) {
+ desc += "error: ";
+ desc += e.what();
+ }
+ desc += "\n";
+
+ out_sha.Write((const unsigned char*)desc.data(), desc.size());
+ if (out_file) {
+ BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
+ }
+ });
+
+ if (out_file) {
+ if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");
+ out_file = nullptr;
+ }
+
+ unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];
+ out_sha.Finalize(out_sha_bytes);
+ std::string out_sha_hex = HexStr(std::begin(out_sha_bytes), std::end(out_sha_bytes));
+
+ // If check below fails, should manually dump the results with:
+ //
+ // CHAIN_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=util_tests/util_ChainMerge
+ //
+ // And verify diff against previous results to make sure the changes are expected.
+ //
+ // Results file is formatted like:
+ //
+ // <input> || <output>
+ BOOST_CHECK_EQUAL(out_sha_hex, "b284f4b4a15dd6bf8c06213a69a004b1960388e1d9917173927db52ac220927f");
+}
+
BOOST_AUTO_TEST_CASE(util_FormatMoney)
{
BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
@@ -1217,4 +1479,43 @@ BOOST_AUTO_TEST_CASE(test_DirIsWritable)
fs::remove(tmpdirname);
}
+BOOST_AUTO_TEST_CASE(test_ToLower)
+{
+ BOOST_CHECK_EQUAL(ToLower('@'), '@');
+ BOOST_CHECK_EQUAL(ToLower('A'), 'a');
+ BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
+ BOOST_CHECK_EQUAL(ToLower('['), '[');
+ BOOST_CHECK_EQUAL(ToLower(0), 0);
+ BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');
+
+ std::string testVector;
+ Downcase(testVector);
+ BOOST_CHECK_EQUAL(testVector, "");
+
+ testVector = "#HODL";
+ Downcase(testVector);
+ BOOST_CHECK_EQUAL(testVector, "#hodl");
+
+ testVector = "\x00\xfe\xff";
+ Downcase(testVector);
+ BOOST_CHECK_EQUAL(testVector, "\x00\xfe\xff");
+}
+
+BOOST_AUTO_TEST_CASE(test_ToUpper)
+{
+ BOOST_CHECK_EQUAL(ToUpper('`'), '`');
+ BOOST_CHECK_EQUAL(ToUpper('a'), 'A');
+ BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
+ BOOST_CHECK_EQUAL(ToUpper('{'), '{');
+ BOOST_CHECK_EQUAL(ToUpper(0), 0);
+ BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');
+}
+
+BOOST_AUTO_TEST_CASE(test_Capitalize)
+{
+ BOOST_CHECK_EQUAL(Capitalize(""), "");
+ BOOST_CHECK_EQUAL(Capitalize("bitcoin"), "Bitcoin");
+ BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_threadnames_tests.cpp b/src/test/util_threadnames_tests.cpp
new file mode 100644
index 0000000000..71c0168ca3
--- /dev/null
+++ b/src/test/util_threadnames_tests.cpp
@@ -0,0 +1,73 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/threadnames.h>
+#include <test/setup_common.h>
+
+#include <thread>
+#include <vector>
+#include <set>
+#include <mutex>
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(util_threadnames_tests, BasicTestingSetup)
+
+const std::string TEST_THREAD_NAME_BASE = "test_thread.";
+
+/**
+ * Run a bunch of threads to all call util::ThreadRename.
+ *
+ * @return the set of name each thread has after attempted renaming.
+ */
+std::set<std::string> RenameEnMasse(int num_threads)
+{
+ std::vector<std::thread> threads;
+ std::set<std::string> names;
+ std::mutex lock;
+
+ auto RenameThisThread = [&](int i) {
+ util::ThreadRename(TEST_THREAD_NAME_BASE + std::to_string(i));
+ std::lock_guard<std::mutex> guard(lock);
+ names.insert(util::ThreadGetInternalName());
+ };
+
+ for (int i = 0; i < num_threads; ++i) {
+ threads.push_back(std::thread(RenameThisThread, i));
+ }
+
+ for (std::thread& thread : threads) thread.join();
+
+ return names;
+}
+
+/**
+ * Rename a bunch of threads with the same basename (expect_multiple=true), ensuring suffixes are
+ * applied properly.
+ */
+BOOST_AUTO_TEST_CASE(util_threadnames_test_rename_threaded)
+{
+ BOOST_CHECK_EQUAL(util::ThreadGetInternalName(), "");
+
+#if !defined(HAVE_THREAD_LOCAL)
+ // This test doesn't apply to platforms where we don't have thread_local.
+ return;
+#endif
+
+ std::set<std::string> names = RenameEnMasse(100);
+
+ BOOST_CHECK_EQUAL(names.size(), 100);
+
+ // Names "test_thread.[n]" should exist for n = [0, 99]
+ for (int i = 0; i < 100; ++i) {
+ BOOST_CHECK(names.find(TEST_THREAD_NAME_BASE + std::to_string(i)) != names.end());
+ }
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index 37c4f79133..5dee034b20 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
#include <miner.h>
#include <pow.h>
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <validation.h>
#include <validationinterface.h>
@@ -23,7 +23,7 @@ BOOST_FIXTURE_TEST_SUITE(validation_block_tests, RegtestingSetup)
struct TestSubscriber : public CValidationInterface {
uint256 m_expected_tip;
- TestSubscriber(uint256 tip) : m_expected_tip(tip) {}
+ explicit TestSubscriber(uint256 tip) : m_expected_tip(tip) {}
void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override
{
@@ -54,7 +54,7 @@ std::shared_ptr<CBlock> Block(const uint256& prev_hash)
CScript pubKey;
pubKey << i++ << OP_TRUE;
- auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey, false);
+ auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey);
auto pblock = std::make_shared<CBlock>(ptemplate->block);
pblock->hashPrevBlock = prev_hash;
pblock->nTime = ++time;
@@ -104,8 +104,8 @@ void BuildChain(const uint256& root, int height, const unsigned int invalid_rate
{
if (height <= 0 || blocks.size() >= max_size) return;
- bool gen_invalid = GetRand(100) < invalid_rate;
- bool gen_fork = GetRand(100) < branch_rate;
+ bool gen_invalid = InsecureRandRange(100) < invalid_rate;
+ bool gen_fork = InsecureRandRange(100) < branch_rate;
const std::shared_ptr<const CBlock> pblock = gen_invalid ? BadBlock(root) : GoodBlock(root);
blocks.push_back(pblock);
@@ -137,14 +137,14 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
BOOST_CHECK(ProcessNewBlockHeaders(headers, state, Params()));
// Connect the genesis block and drain any outstanding events
- ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored);
+ BOOST_CHECK(ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored));
SyncWithValidationInterfaceQueue();
// subscribe to events (this subscriber will validate event ordering)
const CBlockIndex* initial_tip = nullptr;
{
LOCK(cs_main);
- initial_tip = chainActive.Tip();
+ initial_tip = ::ChainActive().Tip();
}
TestSubscriber sub(initial_tip->GetBlockHash());
RegisterValidationInterface(&sub);
@@ -152,12 +152,13 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
// create a bunch of threads that repeatedly process a block generated above at random
// this will create parallelism and randomness inside validation - the ValidationInterface
// will subscribe to events generated during block validation and assert on ordering invariance
- boost::thread_group threads;
+ std::vector<std::thread> threads;
for (int i = 0; i < 10; i++) {
- threads.create_thread([&blocks]() {
+ threads.emplace_back([&blocks]() {
bool ignored;
+ FastRandomContext insecure;
for (int i = 0; i < 1000; i++) {
- auto block = blocks[GetRand(blocks.size() - 1)];
+ auto block = blocks[insecure.randrange(blocks.size() - 1)];
ProcessNewBlock(Params(), block, true, &ignored);
}
@@ -171,14 +172,17 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
});
}
- threads.join_all();
+ for (auto& t : threads) {
+ t.join();
+ }
while (GetMainSignals().CallbacksPending() > 0) {
MilliSleep(100);
}
UnregisterValidationInterface(&sub);
- BOOST_CHECK_EQUAL(sub.m_expected_tip, chainActive.Tip()->GetBlockHash());
+ LOCK(cs_main);
+ BOOST_CHECK_EQUAL(sub.m_expected_tip, ::ChainActive().Tip()->GetBlockHash());
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/main_tests.cpp b/src/test/validation_tests.cpp
index 8676a099da..101025d31e 100644
--- a/src/test/main_tests.cpp
+++ b/src/test/validation_tests.cpp
@@ -1,17 +1,17 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
-#include <validation.h>
#include <net.h>
+#include <validation.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <boost/signals2/signal.hpp>
#include <boost/test/unit_test.hpp>
-BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(validation_tests, TestingSetup)
static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams)
{
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 7442825300..38d91b6647 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -1,10 +1,10 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
#include <versionbits.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <chainparams.h>
#include <validation.h>
#include <consensus/params.h>
diff --git a/src/threadinterrupt.cpp b/src/threadinterrupt.cpp
index 7da4e136ef..340106ed99 100644
--- a/src/threadinterrupt.cpp
+++ b/src/threadinterrupt.cpp
@@ -1,10 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <threadinterrupt.h>
+#include <sync.h>
+
CThreadInterrupt::CThreadInterrupt() : flag(false) {}
CThreadInterrupt::operator bool() const
@@ -20,7 +22,7 @@ void CThreadInterrupt::reset()
void CThreadInterrupt::operator()()
{
{
- std::unique_lock<std::mutex> lock(mut);
+ LOCK(mut);
flag.store(true, std::memory_order_release);
}
cond.notify_all();
@@ -28,7 +30,7 @@ void CThreadInterrupt::operator()()
bool CThreadInterrupt::sleep_for(std::chrono::milliseconds rel_time)
{
- std::unique_lock<std::mutex> lock(mut);
+ WAIT_LOCK(mut, lock);
return !cond.wait_for(lock, rel_time, [this]() { return flag.load(std::memory_order_acquire); });
}
diff --git a/src/threadinterrupt.h b/src/threadinterrupt.h
index d373e3c371..2743571379 100644
--- a/src/threadinterrupt.h
+++ b/src/threadinterrupt.h
@@ -1,10 +1,12 @@
-// Copyright (c) 2016 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_THREADINTERRUPT_H
#define BITCOIN_THREADINTERRUPT_H
+#include <sync.h>
+
#include <atomic>
#include <chrono>
#include <condition_variable>
@@ -28,7 +30,7 @@ public:
private:
std::condition_variable cond;
- std::mutex mut;
+ Mutex mut;
std::atomic<bool> flag;
};
diff --git a/src/threadsafety.h b/src/threadsafety.h
index d847269dff..33acddc65c 100644
--- a/src/threadsafety.h
+++ b/src/threadsafety.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
// TL;DR Add GUARDED_BY(mutex) to member variables. The others are
// rarely necessary. Ex: int nFoo GUARDED_BY(cs_foo);
//
-// See http://clang.llvm.org/docs/LanguageExtensions.html#threadsafety
+// See https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
// for documentation. The clang compiler can do advanced static analysis
// of locking when given the -Wthread-safety option.
#define LOCKABLE __attribute__((lockable))
@@ -54,4 +54,15 @@
#define ASSERT_EXCLUSIVE_LOCK(...)
#endif // __GNUC__
+// Utility class for indicating to compiler thread analysis that a mutex is
+// locked (when it couldn't be determined otherwise).
+struct SCOPED_LOCKABLE LockAnnotation
+{
+ template <typename Mutex>
+ explicit LockAnnotation(Mutex& mutex) EXCLUSIVE_LOCK_FUNCTION(mutex)
+ {
+ }
+ ~LockAnnotation() UNLOCK_FUNCTION() {}
+};
+
#endif // BITCOIN_THREADSAFETY_H
diff --git a/src/timedata.cpp b/src/timedata.cpp
index dfb8fe55af..9c022c9ad1 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,8 +11,8 @@
#include <netaddress.h>
#include <sync.h>
#include <ui_interface.h>
-#include <util.h>
-#include <utilstrencodings.h>
+#include <util/system.h>
+#include <util/strencodings.h>
#include <warnings.h>
@@ -94,7 +94,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
{
// If nobody has a time different than ours but within 5 minutes of ours, give a warning
bool fMatch = false;
- for (int64_t nOffset : vSorted)
+ for (const int64_t nOffset : vSorted)
if (nOffset != 0 && abs64(nOffset) < 5 * 60)
fMatch = true;
@@ -109,7 +109,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
}
if (LogAcceptCategory(BCLog::NET)) {
- for (int64_t n : vSorted) {
+ for (const int64_t n : vSorted) {
LogPrint(BCLog::NET, "%+d ", n); /* Continued */
}
LogPrint(BCLog::NET, "| "); /* Continued */
diff --git a/src/timedata.h b/src/timedata.h
index a4fefb5983..b165ecde26 100644
--- a/src/timedata.h
+++ b/src/timedata.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index fbc193c2cf..550e23b222 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -1,13 +1,13 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 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.
#include <torcontrol.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <netbase.h>
#include <net.h>
-#include <util.h>
+#include <util/system.h>
#include <crypto/hmac_sha256.h>
#include <vector>
@@ -15,7 +15,6 @@
#include <set>
#include <stdlib.h>
-#include <boost/bind.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
@@ -459,8 +458,8 @@ TorController::TorController(struct event_base* _base, const std::string& _targe
if (!reconnect_ev)
LogPrintf("tor: Failed to create event for reconnection: out of memory?\n");
// Start connection attempts immediately
- if (!conn.Connect(_target, boost::bind(&TorController::connected_cb, this, _1),
- boost::bind(&TorController::disconnected_cb, this, _1) )) {
+ if (!conn.Connect(_target, std::bind(&TorController::connected_cb, this, std::placeholders::_1),
+ std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) {
LogPrintf("tor: Initiating connection to Tor control port %s failed\n", _target);
}
// Read service private key if cached
@@ -528,7 +527,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
CService resolved(LookupNumeric("127.0.0.1", 9050));
proxyType addrOnion = proxyType(resolved, true);
SetProxy(NET_ONION, addrOnion);
- SetLimited(NET_ONION, false);
+ SetReachable(NET_ONION, true);
}
// Finally - now create the service
@@ -538,7 +537,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
// Note that the 'virtual' port doesn't have to be the same as our internal port, but this is just a convenient
// choice. TODO; refactor the shutdown sequence some day.
_conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, GetListenPort(), GetListenPort()),
- boost::bind(&TorController::add_onion_cb, this, _1, _2));
+ std::bind(&TorController::add_onion_cb, this, std::placeholders::_1, std::placeholders::_2));
} else {
LogPrintf("tor: Authentication failed\n");
}
@@ -597,7 +596,7 @@ void TorController::authchallenge_cb(TorControlConnection& _conn, const TorContr
}
std::vector<uint8_t> computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce);
- _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2));
+ _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2));
} else {
LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n");
}
@@ -646,23 +645,23 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro
if (methods.count("HASHEDPASSWORD")) {
LogPrint(BCLog::TOR, "tor: Using HASHEDPASSWORD authentication\n");
boost::replace_all(torpassword, "\"", "\\\"");
- _conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2));
+ _conn.Command("AUTHENTICATE \"" + torpassword + "\"", std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2));
} else {
LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n");
}
} else if (methods.count("NULL")) {
LogPrint(BCLog::TOR, "tor: Using NULL authentication\n");
- _conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2));
+ _conn.Command("AUTHENTICATE", std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2));
} else if (methods.count("SAFECOOKIE")) {
// Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie
LogPrint(BCLog::TOR, "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile);
std::pair<bool,std::string> status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE);
if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) {
- // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2));
+ // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2));
cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end());
clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0);
GetRandBytes(clientNonce.data(), TOR_NONCE_SIZE);
- _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2));
+ _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), std::bind(&TorController::authchallenge_cb, this, std::placeholders::_1, std::placeholders::_2));
} else {
if (status_cookie.first) {
LogPrintf("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE);
@@ -684,7 +683,7 @@ void TorController::connected_cb(TorControlConnection& _conn)
{
reconnect_timeout = RECONNECT_TIMEOUT_START;
// First send a PROTOCOLINFO command to figure out what authentication is expected
- if (!_conn.Command("PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2)))
+ if (!_conn.Command("PROTOCOLINFO 1", std::bind(&TorController::protocolinfo_cb, this, std::placeholders::_1, std::placeholders::_2)))
LogPrintf("tor: Error sending initial protocolinfo command\n");
}
@@ -711,8 +710,8 @@ void TorController::Reconnect()
/* Try to reconnect and reestablish if we get booted - for example, Tor
* may be restarting.
*/
- if (!conn.Connect(target, boost::bind(&TorController::connected_cb, this, _1),
- boost::bind(&TorController::disconnected_cb, this, _1) )) {
+ if (!conn.Connect(target, std::bind(&TorController::connected_cb, this, std::placeholders::_1),
+ std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) {
LogPrintf("tor: Re-initiating connection to Tor control port %s failed\n", target);
}
}
diff --git a/src/torcontrol.h b/src/torcontrol.h
index 2be6701fa5..079146b540 100644
--- a/src/torcontrol.h
+++ b/src/torcontrol.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/txdb.cpp b/src/txdb.cpp
index eda959e1a1..494b87ad48 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -11,7 +11,7 @@
#include <pow.h>
#include <shutdown.h>
#include <uint256.h>
-#include <util.h>
+#include <util/system.h>
#include <ui_interface.h>
#include <stdint.h>
diff --git a/src/txdb.h b/src/txdb.h
index 84011097ce..c4ece11503 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -37,6 +37,8 @@ static const int64_t nMaxBlockDBCache = 2;
// Unlike for the UTXO database, for the txindex scenario the leveldb cache make
// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
static const int64_t nMaxTxIndexCache = 1024;
+//! Max memory allocated to all block filter index caches combined in MiB.
+static const int64_t max_filter_index_cache = 1024;
//! Max memory allocated to coin DB specific cache (MiB)
static const int64_t nMaxCoinsDBCache = 8;
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index d68c38ad4e..90b28227a0 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,22 +11,20 @@
#include <validation.h>
#include <policy/policy.h>
#include <policy/fees.h>
+#include <policy/settings.h>
#include <reverse_iterator.h>
#include <streams.h>
#include <timedata.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/moneystr.h>
+#include <util/time.h>
CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
int64_t _nTime, unsigned int _entryHeight,
- bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp):
- tx(_tx), nFee(_nFee), nTime(_nTime), entryHeight(_entryHeight),
+ bool _spendsCoinbase, int64_t _sigOpsCost, LockPoints lp)
+ : tx(_tx), nFee(_nFee), nTxWeight(GetTransactionWeight(*tx)), nUsageSize(RecursiveDynamicUsage(tx)), nTime(_nTime), entryHeight(_entryHeight),
spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
{
- nTxWeight = GetTransactionWeight(*tx);
- nUsageSize = RecursiveDynamicUsage(tx);
-
nCountWithDescendants = 1;
nSizeWithDescendants = GetTxSize();
nModFeesWithDescendants = nFee;
@@ -159,9 +157,9 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntr
// GetMemPoolParents() is only valid for entries in the mempool, so we
// iterate mapTx to find parents.
for (unsigned int i = 0; i < tx.vin.size(); i++) {
- txiter piter = mapTx.find(tx.vin[i].prevout.hash);
- if (piter != mapTx.end()) {
- parentHashes.insert(piter);
+ boost::optional<txiter> piter = GetIter(tx.vin[i].prevout.hash);
+ if (piter) {
+ parentHashes.insert(*piter);
if (parentHashes.size() + 1 > limitAncestorCount) {
errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
return false;
@@ -196,7 +194,7 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntr
}
const setEntries & setMemPoolParents = GetMemPoolParents(stageit);
- for (const txiter &phash : setMemPoolParents) {
+ for (txiter phash : setMemPoolParents) {
// If this is a new ancestor, add it.
if (setAncestors.count(phash) == 0) {
parentHashes.insert(phash);
@@ -355,7 +353,7 @@ void CTxMemPool::AddTransactionsUpdated(unsigned int n)
nTransactionsUpdated += n;
}
-void CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate)
+void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate)
{
NotifyEntryAdded(entry.GetSharedTx());
// Add to memory pool without checking anything.
@@ -367,12 +365,10 @@ void CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
// Update transaction for any feeDelta created by PrioritiseTransaction
// TODO: refactor so that the fee delta is calculated before inserting
// into mapTx.
- std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
- if (pos != mapDeltas.end()) {
- const CAmount &delta = pos->second;
- if (delta) {
+ CAmount delta{0};
+ ApplyDelta(entry.GetTx().GetHash(), delta);
+ if (delta) {
mapTx.modify(newit, update_fee_delta(delta));
- }
}
// Update cachedInnerUsage to include contained transaction's usage.
@@ -394,11 +390,8 @@ void CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
// to clean up the mess we're leaving here.
// Update ancestors with information about this tx
- for (const uint256 &phash : setParentTransactions) {
- txiter pit = mapTx.find(phash);
- if (pit != mapTx.end()) {
+ for (const auto& pit : GetIterSet(setParentTransactions)) {
UpdateParent(newit, pit, true);
- }
}
UpdateAncestorsOf(true, newit, setAncestors);
UpdateEntryForAncestors(newit, setAncestors);
@@ -457,7 +450,7 @@ void CTxMemPool::CalculateDescendants(txiter entryit, setEntries& setDescendants
stage.erase(it);
const setEntries &setChildren = GetMemPoolChildren(it);
- for (const txiter &childiter : setChildren) {
+ for (txiter childiter : setChildren) {
if (!setDescendants.count(childiter)) {
stage.insert(childiter);
}
@@ -506,7 +499,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
const CTransaction& tx = it->GetTx();
LockPoints lp = it->GetLockPoints();
bool validLP = TestLockPointValidity(&lp);
- if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(tx, flags, &lp, validLP)) {
+ if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(*this, tx, flags, &lp, validLP)) {
// Note if CheckSequenceLocks fails the LockPoints may still be invalid
// So it's critical that we remove the tx and not depend on the LockPoints.
txToRemove.insert(it);
@@ -640,8 +633,6 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
innerUsage += memusage::DynamicUsage(links.parents) + memusage::DynamicUsage(links.children);
bool fDependsWait = false;
setEntries setParentCheck;
- int64_t parentSizes = 0;
- int64_t parentSigOpCost = 0;
for (const CTxIn &txin : tx.vin) {
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
@@ -649,10 +640,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
const CTransaction& tx2 = it2->GetTx();
assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
fDependsWait = true;
- if (setParentCheck.insert(it2).second) {
- parentSizes += it2->GetTxSize();
- parentSigOpCost += it2->GetSigOpCost();
- }
+ setParentCheck.insert(it2);
} else {
assert(pcoins->HaveCoin(txin.prevout));
}
@@ -777,7 +765,7 @@ std::vector<CTxMemPool::indexed_transaction_set::const_iterator> CTxMemPool::Get
return iters;
}
-void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
+void CTxMemPool::queryHashes(std::vector<uint256>& vtxid) const
{
LOCK(cs);
auto iters = GetSortedDepthAndScore();
@@ -872,6 +860,29 @@ void CTxMemPool::ClearPrioritisation(const uint256 hash)
mapDeltas.erase(hash);
}
+const CTransaction* CTxMemPool::GetConflictTx(const COutPoint& prevout) const
+{
+ const auto it = mapNextTx.find(prevout);
+ return it == mapNextTx.end() ? nullptr : it->second;
+}
+
+boost::optional<CTxMemPool::txiter> CTxMemPool::GetIter(const uint256& txid) const
+{
+ auto it = mapTx.find(txid);
+ if (it != mapTx.end()) return it;
+ return boost::optional<txiter>{};
+}
+
+CTxMemPool::setEntries CTxMemPool::GetIterSet(const std::set<uint256>& hashes) const
+{
+ CTxMemPool::setEntries ret;
+ for (const auto& h : hashes) {
+ const auto mi = GetIter(h);
+ if (mi) ret.insert(*mi);
+ }
+ return ret;
+}
+
bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
{
for (unsigned int i = 0; i < tx.vin.size(); i++)
@@ -907,7 +918,7 @@ size_t CTxMemPool::DynamicMemoryUsage() const {
void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) {
AssertLockHeld(cs);
UpdateForRemoveFromMempool(stage, updateDescendants);
- for (const txiter& it : stage) {
+ for (txiter it : stage) {
removeUnchecked(it, reason);
}
}
@@ -928,13 +939,13 @@ int CTxMemPool::Expire(int64_t time) {
return stage.size();
}
-void CTxMemPool::addUnchecked(const uint256&hash, const CTxMemPoolEntry &entry, bool validFeeEstimate)
+void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, bool validFeeEstimate)
{
setEntries setAncestors;
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
std::string dummy;
CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
- return addUnchecked(hash, entry, setAncestors, validFeeEstimate);
+ return addUnchecked(entry, setAncestors, validFeeEstimate);
}
void CTxMemPool::UpdateChild(txiter entry, txiter child, bool add)
@@ -1080,4 +1091,16 @@ void CTxMemPool::GetTransactionAncestry(const uint256& txid, size_t& ancestors,
}
}
+bool CTxMemPool::IsLoaded() const
+{
+ LOCK(cs);
+ return m_is_loaded;
+}
+
+void CTxMemPool::SetIsLoaded(bool loaded)
+{
+ LOCK(cs);
+ m_is_loaded = loaded;
+}
+
SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand(std::numeric_limits<uint64_t>::max())), k1(GetRand(std::numeric_limits<uint64_t>::max())) {}
diff --git a/src/txmempool.h b/src/txmempool.h
index 0feea08f0b..ce0b762336 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,6 +15,7 @@
#include <amount.h>
#include <coins.h>
+#include <crypto/siphash.h>
#include <indirectmap.h>
#include <policy/feerate.h>
#include <primitives/transaction.h>
@@ -28,6 +29,7 @@
#include <boost/signals2/signal.hpp>
class CBlockIndex;
+extern CCriticalSection 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;
@@ -64,14 +66,14 @@ class CTxMemPool;
class CTxMemPoolEntry
{
private:
- CTransactionRef tx;
- CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
- size_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize())
- size_t nUsageSize; //!< ... and total memory usage
- int64_t nTime; //!< Local time when entering the mempool
- unsigned int entryHeight; //!< Chain height when entering the mempool
- bool spendsCoinbase; //!< keep track of transactions that spend a coinbase
- int64_t sigOpCost; //!< Total sigop cost
+ const CTransactionRef tx;
+ const CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
+ const size_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize())
+ const size_t nUsageSize; //!< ... and total memory usage
+ const int64_t nTime; //!< Local time when entering the mempool
+ const unsigned int entryHeight; //!< Chain height when entering the mempool
+ const bool spendsCoinbase; //!< keep track of transactions that spend a coinbase
+ const int64_t sigOpCost; //!< Total sigop cost
int64_t feeDelta; //!< Used for determining the priority of the transaction for mining in a block
LockPoints lockPoints; //!< Track the height and time at which tx was final
@@ -182,7 +184,7 @@ private:
const LockPoints& lp;
};
-// extracts a transaction hash from CTxMempoolEntry or CTransactionRef
+// extracts a transaction hash from CTxMemPoolEntry or CTransactionRef
struct mempoolentry_txid
{
typedef uint256 result_type;
@@ -342,13 +344,13 @@ struct TxMempoolInfo
* this is passed to the notification signal.
*/
enum class MemPoolRemovalReason {
- UNKNOWN = 0, //! Manually removed or unknown reason
- EXPIRY, //! Expired from mempool
- SIZELIMIT, //! Removed in size limiting
- REORG, //! Removed for reorganization
- BLOCK, //! Removed for block
- CONFLICT, //! Removed for conflict with in-block transaction
- REPLACED //! Removed for replacement
+ UNKNOWN = 0, //!< Manually removed or unknown reason
+ EXPIRY, //!< Expired from mempool
+ SIZELIMIT, //!< Removed in size limiting
+ REORG, //!< Removed for reorganization
+ BLOCK, //!< Removed for block
+ CONFLICT, //!< Removed for conflict with in-block transaction
+ REPLACED, //!< Removed for replacement
};
class SaltedTxidHasher
@@ -453,6 +455,8 @@ private:
void trackPackageRemoved(const CFeeRate& rate) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ bool m_is_loaded GUARDED_BY(cs){false};
+
public:
static const int ROLLING_FEE_HALFLIFE = 60 * 60 * 12; // public only for testing
@@ -483,7 +487,43 @@ public:
>
> indexed_transaction_set;
- mutable CCriticalSection cs;
+ /**
+ * This mutex needs to be locked when accessing `mapTx` or other members
+ * that are guarded by it.
+ *
+ * @par Consistency guarantees
+ *
+ * By design, it is guaranteed that:
+ *
+ * 1. Locking both `cs_main` and `mempool.cs` will give a view of mempool
+ * that is consistent with current chain tip (`::ChainActive()` and
+ * `pcoinsTip`) and is fully populated. Fully populated means that if the
+ * current active chain is missing transactions that were present in a
+ * previously active chain, all the missing transactions will have been
+ * re-added to the mempool and should be present if they meet size and
+ * consistency constraints.
+ *
+ * 2. Locking `mempool.cs` without `cs_main` will give a view of a mempool
+ * consistent with some chain that was active since `cs_main` was last
+ * locked, and that is fully populated as described above. It is ok for
+ * code that only needs to query or remove transactions from the mempool
+ * to lock just `mempool.cs` without `cs_main`.
+ *
+ * To provide these guarantees, it is necessary to lock both `cs_main` and
+ * `mempool.cs` whenever adding transactions to the mempool and whenever
+ * changing the chain tip. It's necessary to keep both mutexes locked until
+ * the mempool is consistent with the new chain tip and fully populated.
+ *
+ * @par Consistency bug
+ *
+ * The second guarantee above is not currently enforced, but
+ * https://github.com/bitcoin/bitcoin/pull/14193 will fix it. No known code
+ * in bitcoin currently depends on second guarantee, but it is important to
+ * fix for third party code that needs be able to frequently poll the
+ * mempool without locking `cs_main` and without encountering missing
+ * transactions during reorgs.
+ */
+ mutable RecursiveMutex cs;
indexed_transaction_set mapTx GUARDED_BY(cs);
using txiter = indexed_transaction_set::nth_index<0>::type::const_iterator;
@@ -539,18 +579,18 @@ public:
// Note that addUnchecked is ONLY called from ATMP outside of tests
// and any other callers may break wallet's in-mempool tracking (due to
// lack of CValidationInterface::TransactionAddedToMempool callbacks).
- void addUnchecked(const uint256& hash, const CTxMemPoolEntry& entry, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs);
- void addUnchecked(const uint256& hash, const CTxMemPoolEntry& entry, setEntries& setAncestors, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void addUnchecked(const CTxMemPoolEntry& entry, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
+ void addUnchecked(const CTxMemPoolEntry& entry, setEntries& setAncestors, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
- void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
+ void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs);
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight);
void clear();
void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs); //lock free
bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb);
- void queryHashes(std::vector<uint256>& vtxid);
+ void queryHashes(std::vector<uint256>& vtxid) const;
bool isSpent(const COutPoint& outpoint) const;
unsigned int GetTransactionsUpdated() const;
void AddTransactionsUpdated(unsigned int n);
@@ -565,7 +605,15 @@ public:
void ApplyDelta(const uint256 hash, CAmount &nFeeDelta) const;
void ClearPrioritisation(const uint256 hash);
-public:
+ /** Get the transaction in the pool that spends the same prevout */
+ const CTransaction* GetConflictTx(const COutPoint& prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+
+ /** Returns an iterator to the given hash, if found */
+ boost::optional<txiter> GetIter(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+
+ /** Translate a set of hashes into a set of pool iterators to avoid repeated lookups */
+ setEntries GetIterSet(const std::set<uint256>& hashes) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+
/** Remove a set of transactions from the mempool.
* If a transaction is in this set, then all in-mempool descendants must
* also be in the set, unless this transaction is being removed for being
@@ -584,7 +632,7 @@ public:
* for). Note: vHashesToUpdate should be the set of transactions from the
* disconnected block that have been accepted back into the mempool.
*/
- void UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate);
+ void UpdateTransactionsFromBlock(const std::vector<uint256>& vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Try to calculate all in-mempool ancestors of entry.
* (these are all calculated including the tx itself)
@@ -626,7 +674,13 @@ public:
*/
void GetTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) const;
- unsigned long size()
+ /** @returns true if the mempool is fully loaded */
+ bool IsLoaded() const;
+
+ /** Sets the current loaded state */
+ void SetIsLoaded(bool loaded);
+
+ unsigned long size() const
{
LOCK(cs);
return mapTx.size();
@@ -638,7 +692,7 @@ public:
return totalTxSize;
}
- bool exists(uint256 hash) const
+ bool exists(const uint256& hash) const
{
LOCK(cs);
return (mapTx.count(hash) != 0);
@@ -700,7 +754,8 @@ private:
* This allows transaction replacement to work as expected, as you want to
* have all inputs "available" to check signatures, and any cycles in the
* dependency graph are checked directly in AcceptToMemoryPool.
- * It also allows you to sign a double-spend directly in signrawtransaction,
+ * It also allows you to sign a double-spend directly in
+ * signrawtransactionwithkey and signrawtransactionwithwallet,
* as long as the conflicting transaction is not yet confirmed.
*/
class CCoinsViewMemPool : public CCoinsViewBacked
diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp
index 72e04f488a..31a95486d7 100644
--- a/src/ui_interface.cpp
+++ b/src/ui_interface.cpp
@@ -1,12 +1,60 @@
-// Copyright (c) 2010-2017 The Bitcoin Core developers
+// Copyright (c) 2010-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
+
+#include <boost/signals2/last_value.hpp>
+#include <boost/signals2/signal.hpp>
CClientUIInterface uiInterface;
+struct UISignals {
+ boost::signals2::signal<CClientUIInterface::ThreadSafeMessageBoxSig, boost::signals2::last_value<bool>> ThreadSafeMessageBox;
+ boost::signals2::signal<CClientUIInterface::ThreadSafeQuestionSig, boost::signals2::last_value<bool>> ThreadSafeQuestion;
+ boost::signals2::signal<CClientUIInterface::InitMessageSig> InitMessage;
+ boost::signals2::signal<CClientUIInterface::NotifyNumConnectionsChangedSig> NotifyNumConnectionsChanged;
+ boost::signals2::signal<CClientUIInterface::NotifyNetworkActiveChangedSig> NotifyNetworkActiveChanged;
+ boost::signals2::signal<CClientUIInterface::NotifyAlertChangedSig> NotifyAlertChanged;
+ boost::signals2::signal<CClientUIInterface::LoadWalletSig> LoadWallet;
+ boost::signals2::signal<CClientUIInterface::ShowProgressSig> ShowProgress;
+ boost::signals2::signal<CClientUIInterface::NotifyBlockTipSig> NotifyBlockTip;
+ boost::signals2::signal<CClientUIInterface::NotifyHeaderTipSig> NotifyHeaderTip;
+ boost::signals2::signal<CClientUIInterface::BannedListChangedSig> BannedListChanged;
+} g_ui_signals;
+
+#define ADD_SIGNALS_IMPL_WRAPPER(signal_name) \
+ boost::signals2::connection CClientUIInterface::signal_name##_connect(std::function<signal_name##Sig> fn) \
+ { \
+ return g_ui_signals.signal_name.connect(fn); \
+ }
+
+ADD_SIGNALS_IMPL_WRAPPER(ThreadSafeMessageBox);
+ADD_SIGNALS_IMPL_WRAPPER(ThreadSafeQuestion);
+ADD_SIGNALS_IMPL_WRAPPER(InitMessage);
+ADD_SIGNALS_IMPL_WRAPPER(NotifyNumConnectionsChanged);
+ADD_SIGNALS_IMPL_WRAPPER(NotifyNetworkActiveChanged);
+ADD_SIGNALS_IMPL_WRAPPER(NotifyAlertChanged);
+ADD_SIGNALS_IMPL_WRAPPER(LoadWallet);
+ADD_SIGNALS_IMPL_WRAPPER(ShowProgress);
+ADD_SIGNALS_IMPL_WRAPPER(NotifyBlockTip);
+ADD_SIGNALS_IMPL_WRAPPER(NotifyHeaderTip);
+ADD_SIGNALS_IMPL_WRAPPER(BannedListChanged);
+
+bool CClientUIInterface::ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeMessageBox(message, caption, style); }
+bool CClientUIInterface::ThreadSafeQuestion(const std::string& message, const std::string& non_interactive_message, const std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeQuestion(message, non_interactive_message, caption, style); }
+void CClientUIInterface::InitMessage(const std::string& message) { return g_ui_signals.InitMessage(message); }
+void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { return g_ui_signals.NotifyNumConnectionsChanged(newNumConnections); }
+void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); }
+void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); }
+void CClientUIInterface::LoadWallet(std::unique_ptr<interfaces::Wallet>& wallet) { return g_ui_signals.LoadWallet(wallet); }
+void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); }
+void CClientUIInterface::NotifyBlockTip(bool b, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(b, i); }
+void CClientUIInterface::NotifyHeaderTip(bool b, const CBlockIndex* i) { return g_ui_signals.NotifyHeaderTip(b, i); }
+void CClientUIInterface::BannedListChanged() { return g_ui_signals.BannedListChanged(); }
+
+
bool InitError(const std::string& str)
{
uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
@@ -17,13 +65,3 @@ void InitWarning(const std::string& str)
{
uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
}
-
-std::string AmountHighWarn(const std::string& optname)
-{
- return strprintf(_("%s is set very high!"), optname);
-}
-
-std::string AmountErrMsg(const char* const optname, const std::string& strValue)
-{
- return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
-}
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 3add369df0..d408f6f889 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -1,20 +1,26 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_UI_INTERFACE_H
#define BITCOIN_UI_INTERFACE_H
+#include <functional>
#include <memory>
#include <stdint.h>
#include <string>
-#include <boost/signals2/last_value.hpp>
-#include <boost/signals2/signal.hpp>
-
-class CWallet;
class CBlockIndex;
+namespace boost {
+namespace signals2 {
+class connection;
+}
+} // namespace boost
+
+namespace interfaces {
+class Wallet;
+} // namespace interfaces
/** General change type (added, updated, removed). */
enum ChangeType
@@ -72,43 +78,48 @@ public:
MSG_ERROR = (ICON_ERROR | BTN_OK | MODAL)
};
+#define ADD_SIGNALS_DECL_WRAPPER(signal_name, rtype, ...) \
+ rtype signal_name(__VA_ARGS__); \
+ using signal_name##Sig = rtype(__VA_ARGS__); \
+ boost::signals2::connection signal_name##_connect(std::function<signal_name##Sig> fn);
+
/** Show message box. */
- boost::signals2::signal<bool (const std::string& message, const std::string& caption, unsigned int style), boost::signals2::last_value<bool> > ThreadSafeMessageBox;
+ ADD_SIGNALS_DECL_WRAPPER(ThreadSafeMessageBox, bool, const std::string& message, const std::string& caption, unsigned int style);
/** If possible, ask the user a question. If not, falls back to ThreadSafeMessageBox(noninteractive_message, caption, style) and returns false. */
- boost::signals2::signal<bool (const std::string& message, const std::string& noninteractive_message, const std::string& caption, unsigned int style), boost::signals2::last_value<bool> > ThreadSafeQuestion;
+ ADD_SIGNALS_DECL_WRAPPER(ThreadSafeQuestion, bool, const std::string& message, const std::string& noninteractive_message, const std::string& caption, unsigned int style);
/** Progress message during initialization. */
- boost::signals2::signal<void (const std::string &message)> InitMessage;
+ ADD_SIGNALS_DECL_WRAPPER(InitMessage, void, const std::string& message);
/** Number of network connections changed. */
- boost::signals2::signal<void (int newNumConnections)> NotifyNumConnectionsChanged;
+ ADD_SIGNALS_DECL_WRAPPER(NotifyNumConnectionsChanged, void, int newNumConnections);
/** Network activity state changed. */
- boost::signals2::signal<void (bool networkActive)> NotifyNetworkActiveChanged;
+ ADD_SIGNALS_DECL_WRAPPER(NotifyNetworkActiveChanged, void, bool networkActive);
/**
* Status bar alerts changed.
*/
- boost::signals2::signal<void ()> NotifyAlertChanged;
+ ADD_SIGNALS_DECL_WRAPPER(NotifyAlertChanged, void, );
/** A wallet has been loaded. */
- boost::signals2::signal<void (std::shared_ptr<CWallet> wallet)> LoadWallet;
+ ADD_SIGNALS_DECL_WRAPPER(LoadWallet, void, std::unique_ptr<interfaces::Wallet>& wallet);
/**
* Show progress e.g. for verifychain.
* resume_possible indicates shutting down now will result in the current progress action resuming upon restart.
*/
- boost::signals2::signal<void (const std::string &title, int nProgress, bool resume_possible)> ShowProgress;
+ ADD_SIGNALS_DECL_WRAPPER(ShowProgress, void, const std::string& title, int nProgress, bool resume_possible);
/** New block has been accepted */
- boost::signals2::signal<void (bool, const CBlockIndex *)> NotifyBlockTip;
+ ADD_SIGNALS_DECL_WRAPPER(NotifyBlockTip, void, bool, const CBlockIndex*);
/** Best header has changed */
- boost::signals2::signal<void (bool, const CBlockIndex *)> NotifyHeaderTip;
+ ADD_SIGNALS_DECL_WRAPPER(NotifyHeaderTip, void, bool, const CBlockIndex*);
/** Banlist did change. */
- boost::signals2::signal<void (void)> BannedListChanged;
+ ADD_SIGNALS_DECL_WRAPPER(BannedListChanged, void, void);
};
/** Show warning message **/
@@ -117,10 +128,6 @@ void InitWarning(const std::string& str);
/** Show error message **/
bool InitError(const std::string& str);
-std::string AmountHighWarn(const std::string& optname);
-
-std::string AmountErrMsg(const char* const optname, const std::string& strValue);
-
extern CClientUIInterface uiInterface;
#endif // BITCOIN_UI_INTERFACE_H
diff --git a/src/uint256.cpp b/src/uint256.cpp
index 82c2e01576..e3bc9712e8 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -1,11 +1,11 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <uint256.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <stdio.h>
#include <string.h>
@@ -29,11 +29,11 @@ void base_blob<BITS>::SetHex(const char* psz)
memset(data, 0, sizeof(data));
// skip leading spaces
- while (isspace(*psz))
+ while (IsSpace(*psz))
psz++;
// skip 0x
- if (psz[0] == '0' && tolower(psz[1]) == 'x')
+ if (psz[0] == '0' && ToLower(psz[1]) == 'x')
psz += 2;
// hex string to uint
diff --git a/src/uint256.h b/src/uint256.h
index e090f10231..97e0cfa015 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,6 @@
#include <stdint.h>
#include <string>
#include <vector>
-#include <crypto/common.h>
/** Template base class for fixed-sized opaque blobs. */
template<unsigned int BITS>
@@ -123,16 +122,6 @@ class uint256 : public base_blob<256> {
public:
uint256() {}
explicit uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {}
-
- /** A cheap hash function that just returns 64 bits from the result, it can be
- * used when the contents are considered uniformly random. It is not appropriate
- * when the value can easily be influenced from outside as e.g. a network adversary could
- * provide values to trigger worst-case behavior.
- */
- uint64_t GetCheapHash() const
- {
- return ReadLE64(data);
- }
};
/* uint256 from const char *.
diff --git a/src/undo.h b/src/undo.h
index f292924165..3f50f4caad 100644
--- a/src/undo.h
+++ b/src/undo.h
@@ -1,15 +1,17 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_UNDO_H
#define BITCOIN_UNDO_H
+#include <coins.h>
#include <compressor.h>
#include <consensus/consensus.h>
#include <primitives/transaction.h>
#include <serialize.h>
+#include <version.h>
/** Undo information for a CTxIn
*
@@ -60,7 +62,7 @@ public:
explicit TxInUndoDeserializer(Coin* coin) : txout(coin) {}
};
-static const size_t MIN_TRANSACTION_INPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxIn(), SER_NETWORK, PROTOCOL_VERSION);
+static const size_t MIN_TRANSACTION_INPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxIn(), PROTOCOL_VERSION);
static const size_t MAX_INPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_INPUT_WEIGHT;
/** Undo information for a CTransaction */
diff --git a/src/univalue/gen/gen.cpp b/src/univalue/gen/gen.cpp
index 17f361941d..85fe20924a 100644
--- a/src/univalue/gen/gen.cpp
+++ b/src/univalue/gen/gen.cpp
@@ -12,8 +12,6 @@
#include <string.h>
#include "univalue.h"
-using namespace std;
-
static bool initEscapes;
static std::string escapes[256];
diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h
index c15b2f051e..91b104e56e 100644
--- a/src/univalue/include/univalue.h
+++ b/src/univalue/include/univalue.h
@@ -15,7 +15,6 @@
#include <cassert>
#include <sstream> // .get_int64()
-#include <utility> // std::pair
class UniValue {
public:
@@ -177,76 +176,9 @@ public:
const UniValue& get_array() const;
enum VType type() const { return getType(); }
- bool push_back(std::pair<std::string,UniValue> pear) {
- return pushKV(pear.first, pear.second);
- }
friend const UniValue& find_value( const UniValue& obj, const std::string& name);
};
-//
-// The following were added for compatibility with json_spirit.
-// Most duplicate other methods, and should be removed.
-//
-static inline std::pair<std::string,UniValue> Pair(const char *cKey, const char *cVal)
-{
- std::string key(cKey);
- UniValue uVal(cVal);
- return std::make_pair(key, uVal);
-}
-
-static inline std::pair<std::string,UniValue> Pair(const char *cKey, std::string strVal)
-{
- std::string key(cKey);
- UniValue uVal(strVal);
- return std::make_pair(key, uVal);
-}
-
-static inline std::pair<std::string,UniValue> Pair(const char *cKey, uint64_t u64Val)
-{
- std::string key(cKey);
- UniValue uVal(u64Val);
- return std::make_pair(key, uVal);
-}
-
-static inline std::pair<std::string,UniValue> Pair(const char *cKey, int64_t i64Val)
-{
- std::string key(cKey);
- UniValue uVal(i64Val);
- return std::make_pair(key, uVal);
-}
-
-static inline std::pair<std::string,UniValue> Pair(const char *cKey, bool iVal)
-{
- std::string key(cKey);
- UniValue uVal(iVal);
- return std::make_pair(key, uVal);
-}
-
-static inline std::pair<std::string,UniValue> Pair(const char *cKey, int iVal)
-{
- std::string key(cKey);
- UniValue uVal(iVal);
- return std::make_pair(key, uVal);
-}
-
-static inline std::pair<std::string,UniValue> Pair(const char *cKey, double dVal)
-{
- std::string key(cKey);
- UniValue uVal(dVal);
- return std::make_pair(key, uVal);
-}
-
-static inline std::pair<std::string,UniValue> Pair(const char *cKey, const UniValue& uVal)
-{
- std::string key(cKey);
- return std::make_pair(key, uVal);
-}
-
-static inline std::pair<std::string,UniValue> Pair(std::string key, const UniValue& uVal)
-{
- return std::make_pair(key, uVal);
-}
-
enum jtokentype {
JTOK_ERR = -1,
JTOK_NONE = 0, // eof
diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp
index d8ad7c4b90..4c9c15d63e 100644
--- a/src/univalue/lib/univalue.cpp
+++ b/src/univalue/lib/univalue.cpp
@@ -10,8 +10,6 @@
#include "univalue.h"
-using namespace std;
-
const UniValue NullUniValue;
void UniValue::clear()
@@ -37,15 +35,15 @@ bool UniValue::setBool(bool val_)
return true;
}
-static bool validNumStr(const string& s)
+static bool validNumStr(const std::string& s)
{
- string tokenVal;
+ std::string tokenVal;
unsigned int consumed;
enum jtokentype tt = getJsonToken(tokenVal, consumed, s.data(), s.data() + s.size());
return (tt == JTOK_NUMBER);
}
-bool UniValue::setNumStr(const string& val_)
+bool UniValue::setNumStr(const std::string& val_)
{
if (!validNumStr(val_))
return false;
@@ -58,7 +56,7 @@ bool UniValue::setNumStr(const string& val_)
bool UniValue::setInt(uint64_t val_)
{
- ostringstream oss;
+ std::ostringstream oss;
oss << val_;
@@ -67,7 +65,7 @@ bool UniValue::setInt(uint64_t val_)
bool UniValue::setInt(int64_t val_)
{
- ostringstream oss;
+ std::ostringstream oss;
oss << val_;
@@ -76,7 +74,7 @@ bool UniValue::setInt(int64_t val_)
bool UniValue::setFloat(double val_)
{
- ostringstream oss;
+ std::ostringstream oss;
oss << std::setprecision(16) << val_;
@@ -85,7 +83,7 @@ bool UniValue::setFloat(double val_)
return ret;
}
-bool UniValue::setStr(const string& val_)
+bool UniValue::setStr(const std::string& val_)
{
clear();
typ = VSTR;
diff --git a/src/univalue/lib/univalue_read.cpp b/src/univalue/lib/univalue_read.cpp
index ae75cb462a..14834db24d 100644
--- a/src/univalue/lib/univalue_read.cpp
+++ b/src/univalue/lib/univalue_read.cpp
@@ -8,8 +8,6 @@
#include "univalue.h"
#include "univalue_utffilter.h"
-using namespace std;
-
static bool json_isdigit(int ch)
{
return ((ch >= '0') && (ch <= '9'));
@@ -42,7 +40,7 @@ static const char *hatoui(const char *first, const char *last,
return first;
}
-enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed,
+enum jtokentype getJsonToken(std::string& tokenVal, unsigned int& consumed,
const char *raw, const char *end)
{
tokenVal.clear();
@@ -114,7 +112,7 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed,
case '8':
case '9': {
// part 1: int
- string numStr;
+ std::string numStr;
const char *first = raw;
@@ -174,7 +172,7 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed,
case '"': {
raw++; // skip "
- string valStr;
+ std::string valStr;
JSONUTF8StringFilter writer(valStr);
while (true) {
@@ -255,9 +253,9 @@ bool UniValue::read(const char *raw, size_t size)
clear();
uint32_t expectMask = 0;
- vector<UniValue*> stack;
+ std::vector<UniValue*> stack;
- string tokenVal;
+ std::string tokenVal;
unsigned int consumed;
enum jtokentype tok = JTOK_NONE;
enum jtokentype last_tok = JTOK_NONE;
diff --git a/src/univalue/lib/univalue_write.cpp b/src/univalue/lib/univalue_write.cpp
index cf27835991..827eb9b271 100644
--- a/src/univalue/lib/univalue_write.cpp
+++ b/src/univalue/lib/univalue_write.cpp
@@ -8,11 +8,9 @@
#include "univalue.h"
#include "univalue_escapes.h"
-using namespace std;
-
-static string json_escape(const string& inS)
+static std::string json_escape(const std::string& inS)
{
- string outS;
+ std::string outS;
outS.reserve(inS.size() * 2);
for (unsigned int i = 0; i < inS.size(); i++) {
@@ -28,10 +26,10 @@ static string json_escape(const string& inS)
return outS;
}
-string UniValue::write(unsigned int prettyIndent,
- unsigned int indentLevel) const
+std::string UniValue::write(unsigned int prettyIndent,
+ unsigned int indentLevel) const
{
- string s;
+ std::string s;
s.reserve(1024);
unsigned int modIndent = indentLevel;
@@ -62,12 +60,12 @@ string UniValue::write(unsigned int prettyIndent,
return s;
}
-static void indentStr(unsigned int prettyIndent, unsigned int indentLevel, string& s)
+static void indentStr(unsigned int prettyIndent, unsigned int indentLevel, std::string& s)
{
s.append(prettyIndent * indentLevel, ' ');
}
-void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
+void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const
{
s += "[";
if (prettyIndent)
@@ -89,7 +87,7 @@ void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, s
s += "]";
}
-void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
+void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const
{
s += "{";
if (prettyIndent)
diff --git a/src/univalue/test/unitester.cpp b/src/univalue/test/unitester.cpp
index 2c37794a4b..75c0dc225a 100644
--- a/src/univalue/test/unitester.cpp
+++ b/src/univalue/test/unitester.cpp
@@ -17,8 +17,7 @@
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
-using namespace std;
-string srcdir(JSON_TEST_SRC);
+std::string srcdir(JSON_TEST_SRC);
static bool test_failed = false;
#define d_assert(expr) { if (!(expr)) { test_failed = true; fprintf(stderr, "%s failed\n", filename.c_str()); } }
@@ -30,9 +29,9 @@ static std::string rtrim(std::string s)
return s;
}
-static void runtest(string filename, const string& jdata)
+static void runtest(std::string filename, const std::string& jdata)
{
- string prefix = filename.substr(0, 4);
+ std::string prefix = filename.substr(0, 4);
bool wantPass = (prefix == "pass") || (prefix == "roun");
bool wantFail = (prefix == "fail");
@@ -56,19 +55,19 @@ static void runtest(string filename, const string& jdata)
static void runtest_file(const char *filename_)
{
- string basename(filename_);
- string filename = srcdir + "/" + basename;
+ std::string basename(filename_);
+ std::string filename = srcdir + "/" + basename;
FILE *f = fopen(filename.c_str(), "r");
assert(f != NULL);
- string jdata;
+ std::string jdata;
char buf[4096];
while (!feof(f)) {
int bread = fread(buf, 1, sizeof(buf), f);
assert(!ferror(f));
- string s(buf, bread);
+ std::string s(buf, bread);
jdata += s;
}
diff --git a/src/util/bip32.cpp b/src/util/bip32.cpp
new file mode 100644
index 0000000000..6f176dd5ec
--- /dev/null
+++ b/src/util/bip32.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <sstream>
+#include <stdio.h>
+#include <tinyformat.h>
+#include <util/bip32.h>
+#include <util/strencodings.h>
+
+
+bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath)
+{
+ std::stringstream ss(keypath_str);
+ std::string item;
+ bool first = true;
+ while (std::getline(ss, item, '/')) {
+ if (item.compare("m") == 0) {
+ if (first) {
+ first = false;
+ continue;
+ }
+ return false;
+ }
+ // Finds whether it is hardened
+ uint32_t path = 0;
+ size_t pos = item.find("'");
+ if (pos != std::string::npos) {
+ // The hardened tick can only be in the last index of the string
+ if (pos != item.size() - 1) {
+ return false;
+ }
+ path |= 0x80000000;
+ item = item.substr(0, item.size() - 1); // Drop the last character which is the hardened tick
+ }
+
+ // Ensure this is only numbers
+ if (item.find_first_not_of( "0123456789" ) != std::string::npos) {
+ return false;
+ }
+ uint32_t number;
+ if (!ParseUInt32(item, &number)) {
+ return false;
+ }
+ path |= number;
+
+ keypath.push_back(path);
+ first = false;
+ }
+ return true;
+}
+
+std::string FormatHDKeypath(const std::vector<uint32_t>& path)
+{
+ std::string ret;
+ for (auto i : path) {
+ ret += strprintf("/%i", (i << 1) >> 1);
+ if (i >> 31) ret += '\'';
+ }
+ return ret;
+}
+
+std::string WriteHDKeypath(const std::vector<uint32_t>& keypath)
+{
+ return "m" + FormatHDKeypath(keypath);
+}
diff --git a/src/util/bip32.h b/src/util/bip32.h
new file mode 100644
index 0000000000..7e58b79f38
--- /dev/null
+++ b/src/util/bip32.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_BIP32_H
+#define BITCOIN_UTIL_BIP32_H
+
+#include <attributes.h>
+#include <string>
+#include <vector>
+
+/** Parse an HD keypaths like "m/7/0'/2000". */
+NODISCARD bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath);
+
+/** Write HD keypaths as strings */
+std::string WriteHDKeypath(const std::vector<uint32_t>& keypath);
+std::string FormatHDKeypath(const std::vector<uint32_t>& path);
+
+#endif // BITCOIN_UTIL_BIP32_H
diff --git a/src/util/bytevectorhash.cpp b/src/util/bytevectorhash.cpp
new file mode 100644
index 0000000000..f87d0e04b3
--- /dev/null
+++ b/src/util/bytevectorhash.cpp
@@ -0,0 +1,18 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <crypto/siphash.h>
+#include <random.h>
+#include <util/bytevectorhash.h>
+
+ByteVectorHash::ByteVectorHash()
+{
+ GetRandBytes(reinterpret_cast<unsigned char*>(&m_k0), sizeof(m_k0));
+ GetRandBytes(reinterpret_cast<unsigned char*>(&m_k1), sizeof(m_k1));
+}
+
+size_t ByteVectorHash::operator()(const std::vector<unsigned char>& input) const
+{
+ return CSipHasher(m_k0, m_k1).Write(input.data(), input.size()).Finalize();
+}
diff --git a/src/util/bytevectorhash.h b/src/util/bytevectorhash.h
new file mode 100644
index 0000000000..b88c17460b
--- /dev/null
+++ b/src/util/bytevectorhash.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_BYTEVECTORHASH_H
+#define BITCOIN_UTIL_BYTEVECTORHASH_H
+
+#include <stdint.h>
+#include <vector>
+
+/**
+ * Implementation of Hash named requirement for types that internally store a byte array. This may
+ * be used as the hash function in std::unordered_set or std::unordered_map over such types.
+ * Internally, this uses a random instance of SipHash-2-4.
+ */
+class ByteVectorHash final
+{
+private:
+ uint64_t m_k0, m_k1;
+
+public:
+ ByteVectorHash();
+ size_t operator()(const std::vector<unsigned char>& input) const;
+};
+
+#endif // BITCOIN_UTIL_BYTEVECTORHASH_H
diff --git a/src/util/error.cpp b/src/util/error.cpp
new file mode 100644
index 0000000000..68ffd8b046
--- /dev/null
+++ b/src/util/error.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2010-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/error.h>
+
+#include <util/system.h>
+
+std::string TransactionErrorString(const TransactionError err)
+{
+ switch (err) {
+ case TransactionError::OK:
+ return "No error";
+ case TransactionError::MISSING_INPUTS:
+ return "Missing inputs";
+ case TransactionError::ALREADY_IN_CHAIN:
+ return "Transaction already in block chain";
+ case TransactionError::P2P_DISABLED:
+ return "Peer-to-peer functionality missing or disabled";
+ case TransactionError::MEMPOOL_REJECTED:
+ return "Transaction rejected by AcceptToMemoryPool";
+ case TransactionError::MEMPOOL_ERROR:
+ return "AcceptToMemoryPool failed";
+ case TransactionError::INVALID_PSBT:
+ return "PSBT is not sane";
+ case TransactionError::PSBT_MISMATCH:
+ return "PSBTs not compatible (different transactions)";
+ case TransactionError::SIGHASH_MISMATCH:
+ return "Specified sighash value does not match existing value";
+ // no default case, so the compiler can warn about missing cases
+ }
+ assert(false);
+}
+
+std::string AmountHighWarn(const std::string& optname)
+{
+ return strprintf(_("%s is set very high!"), optname);
+}
+
+std::string AmountErrMsg(const char* const optname, const std::string& strValue)
+{
+ return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
+}
diff --git a/src/util/error.h b/src/util/error.h
new file mode 100644
index 0000000000..d93309551b
--- /dev/null
+++ b/src/util/error.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2010-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_ERROR_H
+#define BITCOIN_UTIL_ERROR_H
+
+/**
+ * util/error.h is a common place for definitions of simple error types and
+ * string functions. Types and functions defined here should not require any
+ * outside dependencies.
+ *
+ * Error types defined here can be used in different parts of the bitcoin
+ * codebase, to avoid the need to write boilerplate code catching and
+ * translating errors passed across wallet/node/rpc/gui code boundaries.
+ */
+
+#include <string>
+
+enum class TransactionError {
+ OK, //!< No error
+ MISSING_INPUTS,
+ ALREADY_IN_CHAIN,
+ P2P_DISABLED,
+ MEMPOOL_REJECTED,
+ MEMPOOL_ERROR,
+ INVALID_PSBT,
+ PSBT_MISMATCH,
+ SIGHASH_MISMATCH,
+};
+
+std::string TransactionErrorString(const TransactionError error);
+
+std::string AmountHighWarn(const std::string& optname);
+
+std::string AmountErrMsg(const char* const optname, const std::string& strValue);
+
+#endif // BITCOIN_UTIL_ERROR_H
diff --git a/src/util/fees.cpp b/src/util/fees.cpp
new file mode 100644
index 0000000000..5fdaa1284c
--- /dev/null
+++ b/src/util/fees.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <policy/fees.h>
+
+#include <string>
+
+std::string StringForFeeReason(FeeReason reason) {
+ static const std::map<FeeReason, std::string> fee_reason_strings = {
+ {FeeReason::NONE, "None"},
+ {FeeReason::HALF_ESTIMATE, "Half Target 60% Threshold"},
+ {FeeReason::FULL_ESTIMATE, "Target 85% Threshold"},
+ {FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"},
+ {FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"},
+ {FeeReason::MEMPOOL_MIN, "Mempool Min Fee"},
+ {FeeReason::PAYTXFEE, "PayTxFee set"},
+ {FeeReason::FALLBACK, "Fallback fee"},
+ {FeeReason::REQUIRED, "Minimum Required Fee"},
+ {FeeReason::MAXTXFEE, "MaxTxFee limit"}
+ };
+ auto reason_string = fee_reason_strings.find(reason);
+
+ if (reason_string == fee_reason_strings.end()) return "Unknown";
+
+ return reason_string->second;
+}
+
+bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
+ static const std::map<std::string, FeeEstimateMode> fee_modes = {
+ {"UNSET", FeeEstimateMode::UNSET},
+ {"ECONOMICAL", FeeEstimateMode::ECONOMICAL},
+ {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
+ };
+ auto mode = fee_modes.find(mode_string);
+
+ if (mode == fee_modes.end()) return false;
+
+ fee_estimate_mode = mode->second;
+ return true;
+}
diff --git a/src/util/fees.h b/src/util/fees.h
new file mode 100644
index 0000000000..fc355ce9c2
--- /dev/null
+++ b/src/util/fees.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_UTIL_FEES_H
+#define BITCOIN_UTIL_FEES_H
+
+#include <string>
+
+enum class FeeEstimateMode;
+enum class FeeReason;
+
+bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode);
+std::string StringForFeeReason(FeeReason reason);
+
+#endif // BITCOIN_UTIL_FEES_H
diff --git a/src/utilmemory.h b/src/util/memory.h
index e71fe92284..15ecf8f80d 100644
--- a/src/utilmemory.h
+++ b/src/util/memory.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_UTILMEMORY_H
-#define BITCOIN_UTILMEMORY_H
+#ifndef BITCOIN_UTIL_MEMORY_H
+#define BITCOIN_UTIL_MEMORY_H
#include <memory>
#include <utility>
diff --git a/src/utilmoneystr.cpp b/src/util/moneystr.cpp
index ea8a817ac4..f4e41eea4f 100644
--- a/src/utilmoneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -1,13 +1,13 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <utilmoneystr.h>
+#include <util/moneystr.h>
#include <primitives/transaction.h>
#include <tinyformat.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
std::string FormatMoney(const CAmount& n)
{
@@ -20,7 +20,7 @@ std::string FormatMoney(const CAmount& n)
// Right-trim excess zeros before the decimal point:
int nTrim = 0;
- for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
+ for (int i = str.size()-1; (str[i] == '0' && IsDigit(str[i-2])); --i)
++nTrim;
if (nTrim)
str.erase(str.size()-nTrim, nTrim);
@@ -41,29 +41,29 @@ bool ParseMoney(const char* pszIn, CAmount& nRet)
std::string strWhole;
int64_t nUnits = 0;
const char* p = pszIn;
- while (isspace(*p))
+ while (IsSpace(*p))
p++;
for (; *p; p++)
{
if (*p == '.')
{
p++;
- int64_t nMult = CENT*10;
- while (isdigit(*p) && (nMult > 0))
+ int64_t nMult = COIN / 10;
+ while (IsDigit(*p) && (nMult > 0))
{
nUnits += nMult * (*p++ - '0');
nMult /= 10;
}
break;
}
- if (isspace(*p))
+ if (IsSpace(*p))
break;
- if (!isdigit(*p))
+ if (!IsDigit(*p))
return false;
strWhole.insert(strWhole.end(), *p);
}
for (; *p; p++)
- if (!isspace(*p))
+ if (!IsSpace(*p))
return false;
if (strWhole.size() > 10) // guard against 63 bit overflow
return false;
diff --git a/src/utilmoneystr.h b/src/util/moneystr.h
index 1cbec49858..b8e2812a96 100644
--- a/src/utilmoneystr.h
+++ b/src/util/moneystr.h
@@ -1,24 +1,25 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**
* Money parsing/formatting utilities.
*/
-#ifndef BITCOIN_UTILMONEYSTR_H
-#define BITCOIN_UTILMONEYSTR_H
-
-#include <stdint.h>
-#include <string>
+#ifndef BITCOIN_UTIL_MONEYSTR_H
+#define BITCOIN_UTIL_MONEYSTR_H
#include <amount.h>
+#include <attributes.h>
+
+#include <cstdint>
+#include <string>
/* Do not use these functions to represent or parse monetary amounts to or from
* JSON but use AmountFromValue and ValueFromAmount for that.
*/
std::string FormatMoney(const CAmount& n);
-bool ParseMoney(const std::string& str, CAmount& nRet);
-bool ParseMoney(const char* pszIn, CAmount& nRet);
+NODISCARD bool ParseMoney(const std::string& str, CAmount& nRet);
+NODISCARD bool ParseMoney(const char* pszIn, CAmount& nRet);
-#endif // BITCOIN_UTILMONEYSTR_H
+#endif // BITCOIN_UTIL_MONEYSTR_H
diff --git a/src/util/rbf.cpp b/src/util/rbf.cpp
new file mode 100644
index 0000000000..d520a9606d
--- /dev/null
+++ b/src/util/rbf.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/rbf.h>
+
+#include <primitives/transaction.h>
+
+bool SignalsOptInRBF(const CTransaction &tx)
+{
+ for (const CTxIn &txin : tx.vin) {
+ if (txin.nSequence <= MAX_BIP125_RBF_SEQUENCE) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/util/rbf.h b/src/util/rbf.h
new file mode 100644
index 0000000000..d3ef110628
--- /dev/null
+++ b/src/util/rbf.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_RBF_H
+#define BITCOIN_UTIL_RBF_H
+
+#include <cstdint>
+
+class CTransaction;
+
+static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd;
+
+// Check whether the sequence numbers on this transaction are signaling
+// opt-in to replace-by-fee, according to BIP 125
+bool SignalsOptInRBF(const CTransaction &tx);
+
+#endif // BITCOIN_UTIL_RBF_H
diff --git a/src/utilstrencodings.cpp b/src/util/strencodings.cpp
index c6927021cb..0acbb4f117 100644
--- a/src/utilstrencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -1,12 +1,13 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <tinyformat.h>
+#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <errno.h>
@@ -19,6 +20,7 @@ static const std::string SAFE_CHARS[] =
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
+ CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
};
std::string SanitizeString(const std::string& str, int rule)
@@ -71,7 +73,7 @@ bool IsHexNumber(const std::string& str)
if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
starting_location = 2;
}
- for (auto c : str.substr(starting_location)) {
+ for (const char c : str.substr(starting_location)) {
if (HexDigit(c) < 0) return false;
}
// Return false for empty string or "0x".
@@ -84,7 +86,7 @@ std::vector<unsigned char> ParseHex(const char* psz)
std::vector<unsigned char> vch;
while (true)
{
- while (isspace(*psz))
+ while (IsSpace(*psz))
psz++;
signed char c = HexDigit(*psz++);
if (c == (signed char)-1)
@@ -139,7 +141,7 @@ std::string EncodeBase64(const std::string& str)
return EncodeBase64((const unsigned char*)str.c_str(), str.size());
}
-std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
+std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
{
static const int decode64_table[256] =
{
@@ -181,14 +183,14 @@ std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
++p;
}
valid = valid && (p - e) % 4 == 0 && p - q < 4;
- if (pfInvalid) *pfInvalid = !valid;
+ if (pf_invalid) *pf_invalid = !valid;
return ret;
}
-std::string DecodeBase64(const std::string& str)
+std::string DecodeBase64(const std::string& str, bool* pf_invalid)
{
- std::vector<unsigned char> vchRet = DecodeBase64(str.c_str());
+ std::vector<unsigned char> vchRet = DecodeBase64(str.c_str(), pf_invalid);
return std::string((const char*)vchRet.data(), vchRet.size());
}
@@ -208,7 +210,7 @@ std::string EncodeBase32(const std::string& str)
return EncodeBase32((const unsigned char*)str.c_str(), str.size());
}
-std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
+std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
{
static const int decode32_table[256] =
{
@@ -250,22 +252,22 @@ std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
++p;
}
valid = valid && (p - e) % 8 == 0 && p - q < 8;
- if (pfInvalid) *pfInvalid = !valid;
+ if (pf_invalid) *pf_invalid = !valid;
return ret;
}
-std::string DecodeBase32(const std::string& str)
+std::string DecodeBase32(const std::string& str, bool* pf_invalid)
{
- std::vector<unsigned char> vchRet = DecodeBase32(str.c_str());
+ std::vector<unsigned char> vchRet = DecodeBase32(str.c_str(), pf_invalid);
return std::string((const char*)vchRet.data(), vchRet.size());
}
-static bool ParsePrechecks(const std::string& str)
+NODISCARD static bool ParsePrechecks(const std::string& str)
{
if (str.empty()) // No empty string allowed
return false;
- if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
+ if (str.size() >= 1 && (IsSpace(str[0]) || IsSpace(str[str.size()-1]))) // No padding allowed
return false;
if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
return false;
@@ -544,3 +546,14 @@ bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
return true;
}
+void Downcase(std::string& str)
+{
+ std::transform(str.begin(), str.end(), str.begin(), [](char c){return ToLower(c);});
+}
+
+std::string Capitalize(std::string str)
+{
+ if (str.empty()) return str;
+ str[0] = ToUpper(str.front());
+ return str;
+}
diff --git a/src/utilstrencodings.h b/src/util/strencodings.h
index 47f9afba1c..7c4364a082 100644
--- a/src/utilstrencodings.h
+++ b/src/util/strencodings.h
@@ -1,22 +1,21 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**
* Utilities for converting data from/to strings.
*/
-#ifndef BITCOIN_UTILSTRENCODINGS_H
-#define BITCOIN_UTILSTRENCODINGS_H
+#ifndef BITCOIN_UTIL_STRENCODINGS_H
+#define BITCOIN_UTIL_STRENCODINGS_H
-#include <stdint.h>
+#include <attributes.h>
+
+#include <cstdint>
+#include <iterator>
#include <string>
#include <vector>
-#define BEGIN(a) ((char*)&(a))
-#define END(a) ((char*)&((&(a))[1]))
-#define UBEGIN(a) ((unsigned char*)&(a))
-#define UEND(a) ((unsigned char*)&((&(a))[1]))
#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
/** Used by SanitizeString() */
@@ -25,6 +24,7 @@ enum SafeChars
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
+ SAFE_CHARS_URI, //!< Chars allowed in URIs (RFC 3986)
};
/**
@@ -45,12 +45,12 @@ bool IsHex(const std::string& str);
* Return true if the string is a hex number, optionally prefixed with "0x"
*/
bool IsHexNumber(const std::string& str);
-std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = nullptr);
-std::string DecodeBase64(const std::string& str);
+std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid = nullptr);
+std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr);
std::string EncodeBase64(const unsigned char* pch, size_t len);
std::string EncodeBase64(const std::string& str);
-std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = nullptr);
-std::string DecodeBase32(const std::string& str);
+std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid = nullptr);
+std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr);
std::string EncodeBase32(const unsigned char* pch, size_t len);
std::string EncodeBase32(const std::string& str);
@@ -72,63 +72,75 @@ constexpr bool IsDigit(char c)
}
/**
+ * Tests if the given character is a whitespace character. The whitespace characters
+ * are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal
+ * tab ('\t'), and vertical tab ('\v').
+ *
+ * This function is locale independent. Under the C locale this function gives the
+ * same result as std::isspace.
+ *
+ * @param[in] c character to test
+ * @return true if the argument is a whitespace character; otherwise false
+ */
+constexpr inline bool IsSpace(char c) noexcept {
+ return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
+}
+
+/**
* Convert string to signed 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-bool ParseInt32(const std::string& str, int32_t *out);
+NODISCARD bool ParseInt32(const std::string& str, int32_t *out);
/**
* Convert string to signed 64-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-bool ParseInt64(const std::string& str, int64_t *out);
+NODISCARD bool ParseInt64(const std::string& str, int64_t *out);
/**
* Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-bool ParseUInt32(const std::string& str, uint32_t *out);
+NODISCARD bool ParseUInt32(const std::string& str, uint32_t *out);
/**
* Convert decimal string to unsigned 64-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-bool ParseUInt64(const std::string& str, uint64_t *out);
+NODISCARD bool ParseUInt64(const std::string& str, uint64_t *out);
/**
* Convert string to double with strict parse error feedback.
* @returns true if the entire string could be parsed as valid double,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-bool ParseDouble(const std::string& str, double *out);
+NODISCARD bool ParseDouble(const std::string& str, double *out);
template<typename T>
-std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
+std::string HexStr(const T itbegin, const T itend)
{
std::string rv;
static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- rv.reserve((itend-itbegin)*3);
+ rv.reserve(std::distance(itbegin, itend) * 2);
for(T it = itbegin; it < itend; ++it)
{
unsigned char val = (unsigned char)(*it);
- if(fSpaces && it != itbegin)
- rv.push_back(' ');
rv.push_back(hexmap[val>>4]);
rv.push_back(hexmap[val&15]);
}
-
return rv;
}
template<typename T>
-inline std::string HexStr(const T& vch, bool fSpaces=false)
+inline std::string HexStr(const T& vch)
{
- return HexStr(vch.begin(), vch.end(), fSpaces);
+ return HexStr(vch.begin(), vch.end());
}
/**
@@ -157,7 +169,7 @@ bool TimingResistantEqual(const T& a, const T& b)
* @returns true on success, false on error.
* @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger.
*/
-bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);
+NODISCARD bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);
/** Convert from one power-of-2 number base to another. */
template<int frombits, int tobits, bool pad, typename O, typename I>
@@ -183,4 +195,48 @@ bool ConvertBits(const O& outfn, I it, I end) {
return true;
}
-#endif // BITCOIN_UTILSTRENCODINGS_H
+/**
+ * Converts the given character to its lowercase equivalent.
+ * This function is locale independent. It only converts uppercase
+ * characters in the standard 7-bit ASCII range.
+ * @param[in] c the character to convert to lowercase.
+ * @return the lowercase equivalent of c; or the argument
+ * if no conversion is possible.
+ */
+constexpr char ToLower(char c)
+{
+ return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c);
+}
+
+/**
+ * Converts the given string to its lowercase equivalent.
+ * This function is locale independent. It only converts uppercase
+ * characters in the standard 7-bit ASCII range.
+ * @param[in,out] str the string to convert to lowercase.
+ */
+void Downcase(std::string& str);
+
+/**
+ * Converts the given character to its uppercase equivalent.
+ * This function is locale independent. It only converts lowercase
+ * characters in the standard 7-bit ASCII range.
+ * @param[in] c the character to convert to uppercase.
+ * @return the uppercase equivalent of c; or the argument
+ * if no conversion is possible.
+ */
+constexpr char ToUpper(char c)
+{
+ return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
+}
+
+/**
+ * Capitalizes the first character of the given string.
+ * This function is locale independent. It only capitalizes the
+ * first character of the argument if it has an uppercase equivalent
+ * in the standard 7-bit ASCII range.
+ * @param[in] str the string to capitalize.
+ * @return string with the first letter capitalized.
+ */
+std::string Capitalize(std::string str);
+
+#endif // BITCOIN_UTIL_STRENCODINGS_H
diff --git a/src/util.cpp b/src/util/system.cpp
index 238554ee4a..6925bda4ef 100644
--- a/src/util.cpp
+++ b/src/util/system.cpp
@@ -1,14 +1,14 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <util.h>
+#include <util/system.h>
#include <chainparamsbase.h>
#include <random.h>
#include <serialize.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <stdarg.h>
@@ -44,11 +44,6 @@
#pragma warning(disable:4717)
#endif
-#ifdef _WIN32_WINNT
-#undef _WIN32_WINNT
-#endif
-#define _WIN32_WINNT 0x0501
-
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif
@@ -58,90 +53,32 @@
#ifndef NOMINMAX
#define NOMINMAX
#endif
+#include <codecvt>
#include <io.h> /* for _commit */
+#include <shellapi.h>
#include <shlobj.h>
#endif
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-
#ifdef HAVE_MALLOPT_ARENA_MAX
#include <malloc.h>
#endif
-#include <boost/interprocess/sync/file_lock.hpp>
-#include <boost/thread.hpp>
-#include <openssl/crypto.h>
-#include <openssl/rand.h>
-#include <openssl/conf.h>
#include <thread>
// Application startup time (used for uptime calculation)
const int64_t nStartupTime = GetTime();
const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf";
-const char * const BITCOIN_PID_FILENAME = "bitcoind.pid";
ArgsManager gArgs;
-CTranslationInterface translationInterface;
-
-/** Init OpenSSL library multithreading support */
-static std::unique_ptr<CCriticalSection[]> ppmutexOpenSSL;
-void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
-{
- if (mode & CRYPTO_LOCK) {
- ENTER_CRITICAL_SECTION(ppmutexOpenSSL[i]);
- } else {
- LEAVE_CRITICAL_SECTION(ppmutexOpenSSL[i]);
- }
-}
-
-// Singleton for wrapping OpenSSL setup/teardown.
-class CInit
-{
-public:
- CInit()
- {
- // Init OpenSSL library multithreading support
- ppmutexOpenSSL.reset(new CCriticalSection[CRYPTO_num_locks()]);
- CRYPTO_set_locking_callback(locking_callback);
-
- // OpenSSL can optionally load a config file which lists optional loadable modules and engines.
- // We don't use them so we don't require the config. However some of our libs may call functions
- // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing
- // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
- // that the config appears to have been loaded and there are no modules/engines available.
- OPENSSL_no_config();
-
-#ifdef WIN32
- // Seed OpenSSL PRNG with current contents of the screen
- RAND_screen();
-#endif
-
- // Seed OpenSSL PRNG with performance counter
- RandAddSeed();
- }
- ~CInit()
- {
- // Securely erase the memory used by the PRNG
- RAND_cleanup();
- // Shutdown OpenSSL library multithreading support
- CRYPTO_set_locking_callback(nullptr);
- // Clear the set of locks now to maintain symmetry with the constructor.
- ppmutexOpenSSL.reset();
- }
-}
-instance_of_cinit;
-
/** A map that contains all the currently held directory locks. After
* successful locking, these will be held here until the global destructor
* cleans them up and thus automatically unlocks them, or ReleaseDirectoryLocks
* is called.
*/
-static std::map<std::string, std::unique_ptr<boost::interprocess::file_lock>> dir_locks;
+static std::map<std::string, std::unique_ptr<fsbridge::FileLock>> dir_locks;
/** Mutex to protect dir_locks. */
static std::mutex cs_dir_locks;
@@ -158,22 +95,23 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b
// Create empty lock file if it doesn't exist.
FILE* file = fsbridge::fopen(pathLockFile, "a");
if (file) fclose(file);
-
- try {
- auto lock = MakeUnique<boost::interprocess::file_lock>(pathLockFile.string().c_str());
- if (!lock->try_lock()) {
- return false;
- }
- if (!probe_only) {
- // Lock successful and we're not just probing, put it into the map
- dir_locks.emplace(pathLockFile.string(), std::move(lock));
- }
- } catch (const boost::interprocess::interprocess_exception& e) {
- return error("Error while attempting to lock directory %s: %s", directory.string(), e.what());
+ auto lock = MakeUnique<fsbridge::FileLock>(pathLockFile);
+ if (!lock->TryLock()) {
+ return error("Error while attempting to lock directory %s: %s", directory.string(), lock->GetReason());
+ }
+ if (!probe_only) {
+ // Lock successful and we're not just probing, put it into the map
+ dir_locks.emplace(pathLockFile.string(), std::move(lock));
}
return true;
}
+void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name)
+{
+ std::lock_guard<std::mutex> lock(cs_dir_locks);
+ dir_locks.erase((directory / lockfile_name).string());
+}
+
void ReleaseDirectoryLocks()
{
std::lock_guard<std::mutex> ulock(cs_dir_locks);
@@ -193,6 +131,14 @@ bool DirIsWritable(const fs::path& directory)
return true;
}
+bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes)
+{
+ constexpr uint64_t min_disk_space = 52428800; // 50 MiB
+
+ uint64_t free_bytes_available = fs::space(dir).available;
+ return free_bytes_available >= min_disk_space + additional_bytes;
+}
+
/**
* Interpret a string argument as a boolean.
*
@@ -224,7 +170,7 @@ public:
/** Determine whether to use config settings in the default section,
* See also comments around ArgsManager::ArgsManager() below. */
- static inline bool UseDefaultSection(const ArgsManager& am, const std::string& arg)
+ static inline bool UseDefaultSection(const ArgsManager& am, const std::string& arg) EXCLUSIVE_LOCKS_REQUIRED(am.cs_args)
{
return (am.m_network == CBaseChainParams::MAIN || am.m_network_only_args.count(arg) == 0);
}
@@ -303,7 +249,7 @@ public:
/* Special test for -testnet and -regtest args, because we
* don't want to be confused by craziness like "[regtest] testnet=1"
*/
- static inline bool GetNetBoolArg(const ArgsManager &am, const std::string& net_arg)
+ static inline bool GetNetBoolArg(const ArgsManager &am, const std::string& net_arg) EXCLUSIVE_LOCKS_REQUIRED(am.cs_args)
{
std::pair<bool,std::string> found_result(false,std::string());
found_result = GetArgHelper(am.m_override_args, net_arg, true);
@@ -378,13 +324,17 @@ ArgsManager::ArgsManager() :
// nothing to do
}
-void ArgsManager::WarnForSectionOnlyArgs()
+const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
{
+ std::set<std::string> unsuitables;
+
+ LOCK(cs_args);
+
// if there's no section selected, don't worry
- if (m_network.empty()) return;
+ if (m_network.empty()) return std::set<std::string> {};
// if it's okay to use the default section for this network, don't worry
- if (m_network == CBaseChainParams::MAIN) return;
+ if (m_network == CBaseChainParams::MAIN) return std::set<std::string> {};
for (const auto& arg : m_network_only_args) {
std::pair<bool, std::string> found_result;
@@ -402,12 +352,29 @@ void ArgsManager::WarnForSectionOnlyArgs()
if (!found_result.first) continue;
// otherwise, issue a warning
- LogPrintf("Warning: Config setting for %s only applied on %s network when in [%s] section.\n", arg, m_network, m_network);
+ unsuitables.insert(arg);
}
+ return unsuitables;
+}
+
+const std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const
+{
+ // Section names to be recognized in the config file.
+ static const std::set<std::string> available_sections{
+ CBaseChainParams::REGTEST,
+ CBaseChainParams::TESTNET,
+ CBaseChainParams::MAIN
+ };
+
+ LOCK(cs_args);
+ std::list<SectionInfo> unrecognized = m_config_sections;
+ unrecognized.remove_if([](const SectionInfo& appeared){ return available_sections.find(appeared.m_name) != available_sections.end(); });
+ return unrecognized;
}
void ArgsManager::SelectConfigNetwork(const std::string& network)
{
+ LOCK(cs_args);
m_network = network;
}
@@ -425,7 +392,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
key.erase(is_index);
}
#ifdef WIN32
- std::transform(key.begin(), key.end(), key.begin(), ::tolower);
+ std::transform(key.begin(), key.end(), key.begin(), ToLower);
if (key[0] == '/')
key[0] = '-';
#endif
@@ -476,6 +443,7 @@ bool ArgsManager::IsArgKnown(const std::string& key) const
arg_no_net = std::string("-") + key.substr(option_index + 1, std::string::npos);
}
+ LOCK(cs_args);
for (const auto& arg_map : m_available_args) {
if (arg_map.second.count(arg_no_net)) return true;
}
@@ -579,6 +547,7 @@ void ArgsManager::AddArg(const std::string& name, const std::string& help, const
eq_index = name.size();
}
+ LOCK(cs_args);
std::map<std::string, Arg>& arg_map = m_available_args[cat];
auto ret = arg_map.emplace(name.substr(0, eq_index), Arg(name.substr(eq_index, name.size() - eq_index), help, debug_only));
assert(ret.second); // Make sure an insertion actually happened
@@ -596,6 +565,7 @@ std::string ArgsManager::GetHelpMessage() const
const bool show_debug = gArgs.GetBoolArg("-help-debug", false);
std::string usage = "";
+ LOCK(cs_args);
for (const auto& arg_map : m_available_args) {
switch(arg_map.first) {
case OptionsCategory::OPTIONS:
@@ -661,7 +631,13 @@ std::string ArgsManager::GetHelpMessage() const
bool HelpRequested(const ArgsManager& args)
{
- return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help");
+ return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help") || args.IsArgSet("-help-debug");
+}
+
+void SetupHelpOptions(ArgsManager& args)
+{
+ args.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
+ args.AddHiddenArgs({"-h", "-help"});
}
static const int screenWidth = 79;
@@ -728,18 +704,17 @@ fs::path GetDefaultDataDir()
#endif
}
-static fs::path g_blocks_path_cached;
static fs::path g_blocks_path_cache_net_specific;
static fs::path pathCached;
static fs::path pathCachedNetSpecific;
static CCriticalSection csPathCached;
-const fs::path &GetBlocksDir(bool fNetSpecific)
+const fs::path &GetBlocksDir()
{
LOCK(csPathCached);
- fs::path &path = fNetSpecific ? g_blocks_path_cache_net_specific : g_blocks_path_cached;
+ fs::path &path = g_blocks_path_cache_net_specific;
// This can be called during exceptions by LogPrintf(), so we cache the
// value so we don't have to do memory allocations after that.
@@ -755,9 +730,8 @@ const fs::path &GetBlocksDir(bool fNetSpecific)
} else {
path = GetDataDir(false);
}
- if (fNetSpecific)
- path /= BaseParams().DataDir();
+ path /= BaseParams().DataDir();
path /= "blocks";
fs::create_directories(path);
return path;
@@ -801,7 +775,6 @@ void ClearDatadirCache()
pathCached = fs::path();
pathCachedNetSpecific = fs::path();
- g_blocks_path_cached = fs::path();
g_blocks_path_cache_net_specific = fs::path();
}
@@ -820,35 +793,59 @@ static std::string TrimString(const std::string& str, const std::string& pattern
return str.substr(front, end - front + 1);
}
-static std::vector<std::pair<std::string, std::string>> GetConfigOptions(std::istream& stream)
+static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections)
{
- std::vector<std::pair<std::string, std::string>> options;
std::string str, prefix;
std::string::size_type pos;
+ int linenr = 1;
while (std::getline(stream, str)) {
+ bool used_hash = false;
if ((pos = str.find('#')) != std::string::npos) {
str = str.substr(0, pos);
+ used_hash = true;
}
const static std::string pattern = " \t\r\n";
str = TrimString(str, pattern);
if (!str.empty()) {
if (*str.begin() == '[' && *str.rbegin() == ']') {
- prefix = str.substr(1, str.size() - 2) + '.';
+ const std::string section = str.substr(1, str.size() - 2);
+ sections.emplace_back(SectionInfo{section, filepath, linenr});
+ prefix = section + '.';
+ } else if (*str.begin() == '-') {
+ error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str);
+ return false;
} else if ((pos = str.find('=')) != std::string::npos) {
std::string name = prefix + TrimString(str.substr(0, pos), pattern);
std::string value = TrimString(str.substr(pos + 1), pattern);
+ if (used_hash && name.find("rpcpassword") != std::string::npos) {
+ error = strprintf("parse error on line %i, using # in rpcpassword can be ambiguous and should be avoided", linenr);
+ return false;
+ }
options.emplace_back(name, value);
+ if ((pos = name.rfind('.')) != std::string::npos && prefix.length() <= pos) {
+ sections.emplace_back(SectionInfo{name.substr(0, pos), filepath, linenr});
+ }
+ } else {
+ error = strprintf("parse error on line %i: %s", linenr, str);
+ if (str.size() >= 2 && str.substr(0, 2) == "no") {
+ error += strprintf(", if you intended to specify a negated option, use %s=1 instead", str);
+ }
+ return false;
}
}
+ ++linenr;
}
- return options;
+ return true;
}
-bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys)
+bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys)
{
LOCK(cs_args);
-
- for (const std::pair<std::string, std::string>& option : GetConfigOptions(stream)) {
+ std::vector<std::pair<std::string, std::string>> options;
+ if (!GetConfigOptions(stream, filepath, error, options, m_config_sections)) {
+ return false;
+ }
+ for (const std::pair<std::string, std::string>& option : options) {
std::string strKey = std::string("-") + option.first;
std::string strValue = option.second;
@@ -876,19 +873,25 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
{
LOCK(cs_args);
m_config_args.clear();
+ m_config_sections.clear();
}
const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME);
- fs::ifstream stream(GetConfigFile(confPath));
+ fsbridge::ifstream stream(GetConfigFile(confPath));
// ok to not have a config file
if (stream.good()) {
- if (!ReadConfigStream(stream, error, ignore_invalid_keys)) {
+ if (!ReadConfigStream(stream, confPath, error, ignore_invalid_keys)) {
return false;
}
// if there is an -includeconf in the override args, but it is empty, that means the user
// passed '-noincludeconf' on the command line, in which case we should not include anything
- if (m_override_args.count("-includeconf") == 0) {
+ bool emptyIncludeConf;
+ {
+ LOCK(cs_args);
+ emptyIncludeConf = m_override_args.count("-includeconf") == 0;
+ }
+ if (emptyIncludeConf) {
std::string chain_id = GetChainName();
std::vector<std::string> includeconf(GetArgs("-includeconf"));
{
@@ -907,9 +910,9 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
}
for (const std::string& to_include : includeconf) {
- fs::ifstream include_config(GetConfigFile(to_include));
+ fsbridge::ifstream include_config(GetConfigFile(to_include));
if (include_config.good()) {
- if (!ReadConfigStream(include_config, error, ignore_invalid_keys)) {
+ if (!ReadConfigStream(include_config, to_include, error, ignore_invalid_keys)) {
return false;
}
LogPrintf("Included configuration file %s\n", to_include.c_str());
@@ -948,6 +951,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
std::string ArgsManager::GetChainName() const
{
+ LOCK(cs_args);
bool fRegTest = ArgsManagerHelper::GetNetBoolArg(*this, "-regtest");
bool fTestNet = ArgsManagerHelper::GetNetBoolArg(*this, "-testnet");
@@ -960,27 +964,10 @@ std::string ArgsManager::GetChainName() const
return CBaseChainParams::MAIN;
}
-#ifndef WIN32
-fs::path GetPidFile()
-{
- return AbsPathForConfigVal(fs::path(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME)));
-}
-
-void CreatePidFile(const fs::path &path, pid_t pid)
-{
- FILE* file = fsbridge::fopen(path, "w");
- if (file)
- {
- fprintf(file, "%d\n", pid);
- fclose(file);
- }
-}
-#endif
-
bool RenameOver(fs::path src, fs::path dest)
{
#ifdef WIN32
- return MoveFileExA(src.string().c_str(), dest.string().c_str(),
+ return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
MOVEFILE_REPLACE_EXISTING) != 0;
#else
int rc = std::rename(src.string().c_str(), dest.string().c_str());
@@ -1098,11 +1085,12 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
fcntl(fileno(file), F_PREALLOCATE, &fst);
}
ftruncate(fileno(file), fst.fst_length);
-#elif defined(__linux__)
+#else
+ #if defined(__linux__)
// Version using posix_fallocate
off_t nEndPos = (off_t)offset + length;
- posix_fallocate(fileno(file), 0, nEndPos);
-#else
+ if (0 == posix_fallocate(fileno(file), 0, nEndPos)) return;
+ #endif
// Fallback version
// TODO: just write one byte per block
static const char buf[65536] = {};
@@ -1122,14 +1110,14 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
#ifdef WIN32
fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
{
- char pszPath[MAX_PATH] = "";
+ WCHAR pszPath[MAX_PATH] = L"";
- if(SHGetSpecialFolderPathA(nullptr, pszPath, nFolder, fCreate))
+ if(SHGetSpecialFolderPathW(nullptr, pszPath, nFolder, fCreate))
{
return fs::path(pszPath);
}
- LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
+ LogPrintf("SHGetSpecialFolderPathW() failed, could not obtain requested path.\n");
return fs::path("");
}
#endif
@@ -1137,25 +1125,13 @@ fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
void runCommand(const std::string& strCommand)
{
if (strCommand.empty()) return;
+#ifndef WIN32
int nErr = ::system(strCommand.c_str());
- if (nErr)
- LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
-}
-
-void RenameThread(const char* name)
-{
-#if defined(PR_SET_NAME)
- // Only the first 15 characters are used (16 - NUL terminator)
- ::prctl(PR_SET_NAME, name, 0, 0, 0);
-#elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
- pthread_set_name_np(pthread_self(), name);
-
-#elif defined(MAC_OSX)
- pthread_setname_np(name);
#else
- // Prevent warnings for unused parameters...
- (void)name;
+ int nErr = ::_wsystem(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().from_bytes(strCommand).c_str());
#endif
+ if (nErr)
+ LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
}
void SetupEnvironment()
@@ -1178,13 +1154,21 @@ void SetupEnvironment()
} catch (const std::runtime_error&) {
setenv("LC_ALL", "C", 1);
}
+#elif defined(WIN32)
+ // Set the default input/output charset is utf-8
+ SetConsoleCP(CP_UTF8);
+ SetConsoleOutputCP(CP_UTF8);
#endif
// The path locale is lazy initialized and to avoid deinitialization errors
// in multithreading environments, it is set explicitly by the main thread.
// A dummy locale is used to extract the internal default locale, used by
// fs::path, which is then used to explicitly imbue the path.
std::locale loc = fs::path::imbue(std::locale::classic());
+#ifndef WIN32
fs::path::imbue(loc);
+#else
+ fs::path::imbue(std::locale(loc, new std::codecvt_utf8_utf16<wchar_t>()));
+#endif
}
bool SetupNetworking()
@@ -1226,10 +1210,10 @@ fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific)
return fs::absolute(path, GetDataDir(net_specific));
}
-int ScheduleBatchPriority(void)
+int ScheduleBatchPriority()
{
#ifdef SCHED_BATCH
- const static sched_param param{0};
+ const static sched_param param{};
if (int ret = pthread_setschedparam(pthread_self(), SCHED_BATCH, &param)) {
LogPrintf("Failed to pthread_setschedparam: %s\n", strerror(errno));
return ret;
@@ -1239,3 +1223,30 @@ int ScheduleBatchPriority(void)
return 1;
#endif
}
+
+namespace util {
+#ifdef WIN32
+WinCmdLineArgs::WinCmdLineArgs()
+{
+ wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_cvt;
+ argv = new char*[argc];
+ args.resize(argc);
+ for (int i = 0; i < argc; i++) {
+ args[i] = utf8_cvt.to_bytes(wargv[i]);
+ argv[i] = &*args[i].begin();
+ }
+ LocalFree(wargv);
+}
+
+WinCmdLineArgs::~WinCmdLineArgs()
+{
+ delete[] argv;
+}
+
+std::pair<int, char**> WinCmdLineArgs::get()
+{
+ return std::make_pair(argc, argv);
+}
+#endif
+} // namespace util
diff --git a/src/util.h b/src/util/system.h
index 23b2a787e4..1a83cb67b1 100644
--- a/src/util.h
+++ b/src/util/system.h
@@ -7,20 +7,23 @@
* Server/client environment: argument handling, config file parsing,
* thread wrappers, startup time
*/
-#ifndef BITCOIN_UTIL_H
-#define BITCOIN_UTIL_H
+#ifndef BITCOIN_UTIL_SYSTEM_H
+#define BITCOIN_UTIL_SYSTEM_H
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif
+#include <attributes.h>
#include <compat.h>
+#include <compat/assumptions.h>
#include <fs.h>
#include <logging.h>
#include <sync.h>
+#include <util/threadnames.h>
#include <tinyformat.h>
-#include <utiltime.h>
-#include <utilmemory.h>
+#include <util/memory.h>
+#include <util/time.h>
#include <atomic>
#include <exception>
@@ -29,35 +32,26 @@
#include <stdint.h>
#include <string>
#include <unordered_set>
+#include <utility>
#include <vector>
-#include <boost/signals2/signal.hpp>
#include <boost/thread/condition_variable.hpp> // for boost::thread_interrupted
// Application startup time (used for uptime calculation)
int64_t GetStartupTime();
-/** Signals for translation. */
-class CTranslationInterface
-{
-public:
- /** Translate a message to the native language of the user. */
- boost::signals2::signal<std::string (const char* psz)> Translate;
-};
-
-extern CTranslationInterface translationInterface;
-
extern const char * const BITCOIN_CONF_FILENAME;
-extern const char * const BITCOIN_PID_FILENAME;
+
+/** Translate a message to the native language of the user. */
+const extern std::function<std::string(const char*)> G_TRANSLATION_FUN;
/**
- * Translation function: Call Translate signal on UI interface, which returns a boost::optional result.
- * If no translation slot is registered, nothing is returned, and simply return the input.
+ * Translation function.
+ * If no translation function is set, simply return the input.
*/
inline std::string _(const char* psz)
{
- boost::optional<std::string> rv = translationInterface.Translate(psz);
- return rv ? (*rv) : psz;
+ return G_TRANSLATION_FUN ? (G_TRANSLATION_FUN)(psz) : psz;
}
void SetupEnvironment();
@@ -77,7 +71,9 @@ int RaiseFileDescriptorLimit(int nMinFD);
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
bool RenameOver(fs::path src, fs::path dest);
bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false);
+void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name);
bool DirIsWritable(const fs::path& directory);
+bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes = 0);
/** Release all directory locks. This is used for unit testing only, at runtime
* the global destructor will take care of the locks.
@@ -86,14 +82,11 @@ void ReleaseDirectoryLocks();
bool TryCreateDirectories(const fs::path& p);
fs::path GetDefaultDataDir();
-const fs::path &GetBlocksDir(bool fNetSpecific = true);
+// The blocks directory is always net specific.
+const fs::path &GetBlocksDir();
const fs::path &GetDataDir(bool fNetSpecific = true);
void ClearDatadirCache();
fs::path GetConfigFile(const std::string& confPath);
-#ifndef WIN32
-fs::path GetPidFile();
-void CreatePidFile(const fs::path &path, pid_t pid);
-#endif
#ifdef WIN32
fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
@@ -136,6 +129,13 @@ enum class OptionsCategory {
HIDDEN // Always the last option to avoid printing these in the help
};
+struct SectionInfo
+{
+ std::string m_name;
+ std::string m_file;
+ int m_line;
+};
+
class ArgsManager
{
protected:
@@ -151,13 +151,14 @@ protected:
};
mutable CCriticalSection cs_args;
- std::map<std::string, std::vector<std::string>> m_override_args;
- std::map<std::string, std::vector<std::string>> m_config_args;
- std::string m_network;
- std::set<std::string> m_network_only_args;
- std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args;
+ std::map<std::string, std::vector<std::string>> m_override_args GUARDED_BY(cs_args);
+ std::map<std::string, std::vector<std::string>> m_config_args GUARDED_BY(cs_args);
+ std::string m_network GUARDED_BY(cs_args);
+ std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
+ std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
+ std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
- bool ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys = false);
+ NODISCARD bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false);
public:
ArgsManager();
@@ -167,8 +168,8 @@ public:
*/
void SelectConfigNetwork(const std::string& network);
- bool ParseParameters(int argc, const char* const argv[], std::string& error);
- bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
+ NODISCARD bool ParseParameters(int argc, const char* const argv[], std::string& error);
+ NODISCARD bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
/**
* Log warnings for options in m_section_only_args when
@@ -176,7 +177,12 @@ public:
* on the command line or in a network-specific section in the
* config file.
*/
- void WarnForSectionOnlyArgs();
+ const std::set<std::string> GetUnsuitableSectionOnlyArgs() const;
+
+ /**
+ * Log warnings for unrecognized section names in the config file.
+ */
+ const std::list<SectionInfo> GetUnrecognizedSections() const;
/**
* Return a vector of strings of the given argument
@@ -271,7 +277,10 @@ public:
/**
* Clear available arguments
*/
- void ClearArgs() { m_available_args.clear(); }
+ void ClearArgs() {
+ LOCK(cs_args);
+ m_available_args.clear();
+ }
/**
* Get the help string
@@ -291,6 +300,9 @@ extern ArgsManager gArgs;
*/
bool HelpRequested(const ArgsManager& args);
+/** Add help options to the args manager */
+void SetupHelpOptions(ArgsManager& args);
+
/**
* Format a string to be used as group of options in help messages
*
@@ -314,15 +326,12 @@ std::string HelpMessageOpt(const std::string& option, const std::string& message
*/
int GetNumCores();
-void RenameThread(const char* name);
-
/**
* .. and a wrapper that just calls func once
*/
template <typename Callable> void TraceThread(const char* name, Callable func)
{
- std::string s = strprintf("bitcoin-%s", name);
- RenameThread(s.c_str());
+ util::ThreadRename(name);
try
{
LogPrintf("%s thread start\n", name);
@@ -353,7 +362,7 @@ std::string CopyrightHolders(const std::string& strPrefix);
* @return The return value of sched_setschedule(), or 1 on systems without
* sched_setschedule().
*/
-int ScheduleBatchPriority(void);
+int ScheduleBatchPriority();
namespace util {
@@ -367,6 +376,21 @@ inline void insert(std::set<TsetT>& dst, const Tsrc& src) {
dst.insert(src.begin(), src.end());
}
+#ifdef WIN32
+class WinCmdLineArgs
+{
+public:
+ WinCmdLineArgs();
+ ~WinCmdLineArgs();
+ std::pair<int, char**> get();
+
+private:
+ int argc;
+ char** argv;
+ std::vector<std::string> args;
+};
+#endif
+
} // namespace util
-#endif // BITCOIN_UTIL_H
+#endif // BITCOIN_UTIL_SYSTEM_H
diff --git a/src/util/threadnames.cpp b/src/util/threadnames.cpp
new file mode 100644
index 0000000000..b221b0c975
--- /dev/null
+++ b/src/util/threadnames.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#include <atomic>
+#include <thread>
+
+#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
+#include <pthread.h>
+#include <pthread_np.h>
+#endif
+
+#include <util/threadnames.h>
+
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h> // For prctl, PR_SET_NAME, PR_GET_NAME
+#endif
+
+//! Set the thread's name at the process level. Does not affect the
+//! internal name.
+static void SetThreadName(const char* name)
+{
+#if defined(PR_SET_NAME)
+ // Only the first 15 characters are used (16 - NUL terminator)
+ ::prctl(PR_SET_NAME, name, 0, 0, 0);
+#elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
+ pthread_set_name_np(pthread_self(), name);
+#elif defined(MAC_OSX)
+ pthread_setname_np(name);
+#else
+ // Prevent warnings for unused parameters...
+ (void)name;
+#endif
+}
+
+// If we have thread_local, just keep thread ID and name in a thread_local
+// global.
+#if defined(HAVE_THREAD_LOCAL)
+
+static thread_local std::string g_thread_name;
+const std::string& util::ThreadGetInternalName() { return g_thread_name; }
+//! Set the in-memory internal name for this thread. Does not affect the process
+//! name.
+static void SetInternalName(std::string name) { g_thread_name = std::move(name); }
+
+// Without thread_local available, don't handle internal name at all.
+#else
+
+static const std::string empty_string;
+const std::string& util::ThreadGetInternalName() { return empty_string; }
+static void SetInternalName(std::string name) { }
+#endif
+
+void util::ThreadRename(std::string&& name)
+{
+ SetThreadName(("bitcoin-" + name).c_str());
+ SetInternalName(std::move(name));
+}
diff --git a/src/util/threadnames.h b/src/util/threadnames.h
new file mode 100644
index 0000000000..aaf07b9bf8
--- /dev/null
+++ b/src/util/threadnames.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_THREADNAMES_H
+#define BITCOIN_UTIL_THREADNAMES_H
+
+#include <string>
+
+namespace util {
+//! Rename a thread both in terms of an internal (in-memory) name as well
+//! as its system thread name.
+void ThreadRename(std::string&&);
+
+//! Get the thread's internal (in-memory) name; used e.g. for identification in
+//! logging.
+const std::string& ThreadGetInternalName();
+
+} // namespace util
+
+#endif // BITCOIN_UTIL_THREADNAMES_H
diff --git a/src/utiltime.cpp b/src/util/time.cpp
index e60996efe1..c0ede98701 100644
--- a/src/utiltime.cpp
+++ b/src/util/time.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,7 +7,7 @@
#include <config/bitcoin-config.h>
#endif
-#include <utiltime.h>
+#include <util/time.h>
#include <atomic>
#include <boost/date_time/posix_time/posix_time.hpp>
@@ -97,14 +97,3 @@ std::string FormatISO8601Date(int64_t nTime) {
#endif
return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday);
}
-
-std::string FormatISO8601Time(int64_t nTime) {
- struct tm ts;
- time_t time_val = nTime;
-#ifdef _MSC_VER
- gmtime_s(&ts, &time_val);
-#else
- gmtime_r(&time_val, &ts);
-#endif
- return strprintf("%02i:%02i:%02iZ", ts.tm_hour, ts.tm_min, ts.tm_sec);
-}
diff --git a/src/utiltime.h b/src/util/time.h
index 3bcbb00c16..68de1c156e 100644
--- a/src/utiltime.h
+++ b/src/util/time.h
@@ -1,10 +1,10 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_UTILTIME_H
-#define BITCOIN_UTILTIME_H
+#ifndef BITCOIN_UTIL_TIME_H
+#define BITCOIN_UTIL_TIME_H
#include <stdint.h>
#include <string>
@@ -33,6 +33,5 @@ void MilliSleep(int64_t n);
*/
std::string FormatISO8601DateTime(int64_t nTime);
std::string FormatISO8601Date(int64_t nTime);
-std::string FormatISO8601Time(int64_t nTime);
-#endif // BITCOIN_UTILTIME_H
+#endif // BITCOIN_UTIL_TIME_H
diff --git a/src/util/url.cpp b/src/util/url.cpp
new file mode 100644
index 0000000000..49eacbf2d0
--- /dev/null
+++ b/src/util/url.cpp
@@ -0,0 +1,21 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/url.h>
+
+#include <event2/http.h>
+#include <stdlib.h>
+#include <string>
+
+std::string urlDecode(const std::string &urlEncoded) {
+ std::string res;
+ if (!urlEncoded.empty()) {
+ char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, nullptr);
+ if (decoded) {
+ res = std::string(decoded);
+ free(decoded);
+ }
+ }
+ return res;
+}
diff --git a/src/util/url.h b/src/util/url.h
new file mode 100644
index 0000000000..3d7315a338
--- /dev/null
+++ b/src/util/url.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_URL_H
+#define BITCOIN_UTIL_URL_H
+
+#include <string>
+
+std::string urlDecode(const std::string &urlEncoded);
+
+#endif // BITCOIN_UTIL_URL_H
diff --git a/src/util/validation.cpp b/src/util/validation.cpp
new file mode 100644
index 0000000000..fe1f5a277e
--- /dev/null
+++ b/src/util/validation.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/validation.h>
+
+#include <consensus/validation.h>
+#include <tinyformat.h>
+
+/** Convert CValidationState to a human-readable message for logging */
+std::string FormatStateMessage(const CValidationState &state)
+{
+ return strprintf("%s%s (code %i)",
+ state.GetRejectReason(),
+ state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage(),
+ state.GetRejectCode());
+}
+
+const std::string strMessageMagic = "Bitcoin Signed Message:\n";
diff --git a/src/util/validation.h b/src/util/validation.h
new file mode 100644
index 0000000000..32559853ee
--- /dev/null
+++ b/src/util/validation.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_VALIDATION_H
+#define BITCOIN_UTIL_VALIDATION_H
+
+#include <string>
+
+class CValidationState;
+
+/** Convert CValidationState to a human-readable message for logging */
+std::string FormatStateMessage(const CValidationState &state);
+
+extern const std::string strMessageMagic;
+
+#endif // BITCOIN_UTIL_VALIDATION_H
diff --git a/src/validation.cpp b/src/validation.cpp
index 563cd59382..4347e0b0cc 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -8,18 +8,20 @@
#include <arith_uint256.h>
#include <chain.h>
#include <chainparams.h>
-#include <checkpoints.h>
#include <checkqueue.h>
#include <consensus/consensus.h>
#include <consensus/merkle.h>
+#include <consensus/tx_check.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <cuckoocache.h>
+#include <flatfile.h>
#include <hash.h>
#include <index/txindex.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/rbf.h>
+#include <policy/settings.h>
#include <pow.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
@@ -34,15 +36,19 @@
#include <txdb.h>
#include <txmempool.h>
#include <ui_interface.h>
+#include <uint256.h>
#include <undo.h>
-#include <util.h>
-#include <utilmoneystr.h>
-#include <utilstrencodings.h>
+#include <util/moneystr.h>
+#include <util/rbf.h>
+#include <util/strencodings.h>
+#include <util/system.h>
+#include <util/validation.h>
#include <validationinterface.h>
#include <warnings.h>
#include <future>
#include <sstream>
+#include <string>
#include <boost/algorithm/string/replace.hpp>
#include <boost/thread.hpp>
@@ -151,37 +157,39 @@ private:
CCriticalSection m_cs_chainstate;
public:
- CChain chainActive;
- BlockMap mapBlockIndex;
+ //! The current chain of blockheaders we consult and build on.
+ //! @see CChain, CBlockIndex.
+ CChain m_chain;
+ BlockMap mapBlockIndex GUARDED_BY(cs_main);
std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
CBlockIndex *pindexBestInvalid = nullptr;
bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock);
+ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) LOCKS_EXCLUDED(cs_main);
/**
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
* that it doesn't descend from an invalid block, and then add it to mapBlockIndex.
*/
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Block (dis)connection on a given view:
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
- CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false);
+ CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Block disconnection on our pcoinsTip:
- bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool);
+ bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Manual block validity manipulation:
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
- bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
- bool RewindBlockIndex(const CChainParams& params);
+ bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
bool LoadGenesisBlock(const CChainParams& chainparams);
void PruneBlockIndexCandidates();
@@ -189,8 +197,8 @@ public:
void UnloadBlockIndex();
private:
- bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace);
- bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool);
+ bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Create a new block index entry for a given block hash */
@@ -202,30 +210,40 @@ private:
*/
void CheckBlockIndex(const Consensus::Params& consensusParams);
- void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state);
+ void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-
+ void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-} g_chainstate;
+ //! Mark a block as not having block data
+ void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+} g_chainstate;
+CChain& ChainActive() { return g_chainstate.m_chain; }
-CCriticalSection cs_main;
+/**
+ * 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;
BlockMap& mapBlockIndex = g_chainstate.mapBlockIndex;
-CChain& chainActive = g_chainstate.chainActive;
CBlockIndex *pindexBestHeader = nullptr;
-CWaitableCriticalSection g_best_block_mutex;
-CConditionVariable g_best_block_cv;
+Mutex g_best_block_mutex;
+std::condition_variable g_best_block_cv;
uint256 g_best_block;
int nScriptCheckThreads = 0;
std::atomic_bool fImporting(false);
std::atomic_bool fReindex(false);
bool fHavePruned = false;
bool fPruneMode = false;
-bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
bool fRequireStandard = true;
bool fCheckBlockIndex = false;
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
@@ -238,17 +256,13 @@ uint256 hashAssumeValid;
arith_uint256 nMinimumChainWork;
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
-CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
CBlockPolicyEstimator feeEstimator;
CTxMemPool mempool(&feeEstimator);
-std::atomic_bool g_is_mempool_loaded{false};
/** Constant stuff for coinbase transactions we create: */
CScript COINBASE_FLAGS;
-const std::string strMessageMagic = "Bitcoin Signed Message:\n";
-
// Internal stuff
namespace {
CBlockIndex *&pindexBestInvalid = g_chainstate.pindexBestInvalid;
@@ -309,7 +323,9 @@ static bool FlushStateToDisk(const CChainParams& chainParams, CValidationState &
static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight);
static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = nullptr);
-static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
+static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly = false);
+static FlatFileSeq BlockFileSeq();
+static FlatFileSeq UndoFileSeq();
bool CheckFinalTx(const CTransaction &tx, int flags)
{
@@ -323,13 +339,13 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
// scheduled, so no flags are set.
flags = std::max(flags, 0);
- // CheckFinalTx() uses chainActive.Height()+1 to evaluate
+ // CheckFinalTx() uses ::ChainActive().Height()+1 to evaluate
// nLockTime because when IsFinalTx() is called within
// CBlock::AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a
// transaction can be part of the *next* block, we need to call
- // IsFinalTx() with one more than chainActive.Height().
- const int nBlockHeight = chainActive.Height() + 1;
+ // IsFinalTx() with one more than ::ChainActive().Height().
+ const int nBlockHeight = ::ChainActive().Height() + 1;
// BIP113 requires that time-locked transactions have nLockTime set to
// less than the median time of the previous block they're contained in.
@@ -337,7 +353,7 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
// chain tip, so we use that to calculate the median time passed to
// IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set.
const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
- ? chainActive.Tip()->GetMedianTimePast()
+ ? ::ChainActive().Tip()->GetMedianTimePast()
: GetAdjustedTime();
return IsFinalTx(tx, nBlockHeight, nBlockTime);
@@ -350,9 +366,9 @@ bool TestLockPointValidity(const LockPoints* lp)
// If there are relative lock times then the maxInputBlock will be set
// If there are no relative lock times, the LockPoints don't depend on the chain
if (lp->maxInputBlock) {
- // Check whether chainActive is an extension of the block at which the LockPoints
+ // Check whether ::ChainActive() is an extension of the block at which the LockPoints
// calculation was valid. If not LockPoints are no longer valid
- if (!chainActive.Contains(lp->maxInputBlock)) {
+ if (!::ChainActive().Contains(lp->maxInputBlock)) {
return false;
}
}
@@ -361,22 +377,22 @@ bool TestLockPointValidity(const LockPoints* lp)
return true;
}
-bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool useExistingLockPoints)
+bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp, bool useExistingLockPoints)
{
AssertLockHeld(cs_main);
- AssertLockHeld(mempool.cs);
+ AssertLockHeld(pool.cs);
- CBlockIndex* tip = chainActive.Tip();
+ CBlockIndex* tip = ::ChainActive().Tip();
assert(tip != nullptr);
CBlockIndex index;
index.pprev = tip;
- // CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
+ // CheckSequenceLocks() uses ::ChainActive().Height()+1 to evaluate
// height based locks because when SequenceLocks() is called within
// ConnectBlock(), the height of the block *being*
// evaluated is what is used.
// Thus if we want to know if a transaction can be part of the
- // *next* block, we need to use one more than chainActive.Height()
+ // *next* block, we need to use one more than ::ChainActive().Height()
index.nHeight = tip->nHeight + 1;
std::pair<int, int64_t> lockPair;
@@ -386,8 +402,8 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
lockPair.second = lp->time;
}
else {
- // pcoinsTip contains the UTXO set for chainActive.Tip()
- CCoinsViewMemPool viewMemPool(pcoinsTip.get(), mempool);
+ // pcoinsTip contains the UTXO set for ::ChainActive().Tip()
+ CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool);
std::vector<int> prevheights;
prevheights.resize(tx.vin.size());
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
@@ -421,7 +437,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
// lock on a mempool input, so we can use the return value of
// CheckSequenceLocks to indicate the LockPoints validity
int maxInputHeight = 0;
- for (int height : prevheights) {
+ for (const int height : prevheights) {
// Can ignore mempool inputs since we'll fail if they had non-zero locks
if (height != tip->nHeight+1) {
maxInputHeight = std::max(maxInputHeight, height);
@@ -448,23 +464,14 @@ static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age)
pcoinsTip->Uncache(removed);
}
-/** Convert CValidationState to a human-readable message for logging */
-std::string FormatStateMessage(const CValidationState &state)
-{
- return strprintf("%s%s (code %i)",
- state.GetRejectReason(),
- state.GetDebugMessage().empty() ? "" : ", "+state.GetDebugMessage(),
- state.GetRejectCode());
-}
-
-static bool IsCurrentForFeeEstimation()
+static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
if (IsInitialBlockDownload())
return false;
- if (chainActive.Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE))
+ if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE))
return false;
- if (chainActive.Height() < pindexBestHeader->nHeight - 1)
+ if (::ChainActive().Height() < pindexBestHeader->nHeight - 1)
return false;
return true;
}
@@ -482,7 +489,7 @@ static bool IsCurrentForFeeEstimation()
* and instead just erase from the mempool as needed.
*/
-static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool)
+static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
std::vector<uint256> vHashUpdate;
@@ -516,7 +523,7 @@ static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool,
mempool.UpdateTransactionsFromBlock(vHashUpdate);
// We also need to remove any now-immature transactions
- mempool.removeForReorg(pcoinsTip.get(), chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
+ mempool.removeForReorg(pcoinsTip.get(), ::ChainActive().Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
// Re-limit mempool size, in case we added any transactions
LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
}
@@ -524,7 +531,7 @@ static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool,
// Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool
// were somehow broken and returning the wrong scriptPubKeys
static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& view, const CTxMemPool& pool,
- unsigned int flags, bool cacheSigStore, PrecomputedTransactionData& txdata) {
+ unsigned int flags, bool cacheSigStore, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
AssertLockHeld(cs_main);
// pool.cs should be locked already, but go ahead and re-take the lock here
@@ -557,9 +564,16 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationSt
return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, txdata);
}
+/**
+ * @param[out] coins_to_uncache Return any outpoints which were not previously present in the
+ * coins cache, but were added as a result of validating the tx
+ * for mempool acceptance. This allows the caller to optionally
+ * remove the cache additions if the associated transaction ends
+ * up being rejected by the mempool.
+ */
static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
- bool bypass_limits, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache, bool test_accept)
+ bool bypass_limits, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache, bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
const CTransaction& tx = *ptx;
const uint256 hash = tx.GetHash();
@@ -574,38 +588,36 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// Coinbase is only valid in a block, not as a loose transaction
if (tx.IsCoinBase())
- return state.DoS(100, false, REJECT_INVALID, "coinbase");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "coinbase");
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
std::string reason;
if (fRequireStandard && !IsStandardTx(tx, reason))
- return state.DoS(0, false, REJECT_NONSTANDARD, reason);
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, 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 reduce unnecessary malloc overhead.
- if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) < MIN_STANDARD_TX_NONWITNESS_SIZE)
- return state.DoS(0, false, REJECT_NONSTANDARD, "tx-size-small");
+ if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) < MIN_STANDARD_TX_NONWITNESS_SIZE)
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "tx-size-small");
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
- return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
+ return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-final");
// is it already in the memory pool?
if (pool.exists(hash)) {
- return state.Invalid(false, REJECT_DUPLICATE, "txn-already-in-mempool");
+ return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, REJECT_DUPLICATE, "txn-already-in-mempool");
}
// Check for conflicts with in-memory transactions
std::set<uint256> setConflicts;
for (const CTxIn &txin : tx.vin)
{
- auto itConflicting = pool.mapNextTx.find(txin.prevout);
- if (itConflicting != pool.mapNextTx.end())
- {
- const CTransaction *ptxConflicting = itConflicting->second;
+ const CTransaction* ptxConflicting = pool.GetConflictTx(txin.prevout);
+ if (ptxConflicting) {
if (!setConflicts.count(ptxConflicting->GetHash()))
{
// Allow opt-out of transaction replacement by setting
@@ -633,7 +645,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
}
if (fReplacementOptOut) {
- return state.Invalid(false, REJECT_DUPLICATE, "txn-mempool-conflict");
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_DUPLICATE, "txn-mempool-conflict");
}
setConflicts.insert(ptxConflicting->GetHash());
@@ -654,12 +666,16 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
coins_to_uncache.push_back(txin.prevout);
}
+
+ // Note: this call may add txin.prevout to the coins cache
+ // (pcoinsTip.cacheCoins) by way of FetchCoin(). It should be removed
+ // later (via coins_to_uncache) if this tx turns out to be invalid.
if (!view.HaveCoin(txin.prevout)) {
// Are inputs missing because we already have the tx?
for (size_t out = 0; out < tx.vout.size(); out++) {
// Optimistically just do efficient check of cache for outputs
if (pcoinsTip->HaveCoinInCache(COutPoint(hash, out))) {
- return state.Invalid(false, REJECT_DUPLICATE, "txn-already-known");
+ return state.Invalid(ValidationInvalidReason::TX_CONFLICT, false, REJECT_DUPLICATE, "txn-already-known");
}
}
// Otherwise assume this might be an orphan tx for which we just haven't seen parents yet
@@ -681,8 +697,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// be mined yet.
// Must keep pool.cs for this unless we change CheckSequenceLocks to take a
// CoinsViewCache instead of create its own
- if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
- return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final");
+ if (!CheckSequenceLocks(pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
+ return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-BIP68-final");
CAmount nFees = 0;
if (!Consensus::CheckTxInputs(tx, state, view, GetSpendHeight(view), nFees)) {
@@ -691,11 +707,11 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// Check for non-standard pay-to-script-hash in inputs
if (fRequireStandard && !AreInputsStandard(tx, view))
- return state.Invalid(false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs");
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs");
// Check for non-standard witness in P2WSH
if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, view))
- return state.DoS(0, false, REJECT_NONSTANDARD, "bad-witness-nonstandard", true);
+ return state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false, REJECT_NONSTANDARD, "bad-witness-nonstandard");
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS);
@@ -714,31 +730,26 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
}
- CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, chainActive.Height(),
+ CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, ::ChainActive().Height(),
fSpendsCoinbase, nSigOpsCost, lp);
unsigned int nSize = entry.GetTxSize();
- // Check that the transaction doesn't have an excessive number of
- // sigops, making it impossible to mine. Since the coinbase transaction
- // itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
- // MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
- // merely non-standard transaction.
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
- return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false,
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops",
strprintf("%d", nSigOpsCost));
CAmount mempoolRejectFee = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
if (!bypass_limits && mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
- return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nModifiedFees, mempoolRejectFee));
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", strprintf("%d < %d", nModifiedFees, mempoolRejectFee));
}
// No transactions are allowed below minRelayTxFee except from disconnected blocks
if (!bypass_limits && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) {
- return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met", false, strprintf("%d < %d", nModifiedFees, ::minRelayTxFee.GetFee(nSize)));
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "min relay fee not met", strprintf("%d < %d", nModifiedFees, ::minRelayTxFee.GetFee(nSize)));
}
if (nAbsurdFee && nFees > nAbsurdFee)
- return state.Invalid(false,
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false,
REJECT_HIGHFEE, "absurdly-high-fee",
strprintf("%d > %d", nFees, nAbsurdFee));
@@ -750,7 +761,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
std::string errString;
if (!pool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
- return state.DoS(0, false, REJECT_NONSTANDARD, "too-long-mempool-chain", false, errString);
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "too-long-mempool-chain", errString);
}
// A transaction that spends outputs that would be replaced by it is invalid. Now
@@ -762,8 +773,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
const uint256 &hashAncestor = ancestorIt->GetTx().GetHash();
if (setConflicts.count(hashAncestor))
{
- return state.DoS(10, false,
- REJECT_INVALID, "bad-txns-spends-conflicting-tx", false,
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-spends-conflicting-tx",
strprintf("%s spends conflicting transaction %s",
hash.ToString(),
hashAncestor.ToString()));
@@ -786,16 +796,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
CFeeRate newFeeRate(nModifiedFees, nSize);
std::set<uint256> setConflictsParents;
const int maxDescendantsToVisit = 100;
- CTxMemPool::setEntries setIterConflicting;
- for (const uint256 &hashConflicting : setConflicts)
- {
- CTxMemPool::txiter mi = pool.mapTx.find(hashConflicting);
- if (mi == pool.mapTx.end())
- continue;
-
- // Save these to avoid repeated lookups
- setIterConflicting.insert(mi);
-
+ const CTxMemPool::setEntries setIterConflicting = pool.GetIterSet(setConflicts);
+ for (const auto& mi : setIterConflicting) {
// Don't allow the replacement to reduce the feerate of the
// mempool.
//
@@ -813,8 +815,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize());
if (newFeeRate <= oldFeeRate)
{
- return state.DoS(0, false,
- REJECT_INSUFFICIENTFEE, "insufficient fee", false,
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee",
strprintf("rejecting replacement %s; new feerate %s <= old feerate %s",
hash.ToString(),
newFeeRate.ToString(),
@@ -842,8 +843,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
nConflictingSize += it->GetTxSize();
}
} else {
- return state.DoS(0, false,
- REJECT_NONSTANDARD, "too many potential replacements", false,
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "too many potential replacements",
strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
hash.ToString(),
nConflictingCount,
@@ -861,11 +861,11 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// Rather than check the UTXO set - potentially expensive -
// it's cheaper to just check if the new input refers to a
// tx that's in the mempool.
- if (pool.mapTx.find(tx.vin[j].prevout.hash) != pool.mapTx.end())
- return state.DoS(0, false,
- REJECT_NONSTANDARD, "replacement-adds-unconfirmed", false,
+ if (pool.exists(tx.vin[j].prevout.hash)) {
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_NONSTANDARD, "replacement-adds-unconfirmed",
strprintf("replacement %s adds unconfirmed input, idx %d",
hash.ToString(), j));
+ }
}
}
@@ -874,8 +874,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// transactions would not be paid for.
if (nModifiedFees < nConflictingFees)
{
- return state.DoS(0, false,
- REJECT_INSUFFICIENTFEE, "insufficient fee", false,
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee",
strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees)));
}
@@ -885,8 +884,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
CAmount nDeltaFees = nModifiedFees - nConflictingFees;
if (nDeltaFees < ::incrementalRelayFee.GetFee(nSize))
{
- return state.DoS(0, false,
- REJECT_INSUFFICIENTFEE, "insufficient fee", false,
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "insufficient fee",
strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
hash.ToString(),
FormatMoney(nDeltaFees),
@@ -894,10 +892,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
}
- unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
- if (!chainparams.RequireStandard()) {
- scriptVerifyFlags = gArgs.GetArg("-promiscuousmempoolflags", scriptVerifyFlags);
- }
+ constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
@@ -910,8 +905,10 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
if (!tx.HasWitness() && CheckInputs(tx, stateDummy, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, false, txdata) &&
!CheckInputs(tx, stateDummy, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, false, txdata)) {
// Only the witness is missing, so the transaction itself may be fine.
- state.SetCorruptionPossible();
+ state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false,
+ state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage());
}
+ assert(IsTransactionReason(state.GetReason()));
return false; // state filled in by CheckInputs
}
@@ -930,22 +927,10 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks (using TestBlockValidity), however allowing such
// transactions into the mempool can be exploited as a DoS attack.
- unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(chainActive.Tip(), Params().GetConsensus());
+ unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(::ChainActive().Tip(), chainparams.GetConsensus());
if (!CheckInputsFromMempoolAndCache(tx, state, view, pool, currentBlockScriptVerifyFlags, true, txdata)) {
- // If we're using promiscuousmempoolflags, we may hit this normally
- // Check if current block has some flags that scriptVerifyFlags
- // does not before printing an ominous warning
- if (!(~scriptVerifyFlags & currentBlockScriptVerifyFlags)) {
- return error("%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against latest-block but not STANDARD flags %s, %s",
+ return error("%s: BUG! PLEASE REPORT THIS! CheckInputs failed against latest-block but not STANDARD flags %s, %s",
__func__, hash.ToString(), FormatStateMessage(state));
- } else {
- if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, false, txdata)) {
- return error("%s: ConnectInputs failed against MANDATORY but not STANDARD flags due to promiscuous mempool %s, %s",
- __func__, hash.ToString(), FormatStateMessage(state));
- } else {
- LogPrintf("Warning: -promiscuousmempool flags set to not include currently enforced soft forks, this may break mining or otherwise cause instability!\n");
- }
- }
}
if (test_accept) {
@@ -974,13 +959,13 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation() && pool.HasNoInputsOf(tx);
// Store transaction in memory
- pool.addUnchecked(hash, entry, setAncestors, validForFeeEstimation);
+ pool.addUnchecked(entry, setAncestors, validForFeeEstimation);
// trim mempool and check if tx was trimmed
if (!bypass_limits) {
LimitMempoolSize(pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
if (!pool.exists(hash))
- return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");
+ return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool full");
}
}
@@ -992,11 +977,16 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
/** (try to) add transaction to memory pool with a specified acceptance time **/
static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
- bool bypass_limits, const CAmount nAbsurdFee, bool test_accept)
+ bool bypass_limits, const CAmount nAbsurdFee, bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
std::vector<COutPoint> coins_to_uncache;
bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, pfMissingInputs, nAcceptTime, plTxnReplaced, bypass_limits, nAbsurdFee, coins_to_uncache, test_accept);
if (!res) {
+ // Remove coins that were not present in the coins cache before calling ATMPW;
+ // this is to prevent memory DoS in case we receive a large number of
+ // invalid transactions that attempt to overrun the in-memory coins cache
+ // (`CCoinsViewCache::cacheCoins`).
+
for (const COutPoint& hashTx : coins_to_uncache)
pcoinsTip->Uncache(hashTx);
}
@@ -1018,13 +1008,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
* Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock.
* If blockIndex is provided, the transaction is fetched from the corresponding block.
*/
-bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus::Params& consensusParams, uint256& hashBlock, bool fAllowSlow, CBlockIndex* blockIndex)
+bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus::Params& consensusParams, uint256& hashBlock, const CBlockIndex* const block_index)
{
- CBlockIndex* pindexSlow = blockIndex;
-
LOCK(cs_main);
- if (!blockIndex) {
+ if (!block_index) {
CTransactionRef ptx = mempool.get(hash);
if (ptx) {
txOut = ptx;
@@ -1034,20 +1022,13 @@ bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus
if (g_txindex) {
return g_txindex->FindTx(hash, hashBlock, txOut);
}
-
- if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it
- const Coin& coin = AccessByTxid(*pcoinsTip, hash);
- if (!coin.IsSpent()) pindexSlow = chainActive[coin.nHeight];
- }
- }
-
- if (pindexSlow) {
+ } else {
CBlock block;
- if (ReadBlockFromDisk(block, pindexSlow, consensusParams)) {
+ if (ReadBlockFromDisk(block, block_index, consensusParams)) {
for (const auto& tx : block.vtx) {
if (tx->GetHash() == hash) {
txOut = tx;
- hashBlock = pindexSlow->GetBlockHash();
+ hashBlock = block_index->GetBlockHash();
return true;
}
}
@@ -1067,7 +1048,7 @@ bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus
// CBlock and CBlockIndex
//
-static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
+static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart)
{
// Open history file to append
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
@@ -1075,7 +1056,7 @@ static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMes
return error("WriteBlockToDisk: OpenBlockFile failed");
// Write index header
- unsigned int nSize = GetSerializeSize(fileout, block);
+ unsigned int nSize = GetSerializeSize(block, fileout.GetVersion());
fileout << messageStart << nSize;
// Write block
@@ -1088,7 +1069,7 @@ static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMes
return true;
}
-bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
+bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams)
{
block.SetNull();
@@ -1114,7 +1095,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus:
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
{
- CDiskBlockPos blockPos;
+ FlatFilePos blockPos;
{
LOCK(cs_main);
blockPos = pindex->GetBlockPos();
@@ -1128,9 +1109,9 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
return true;
}
-bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& message_start)
+bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start)
{
- CDiskBlockPos hpos = pos;
+ FlatFilePos hpos = pos;
hpos.nPos -= 8; // Seek back 8 bytes for meta header
CAutoFile filein(OpenBlockFile(hpos, true), SER_DISK, CLIENT_VERSION);
if (filein.IsNull()) {
@@ -1165,7 +1146,7 @@ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CDiskBlockPos& pos,
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start)
{
- CDiskBlockPos block_pos;
+ FlatFilePos block_pos;
{
LOCK(cs_main);
block_pos = pindex->GetBlockPos();
@@ -1200,11 +1181,11 @@ bool IsInitialBlockDownload()
return false;
if (fImporting || fReindex)
return true;
- if (chainActive.Tip() == nullptr)
+ if (::ChainActive().Tip() == nullptr)
return true;
- if (chainActive.Tip()->nChainWork < nMinimumChainWork)
+ if (::ChainActive().Tip()->nChainWork < nMinimumChainWork)
return true;
- if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
+ if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
return true;
LogPrintf("Leaving InitialBlockDownload (latching to false)\n");
latchToFalse.store(true, std::memory_order_relaxed);
@@ -1231,7 +1212,7 @@ static void AlertNotify(const std::string& strMessage)
t.detach(); // thread runs free
}
-static void CheckForkWarningConditions()
+static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
// Before we get past initial download, we cannot reliably alert about forks
@@ -1241,10 +1222,10 @@ static void CheckForkWarningConditions()
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
// of our head, drop it
- if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 72)
+ if (pindexBestForkTip && ::ChainActive().Height() - pindexBestForkTip->nHeight >= 72)
pindexBestForkTip = nullptr;
- if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6)))
+ if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > ::ChainActive().Tip()->nChainWork + (GetBlockProof(*::ChainActive().Tip()) * 6)))
{
if (!GetfLargeWorkForkFound() && pindexBestForkBase)
{
@@ -1272,12 +1253,12 @@ static void CheckForkWarningConditions()
}
}
-static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
+static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
// If we are on a fork that is sufficiently large, set a warning flag
CBlockIndex* pfork = pindexNewForkTip;
- CBlockIndex* plonger = chainActive.Tip();
+ CBlockIndex* plonger = ::ChainActive().Tip();
while (pfork && pfork != plonger)
{
while (plonger && plonger->nHeight > pfork->nHeight)
@@ -1296,7 +1277,7 @@ static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
if (pfork && (!pindexBestForkTip || pindexNewForkTip->nHeight > pindexBestForkTip->nHeight) &&
pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) &&
- chainActive.Height() - pindexNewForkTip->nHeight < 72)
+ ::ChainActive().Height() - pindexNewForkTip->nHeight < 72)
{
pindexBestForkTip = pindexNewForkTip;
pindexBestForkBase = pfork;
@@ -1305,7 +1286,7 @@ static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
CheckForkWarningConditions();
}
-void static InvalidChainFound(CBlockIndex* pindexNew)
+void static InvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
pindexBestInvalid = pindexNew;
@@ -1313,16 +1294,16 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
LogPrintf("%s: invalid block=%s height=%d log2_work=%.8g date=%s\n", __func__,
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,
log(pindexNew->nChainWork.getdouble())/log(2.0), FormatISO8601DateTime(pindexNew->GetBlockTime()));
- CBlockIndex *tip = chainActive.Tip();
+ CBlockIndex *tip = ::ChainActive().Tip();
assert (tip);
LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__,
- tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0),
+ tip->GetBlockHash().ToString(), ::ChainActive().Height(), log(tip->nChainWork.getdouble())/log(2.0),
FormatISO8601DateTime(tip->GetBlockTime()));
CheckForkWarningConditions();
}
void CChainState::InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) {
- if (!state.CorruptionPossible()) {
+ if (state.GetReason() != ValidationInvalidReason::BLOCK_MUTATED) {
pindex->nStatus |= BLOCK_FAILED_VALID;
m_failed_blocks.insert(pindex);
setDirtyBlockIndex.insert(pindex);
@@ -1390,9 +1371,12 @@ void InitScriptExecutionCache() {
* which are matched. This is useful for checking blocks where we will likely never need the cache
* entry again.
*
+ * Note that we may set state.reason to NOT_STANDARD for extra soft-fork flags in flags, block-checking
+ * callers should probably reset it to CONSENSUS in such cases.
+ *
* Non-static (and re-declared) in src/test/txvalidationcache_tests.cpp
*/
-bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks)
+bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
if (!tx.IsCoinBase())
{
@@ -1445,22 +1429,26 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// Check whether the failure was caused by a
// non-mandatory script verification check, such as
// non-standard DER encodings or non-null dummy
- // arguments; if so, don't trigger DoS protection to
- // avoid splitting the network between upgraded and
- // non-upgraded nodes.
+ // arguments; if so, ensure we return NOT_STANDARD
+ // instead of CONSENSUS to avoid downstream users
+ // splitting the network between upgraded and
+ // non-upgraded nodes by banning CONSENSUS-failing
+ // data providers.
CScriptCheck check2(coin.out, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheSigStore, &txdata);
if (check2())
- return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
+ return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
}
- // Failures of other flags indicate a transaction that is
- // invalid in new blocks, e.g. an invalid P2SH. We DoS ban
- // such nodes as they are not following the protocol. That
- // said during an upgrade careful thought should be taken
- // as to the correct behavior - we may want to continue
- // peering with non-upgraded nodes even after soft-fork
- // super-majority signaling has occurred.
- return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
+ // MANDATORY flag failures correspond to
+ // ValidationInvalidReason::CONSENSUS. Because CONSENSUS
+ // failures are the most serious case of validation
+ // failures, we may need to consider using
+ // RECENT_CONSENSUS_CHANGE for any script failure that
+ // could be due to non-upgraded nodes which we may want to
+ // support, to avoid splitting the network (but this
+ // depends on the details of how net_processing handles
+ // such errors).
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
}
}
@@ -1475,9 +1463,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
return true;
}
-namespace {
-
-bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
+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);
@@ -1485,7 +1471,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
return error("%s: OpenUndoFile failed", __func__);
// Write index header
- unsigned int nSize = GetSerializeSize(fileout, blockundo);
+ unsigned int nSize = GetSerializeSize(blockundo, fileout.GetVersion());
fileout << messageStart << nSize;
// Write undo data
@@ -1504,9 +1490,9 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
return true;
}
-static bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex *pindex)
+bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex)
{
- CDiskBlockPos pos = pindex->GetUndoPos();
+ FlatFilePos pos = pindex->GetUndoPos();
if (pos.IsNull()) {
return error("%s: no undo data available", __func__);
}
@@ -1553,8 +1539,6 @@ static bool AbortNode(CValidationState& state, const std::string& strMessage, co
return state.Error(strMessage);
}
-} // namespace
-
/**
* Restore the UTXO in a Coin at a given COutPoint
* @param undo The Coin to be restored.
@@ -1652,38 +1636,25 @@ void static FlushBlockFile(bool fFinalize = false)
{
LOCK(cs_LastBlockFile);
- CDiskBlockPos posOld(nLastBlockFile, 0);
- bool status = true;
-
- FILE *fileOld = OpenBlockFile(posOld);
- if (fileOld) {
- if (fFinalize)
- status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize);
- status &= FileCommit(fileOld);
- fclose(fileOld);
- }
-
- fileOld = OpenUndoFile(posOld);
- if (fileOld) {
- if (fFinalize)
- status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize);
- status &= FileCommit(fileOld);
- fclose(fileOld);
- }
+ FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize);
+ FlatFilePos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize);
+ bool status = true;
+ status &= BlockFileSeq().Flush(block_pos_old, fFinalize);
+ status &= UndoFileSeq().Flush(undo_pos_old, fFinalize);
if (!status) {
AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error.");
}
}
-static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
+static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize);
static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams)
{
// Write undo information to disk
if (pindex->GetUndoPos().IsNull()) {
- CDiskBlockPos _pos;
- if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
+ FlatFilePos _pos;
+ if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40))
return error("ConnectBlock(): FindUndoPos failed");
if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart()))
return AbortNode(state, "Failed to write undo data");
@@ -1699,13 +1670,12 @@ static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState&
static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
-void ThreadScriptCheck() {
- RenameThread("bitcoin-scriptch");
+void ThreadScriptCheck(int worker_num) {
+ util::ThreadRename(strprintf("scriptch.%i", worker_num));
scriptcheckqueue.Thread();
}
-// Protected by cs_main
-VersionBitsCache versionbitscache;
+VersionBitsCache versionbitscache GUARDED_BY(cs_main);
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
{
@@ -1746,8 +1716,7 @@ public:
}
};
-// Protected by cs_main
-static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS];
+static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_main);
// 0.13.0 was shipped with a segwit deployment defined for testnet, but not for
// mainnet. We no longer need to support disabling the segwit deployment
@@ -1758,7 +1727,7 @@ static bool IsScriptWitnessEnabled(const Consensus::Params& params)
return params.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0;
}
-static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) {
+static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
AssertLockHeld(cs_main);
unsigned int flags = SCRIPT_VERIFY_NONE;
@@ -1839,7 +1808,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
// re-enforce that rule here (at least until we make it impossible for
// GetAdjustedTime() to go backward).
if (!CheckBlock(block, state, chainparams.GetConsensus(), !fJustCheck, !fJustCheck)) {
- if (state.CorruptionPossible()) {
+ if (state.GetReason() == ValidationInvalidReason::BLOCK_MUTATED) {
// We don't write down blocks to disk if they may have been
// corrupted, so this should be impossible unless we're having hardware
// problems.
@@ -1974,7 +1943,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
for (const auto& tx : block.vtx) {
for (size_t o = 0; o < tx->vout.size(); o++) {
if (view.HaveCoin(COutPoint(tx->GetHash(), o))) {
- return state.DoS(100, error("ConnectBlock(): tried to overwrite transaction"),
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, error("ConnectBlock(): tried to overwrite transaction"),
REJECT_INVALID, "bad-txns-BIP30");
}
}
@@ -2014,11 +1983,19 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
{
CAmount txfee = 0;
if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, txfee)) {
+ if (!IsBlockReason(state.GetReason())) {
+ // CheckTxInputs may return MISSING_INPUTS or
+ // PREMATURE_SPEND but we can't return that, as it's not
+ // defined for a block, so we reset the reason flag to
+ // CONSENSUS here.
+ state.Invalid(ValidationInvalidReason::CONSENSUS, false,
+ state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage());
+ }
return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
}
nFees += txfee;
if (!MoneyRange(nFees)) {
- return state.DoS(100, error("%s: accumulated fee in the block out of range.", __func__),
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: accumulated fee in the block out of range.", __func__),
REJECT_INVALID, "bad-txns-accumulated-fee-outofrange");
}
@@ -2031,7 +2008,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
}
if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) {
- return state.DoS(100, error("%s: contains a non-BIP68-final transaction", __func__),
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: contains a non-BIP68-final transaction", __func__),
REJECT_INVALID, "bad-txns-nonfinal");
}
}
@@ -2042,7 +2019,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
// * witness (when witness enabled in flags and excludes coinbase)
nSigOpsCost += GetTransactionSigOpCost(tx, view, flags);
if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST)
- return state.DoS(100, error("ConnectBlock(): too many sigops"),
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, error("ConnectBlock(): too many sigops"),
REJECT_INVALID, "bad-blk-sigops");
txdata.emplace_back(tx);
@@ -2050,9 +2027,20 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
{
std::vector<CScriptCheck> vChecks;
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
- if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : nullptr))
+ if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : nullptr)) {
+ if (state.GetReason() == ValidationInvalidReason::TX_NOT_STANDARD) {
+ // CheckInputs may return NOT_STANDARD for extra flags we passed,
+ // but we can't return that, as it's not defined for a block, so
+ // we reset the reason flag to CONSENSUS here.
+ // In the event of a future soft-fork, we may need to
+ // consider whether rewriting to CONSENSUS or
+ // RECENT_CONSENSUS_CHANGE would be more appropriate.
+ state.Invalid(ValidationInvalidReason::CONSENSUS, false,
+ state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage());
+ }
return error("ConnectBlock(): CheckInputs on %s failed with %s",
tx.GetHash().ToString(), FormatStateMessage(state));
+ }
control.Add(vChecks);
}
@@ -2067,13 +2055,13 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus());
if (block.vtx[0]->GetValueOut() > blockReward)
- return state.DoS(100,
+ return state.Invalid(ValidationInvalidReason::CONSENSUS,
error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
block.vtx[0]->GetValueOut(), blockReward),
REJECT_INVALID, "bad-cb-amount");
if (!control.Wait())
- return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed");
int64_t nTime4 = GetTimeMicros(); nTimeVerify += nTime4 - nTime2;
LogPrint(BCLog::BENCH, " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)]\n", nInputs - 1, MILLI * (nTime4 - nTime2), nInputs <= 1 ? 0 : MILLI * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * MICRO, nTimeVerify * MILLI / nBlocksTotal);
@@ -2161,8 +2149,9 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
// Write blocks and block index to disk.
if (fDoFullFlush || fPeriodicWrite) {
// Depend on nMinDiskSpace to ensure we can write block index
- if (!CheckDiskSpace(0, true))
- return state.Error("out of disk space");
+ if (!CheckDiskSpace(GetBlocksDir())) {
+ return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
+ }
// First make sure all block and undo data is flushed to disk.
FlushBlockFile();
// Then update all block file information (which may refer to block and undo files).
@@ -2195,8 +2184,9 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
// twice (once in the log, and once in the tables). This is already
// an overestimation, as most will delete an existing entry or
// overwrite one. Still, use a conservative safety factor of 2.
- if (!CheckDiskSpace(48 * 2 * 2 * pcoinsTip->GetCacheSize()))
- return state.Error("out of disk space");
+ if (!CheckDiskSpace(GetDataDir(), 48 * 2 * 2 * pcoinsTip->GetCacheSize())) {
+ return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
+ }
// Flush the chainstate (which may refer to block index entries).
if (!pcoinsTip->Flush())
return AbortNode(state, "Failed to write to coin database");
@@ -2206,7 +2196,7 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
}
if (full_flush_completed) {
// Update best block in wallet (so we can detect restored wallets).
- GetMainSignals().ChainStateFlushed(chainActive.GetLocator());
+ GetMainSignals().ChainStateFlushed(::ChainActive().GetLocator());
}
} catch (const std::runtime_error& e) {
return AbortNode(state, std::string("System error while flushing: ") + e.what());
@@ -2254,7 +2244,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
mempool.AddTransactionsUpdated(1);
{
- WaitableLock lock(g_best_block_mutex);
+ LOCK(g_best_block_mutex);
g_best_block = pindexNew->GetBlockHash();
g_best_block_cv.notify_all();
}
@@ -2286,12 +2276,6 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
}
if (nUpgraded > 0)
AppendWarning(warningMessages, strprintf(_("%d of last 100 blocks have unexpected version"), nUpgraded));
- if (nUpgraded > 100/2)
- {
- std::string strWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect");
- // notify GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
- DoWarning(strWarning);
- }
}
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, /* Continued */
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion,
@@ -2304,7 +2288,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
}
-/** Disconnect chainActive's tip.
+/** Disconnect m_chain's tip.
* After calling, the mempool will be in an inconsistent state, with
* transactions from disconnected blocks being added to disconnectpool. You
* should make the mempool consistent again by calling UpdateMempoolForReorg.
@@ -2316,7 +2300,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
*/
bool CChainState::DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool)
{
- CBlockIndex *pindexDelete = chainActive.Tip();
+ CBlockIndex *pindexDelete = m_chain.Tip();
assert(pindexDelete);
// Read block from disk.
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
@@ -2351,7 +2335,7 @@ bool CChainState::DisconnectTip(CValidationState& state, const CChainParams& cha
}
}
- chainActive.SetTip(pindexDelete->pprev);
+ m_chain.SetTip(pindexDelete->pprev);
UpdateTip(pindexDelete->pprev, chainparams);
// Let wallets know transactions went from 1-confirmed to
@@ -2392,14 +2376,11 @@ class ConnectTrace {
private:
std::vector<PerBlockConnectTrace> blocksConnected;
CTxMemPool &pool;
+ boost::signals2::scoped_connection m_connNotifyEntryRemoved;
public:
explicit ConnectTrace(CTxMemPool &_pool) : blocksConnected(1), pool(_pool) {
- pool.NotifyEntryRemoved.connect(boost::bind(&ConnectTrace::NotifyEntryRemoved, this, _1, _2));
- }
-
- ~ConnectTrace() {
- pool.NotifyEntryRemoved.disconnect(boost::bind(&ConnectTrace::NotifyEntryRemoved, this, _1, _2));
+ m_connNotifyEntryRemoved = pool.NotifyEntryRemoved.connect(std::bind(&ConnectTrace::NotifyEntryRemoved, this, std::placeholders::_1, std::placeholders::_2));
}
void BlockConnected(CBlockIndex* pindex, std::shared_ptr<const CBlock> pblock) {
@@ -2432,14 +2413,14 @@ public:
};
/**
- * Connect a new block to chainActive. pblock is either nullptr or a pointer to a CBlock
+ * Connect a new block to m_chain. pblock is either nullptr or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*
* The block is added to connectTrace if connection succeeds.
*/
bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool)
{
- assert(pindexNew->pprev == chainActive.Tip());
+ assert(pindexNew->pprev == m_chain.Tip());
// Read block from disk.
int64_t nTime1 = GetTimeMicros();
std::shared_ptr<const CBlock> pthisBlock;
@@ -2463,7 +2444,7 @@ bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainp
if (!rv) {
if (state.IsInvalid())
InvalidBlockFound(pindexNew, state);
- return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
+ return error("%s: ConnectBlock %s failed, %s", __func__, pindexNew->GetBlockHash().ToString(), FormatStateMessage(state));
}
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
LogPrint(BCLog::BENCH, " - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime3 - nTime2) * MILLI, nTimeConnectTotal * MICRO, nTimeConnectTotal * MILLI / nBlocksTotal);
@@ -2480,8 +2461,8 @@ bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainp
// Remove conflicting transactions from the mempool.;
mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight);
disconnectpool.removeForBlock(blockConnecting.vtx);
- // Update chainActive & related variables.
- chainActive.SetTip(pindexNew);
+ // Update m_chain & related variables.
+ m_chain.SetTip(pindexNew);
UpdateTip(pindexNew, chainparams);
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
@@ -2512,8 +2493,8 @@ CBlockIndex* CChainState::FindMostWorkChain() {
// Just going until the active chain is an optimization, as we know all blocks in it are valid already.
CBlockIndex *pindexTest = pindexNew;
bool fInvalidAncestor = false;
- while (pindexTest && !chainActive.Contains(pindexTest)) {
- assert(pindexTest->nChainTx || pindexTest->nHeight == 0);
+ while (pindexTest && !m_chain.Contains(pindexTest)) {
+ assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0);
// Pruned nodes may have entries in setBlockIndexCandidates for
// which block files have been deleted. Remove those as candidates
@@ -2555,7 +2536,7 @@ void CChainState::PruneBlockIndexCandidates() {
// Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails.
std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
- while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) {
+ while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, m_chain.Tip())) {
setBlockIndexCandidates.erase(it++);
}
// Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
@@ -2570,13 +2551,13 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
{
AssertLockHeld(cs_main);
- const CBlockIndex *pindexOldTip = chainActive.Tip();
- const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
+ const CBlockIndex *pindexOldTip = m_chain.Tip();
+ const CBlockIndex *pindexFork = m_chain.FindFork(pindexMostWork);
// Disconnect active blocks which are no longer in the best chain.
bool fBlocksDisconnected = false;
DisconnectedBlockTransactions disconnectpool;
- while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
+ while (m_chain.Tip() && m_chain.Tip() != pindexFork) {
if (!DisconnectTip(state, chainparams, &disconnectpool)) {
// This is likely a fatal error, but keep the mempool consistent,
// just in case. Only remove from the mempool in this case.
@@ -2608,7 +2589,7 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
- if (!state.CorruptionPossible()) {
+ if (state.GetReason() != ValidationInvalidReason::BLOCK_MUTATED) {
InvalidChainFound(vpindexToConnect.front());
}
state = CValidationState();
@@ -2624,7 +2605,7 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
}
} else {
PruneBlockIndexCandidates();
- if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
+ if (!pindexOldTip || m_chain.Tip()->nChainWork > pindexOldTip->nChainWork) {
// We're in a better position than we were. Return temporarily to release the lock.
fContinue = false;
break;
@@ -2670,6 +2651,14 @@ static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
}
}
+static void LimitValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main) {
+ AssertLockNotHeld(cs_main);
+
+ if (GetMainSignals().CallbacksPending() > 10) {
+ SyncWithValidationInterfaceQueue();
+ }
+}
+
/**
* Make the best chain active, in multiple steps. The result is either failure
* or an activated best chain. pblock is either nullptr or a pointer to a block
@@ -2698,19 +2687,17 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
do {
boost::this_thread::interruption_point();
- if (GetMainSignals().CallbacksPending() > 10) {
- // Block until the validation queue drains. This should largely
- // never happen in normal operation, however may happen during
- // reindex, causing memory blowup if we run too far ahead.
- // Note that if a validationinterface callback ends up calling
- // ActivateBestChain this may lead to a deadlock! We should
- // probably have a DEBUG_LOCKORDER test for this in the future.
- SyncWithValidationInterfaceQueue();
- }
+ // Block until the validation queue drains. This should largely
+ // never happen in normal operation, however may happen during
+ // reindex, causing memory blowup if we run too far ahead.
+ // Note that if a validationinterface callback ends up calling
+ // ActivateBestChain this may lead to a deadlock! We should
+ // probably have a DEBUG_LOCKORDER test for this in the future.
+ LimitValidationInterfaceQueue();
{
LOCK(cs_main);
- CBlockIndex* starting_tip = chainActive.Tip();
+ CBlockIndex* starting_tip = m_chain.Tip();
bool blocks_connected = false;
do {
// We absolutely may not unlock cs_main until we've made forward progress
@@ -2722,7 +2709,7 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
}
// Whether we have anything to do at all.
- if (pindexMostWork == nullptr || pindexMostWork == chainActive.Tip()) {
+ if (pindexMostWork == nullptr || pindexMostWork == m_chain.Tip()) {
break;
}
@@ -2736,16 +2723,16 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
// Wipe cache, we may need another branch now.
pindexMostWork = nullptr;
}
- pindexNewTip = chainActive.Tip();
+ pindexNewTip = m_chain.Tip();
for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) {
assert(trace.pblock && trace.pindex);
GetMainSignals().BlockConnected(trace.pblock, trace.pindex, trace.conflictedTxs);
}
- } while (!chainActive.Tip() || (starting_tip && CBlockIndexWorkComparator()(chainActive.Tip(), starting_tip)));
+ } while (!m_chain.Tip() || (starting_tip && CBlockIndexWorkComparator()(m_chain.Tip(), starting_tip)));
if (!blocks_connected) return true;
- const CBlockIndex* pindexFork = chainActive.FindFork(starting_tip);
+ const CBlockIndex* pindexFork = m_chain.FindFork(starting_tip);
bool fInitialDownload = IsInitialBlockDownload();
// Notify external listeners about the new tip.
@@ -2787,15 +2774,15 @@ bool CChainState::PreciousBlock(CValidationState& state, const CChainParams& par
{
{
LOCK(cs_main);
- if (pindex->nChainWork < chainActive.Tip()->nChainWork) {
+ if (pindex->nChainWork < m_chain.Tip()->nChainWork) {
// Nothing to do, this block is not at the tip.
return true;
}
- if (chainActive.Tip()->nChainWork > nLastPreciousChainwork) {
+ if (m_chain.Tip()->nChainWork > nLastPreciousChainwork) {
// The chain has been extended since the last call, reset the counter.
nBlockReverseSequenceId = -1;
}
- nLastPreciousChainwork = chainActive.Tip()->nChainWork;
+ nLastPreciousChainwork = m_chain.Tip()->nChainWork;
setBlockIndexCandidates.erase(pindex);
pindex->nSequenceId = nBlockReverseSequenceId;
if (nBlockReverseSequenceId > std::numeric_limits<int32_t>::min()) {
@@ -2803,7 +2790,7 @@ bool CChainState::PreciousBlock(CValidationState& state, const CChainParams& par
// call preciousblock 2**31-1 times on the same set of tips...
nBlockReverseSequenceId--;
}
- if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->nChainTx) {
+ if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->HaveTxsDownloaded()) {
setBlockIndexCandidates.insert(pindex);
PruneBlockIndexCandidates();
}
@@ -2817,67 +2804,89 @@ bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIn
bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex)
{
- AssertLockHeld(cs_main);
+ CBlockIndex* to_mark_failed = pindex;
+ bool pindex_was_in_chain = false;
+ int disconnected = 0;
- // We first disconnect backwards and then mark the blocks as invalid.
- // This prevents a case where pruned nodes may fail to invalidateblock
- // and be left unable to start as they have no tip candidates (as there
- // are no blocks that meet the "have data and are not invalid per
- // nStatus" criteria for inclusion in setBlockIndexCandidates).
+ // Disconnect (descendants of) pindex, and mark them invalid.
+ while (true) {
+ if (ShutdownRequested()) break;
- bool pindex_was_in_chain = false;
- CBlockIndex *invalid_walk_tip = chainActive.Tip();
+ // Make sure the queue of validation callbacks doesn't grow unboundedly.
+ LimitValidationInterfaceQueue();
- DisconnectedBlockTransactions disconnectpool;
- while (chainActive.Contains(pindex)) {
+ LOCK(cs_main);
+ if (!m_chain.Contains(pindex)) break;
pindex_was_in_chain = true;
- // ActivateBestChain considers blocks already in chainActive
- // unconditionally valid already, so force disconnect away from it.
- if (!DisconnectTip(state, chainparams, &disconnectpool)) {
- // It's probably hopeless to try to make the mempool consistent
- // here if DisconnectTip failed, but we can try.
- UpdateMempoolForReorg(disconnectpool, false);
- return false;
- }
- }
+ CBlockIndex *invalid_walk_tip = m_chain.Tip();
- // Now mark the blocks we just disconnected as descendants invalid
- // (note this may not be all descendants).
- while (pindex_was_in_chain && invalid_walk_tip != pindex) {
- invalid_walk_tip->nStatus |= BLOCK_FAILED_CHILD;
+ // ActivateBestChain considers blocks already in m_chain
+ // unconditionally valid already, so force disconnect away from it.
+ DisconnectedBlockTransactions disconnectpool;
+ bool ret = DisconnectTip(state, chainparams, &disconnectpool);
+ // DisconnectTip will add transactions to disconnectpool.
+ // Adjust the mempool to be consistent with the new tip, adding
+ // transactions back to the mempool if disconnecting was successful,
+ // and we're not doing a very deep invalidation (in which case
+ // keeping the mempool up to date is probably futile anyway).
+ UpdateMempoolForReorg(disconnectpool, /* fAddToMempool = */ (++disconnected <= 10) && ret);
+ if (!ret) return false;
+ assert(invalid_walk_tip->pprev == m_chain.Tip());
+
+ // We immediately mark the disconnected blocks as invalid.
+ // This prevents a case where pruned nodes may fail to invalidateblock
+ // and be left unable to start as they have no tip candidates (as there
+ // are no blocks that meet the "have data and are not invalid per
+ // nStatus" criteria for inclusion in setBlockIndexCandidates).
+ invalid_walk_tip->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(invalid_walk_tip);
setBlockIndexCandidates.erase(invalid_walk_tip);
- invalid_walk_tip = invalid_walk_tip->pprev;
+ setBlockIndexCandidates.insert(invalid_walk_tip->pprev);
+ if (invalid_walk_tip->pprev == to_mark_failed && (to_mark_failed->nStatus & BLOCK_FAILED_VALID)) {
+ // We only want to mark the last disconnected block as BLOCK_FAILED_VALID; its children
+ // need to be BLOCK_FAILED_CHILD instead.
+ to_mark_failed->nStatus = (to_mark_failed->nStatus ^ BLOCK_FAILED_VALID) | BLOCK_FAILED_CHILD;
+ setDirtyBlockIndex.insert(to_mark_failed);
+ }
+
+ // Track the last disconnected block, so we can correct its BLOCK_FAILED_CHILD status in future
+ // iterations, or, if it's the last one, call InvalidChainFound on it.
+ to_mark_failed = invalid_walk_tip;
}
- // Mark the block itself as invalid.
- pindex->nStatus |= BLOCK_FAILED_VALID;
- setDirtyBlockIndex.insert(pindex);
- setBlockIndexCandidates.erase(pindex);
- m_failed_blocks.insert(pindex);
+ {
+ LOCK(cs_main);
+ if (m_chain.Contains(to_mark_failed)) {
+ // If the to-be-marked invalid block is in the active chain, something is interfering and we can't proceed.
+ return false;
+ }
- // DisconnectTip will add transactions to disconnectpool; try to add these
- // back to the mempool.
- UpdateMempoolForReorg(disconnectpool, true);
+ // Mark pindex (or the last disconnected block) as invalid, even when it never was in the main chain
+ to_mark_failed->nStatus |= BLOCK_FAILED_VALID;
+ setDirtyBlockIndex.insert(to_mark_failed);
+ setBlockIndexCandidates.erase(to_mark_failed);
+ m_failed_blocks.insert(to_mark_failed);
- // The resulting new best tip may not be in setBlockIndexCandidates anymore, so
- // add it again.
- BlockMap::iterator it = mapBlockIndex.begin();
- while (it != mapBlockIndex.end()) {
- if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && !setBlockIndexCandidates.value_comp()(it->second, chainActive.Tip())) {
- setBlockIndexCandidates.insert(it->second);
+ // The resulting new best tip may not be in setBlockIndexCandidates anymore, so
+ // add it again.
+ BlockMap::iterator it = mapBlockIndex.begin();
+ while (it != mapBlockIndex.end()) {
+ if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(it->second, m_chain.Tip())) {
+ setBlockIndexCandidates.insert(it->second);
+ }
+ it++;
}
- it++;
- }
- InvalidChainFound(pindex);
+ InvalidChainFound(to_mark_failed);
+ }
// Only notify about a new block tip if the active chain was modified.
if (pindex_was_in_chain) {
- uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev);
+ uiInterface.NotifyBlockTip(IsInitialBlockDownload(), to_mark_failed->pprev);
}
return true;
}
+
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) {
return g_chainstate.InvalidateBlock(state, chainparams, pindex);
}
@@ -2893,7 +2902,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
it->second->nStatus &= ~BLOCK_FAILED_MASK;
setDirtyBlockIndex.insert(it->second);
- if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
+ if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), it->second)) {
setBlockIndexCandidates.insert(it->second);
}
if (it->second == pindexBestInvalid) {
@@ -2957,7 +2966,7 @@ CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block)
}
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
-void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
+void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams)
{
pindexNew->nTx = block.vtx.size();
pindexNew->nChainTx = 0;
@@ -2971,7 +2980,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
setDirtyBlockIndex.insert(pindexNew);
- if (pindexNew->pprev == nullptr || pindexNew->pprev->nChainTx) {
+ if (pindexNew->pprev == nullptr || pindexNew->pprev->HaveTxsDownloaded()) {
// If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
std::deque<CBlockIndex*> queue;
queue.push_back(pindexNew);
@@ -2985,7 +2994,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
LOCK(cs_nBlockSequenceId);
pindex->nSequenceId = nBlockSequenceId++;
}
- if (chainActive.Tip() == nullptr || !setBlockIndexCandidates.value_comp()(pindex, chainActive.Tip())) {
+ if (m_chain.Tip() == nullptr || !setBlockIndexCandidates.value_comp()(pindex, m_chain.Tip())) {
setBlockIndexCandidates.insert(pindex);
}
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex);
@@ -3003,7 +3012,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
}
}
-static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
+static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
{
LOCK(cs_LastBlockFile);
@@ -3038,21 +3047,13 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int
vinfoBlockFile[nFile].nSize += nAddSize;
if (!fKnown) {
- unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
- unsigned int nNewChunks = (vinfoBlockFile[nFile].nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
- if (nNewChunks > nOldChunks) {
- if (fPruneMode)
- fCheckForPruning = true;
- if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos, true)) {
- FILE *file = OpenBlockFile(pos);
- if (file) {
- LogPrintf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile);
- AllocateFileRange(file, pos.nPos, nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos);
- fclose(file);
- }
- }
- else
- return error("out of disk space");
+ bool out_of_space;
+ size_t bytes_allocated = BlockFileSeq().Allocate(pos, nAddSize, out_of_space);
+ if (out_of_space) {
+ return AbortNode("Disk space is low!", _("Error: Disk space is low!"));
+ }
+ if (bytes_allocated != 0 && fPruneMode) {
+ fCheckForPruning = true;
}
}
@@ -3060,32 +3061,23 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int
return true;
}
-static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
+static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize)
{
pos.nFile = nFile;
LOCK(cs_LastBlockFile);
- unsigned int nNewSize;
pos.nPos = vinfoBlockFile[nFile].nUndoSize;
- nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize;
+ vinfoBlockFile[nFile].nUndoSize += nAddSize;
setDirtyFileInfo.insert(nFile);
- unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
- unsigned int nNewChunks = (nNewSize + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
- if (nNewChunks > nOldChunks) {
- if (fPruneMode)
- fCheckForPruning = true;
- if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos, true)) {
- FILE *file = OpenUndoFile(pos);
- if (file) {
- LogPrintf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile);
- AllocateFileRange(file, pos.nPos, nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos);
- fclose(file);
- }
- }
- else
- return state.Error("out of disk space");
+ bool out_of_space;
+ size_t bytes_allocated = UndoFileSeq().Allocate(pos, nAddSize, out_of_space);
+ if (out_of_space) {
+ return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
+ }
+ if (bytes_allocated != 0 && fPruneMode) {
+ fCheckForPruning = true;
}
return true;
@@ -3095,7 +3087,7 @@ static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state,
{
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
- return state.DoS(50, false, REJECT_INVALID, "high-hash", false, "proof of work failed");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "high-hash", "proof of work failed");
return true;
}
@@ -3117,13 +3109,13 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
bool mutated;
uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated);
if (block.hashMerkleRoot != hashMerkleRoot2)
- return state.DoS(100, false, REJECT_INVALID, "bad-txnmrklroot", true, "hashMerkleRoot mismatch");
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-txnmrklroot", "hashMerkleRoot mismatch");
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
// of transactions in a block without affecting the merkle root of a block,
// while still invalidating it.
if (mutated)
- return state.DoS(100, false, REJECT_INVALID, "bad-txns-duplicate", true, "duplicate transaction");
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-txns-duplicate", "duplicate transaction");
}
// All potential-corruption validation must be done before we do any
@@ -3133,20 +3125,20 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
// checks that use witness data may be performed here.
// Size limits
- if (block.vtx.empty() || block.vtx.size() * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
- return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed");
+ if (block.vtx.empty() || block.vtx.size() * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT || ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-length", "size limits failed");
// First transaction must be coinbase, the rest must not be
if (block.vtx.empty() || !block.vtx[0]->IsCoinBase())
- return state.DoS(100, false, REJECT_INVALID, "bad-cb-missing", false, "first tx is not coinbase");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-missing", "first tx is not coinbase");
for (unsigned int i = 1; i < block.vtx.size(); i++)
if (block.vtx[i]->IsCoinBase())
- return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-multiple", "more than one coinbase");
// Check transactions
for (const auto& tx : block.vtx)
- if (!CheckTransaction(*tx, state, false))
- return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
+ if (!CheckTransaction(*tx, state, true))
+ return state.Invalid(state.GetReason(), false, state.GetRejectCode(), state.GetRejectReason(),
strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage()));
unsigned int nSigOps = 0;
@@ -3155,7 +3147,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
nSigOps += GetLegacySigOpCount(*tx);
}
if (nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST)
- return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", false, "out-of-bounds SigOpCount");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-sigops", "out-of-bounds SigOpCount");
if (fCheckPOW && fCheckMerkleRoot)
block.fChecked = true;
@@ -3231,6 +3223,22 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
return commitment;
}
+//! Returns last CBlockIndex* that is a checkpoint
+static CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+{
+ const MapCheckpoints& checkpoints = data.mapCheckpoints;
+
+ for (const MapCheckpoints::value_type& i : reverse_iterate(checkpoints))
+ {
+ const uint256& hash = i.second;
+ CBlockIndex* pindex = LookupBlockIndex(hash);
+ if (pindex) {
+ return pindex;
+ }
+ }
+ return nullptr;
+}
+
/** Context-dependent validity checks.
* By "context", we mean only the previous block headers, but not the UTXO
* set; UTXO-related validity checks are done in ConnectBlock().
@@ -3240,7 +3248,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
* in ConnectBlock().
* Note that -reindex-chainstate skips the validation that happens here!
*/
-static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
+static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
assert(pindexPrev != nullptr);
const int nHeight = pindexPrev->nHeight + 1;
@@ -3248,32 +3256,32 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta
// Check proof of work
const Consensus::Params& consensusParams = params.GetConsensus();
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
- return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "bad-diffbits", "incorrect proof of work");
// Check against checkpoints
if (fCheckpointsEnabled) {
// Don't accept any forks from the main chain prior to last checkpoint.
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
// MapBlockIndex.
- CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(params.Checkpoints());
+ CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
- return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint");
+ return state.Invalid(ValidationInvalidReason::BLOCK_CHECKPOINT, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint");
}
// Check timestamp against prev
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
- return state.Invalid(false, REJECT_INVALID, "time-too-old", "block's timestamp is too early");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "time-too-old", "block's timestamp is too early");
// Check timestamp
if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME)
- return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future");
+ return state.Invalid(ValidationInvalidReason::BLOCK_TIME_FUTURE, false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future");
// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
// check for version 2, 3 and 4 upgrades
if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
(block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) ||
(block.nVersion < 4 && nHeight >= consensusParams.BIP65Height))
- return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion),
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion),
strprintf("rejected nVersion=0x%08x block", block.nVersion));
return true;
@@ -3292,6 +3300,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// Start enforcing BIP113 (Median Time Past) using versionbits logic.
int nLockTimeFlags = 0;
if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, versionbitscache) == ThresholdState::ACTIVE) {
+ assert(pindexPrev != nullptr);
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
}
@@ -3302,7 +3311,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// Check that all transactions are finalized
for (const auto& tx : block.vtx) {
if (!IsFinalTx(*tx, nHeight, nLockTimeCutoff)) {
- return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-nonfinal", "non-final transaction");
}
}
@@ -3312,7 +3321,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
CScript expect = CScript() << nHeight;
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
!std::equal(expect.begin(), expect.end(), block.vtx[0]->vin[0].scriptSig.begin())) {
- return state.DoS(100, false, REJECT_INVALID, "bad-cb-height", false, "block height mismatch in coinbase");
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-cb-height", "block height mismatch in coinbase");
}
}
@@ -3334,11 +3343,11 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// already does not permit it, it is impossible to trigger in the
// witness tree.
if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
- return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness reserved value size", __func__));
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__));
}
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0]->vin[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
- return state.DoS(100, false, REJECT_INVALID, "bad-witness-merkle-match", true, strprintf("%s : witness merkle commitment mismatch", __func__));
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__));
}
fHaveWitness = true;
}
@@ -3348,7 +3357,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
if (!fHaveWitness) {
for (const auto& tx : block.vtx) {
if (tx->HasWitness()) {
- return state.DoS(100, false, REJECT_INVALID, "unexpected-witness", true, strprintf("%s : unexpected witness data found", __func__));
+ return state.Invalid(ValidationInvalidReason::BLOCK_MUTATED, false, REJECT_INVALID, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__));
}
}
}
@@ -3360,7 +3369,7 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
// the block hash, so we couldn't mark the block as permanently
// failed).
if (GetBlockWeight(block) > MAX_BLOCK_WEIGHT) {
- return state.DoS(100, false, REJECT_INVALID, "bad-blk-weight", false, strprintf("%s : weight limit failed", __func__));
+ return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-blk-weight", strprintf("%s : weight limit failed", __func__));
}
return true;
@@ -3380,7 +3389,7 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
if (ppindex)
*ppindex = pindex;
if (pindex->nStatus & BLOCK_FAILED_MASK)
- return state.Invalid(error("%s: block %s is marked invalid", __func__, hash.ToString()), 0, "duplicate");
+ return state.Invalid(ValidationInvalidReason::CACHED_INVALID, error("%s: block %s is marked invalid", __func__, hash.ToString()), 0, "duplicate");
return true;
}
@@ -3391,17 +3400,37 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
CBlockIndex* pindexPrev = nullptr;
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end())
- return state.DoS(10, error("%s: prev block not found", __func__), 0, "prev-blk-not-found");
+ return state.Invalid(ValidationInvalidReason::BLOCK_MISSING_PREV, error("%s: prev block not found", __func__), 0, "prev-blk-not-found");
pindexPrev = (*mi).second;
if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
- return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
- // If the previous block index isn't valid, determine if it descends from any block which
- // has been found invalid (m_failed_blocks), then mark pindexPrev and any blocks
- // between them as failed.
+ /* Determine if this block descends from any block which has been found
+ * invalid (m_failed_blocks), then mark pindexPrev and any blocks between
+ * them as failed. For example:
+ *
+ * D3
+ * /
+ * B2 - C2
+ * / \
+ * A D2 - E2 - F2
+ * \
+ * B1 - C1 - D1 - E1
+ *
+ * In the case that we attempted to reorg from E1 to F2, only to find
+ * C2 to be invalid, we would mark D2, E2, and F2 as BLOCK_FAILED_CHILD
+ * but NOT D3 (it was not in any of our candidate sets at the time).
+ *
+ * In any case D3 will also be marked as BLOCK_FAILED_CHILD at restart
+ * in LoadBlockIndex.
+ */
if (!pindexPrev->IsValid(BLOCK_VALID_SCRIPTS)) {
+ // The above does not mean "invalid": it checks if the previous block
+ // hasn't been validated up to BLOCK_VALID_SCRIPTS. This is a performance
+ // optimization, in the common case of adding a new block to the tip,
+ // we don't need to iterate over the failed blocks list.
for (const CBlockIndex* failedit : m_failed_blocks) {
if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) {
assert(failedit->nStatus & BLOCK_FAILED_VALID);
@@ -3411,7 +3440,7 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
setDirtyBlockIndex.insert(invalid_walk);
invalid_walk = invalid_walk->pprev;
}
- return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
+ return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_PREV, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
}
}
}
@@ -3449,26 +3478,26 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio
}
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
-static CDiskBlockPos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const CDiskBlockPos* dbp) {
- unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
- CDiskBlockPos blockPos;
+static FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const FlatFilePos* dbp) {
+ unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION);
+ FlatFilePos blockPos;
if (dbp != nullptr)
blockPos = *dbp;
if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) {
error("%s: FindBlockPos failed", __func__);
- return CDiskBlockPos();
+ return FlatFilePos();
}
if (dbp == nullptr) {
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) {
AbortNode("Failed to write block");
- return CDiskBlockPos();
+ return FlatFilePos();
}
}
return blockPos;
}
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
-bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock)
+bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock)
{
const CBlock& block = *pblock;
@@ -3485,13 +3514,13 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
// process an unrequested block if it's new and has enough work to
// advance our tip, and isn't too many blocks ahead.
bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA;
- bool fHasMoreOrSameWork = (chainActive.Tip() ? pindex->nChainWork >= chainActive.Tip()->nChainWork : true);
+ bool fHasMoreOrSameWork = (m_chain.Tip() ? pindex->nChainWork >= m_chain.Tip()->nChainWork : true);
// Blocks that are too out-of-order needlessly limit the effectiveness of
// pruning, because pruning will not delete block files that contain any
// blocks which are too close in height to the tip. Apply this test
// regardless of whether pruning is enabled; it should generally be safe to
// not process unrequested blocks.
- bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP));
+ bool fTooFarAhead = (pindex->nHeight > int(m_chain.Height() + MIN_BLOCKS_TO_KEEP));
// TODO: Decouple this function from the block download logic by removing fRequested
// This requires some new chain data structure to efficiently look up if a
@@ -3515,7 +3544,8 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
if (!CheckBlock(block, state, chainparams.GetConsensus()) ||
!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindex->pprev)) {
- if (state.IsInvalid() && !state.CorruptionPossible()) {
+ assert(IsBlockReason(state.GetReason()));
+ if (state.IsInvalid() && state.GetReason() != ValidationInvalidReason::BLOCK_MUTATED) {
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
}
@@ -3524,13 +3554,13 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
// Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW
// (but if it does not build on our best tip, let the SendMessages loop relay it)
- if (!IsInitialBlockDownload() && chainActive.Tip() == pindex->pprev)
+ if (!IsInitialBlockDownload() && m_chain.Tip() == pindex->pprev)
GetMainSignals().NewPoWValidBlock(pindex, pblock);
// Write block to history file
if (fNewBlock) *fNewBlock = true;
try {
- CDiskBlockPos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp);
+ FlatFilePos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp);
if (blockPos.IsNull()) {
state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__));
return false;
@@ -3555,12 +3585,14 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
CBlockIndex *pindex = nullptr;
if (fNewBlock) *fNewBlock = false;
CValidationState state;
- // Ensure that CheckBlock() passes before calling AcceptBlock, as
- // belt-and-suspenders.
- bool ret = CheckBlock(*pblock, state, chainparams.GetConsensus());
+ // CheckBlock() does not support multi-threaded block validation because CBlock::fChecked can cause data race.
+ // Therefore, the following critical section must include the CheckBlock() call as well.
LOCK(cs_main);
+ // Ensure that CheckBlock() passes before calling AcceptBlock, as
+ // belt-and-suspenders.
+ bool ret = CheckBlock(*pblock, state, chainparams.GetConsensus());
if (ret) {
// Store to disk
ret = g_chainstate.AcceptBlock(pblock, state, chainparams, &pindex, fForceProcessing, nullptr, fNewBlock);
@@ -3583,7 +3615,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot)
{
AssertLockHeld(cs_main);
- assert(pindexPrev && pindexPrev == chainActive.Tip());
+ assert(pindexPrev && pindexPrev == ::ChainActive().Tip());
CCoinsViewCache viewNew(pcoinsTip.get());
uint256 block_hash(block.GetHash());
CBlockIndex indexDummy(block);
@@ -3659,9 +3691,9 @@ void PruneOneBlockFile(const int fileNumber)
void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
{
for (std::set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) {
- CDiskBlockPos pos(*it, 0);
- fs::remove(GetBlockPosFilename(pos, "blk"));
- fs::remove(GetBlockPosFilename(pos, "rev"));
+ FlatFilePos pos(*it, 0);
+ fs::remove(BlockFileSeq().FileName(pos));
+ fs::remove(UndoFileSeq().FileName(pos));
LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, *it);
}
}
@@ -3672,11 +3704,11 @@ static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPr
assert(fPruneMode && nManualPruneHeight > 0);
LOCK2(cs_main, cs_LastBlockFile);
- if (chainActive.Tip() == nullptr)
+ if (::ChainActive().Tip() == nullptr)
return;
// last block to prune is the lesser of (user-specified height, MIN_BLOCKS_TO_KEEP from the tip)
- unsigned int nLastBlockWeCanPrune = std::min((unsigned)nManualPruneHeight, chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP);
+ unsigned int nLastBlockWeCanPrune = std::min((unsigned)nManualPruneHeight, ::ChainActive().Tip()->nHeight - MIN_BLOCKS_TO_KEEP);
int count=0;
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
if (vinfoBlockFile[fileNumber].nSize == 0 || vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
@@ -3716,14 +3748,14 @@ void PruneBlockFilesManual(int nManualPruneHeight)
static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
{
LOCK2(cs_main, cs_LastBlockFile);
- if (chainActive.Tip() == nullptr || nPruneTarget == 0) {
+ if (::ChainActive().Tip() == nullptr || nPruneTarget == 0) {
return;
}
- if ((uint64_t)chainActive.Tip()->nHeight <= nPruneAfterHeight) {
+ if ((uint64_t)::ChainActive().Tip()->nHeight <= nPruneAfterHeight) {
return;
}
- unsigned int nLastBlockWeCanPrune = chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP;
+ unsigned int nLastBlockWeCanPrune = ::ChainActive().Tip()->nHeight - MIN_BLOCKS_TO_KEEP;
uint64_t nCurrentUsage = CalculateCurrentUsage();
// We don't check to prune until after we've allocated new space for files
// So we should leave a buffer under our target to account for another allocation
@@ -3769,52 +3801,28 @@ static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfte
nLastBlockWeCanPrune, count);
}
-bool CheckDiskSpace(uint64_t nAdditionalBytes, bool blocks_dir)
+static FlatFileSeq BlockFileSeq()
{
- uint64_t nFreeBytesAvailable = fs::space(blocks_dir ? GetBlocksDir() : GetDataDir()).available;
-
- // Check for nMinDiskSpace bytes (currently 50MB)
- if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes)
- return AbortNode("Disk space is low!", _("Error: Disk space is low!"));
-
- return true;
+ return FlatFileSeq(GetBlocksDir(), "blk", BLOCKFILE_CHUNK_SIZE);
}
-static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
+static FlatFileSeq UndoFileSeq()
{
- if (pos.IsNull())
- return nullptr;
- fs::path path = GetBlockPosFilename(pos, prefix);
- fs::create_directories(path.parent_path());
- FILE* file = fsbridge::fopen(path, fReadOnly ? "rb": "rb+");
- if (!file && !fReadOnly)
- file = fsbridge::fopen(path, "wb+");
- if (!file) {
- LogPrintf("Unable to open file %s\n", path.string());
- return nullptr;
- }
- if (pos.nPos) {
- if (fseek(file, pos.nPos, SEEK_SET)) {
- LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string());
- fclose(file);
- return nullptr;
- }
- }
- return file;
+ return FlatFileSeq(GetBlocksDir(), "rev", UNDOFILE_CHUNK_SIZE);
}
-FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) {
- return OpenDiskFile(pos, "blk", fReadOnly);
+FILE* OpenBlockFile(const FlatFilePos &pos, bool fReadOnly) {
+ return BlockFileSeq().Open(pos, fReadOnly);
}
/** Open an undo file (rev?????.dat) */
-static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
- return OpenDiskFile(pos, "rev", fReadOnly);
+static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly) {
+ return UndoFileSeq().Open(pos, fReadOnly);
}
-fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix)
+fs::path GetBlockPosFilename(const FlatFilePos &pos)
{
- return GetBlocksDir() / strprintf("%s%05u.dat", prefix, pos.nFile);
+ return BlockFileSeq().FileName(pos);
}
CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
@@ -3842,8 +3850,6 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }))
return false;
- boost::this_thread::interruption_point();
-
// Calculate nChainWork
std::vector<std::pair<int, CBlockIndex*> > vSortedByHeight;
vSortedByHeight.reserve(mapBlockIndex.size());
@@ -3863,7 +3869,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
// Pruned nodes may have deleted the block.
if (pindex->nTx > 0) {
if (pindex->pprev) {
- if (pindex->pprev->nChainTx) {
+ if (pindex->pprev->HaveTxsDownloaded()) {
pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
} else {
pindex->nChainTx = 0;
@@ -3877,7 +3883,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
pindex->nStatus |= BLOCK_FAILED_CHILD;
setDirtyBlockIndex.insert(pindex);
}
- if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->nChainTx || pindex->pprev == nullptr))
+ if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))
setBlockIndexCandidates.insert(pindex);
if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
pindexBestInvalid = pindex;
@@ -3924,7 +3930,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
}
for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++)
{
- CDiskBlockPos pos(*it, 0);
+ FlatFilePos pos(*it, 0);
if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) {
return false;
}
@@ -3946,33 +3952,23 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
bool LoadChainTip(const CChainParams& chainparams)
{
AssertLockHeld(cs_main);
+ assert(!pcoinsTip->GetBestBlock().IsNull()); // Never called when the coins view is empty
- if (chainActive.Tip() && chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) return true;
-
- if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) {
- // In case we just added the genesis block, connect it now, so
- // that we always have a chainActive.Tip() when we return.
- LogPrintf("%s: Connecting genesis block...\n", __func__);
- CValidationState state;
- if (!ActivateBestChain(state, chainparams)) {
- LogPrintf("%s: failed to activate chain (%s)\n", __func__, FormatStateMessage(state));
- return false;
- }
- }
+ if (::ChainActive().Tip() && ::ChainActive().Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) return true;
// Load pointer to end of best chain
CBlockIndex* pindex = LookupBlockIndex(pcoinsTip->GetBestBlock());
if (!pindex) {
return false;
}
- chainActive.SetTip(pindex);
+ ::ChainActive().SetTip(pindex);
g_chainstate.PruneBlockIndexCandidates();
LogPrintf("Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n",
- chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(),
- FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()),
- GuessVerificationProgress(chainparams.TxData(), chainActive.Tip()));
+ ::ChainActive().Tip()->GetBlockHash().ToString(), ::ChainActive().Height(),
+ FormatISO8601DateTime(::ChainActive().Tip()->GetBlockTime()),
+ GuessVerificationProgress(chainparams.TxData(), ::ChainActive().Tip()));
return true;
}
@@ -3989,12 +3985,12 @@ CVerifyDB::~CVerifyDB()
bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
{
LOCK(cs_main);
- if (chainActive.Tip() == nullptr || chainActive.Tip()->pprev == nullptr)
+ if (::ChainActive().Tip() == nullptr || ::ChainActive().Tip()->pprev == nullptr)
return true;
// Verify blocks in the best chain
- if (nCheckDepth <= 0 || nCheckDepth > chainActive.Height())
- nCheckDepth = chainActive.Height();
+ if (nCheckDepth <= 0 || nCheckDepth > ::ChainActive().Height())
+ nCheckDepth = ::ChainActive().Height();
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
CCoinsViewCache coins(coinsview);
@@ -4004,16 +4000,16 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
CValidationState state;
int reportDone = 0;
LogPrintf("[0%%]..."); /* Continued */
- for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
+ for (pindex = ::ChainActive().Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
boost::this_thread::interruption_point();
- int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
+ const int percentageDone = std::max(1, std::min(99, (int)(((double)(::ChainActive().Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
if (reportDone < percentageDone/10) {
// report every 10% step
LogPrintf("[%d%%]...", percentageDone); /* Continued */
reportDone = percentageDone/10;
}
uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, false);
- if (pindex->nHeight <= chainActive.Height()-nCheckDepth)
+ if (pindex->nHeight <= ::ChainActive().Height()-nCheckDepth)
break;
if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
// If pruning, only go back as far as we have data.
@@ -4055,17 +4051,23 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
return true;
}
if (pindexFailure)
- return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
+ return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", ::ChainActive().Height() - pindexFailure->nHeight + 1, nGoodTransactions);
// store block count as we move pindex at check level >= 4
- int block_count = chainActive.Height() - pindex->nHeight;
+ int block_count = ::ChainActive().Height() - pindex->nHeight;
// check level 4: try reconnecting blocks
if (nCheckLevel >= 4) {
- while (pindex != chainActive.Tip()) {
+ while (pindex != ::ChainActive().Tip()) {
boost::this_thread::interruption_point();
- uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))), false);
- pindex = chainActive.Next(pindex);
+ const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(::ChainActive().Height() - pindex->nHeight)) / (double)nCheckDepth * 50)));
+ if (reportDone < percentageDone/10) {
+ // report every 10% step
+ LogPrintf("[%d%%]...", percentageDone); /* Continued */
+ reportDone = percentageDone/10;
+ }
+ uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, false);
+ pindex = ::ChainActive().Next(pindex);
CBlock block;
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
@@ -4157,6 +4159,7 @@ bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view)
for (int nHeight = nForkHeight + 1; nHeight <= pindexNew->nHeight; ++nHeight) {
const CBlockIndex* pindex = pindexNew->GetAncestor(nHeight);
LogPrintf("Rolling forward %s (%i)\n", pindex->GetBlockHash().ToString(), nHeight);
+ uiInterface.ShowProgress(_("Replaying blocks..."), (int) ((nHeight - nForkHeight) * 100.0 / (pindexNew->nHeight - nForkHeight)) , false);
if (!RollforwardBlock(pindex, cache, params)) return false;
}
@@ -4170,38 +4173,114 @@ bool ReplayBlocks(const CChainParams& params, CCoinsView* view) {
return g_chainstate.ReplayBlocks(params, view);
}
+//! Helper for CChainState::RewindBlockIndex
+void CChainState::EraseBlockData(CBlockIndex* index)
+{
+ AssertLockHeld(cs_main);
+ assert(!m_chain.Contains(index)); // Make sure this block isn't active
+
+ // Reduce validity
+ index->nStatus = std::min<unsigned int>(index->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) | (index->nStatus & ~BLOCK_VALID_MASK);
+ // Remove have-data flags.
+ index->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO);
+ // Remove storage location.
+ index->nFile = 0;
+ index->nDataPos = 0;
+ index->nUndoPos = 0;
+ // Remove various other things
+ index->nTx = 0;
+ index->nChainTx = 0;
+ index->nSequenceId = 0;
+ // Make sure it gets written.
+ setDirtyBlockIndex.insert(index);
+ // Update indexes
+ setBlockIndexCandidates.erase(index);
+ std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> ret = mapBlocksUnlinked.equal_range(index->pprev);
+ while (ret.first != ret.second) {
+ if (ret.first->second == index) {
+ mapBlocksUnlinked.erase(ret.first++);
+ } else {
+ ++ret.first;
+ }
+ }
+ // Mark parent as eligible for main chain again
+ if (index->pprev && index->pprev->IsValid(BLOCK_VALID_TRANSACTIONS) && index->pprev->HaveTxsDownloaded()) {
+ setBlockIndexCandidates.insert(index->pprev);
+ }
+}
+
bool CChainState::RewindBlockIndex(const CChainParams& params)
{
- LOCK(cs_main);
+ // Note that during -reindex-chainstate we are called with an empty m_chain!
- // Note that during -reindex-chainstate we are called with an empty chainActive!
+ // First erase all post-segwit blocks without witness not in the main chain,
+ // as this can we done without costly DisconnectTip calls. Active
+ // blocks will be dealt with below (releasing cs_main in between).
+ {
+ LOCK(cs_main);
+ for (const auto& entry : mapBlockIndex) {
+ if (IsWitnessEnabled(entry.second->pprev, params.GetConsensus()) && !(entry.second->nStatus & BLOCK_OPT_WITNESS) && !m_chain.Contains(entry.second)) {
+ EraseBlockData(entry.second);
+ }
+ }
+ }
+ // Find what height we need to reorganize to.
+ CBlockIndex *tip;
int nHeight = 1;
- while (nHeight <= chainActive.Height()) {
- // Although SCRIPT_VERIFY_WITNESS is now generally enforced on all
- // blocks in ConnectBlock, we don't need to go back and
- // re-download/re-verify blocks from before segwit actually activated.
- if (IsWitnessEnabled(chainActive[nHeight - 1], params.GetConsensus()) && !(chainActive[nHeight]->nStatus & BLOCK_OPT_WITNESS)) {
- break;
+ {
+ LOCK(cs_main);
+ while (nHeight <= m_chain.Height()) {
+ // Although SCRIPT_VERIFY_WITNESS is now generally enforced on all
+ // blocks in ConnectBlock, we don't need to go back and
+ // re-download/re-verify blocks from before segwit actually activated.
+ if (IsWitnessEnabled(m_chain[nHeight - 1], params.GetConsensus()) && !(m_chain[nHeight]->nStatus & BLOCK_OPT_WITNESS)) {
+ break;
+ }
+ nHeight++;
}
- nHeight++;
- }
+ tip = m_chain.Tip();
+ }
// nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
+
CValidationState state;
- CBlockIndex* pindex = chainActive.Tip();
- while (chainActive.Height() >= nHeight) {
- if (fPruneMode && !(chainActive.Tip()->nStatus & BLOCK_HAVE_DATA)) {
- // If pruning, don't try rewinding past the HAVE_DATA point;
- // since older blocks can't be served anyway, there's
- // no need to walk further, and trying to DisconnectTip()
- // will fail (and require a needless reindex/redownload
- // of the blockchain).
- break;
- }
- if (!DisconnectTip(state, params, nullptr)) {
- return error("RewindBlockIndex: unable to disconnect block at height %i (%s)", pindex->nHeight, FormatStateMessage(state));
+ // Loop until the tip is below nHeight, or we reach a pruned block.
+ while (!ShutdownRequested()) {
+ {
+ LOCK(cs_main);
+ // Make sure nothing changed from under us (this won't happen because RewindBlockIndex runs before importing/network are active)
+ assert(tip == m_chain.Tip());
+ if (tip == nullptr || tip->nHeight < nHeight) break;
+ if (fPruneMode && !(tip->nStatus & BLOCK_HAVE_DATA)) {
+ // If pruning, don't try rewinding past the HAVE_DATA point;
+ // since older blocks can't be served anyway, there's
+ // no need to walk further, and trying to DisconnectTip()
+ // will fail (and require a needless reindex/redownload
+ // of the blockchain).
+ break;
+ }
+
+ // Disconnect block
+ if (!DisconnectTip(state, params, nullptr)) {
+ return error("RewindBlockIndex: unable to disconnect block at height %i (%s)", tip->nHeight, FormatStateMessage(state));
+ }
+
+ // Reduce validity flag and have-data flags.
+ // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
+ // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
+ // Note: If we encounter an insufficiently validated block that
+ // is on m_chain, it must be because we are a pruning node, and
+ // this block or some successor doesn't HAVE_DATA, so we were unable to
+ // rewind all the way. Blocks remaining on m_chain at this point
+ // must not have their validity reduced.
+ EraseBlockData(tip);
+
+ tip = tip->pprev;
}
+ // Make sure the queue of validation callbacks doesn't grow unboundedly.
+ LimitValidationInterfaceQueue();
+
// Occasionally flush state to disk.
if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC)) {
LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state));
@@ -4209,53 +4288,15 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
}
}
- // Reduce validity flag and have-data flags.
- // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
- // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
- for (const auto& entry : mapBlockIndex) {
- CBlockIndex* pindexIter = entry.second;
-
- // Note: If we encounter an insufficiently validated block that
- // is on chainActive, it must be because we are a pruning node, and
- // this block or some successor doesn't HAVE_DATA, so we were unable to
- // rewind all the way. Blocks remaining on chainActive at this point
- // must not have their validity reduced.
- if (IsWitnessEnabled(pindexIter->pprev, params.GetConsensus()) && !(pindexIter->nStatus & BLOCK_OPT_WITNESS) && !chainActive.Contains(pindexIter)) {
- // Reduce validity
- pindexIter->nStatus = std::min<unsigned int>(pindexIter->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) | (pindexIter->nStatus & ~BLOCK_VALID_MASK);
- // Remove have-data flags.
- pindexIter->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO);
- // Remove storage location.
- pindexIter->nFile = 0;
- pindexIter->nDataPos = 0;
- pindexIter->nUndoPos = 0;
- // Remove various other things
- pindexIter->nTx = 0;
- pindexIter->nChainTx = 0;
- pindexIter->nSequenceId = 0;
- // Make sure it gets written.
- setDirtyBlockIndex.insert(pindexIter);
- // Update indexes
- setBlockIndexCandidates.erase(pindexIter);
- std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> ret = mapBlocksUnlinked.equal_range(pindexIter->pprev);
- while (ret.first != ret.second) {
- if (ret.first->second == pindexIter) {
- mapBlocksUnlinked.erase(ret.first++);
- } else {
- ++ret.first;
- }
- }
- } else if (pindexIter->IsValid(BLOCK_VALID_TRANSACTIONS) && pindexIter->nChainTx) {
- setBlockIndexCandidates.insert(pindexIter);
- }
- }
-
- if (chainActive.Tip() != nullptr) {
- // We can't prune block index candidates based on our tip if we have
- // no tip due to chainActive being empty!
- PruneBlockIndexCandidates();
+ {
+ LOCK(cs_main);
+ if (m_chain.Tip() != nullptr) {
+ // We can't prune block index candidates based on our tip if we have
+ // no tip due to m_chain being empty!
+ PruneBlockIndexCandidates();
- CheckBlockIndex(params.GetConsensus());
+ CheckBlockIndex(params.GetConsensus());
+ }
}
return true;
@@ -4266,8 +4307,8 @@ bool RewindBlockIndex(const CChainParams& params) {
return false;
}
- if (chainActive.Tip() != nullptr) {
- // FlushStateToDisk can possibly read chainActive. Be conservative
+ if (::ChainActive().Tip() != nullptr) {
+ // FlushStateToDisk can possibly read ::ChainActive(). Be conservative
// and skip it here, we're about to -reindex-chainstate anyway, so
// it'll get called a bunch real soon.
CValidationState state;
@@ -4292,7 +4333,7 @@ void CChainState::UnloadBlockIndex() {
void UnloadBlockIndex()
{
LOCK(cs_main);
- chainActive.SetTip(nullptr);
+ ::ChainActive().SetTip(nullptr);
pindexBestInvalid = nullptr;
pindexBestHeader = nullptr;
mempool.clear();
@@ -4306,7 +4347,7 @@ void UnloadBlockIndex()
warningcache[b].clear();
}
- for (BlockMap::value_type& entry : mapBlockIndex) {
+ for (const BlockMap::value_type& entry : mapBlockIndex) {
delete entry.second;
}
mapBlockIndex.clear();
@@ -4342,15 +4383,15 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
LOCK(cs_main);
// Check whether we're already initialized by checking for genesis in
- // mapBlockIndex. Note that we can't use chainActive here, since it is
+ // mapBlockIndex. Note that we can't use m_chain here, since it is
// set based on the coins db, not the block index db, which is the only
// thing loaded at this point.
if (mapBlockIndex.count(chainparams.GenesisBlock().GetHash()))
return true;
try {
- CBlock &block = const_cast<CBlock&>(chainparams.GenesisBlock());
- CDiskBlockPos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr);
+ const CBlock& block = chainparams.GenesisBlock();
+ FlatFilePos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr);
if (blockPos.IsNull())
return error("%s: writing genesis block to disk failed", __func__);
CBlockIndex *pindex = AddToBlockIndex(block);
@@ -4367,10 +4408,10 @@ bool LoadGenesisBlock(const CChainParams& chainparams)
return g_chainstate.LoadGenesisBlock(chainparams);
}
-bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp)
+bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos *dbp)
{
// Map of disk positions for blocks with unknown parent (only used for reindex)
- static std::multimap<uint256, CDiskBlockPos> mapBlocksUnknownParent;
+ static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
int64_t nStart = GetTimeMillis();
int nLoaded = 0;
@@ -4456,9 +4497,9 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
while (!queue.empty()) {
uint256 head = queue.front();
queue.pop_front();
- std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
+ std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
while (range.first != range.second) {
- std::multimap<uint256, CDiskBlockPos>::iterator it = range.first;
+ std::multimap<uint256, FlatFilePos>::iterator it = range.first;
std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
if (ReadBlockFromDisk(*pblockrecursive, it->second, chainparams.GetConsensus()))
{
@@ -4499,15 +4540,15 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
// During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain,
// so we have the genesis block in mapBlockIndex but no active chain. (A few of the tests when
- // iterating the block tree require that chainActive has been initialized.)
- if (chainActive.Height() < 0) {
+ // iterating the block tree require that m_chain has been initialized.)
+ if (m_chain.Height() < 0) {
assert(mapBlockIndex.size() <= 1);
return;
}
// Build forward-pointing map of the entire block tree.
std::multimap<CBlockIndex*,CBlockIndex*> forward;
- for (auto& entry : mapBlockIndex) {
+ for (const std::pair<const uint256, CBlockIndex*>& entry : mapBlockIndex) {
forward.insert(std::make_pair(entry.second->pprev, entry.second));
}
@@ -4544,9 +4585,9 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
if (pindex->pprev == nullptr) {
// Genesis block checks.
assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match.
- assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block.
+ assert(pindex == m_chain.Genesis()); // The current active chain's genesis block must be this block.
}
- if (pindex->nChainTx == 0) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
+ if (!pindex->HaveTxsDownloaded()) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
if (!fHavePruned) {
@@ -4559,9 +4600,9 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
}
if (pindex->nStatus & BLOCK_HAVE_UNDO) assert(pindex->nStatus & BLOCK_HAVE_DATA);
assert(((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0)); // This is pruning-independent.
- // All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to nChainTx being set.
- assert((pindexFirstNeverProcessed != nullptr) == (pindex->nChainTx == 0)); // nChainTx != 0 is used to signal that all parent blocks have been processed (but may have been pruned).
- assert((pindexFirstNotTransactionsValid != nullptr) == (pindex->nChainTx == 0));
+ // All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to HaveTxsDownloaded().
+ assert((pindexFirstNeverProcessed == nullptr) == pindex->HaveTxsDownloaded());
+ assert((pindexFirstNotTransactionsValid == nullptr) == pindex->HaveTxsDownloaded());
assert(pindex->nHeight == nHeight); // nHeight must be consistent.
assert(pindex->pprev == nullptr || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's.
assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.
@@ -4573,13 +4614,13 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
// Checks for not-invalid blocks.
assert((pindex->nStatus & BLOCK_FAILED_MASK) == 0); // The failed mask cannot be set for blocks without invalid parents.
}
- if (!CBlockIndexWorkComparator()(pindex, chainActive.Tip()) && pindexFirstNeverProcessed == nullptr) {
+ if (!CBlockIndexWorkComparator()(pindex, m_chain.Tip()) && pindexFirstNeverProcessed == nullptr) {
if (pindexFirstInvalid == nullptr) {
// If this block sorts at least as good as the current tip and
// is valid and we have all data for its parents, it must be in
- // setBlockIndexCandidates. chainActive.Tip() must also be there
+ // setBlockIndexCandidates. m_chain.Tip() must also be there
// even if some data has been pruned.
- if (pindexFirstMissing == nullptr || pindex == chainActive.Tip()) {
+ if (pindexFirstMissing == nullptr || pindex == m_chain.Tip()) {
assert(setBlockIndexCandidates.count(pindex));
}
// If some parent is missing, then it could be that this block was in
@@ -4613,11 +4654,11 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
// - it has a descendant that at some point had more work than the
// tip, and
// - we tried switching to that descendant but were missing
- // data for some intermediate block between chainActive and the
+ // data for some intermediate block between m_chain and the
// tip.
- // So if this block is itself better than chainActive.Tip() and it wasn't in
+ // So if this block is itself better than m_chain.Tip() and it wasn't in
// setBlockIndexCandidates, then it must be in mapBlocksUnlinked.
- if (!CBlockIndexWorkComparator()(pindex, chainActive.Tip()) && setBlockIndexCandidates.count(pindex) == 0) {
+ if (!CBlockIndexWorkComparator()(pindex, m_chain.Tip()) && setBlockIndexCandidates.count(pindex) == 0) {
if (pindexFirstInvalid == nullptr) {
assert(foundInUnlinked);
}
@@ -4688,24 +4729,24 @@ CBlockFileInfo* GetBlockFileInfo(size_t n)
ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos)
{
LOCK(cs_main);
- return VersionBitsState(chainActive.Tip(), params, pos, versionbitscache);
+ return VersionBitsState(::ChainActive().Tip(), params, pos, versionbitscache);
}
BIP9Stats VersionBitsTipStatistics(const Consensus::Params& params, Consensus::DeploymentPos pos)
{
LOCK(cs_main);
- return VersionBitsStatistics(chainActive.Tip(), params, pos);
+ return VersionBitsStatistics(::ChainActive().Tip(), params, pos);
}
int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos)
{
LOCK(cs_main);
- return VersionBitsStateSinceHeight(chainActive.Tip(), params, pos, versionbitscache);
+ return VersionBitsStateSinceHeight(::ChainActive().Tip(), params, pos, versionbitscache);
}
static const uint64_t MEMPOOL_DUMP_VERSION = 1;
-bool LoadMempool(void)
+bool LoadMempool(CTxMemPool& pool)
{
const CChainParams& chainparams = Params();
int64_t nExpiryTimeout = gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
@@ -4740,12 +4781,12 @@ bool LoadMempool(void)
CAmount amountdelta = nFeeDelta;
if (amountdelta) {
- mempool.PrioritiseTransaction(tx->GetHash(), amountdelta);
+ pool.PrioritiseTransaction(tx->GetHash(), amountdelta);
}
CValidationState state;
if (nTime + nExpiryTimeout > nNow) {
LOCK(cs_main);
- AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, nullptr /* pfMissingInputs */, nTime,
+ AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, nullptr /* pfMissingInputs */, nTime,
nullptr /* plTxnReplaced */, false /* bypass_limits */, 0 /* nAbsurdFee */,
false /* test_accept */);
if (state.IsValid()) {
@@ -4755,7 +4796,7 @@ bool LoadMempool(void)
// wallet(s) having loaded it while we were processing
// mempool transactions; consider these as valid, instead of
// failed, but mark them as 'already there'
- if (mempool.exists(tx->GetHash())) {
+ if (pool.exists(tx->GetHash())) {
++already_there;
} else {
++failed;
@@ -4771,7 +4812,7 @@ bool LoadMempool(void)
file >> mapDeltas;
for (const auto& i : mapDeltas) {
- mempool.PrioritiseTransaction(i.first, i.second);
+ pool.PrioritiseTransaction(i.first, i.second);
}
} catch (const std::exception& e) {
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
@@ -4782,19 +4823,22 @@ bool LoadMempool(void)
return true;
}
-bool DumpMempool(void)
+bool DumpMempool(const CTxMemPool& pool)
{
int64_t start = GetTimeMicros();
std::map<uint256, CAmount> mapDeltas;
std::vector<TxMempoolInfo> vinfo;
+ static Mutex dump_mutex;
+ LOCK(dump_mutex);
+
{
- LOCK(mempool.cs);
- for (const auto &i : mempool.mapDeltas) {
+ LOCK(pool.cs);
+ for (const auto &i : pool.mapDeltas) {
mapDeltas[i.first] = i.second;
}
- vinfo = mempool.infoAll();
+ vinfo = pool.infoAll();
}
int64_t mid = GetTimeMicros();
diff --git a/src/validation.h b/src/validation.h
index ce46a5a782..ad978f0e05 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,14 +12,16 @@
#include <amount.h>
#include <coins.h>
+#include <crypto/common.h> // for ReadLE64
#include <fs.h>
-#include <protocol.h> // For CMessageHeader::MessageStartChars
#include <policy/feerate.h>
+#include <protocol.h> // For CMessageHeader::MessageStartChars
#include <script/script_error.h>
#include <sync.h>
#include <versionbits.h>
#include <algorithm>
+#include <atomic>
#include <exception>
#include <map>
#include <memory>
@@ -29,10 +31,9 @@
#include <utility>
#include <vector>
-#include <atomic>
-
class CBlockIndex;
class CBlockTreeDB;
+class CBlockUndo;
class CChainParams;
class CCoinsViewDB;
class CInv;
@@ -49,15 +50,9 @@ struct LockPoints;
/** Default for -whitelistrelay. */
static const bool DEFAULT_WHITELISTRELAY = true;
/** Default for -whitelistforcerelay. */
-static const bool DEFAULT_WHITELISTFORCERELAY = true;
+static const bool DEFAULT_WHITELISTFORCERELAY = false;
/** Default for -minrelaytxfee, minimum relay fee for transactions */
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
-//! -maxtxfee default
-static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN;
-//! Discourage users to set fees higher than this amount (in satoshis) per kB
-static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN;
-//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
-static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB;
/** Default for -limitancestorcount, max number of in-mempool ancestors */
static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25;
/** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */
@@ -113,10 +108,9 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
/** Maximum age of our tip in seconds for us to be considered current for fee estimation */
static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
-/** Default for -permitbaremultisig */
-static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
+static const char* const DEFAULT_BLOCKFILTERINDEX = "0";
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
/** Default for -persistmempool */
static const bool DEFAULT_PERSIST_MEMPOOL = true;
@@ -138,34 +132,30 @@ static const int DEFAULT_STOPATHEIGHT = 0;
struct BlockHasher
{
- size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); }
+ // this used to call `GetCheapHash()` in uint256, which was later moved; the
+ // cheap hash function simply calls ReadLE64() however, so the end result is
+ // identical
+ size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); }
};
extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool;
-extern std::atomic_bool g_is_mempool_loaded;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
-extern BlockMap& mapBlockIndex;
-extern uint64_t nLastBlockTx;
-extern uint64_t nLastBlockWeight;
-extern const std::string strMessageMagic;
-extern CWaitableCriticalSection g_best_block_mutex;
-extern CConditionVariable g_best_block_cv;
+extern BlockMap& mapBlockIndex GUARDED_BY(cs_main);
+extern Mutex g_best_block_mutex;
+extern std::condition_variable g_best_block_cv;
extern uint256 g_best_block;
extern std::atomic_bool fImporting;
extern std::atomic_bool fReindex;
extern int nScriptCheckThreads;
-extern bool fIsBareMultisigStd;
extern bool fRequireStandard;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
extern size_t nCoinCacheUsage;
/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
extern CFeeRate minRelayTxFee;
-/** Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendrawtransaction) */
-extern CAmount maxTxFee;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
extern int64_t nMaxTipAge;
extern bool fEnableReplacement;
@@ -179,9 +169,6 @@ extern arith_uint256 nMinimumChainWork;
/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex *pindexBestHeader;
-/** Minimum disk space required - used in CheckDiskSpace() */
-static const uint64_t nMinDiskSpace = 52428800;
-
/** Pruning-related variables and constants */
/** True if any block files have ever been pruned. */
extern bool fHavePruned;
@@ -189,7 +176,7 @@ extern bool fHavePruned;
extern bool fPruneMode;
/** Number of MiB of block files that we're trying to stay below. */
extern uint64_t nPruneTarget;
-/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */
+/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ::ChainActive().Tip() will not be pruned. */
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
/** Minimum blocks required to signal NODE_NETWORK_LIMITED */
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
@@ -197,14 +184,14 @@ static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
static const signed int DEFAULT_CHECKBLOCKS = 6;
static const unsigned int DEFAULT_CHECKLEVEL = 3;
-// Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat)
+// Require that user allocate at least 550 MiB for block & undo files (blk???.dat and rev???.dat)
// At 1MB per block, 288 blocks = 288MB.
// Add 15% for Undo data = 331MB
// Add 20% for Orphan block rate = 397MB
// We want the low water mark after pruning to be at least 397 MB and since we prune in
// full block file chunks, we need the high water mark which triggers the prune to be
// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB
-// Setting the target to > than 550MB will make it likely we can respect the target.
+// Setting the target to >= 550 MiB will make it likely we can respect the target.
static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
/**
@@ -243,29 +230,27 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
*/
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr, CBlockHeader* first_invalid = nullptr) LOCKS_EXCLUDED(cs_main);
-/** Check whether enough disk space is available for an incoming block */
-bool CheckDiskSpace(uint64_t nAdditionalBytes = 0, bool blocks_dir = false);
/** Open a block file (blk?????.dat) */
-FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
+FILE* OpenBlockFile(const FlatFilePos &pos, bool fReadOnly = false);
/** Translation to a filesystem path */
-fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix);
+fs::path GetBlockPosFilename(const FlatFilePos &pos);
/** Import blocks from an external file */
-bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = nullptr);
+bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos *dbp = nullptr);
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
bool LoadGenesisBlock(const CChainParams& chainparams);
/** Load the block tree and coins database from disk,
* initializing state if we're running with -reindex. */
bool LoadBlockIndex(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Update the chain tip based on database information. */
-bool LoadChainTip(const CChainParams& chainparams);
+bool LoadChainTip(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Unload database information */
void UnloadBlockIndex();
/** Run an instance of the script checking thread */
-void ThreadScriptCheck();
+void ThreadScriptCheck(int worker_num);
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool IsInitialBlockDownload();
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
-bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr);
+bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, const CBlockIndex* const blockIndex = nullptr);
/**
* Find the best known block, and make it the tip of the block chain
*
@@ -284,7 +269,7 @@ uint64_t CalculateCurrentUsage();
/**
* Mark one block file as pruned.
*/
-void PruneOneBlockFile(const int fileNumber);
+void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Actually unlink the specified files
@@ -302,10 +287,7 @@ void PruneBlockFilesManual(int nManualPruneHeight);
* plTxnReplaced will be appended to with all transactions replaced from mempool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
- bool bypass_limits, const CAmount nAbsurdFee, bool test_accept=false);
-
-/** Convert CValidationState to a human-readable message for logging */
-std::string FormatStateMessage(const CValidationState &state);
+ bool bypass_limits, const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Get the BIP9 state for a given deployment at the current tip. */
ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos);
@@ -329,12 +311,12 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
*
* See consensus/consensus.h for flag definitions.
*/
-bool CheckFinalTx(const CTransaction &tx, int flags = -1);
+bool CheckFinalTx(const CTransaction &tx, int flags = -1) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Test whether the LockPoints height and time are still valid on the current chain
*/
-bool TestLockPointValidity(const LockPoints* lp);
+bool TestLockPointValidity(const LockPoints* lp) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Check if transaction will be BIP 68 final in the next block to be created.
@@ -347,7 +329,7 @@ bool TestLockPointValidity(const LockPoints* lp);
*
* See consensus/consensus.h for flag definitions.
*/
-bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false);
+bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Closure representing one script verification
@@ -389,11 +371,13 @@ void InitScriptExecutionCache();
/** Functions for disk access for blocks */
-bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
+bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams);
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
-bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& message_start);
+bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start);
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start);
+bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
+
/** Functions for validating blocks and updating the block tree */
/** Context-independent validity checks */
@@ -409,7 +393,7 @@ bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& pa
bool IsNullDummyEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
-bool RewindBlockIndex(const CChainParams& params);
+bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
/** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */
void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams);
@@ -428,7 +412,7 @@ public:
/** Replay blocks that aren't fully applied to the database. */
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
-inline CBlockIndex* LookupBlockIndex(const uint256& hash)
+inline CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
BlockMap::const_iterator it = mapBlockIndex.find(hash);
@@ -436,7 +420,7 @@ inline CBlockIndex* LookupBlockIndex(const uint256& hash)
}
/** Find the last common block between the parameter chain and a locator. */
-CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
+CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Mark a block as precious and reorganize.
*
@@ -446,13 +430,13 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main);
/** Mark a block as invalid. */
-bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
/** Remove invalidity status from a block and its descendants. */
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/** The currently-connected chain of blocks (protected by cs_main). */
-extern CChain& chainActive;
+/** @returns the most-work chain. */
+CChain& ChainActive();
/** Global variable that points to the coins database (protected by cs_main) */
extern std::unique_ptr<CCoinsViewDB> pcoinsdbview;
@@ -489,10 +473,10 @@ static const unsigned int REJECT_HIGHFEE = 0x100;
CBlockFileInfo* GetBlockFileInfo(size_t n);
/** Dump the mempool to disk. */
-bool DumpMempool();
+bool DumpMempool(const CTxMemPool& pool);
/** Load the mempool from disk. */
-bool LoadMempool();
+bool LoadMempool(CTxMemPool& pool);
//! Check whether the block associated with this index entry is pruned or not.
inline bool IsBlockPruned(const CBlockIndex* pblockindex)
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index aff4c44cea..5d0ee1d1fc 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,17 +7,28 @@
#include <primitives/block.h>
#include <scheduler.h>
-#include <sync.h>
#include <txmempool.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <list>
#include <atomic>
#include <future>
+#include <utility>
#include <boost/signals2/signal.hpp>
+struct ValidationInterfaceConnections {
+ boost::signals2::scoped_connection UpdatedBlockTip;
+ boost::signals2::scoped_connection TransactionAddedToMempool;
+ boost::signals2::scoped_connection BlockConnected;
+ boost::signals2::scoped_connection BlockDisconnected;
+ boost::signals2::scoped_connection TransactionRemovedFromMempool;
+ boost::signals2::scoped_connection ChainStateFlushed;
+ boost::signals2::scoped_connection BlockChecked;
+ boost::signals2::scoped_connection NewPoWValidBlock;
+};
+
struct MainSignalsInstance {
boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool;
@@ -25,7 +36,6 @@ struct MainSignalsInstance {
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
- boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast;
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
@@ -33,12 +43,18 @@ struct MainSignalsInstance {
// but must ensure all callbacks happen in-order, so we end up creating
// our own queue here :(
SingleThreadedSchedulerClient m_schedulerClient;
+ std::unordered_map<CValidationInterface*, ValidationInterfaceConnections> m_connMainSignals;
explicit MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {}
};
static CMainSignals g_signals;
+// This map has to a separate global instead of a member of MainSignalsInstance,
+// because RegisterWithMempoolSignals is currently called before RegisterBackgroundSignalScheduler,
+// so MainSignalsInstance hasn't been created yet.
+static std::unordered_map<CTxMemPool*, boost::signals2::scoped_connection> g_connNotifyEntryRemoved;
+
void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) {
assert(!m_internals);
m_internals.reset(new MainSignalsInstance(&scheduler));
@@ -60,11 +76,14 @@ size_t CMainSignals::CallbacksPending() {
}
void CMainSignals::RegisterWithMempoolSignals(CTxMemPool& pool) {
- pool.NotifyEntryRemoved.connect(boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2));
+ g_connNotifyEntryRemoved.emplace(std::piecewise_construct,
+ std::forward_as_tuple(&pool),
+ std::forward_as_tuple(pool.NotifyEntryRemoved.connect(std::bind(&CMainSignals::MempoolEntryRemoved, this, std::placeholders::_1, std::placeholders::_2)))
+ );
}
void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool& pool) {
- pool.NotifyEntryRemoved.disconnect(boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2));
+ g_connNotifyEntryRemoved.erase(&pool);
}
CMainSignals& GetMainSignals()
@@ -73,42 +92,28 @@ CMainSignals& GetMainSignals()
}
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
- g_signals.m_internals->UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
- g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
- g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
- g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
- g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
- g_signals.m_internals->ChainStateFlushed.connect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1));
- g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
- g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
- g_signals.m_internals->NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
+ ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn];
+ conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ conns.TransactionAddedToMempool = g_signals.m_internals->TransactionAddedToMempool.connect(std::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, std::placeholders::_1));
+ conns.BlockConnected = g_signals.m_internals->BlockConnected.connect(std::bind(&CValidationInterface::BlockConnected, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ conns.BlockDisconnected = g_signals.m_internals->BlockDisconnected.connect(std::bind(&CValidationInterface::BlockDisconnected, pwalletIn, std::placeholders::_1));
+ conns.TransactionRemovedFromMempool = g_signals.m_internals->TransactionRemovedFromMempool.connect(std::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, std::placeholders::_1));
+ conns.ChainStateFlushed = g_signals.m_internals->ChainStateFlushed.connect(std::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, std::placeholders::_1));
+ conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2));
+ conns.NewPoWValidBlock = g_signals.m_internals->NewPoWValidBlock.connect(std::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, std::placeholders::_1, std::placeholders::_2));
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
- g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
- g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
- g_signals.m_internals->ChainStateFlushed.disconnect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1));
- g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
- g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
- g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
- g_signals.m_internals->TransactionRemovedFromMempool.disconnect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
- g_signals.m_internals->UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
- g_signals.m_internals->NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
+ if (g_signals.m_internals) {
+ g_signals.m_internals->m_connMainSignals.erase(pwalletIn);
+ }
}
void UnregisterAllValidationInterfaces() {
if (!g_signals.m_internals) {
return;
}
- g_signals.m_internals->BlockChecked.disconnect_all_slots();
- g_signals.m_internals->Broadcast.disconnect_all_slots();
- g_signals.m_internals->ChainStateFlushed.disconnect_all_slots();
- g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots();
- g_signals.m_internals->BlockConnected.disconnect_all_slots();
- g_signals.m_internals->BlockDisconnected.disconnect_all_slots();
- g_signals.m_internals->TransactionRemovedFromMempool.disconnect_all_slots();
- g_signals.m_internals->UpdatedBlockTip.disconnect_all_slots();
- g_signals.m_internals->NewPoWValidBlock.disconnect_all_slots();
+ g_signals.m_internals->m_connMainSignals.clear();
}
void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) {
@@ -167,10 +172,6 @@ void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
});
}
-void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) {
- m_internals->Broadcast(nBestBlockTime, connman);
-}
-
void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
m_internals->BlockChecked(block, state);
}
diff --git a/src/validationinterface.h b/src/validationinterface.h
index bddc28d24a..ea1b2e7e76 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,16 +7,17 @@
#define BITCOIN_VALIDATIONINTERFACE_H
#include <primitives/transaction.h> // CTransaction(Ref)
+#include <sync.h>
#include <functional>
#include <memory>
+extern CCriticalSection cs_main;
class CBlock;
class CBlockIndex;
struct CBlockLocator;
class CBlockIndex;
class CConnman;
-class CReserveScript;
class CValidationInterface;
class CValidationState;
class uint256;
@@ -51,7 +52,7 @@ void CallFunctionInValidationInterfaceQueue(std::function<void ()> func);
* });
* promise.get_future().wait();
*/
-void SyncWithValidationInterfaceQueue();
+void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main);
/**
* Implement this to subscribe to events generated in validation
@@ -132,8 +133,6 @@ protected:
* Called on a background thread.
*/
virtual void ChainStateFlushed(const CBlockLocator &locator) {}
- /** Tells listeners to broadcast their data. */
- virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {}
/**
* Notifies listeners of a block validation result.
* If the provided CValidationState IsValid, the provided block
@@ -182,7 +181,6 @@ public:
void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
void BlockDisconnected(const std::shared_ptr<const CBlock> &);
void ChainStateFlushed(const CBlockLocator &);
- void Broadcast(int64_t nBestBlockTime, CConnman* connman);
void BlockChecked(const CBlock&, const CValidationState&);
void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&);
};
diff --git a/src/version.h b/src/version.h
index 4b38547f35..d932b512d4 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
index e3ec078173..3f297c0ebb 100644
--- a/src/versionbits.cpp
+++ b/src/versionbits.cpp
@@ -1,25 +1,10 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <versionbits.h>
#include <consensus/params.h>
-const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
- {
- /*.name =*/ "testdummy",
- /*.gbt_force =*/ true,
- },
- {
- /*.name =*/ "csv",
- /*.gbt_force =*/ true,
- },
- {
- /*.name =*/ "segwit",
- /*.gbt_force =*/ true,
- }
-};
-
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
int nPeriod = Period(params);
diff --git a/src/versionbits.h b/src/versionbits.h
index 8962a65057..cdc947cd9e 100644
--- a/src/versionbits.h
+++ b/src/versionbits.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -30,13 +30,6 @@ enum class ThresholdState {
// will either be nullptr or a block with (height + 1) % Period() == 0.
typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
-struct VBDeploymentInfo {
- /** Deployment name */
- const char *name;
- /** Whether GBT clients can safely ignore this rule in simplified usage */
- bool gbt_force;
-};
-
struct BIP9Stats {
int period;
int threshold;
@@ -45,8 +38,6 @@ struct BIP9Stats {
bool possible;
};
-extern const struct VBDeploymentInfo VersionBitsDeploymentInfo[];
-
/**
* Abstract class that implements BIP9-style threshold logic, and caches results.
*/
diff --git a/src/versionbitsinfo.cpp b/src/versionbitsinfo.cpp
new file mode 100644
index 0000000000..ecf3482927
--- /dev/null
+++ b/src/versionbitsinfo.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <versionbitsinfo.h>
+
+#include <consensus/params.h>
+
+const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
+ {
+ /*.name =*/ "testdummy",
+ /*.gbt_force =*/ true,
+ },
+ {
+ /*.name =*/ "csv",
+ /*.gbt_force =*/ true,
+ },
+ {
+ /*.name =*/ "segwit",
+ /*.gbt_force =*/ true,
+ }
+};
diff --git a/src/versionbitsinfo.h b/src/versionbitsinfo.h
new file mode 100644
index 0000000000..a7822bc747
--- /dev/null
+++ b/src/versionbitsinfo.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_VERSIONBITSINFO_H
+#define BITCOIN_VERSIONBITSINFO_H
+
+struct VBDeploymentInfo {
+ /** Deployment name */
+ const char *name;
+ /** Whether GBT clients can safely ignore this rule in simplified usage */
+ bool gbt_force;
+};
+
+extern const struct VBDeploymentInfo VersionBitsDeploymentInfo[];
+
+#endif // BITCOIN_VERSIONBITSINFO_H
diff --git a/src/wallet/coincontrol.cpp b/src/wallet/coincontrol.cpp
index 645981faa4..87d2c4f06e 100644
--- a/src/wallet/coincontrol.cpp
+++ b/src/wallet/coincontrol.cpp
@@ -4,7 +4,7 @@
#include <wallet/coincontrol.h>
-#include <util.h>
+#include <util/system.h>
void CCoinControl::SetNull()
{
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index fbe6c43e24..12ba032dff 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -36,6 +36,8 @@ public:
bool m_avoid_partial_spends;
//! Fee estimation mode to control arguments to estimateSmartFee
FeeEstimateMode m_fee_mode;
+ //! Minimum chain depth value for coin availability
+ int m_min_depth{0};
CCoinControl()
{
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index 1a810e763f..8a37f374a1 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -1,10 +1,13 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <wallet/coinselection.h>
-#include <util.h>
-#include <utilmoneystr.h>
+
+#include <util/system.h>
+#include <util/moneystr.h>
+
+#include <boost/optional.hpp>
// Descending order comparator
struct {
@@ -220,7 +223,7 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
std::vector<OutputGroup> applicable_groups;
CAmount nTotalLower = 0;
- random_shuffle(groups.begin(), groups.end(), GetRandInt);
+ Shuffle(groups.begin(), groups.end(), FastRandomContext());
for (const OutputGroup& group : groups) {
if (group.m_value == nTargetValue) {
@@ -299,12 +302,12 @@ void OutputGroup::Insert(const CInputCoin& output, int depth, bool from_me, size
m_from_me &= from_me;
m_value += output.effective_value;
m_depth = std::min(m_depth, depth);
- // m_ancestors is currently the max ancestor count for all coins in the group; however, this is
- // not ideal, as a wallet will consider e.g. thirty 2-ancestor coins as having two ancestors,
- // when in reality it has 60 ancestors.
- m_ancestors = std::max(m_ancestors, ancestors);
- // m_descendants is the count as seen from the top ancestor, not the descendants as seen from the
- // coin itself; thus, this value is accurate
+ // ancestors here express the number of ancestors the new coin will end up having, which is
+ // the sum, rather than the max; this will overestimate in the cases where multiple inputs
+ // have common ancestors
+ m_ancestors += ancestors;
+ // descendants is the count as seen from the top ancestor, not the descendants as seen from the
+ // coin itself; thus, this value is counted as the max, not the sum
m_descendants = std::max(m_descendants, descendants);
effective_value = m_value;
}
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index 1be776e695..5348401f45 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,7 @@
#include <random.h>
//! target minimum change amount
-static const CAmount MIN_CHANGE = CENT;
+static constexpr CAmount MIN_CHANGE{COIN / 100};
//! final minimum change amount after paying for fees
static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2;
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp
index 6ad18721fd..dd56ea10ab 100644
--- a/src/wallet/crypter.cpp
+++ b/src/wallet/crypter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <crypto/sha512.h>
#include <script/script.h>
#include <script/standard.h>
-#include <util.h>
+#include <util/system.h>
#include <string>
#include <vector>
@@ -175,14 +175,14 @@ bool CCryptoKeyStore::Lock()
return true;
}
-bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
+bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys)
{
{
LOCK(cs_KeyStore);
if (!SetCrypted())
return false;
- bool keyPass = false;
+ bool keyPass = mapCryptedKeys.empty(); // Always pass when there are no encrypted keys
bool keyFail = false;
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
for (; mi != mapCryptedKeys.end(); ++mi)
@@ -202,9 +202,9 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
if (keyPass && keyFail)
{
LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
- assert(false);
+ throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
}
- if (keyFail || !keyPass)
+ if (keyFail || (!keyPass && !accept_no_keys))
return false;
vMasterKey = vMasterKeyIn;
fDecryptionThoroughlyChecked = true;
@@ -311,7 +311,7 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
return false;
fUseCrypto = true;
- for (KeyMap::value_type& mKey : mapKeys)
+ for (const KeyMap::value_type& mKey : mapKeys)
{
const CKey &key = mKey.second;
CPubKey vchPubKey = key.GetPubKey();
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index 52842cd978..8e195ca8fa 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -133,7 +133,7 @@ protected:
//! will encrypt previously unencrypted keys
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
- bool Unlock(const CKeyingMaterial& vMasterKeyIn);
+ bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys = false);
CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
public:
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 01b8eacccb..546e3d54eb 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <addrman.h>
#include <hash.h>
#include <protocol.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
#include <wallet/walletutil.h>
#include <stdint.h>
@@ -20,6 +20,7 @@
#include <boost/thread.hpp>
namespace {
+
//! Make sure database has a unique fileid within the environment. If it
//! doesn't, throw an error. BDB caches do not work properly when more than one
//! open database has the same fileid (values written to one database may show
@@ -29,36 +30,34 @@ namespace {
//! (https://docs.oracle.com/cd/E17275_01/html/programmer_reference/program_copy.html),
//! so bitcoin should never create different databases with the same fileid, but
//! this error can be triggered if users manually copy database files.
-void CheckUniqueFileid(const BerkeleyEnvironment& env, const std::string& filename, Db& db)
+void CheckUniqueFileid(const BerkeleyEnvironment& env, const std::string& filename, Db& db, WalletDatabaseFileId& fileid)
{
if (env.IsMock()) return;
- u_int8_t fileid[DB_FILE_ID_LEN];
- int ret = db.get_mpf()->get_fileid(fileid);
+ int ret = db.get_mpf()->get_fileid(fileid.value);
if (ret != 0) {
throw std::runtime_error(strprintf("BerkeleyBatch: Can't open database %s (get_fileid failed with %d)", filename, ret));
}
- for (const auto& item : env.mapDb) {
- u_int8_t item_fileid[DB_FILE_ID_LEN];
- if (item.second && item.second->get_mpf()->get_fileid(item_fileid) == 0 &&
- memcmp(fileid, item_fileid, sizeof(fileid)) == 0) {
- const char* item_filename = nullptr;
- item.second->get_dbname(&item_filename, nullptr);
+ for (const auto& item : env.m_fileids) {
+ if (fileid == item.second && &fileid != &item.second) {
throw std::runtime_error(strprintf("BerkeleyBatch: Can't open database %s (duplicates fileid %s from %s)", filename,
- HexStr(std::begin(item_fileid), std::end(item_fileid)),
- item_filename ? item_filename : "(unknown database)"));
+ HexStr(std::begin(item.second.value), std::end(item.second.value)), item.first));
}
}
}
CCriticalSection cs_db;
-std::map<std::string, BerkeleyEnvironment> g_dbenvs GUARDED_BY(cs_db); //!< Map from directory name to open db environment.
+std::map<std::string, std::weak_ptr<BerkeleyEnvironment>> g_dbenvs GUARDED_BY(cs_db); //!< Map from directory name to db environment.
} // namespace
-BerkeleyEnvironment* GetWalletEnv(const fs::path& wallet_path, std::string& database_filename)
+bool WalletDatabaseFileId::operator==(const WalletDatabaseFileId& rhs) const
+{
+ return memcmp(value, &rhs.value, sizeof(value)) == 0;
+}
+
+static void SplitWalletPath(const fs::path& wallet_path, fs::path& env_directory, std::string& database_filename)
{
- fs::path env_directory;
if (fs::is_regular_file(wallet_path)) {
// Special case for backwards compatibility: if wallet path points to an
// existing file, treat it as the path to a BDB data file in a parent
@@ -71,12 +70,47 @@ BerkeleyEnvironment* GetWalletEnv(const fs::path& wallet_path, std::string& data
env_directory = wallet_path;
database_filename = "wallet.dat";
}
+}
+
+bool IsWalletLoaded(const fs::path& wallet_path)
+{
+ fs::path env_directory;
+ std::string database_filename;
+ SplitWalletPath(wallet_path, env_directory, database_filename);
LOCK(cs_db);
- // Note: An ununsed temporary BerkeleyEnvironment object may be created inside the
- // emplace function if the key already exists. This is a little inefficient,
- // but not a big concern since the map will be changed in the future to hold
- // pointers instead of objects, anyway.
- return &g_dbenvs.emplace(std::piecewise_construct, std::forward_as_tuple(env_directory.string()), std::forward_as_tuple(env_directory)).first->second;
+ auto env = g_dbenvs.find(env_directory.string());
+ if (env == g_dbenvs.end()) return false;
+ auto database = env->second.lock();
+ return database && database->IsDatabaseLoaded(database_filename);
+}
+
+fs::path WalletDataFilePath(const fs::path& wallet_path)
+{
+ fs::path env_directory;
+ std::string database_filename;
+ SplitWalletPath(wallet_path, env_directory, database_filename);
+ return env_directory / database_filename;
+}
+
+/**
+ * @param[in] wallet_path Path to wallet directory. Or (for backwards compatibility only) a path to a berkeley btree data file inside a wallet directory.
+ * @param[out] database_filename Filename of berkeley btree data file inside the wallet directory.
+ * @return A shared pointer to the BerkeleyEnvironment object for the wallet directory, never empty because ~BerkeleyEnvironment
+ * erases the weak pointer from the g_dbenvs map.
+ * @post A new BerkeleyEnvironment weak pointer is inserted into g_dbenvs if the directory path key was not already in the map.
+ */
+std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& wallet_path, std::string& database_filename)
+{
+ fs::path env_directory;
+ SplitWalletPath(wallet_path, env_directory, database_filename);
+ LOCK(cs_db);
+ auto inserted = g_dbenvs.emplace(env_directory.string(), std::weak_ptr<BerkeleyEnvironment>());
+ if (inserted.second) {
+ auto env = std::make_shared<BerkeleyEnvironment>(env_directory.string());
+ inserted.first->second = env;
+ return env;
+ }
+ return inserted.first->second.lock();
}
//
@@ -90,21 +124,28 @@ void BerkeleyEnvironment::Close()
fDbEnvInit = false;
- for (auto& db : mapDb) {
+ for (auto& db : m_databases) {
auto count = mapFileUseCount.find(db.first);
assert(count == mapFileUseCount.end() || count->second == 0);
- if (db.second) {
- db.second->close(0);
- delete db.second;
- db.second = nullptr;
+ BerkeleyDatabase& database = db.second.get();
+ if (database.m_db) {
+ database.m_db->close(0);
+ database.m_db.reset();
}
}
+ FILE* error_file = nullptr;
+ dbenv->get_errfile(&error_file);
+
int ret = dbenv->close(0);
if (ret != 0)
LogPrintf("BerkeleyEnvironment::Close: Error %d closing database environment: %s\n", ret, DbEnv::strerror(ret));
if (!fMockDb)
DbEnv((u_int32_t)0).remove(strPath.c_str(), 0);
+
+ if (error_file) fclose(error_file);
+
+ UnlockDirectory(strPath, ".walletlock");
}
void BerkeleyEnvironment::Reset()
@@ -121,6 +162,8 @@ BerkeleyEnvironment::BerkeleyEnvironment(const fs::path& dir_path) : strPath(dir
BerkeleyEnvironment::~BerkeleyEnvironment()
{
+ LOCK(cs_db);
+ g_dbenvs.erase(strPath);
Close();
}
@@ -198,10 +241,10 @@ bool BerkeleyEnvironment::Open(bool retry)
return true;
}
-void BerkeleyEnvironment::MakeMock()
+//! Construct an in-memory mock Berkeley environment for testing and as a place-holder for g_dbenvs emplace
+BerkeleyEnvironment::BerkeleyEnvironment()
{
- if (fDbEnvInit)
- throw std::runtime_error("BerkeleyEnvironment::MakeMock: Already initialized");
+ Reset();
boost::this_thread::interruption_point();
@@ -247,10 +290,49 @@ BerkeleyEnvironment::VerifyResult BerkeleyEnvironment::Verify(const std::string&
return (fRecovered ? VerifyResult::RECOVER_OK : VerifyResult::RECOVER_FAIL);
}
+BerkeleyBatch::SafeDbt::SafeDbt()
+{
+ m_dbt.set_flags(DB_DBT_MALLOC);
+}
+
+BerkeleyBatch::SafeDbt::SafeDbt(void* data, size_t size)
+ : m_dbt(data, size)
+{
+}
+
+BerkeleyBatch::SafeDbt::~SafeDbt()
+{
+ if (m_dbt.get_data() != nullptr) {
+ // Clear memory, e.g. in case it was a private key
+ memory_cleanse(m_dbt.get_data(), m_dbt.get_size());
+ // under DB_DBT_MALLOC, data is malloced by the Dbt, but must be
+ // freed by the caller.
+ // https://docs.oracle.com/cd/E17275_01/html/api_reference/C/dbt.html
+ if (m_dbt.get_flags() & DB_DBT_MALLOC) {
+ free(m_dbt.get_data());
+ }
+ }
+}
+
+const void* BerkeleyBatch::SafeDbt::get_data() const
+{
+ return m_dbt.get_data();
+}
+
+u_int32_t BerkeleyBatch::SafeDbt::get_size() const
+{
+ return m_dbt.get_size();
+}
+
+BerkeleyBatch::SafeDbt::operator Dbt*()
+{
+ return &m_dbt;
+}
+
bool BerkeleyBatch::Recover(const fs::path& file_path, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename)
{
std::string filename;
- BerkeleyEnvironment* env = GetWalletEnv(file_path, filename);
+ std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, filename);
// Recovery procedure:
// move wallet file to walletfilename.timestamp.bak
@@ -319,18 +401,11 @@ bool BerkeleyBatch::Recover(const fs::path& file_path, void *callbackDataIn, boo
bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& errorStr)
{
std::string walletFile;
- BerkeleyEnvironment* env = GetWalletEnv(file_path, walletFile);
+ std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, walletFile);
fs::path walletDir = env->Directory();
- LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
- LogPrintf("Using wallet %s\n", walletFile);
-
- // Wallet file must be a plain filename without a directory
- if (walletFile != fs::basename(walletFile) + fs::extension(walletFile))
- {
- errorStr = strprintf(_("Wallet %s resides outside wallet directory %s"), walletFile, walletDir.string());
- return false;
- }
+ LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(nullptr, nullptr, nullptr));
+ LogPrintf("Using wallet %s\n", file_path.string());
if (!env->Open(true /* retry */)) {
errorStr = strprintf(_("Error initializing wallet database environment %s!"), walletDir);
@@ -343,7 +418,7 @@ bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& er
bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
{
std::string walletFile;
- BerkeleyEnvironment* env = GetWalletEnv(file_path, walletFile);
+ std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, walletFile);
fs::path walletDir = env->Directory();
if (fs::exists(walletDir / walletFile))
@@ -447,7 +522,7 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
{
fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
fFlushOnClose = fFlushOnCloseIn;
- env = database.env;
+ env = database.env.get();
if (database.IsDummy()) {
return;
}
@@ -463,7 +538,7 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
if (!env->Open(false /* retry */))
throw std::runtime_error("BerkeleyBatch: Failed to open database environment.");
- pdb = env->mapDb[strFilename];
+ pdb = database.m_db.get();
if (pdb == nullptr) {
int ret;
std::unique_ptr<Db> pdb_temp = MakeUnique<Db>(env->dbenv.get(), 0);
@@ -503,12 +578,12 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
// be implemented, so no equality checks are needed at all. (Newer
// versions of BDB have an set_lk_exclusive method for this
// purpose, but the older version we use does not.)
- for (auto& env : g_dbenvs) {
- CheckUniqueFileid(env.second, strFilename, *pdb_temp);
+ for (const auto& env : g_dbenvs) {
+ CheckUniqueFileid(*env.second.lock().get(), strFilename, *pdb_temp, this->env->m_fileids[strFilename]);
}
pdb = pdb_temp.release();
- env->mapDb[strFilename] = pdb;
+ database.m_db.reset(pdb);
if (fCreate && !Exists(std::string("version"))) {
bool fTmp = fReadOnly;
@@ -556,28 +631,56 @@ void BerkeleyBatch::Close()
LOCK(cs_db);
--env->mapFileUseCount[strFile];
}
+ env->m_db_in_use.notify_all();
}
void BerkeleyEnvironment::CloseDb(const std::string& strFile)
{
{
LOCK(cs_db);
- if (mapDb[strFile] != nullptr) {
+ auto it = m_databases.find(strFile);
+ assert(it != m_databases.end());
+ BerkeleyDatabase& database = it->second.get();
+ if (database.m_db) {
// Close the database handle
- Db* pdb = mapDb[strFile];
- pdb->close(0);
- delete pdb;
- mapDb[strFile] = nullptr;
+ database.m_db->close(0);
+ database.m_db.reset();
}
}
}
+void BerkeleyEnvironment::ReloadDbEnv()
+{
+ // Make sure that no Db's are in use
+ AssertLockNotHeld(cs_db);
+ std::unique_lock<CCriticalSection> lock(cs_db);
+ m_db_in_use.wait(lock, [this](){
+ for (auto& count : mapFileUseCount) {
+ if (count.second > 0) return false;
+ }
+ return true;
+ });
+
+ std::vector<std::string> filenames;
+ for (auto it : m_databases) {
+ filenames.push_back(it.first);
+ }
+ // Close the individual Db's
+ for (const std::string& filename : filenames) {
+ CloseDb(filename);
+ }
+ // Reset the environment
+ Flush(true); // This will flush and close the environment
+ Reset();
+ Open(true);
+}
+
bool BerkeleyBatch::Rewrite(BerkeleyDatabase& database, const char* pszSkip)
{
if (database.IsDummy()) {
return true;
}
- BerkeleyEnvironment *env = database.env;
+ BerkeleyEnvironment *env = database.env.get();
const std::string& strFile = database.strFile;
while (true) {
{
@@ -665,7 +768,7 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
{
int64_t nStart = GetTimeMillis();
// Flush log data to the actual data file on all files that are not in use
- LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
+ LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: [%s] Flush(%s)%s\n", strPath, fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
if (!fDbEnvInit)
return;
{
@@ -697,7 +800,6 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
if (!fMockDb) {
fs::remove_all(fs::path(strPath) / "database");
}
- g_dbenvs.erase(strPath);
}
}
}
@@ -709,7 +811,7 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database)
return true;
}
bool ret = false;
- BerkeleyEnvironment *env = database.env;
+ BerkeleyEnvironment *env = database.env.get();
const std::string& strFile = database.strFile;
TRY_LOCK(cs_db, lockDb);
if (lockDb)
@@ -768,7 +870,7 @@ bool BerkeleyDatabase::Backup(const std::string& strDest)
env->mapFileUseCount.erase(strFile);
// Copy wallet file
- fs::path pathSrc = GetWalletDir() / strFile;
+ fs::path pathSrc = env->Directory() / strFile;
fs::path pathDest(strDest);
if (fs::is_directory(pathDest))
pathDest /= strFile;
@@ -783,7 +885,7 @@ bool BerkeleyDatabase::Backup(const std::string& strDest)
LogPrintf("copied %s to %s\n", strFile, pathDest.string());
return true;
} catch (const fs::filesystem_error& e) {
- LogPrintf("error copying %s to %s - %s\n", strFile, pathDest.string(), e.what());
+ LogPrintf("error copying %s to %s - %s\n", strFile, pathDest.string(), fsbridge::get_filesystem_error_message(e));
return false;
}
}
@@ -796,6 +898,24 @@ void BerkeleyDatabase::Flush(bool shutdown)
{
if (!IsDummy()) {
env->Flush(shutdown);
- if (shutdown) env = nullptr;
+ if (shutdown) {
+ LOCK(cs_db);
+ g_dbenvs.erase(env->Directory().string());
+ env = nullptr;
+ } else {
+ // TODO: To avoid g_dbenvs.erase erasing the environment prematurely after the
+ // first database shutdown when multiple databases are open in the same
+ // environment, should replace raw database `env` pointers with shared or weak
+ // pointers, or else separate the database and environment shutdowns so
+ // environments can be shut down after databases.
+ env->m_fileids.erase(strFile);
+ }
+ }
+}
+
+void BerkeleyDatabase::ReloadDbEnv()
+{
+ if (!IsDummy()) {
+ env->ReloadDbEnv();
}
}
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 5e61280f7a..b3856fbaf9 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,13 +11,14 @@
#include <serialize.h>
#include <streams.h>
#include <sync.h>
-#include <util.h>
+#include <util/system.h>
#include <version.h>
#include <atomic>
#include <map>
#include <memory>
#include <string>
+#include <unordered_map>
#include <vector>
#include <db_cxx.h>
@@ -25,6 +26,13 @@
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
static const bool DEFAULT_WALLET_PRIVDB = true;
+struct WalletDatabaseFileId {
+ u_int8_t value[DB_FILE_ID_LEN];
+ bool operator==(const WalletDatabaseFileId& rhs) const;
+};
+
+class BerkeleyDatabase;
+
class BerkeleyEnvironment
{
private:
@@ -37,15 +45,18 @@ private:
public:
std::unique_ptr<DbEnv> dbenv;
std::map<std::string, int> mapFileUseCount;
- std::map<std::string, Db*> mapDb;
+ std::map<std::string, std::reference_wrapper<BerkeleyDatabase>> m_databases;
+ std::unordered_map<std::string, WalletDatabaseFileId> m_fileids;
+ std::condition_variable_any m_db_in_use;
BerkeleyEnvironment(const fs::path& env_directory);
+ BerkeleyEnvironment();
~BerkeleyEnvironment();
void Reset();
- void MakeMock();
bool IsMock() const { return fMockDb; }
bool IsInitialized() const { return fDbEnvInit; }
+ bool IsDatabaseLoaded(const std::string& db_filename) const { return m_databases.find(db_filename) != m_databases.end(); }
fs::path Directory() const { return strPath; }
/**
@@ -75,6 +86,7 @@ public:
void CheckpointLSN(const std::string& strFile);
void CloseDb(const std::string& strFile);
+ void ReloadDbEnv();
DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
{
@@ -86,8 +98,14 @@ public:
}
};
+/** Return whether a wallet database is currently loaded. */
+bool IsWalletLoaded(const fs::path& wallet_path);
+
+/** Given a wallet directory path or legacy file path, return path to main data file in the wallet database. */
+fs::path WalletDataFilePath(const fs::path& wallet_path);
+
/** Get BerkeleyEnvironment and database filename given a wallet path. */
-BerkeleyEnvironment* GetWalletEnv(const fs::path& wallet_path, std::string& database_filename);
+std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& wallet_path, std::string& database_filename);
/** An instance of this class represents one database.
* For BerkeleyDB this is just a (env, strFile) tuple.
@@ -102,21 +120,25 @@ public:
}
/** Create DB handle to real database */
- BerkeleyDatabase(const fs::path& wallet_path, bool mock = false) :
- nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0)
+ BerkeleyDatabase(std::shared_ptr<BerkeleyEnvironment> env, std::string filename) :
+ nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(std::move(env)), strFile(std::move(filename))
{
- env = GetWalletEnv(wallet_path, strFile);
- if (mock) {
- env->Close();
- env->Reset();
- env->MakeMock();
+ auto inserted = this->env->m_databases.emplace(strFile, std::ref(*this));
+ assert(inserted.second);
+ }
+
+ ~BerkeleyDatabase() {
+ if (env) {
+ size_t erased = env->m_databases.erase(strFile);
+ assert(erased == 1);
}
}
/** Return object for accessing database at specified path. */
static std::unique_ptr<BerkeleyDatabase> Create(const fs::path& path)
{
- return MakeUnique<BerkeleyDatabase>(path);
+ std::string filename;
+ return MakeUnique<BerkeleyDatabase>(GetWalletEnv(path, filename), std::move(filename));
}
/** Return object for accessing dummy database with no read/write capabilities. */
@@ -128,7 +150,7 @@ public:
/** Return object for accessing temporary in-memory database. */
static std::unique_ptr<BerkeleyDatabase> CreateMock()
{
- return MakeUnique<BerkeleyDatabase>("", true /* mock */);
+ return MakeUnique<BerkeleyDatabase>(std::make_shared<BerkeleyEnvironment>(), "");
}
/** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
@@ -145,14 +167,28 @@ public:
void IncrementUpdateCounter();
+ void ReloadDbEnv();
+
std::atomic<unsigned int> nUpdateCounter;
unsigned int nLastSeen;
unsigned int nLastFlushed;
int64_t nLastWalletUpdate;
+ /**
+ * Pointer to shared database environment.
+ *
+ * Normally there is only one BerkeleyDatabase object per
+ * BerkeleyEnvivonment, but in the special, backwards compatible case where
+ * multiple wallet BDB data files are loaded from the same directory, this
+ * will point to a shared instance that gets freed when the last data file
+ * is closed.
+ */
+ std::shared_ptr<BerkeleyEnvironment> env;
+
+ /** Database pointer. This is initialized lazily and reset during flushes, so it can be null. */
+ std::unique_ptr<Db> m_db;
+
private:
- /** BerkeleyDB specific */
- BerkeleyEnvironment *env;
std::string strFile;
/** Return whether this database handle is a dummy for testing.
@@ -162,10 +198,29 @@ private:
bool IsDummy() { return env == nullptr; }
};
-
/** RAII class that provides access to a Berkeley database */
class BerkeleyBatch
{
+ /** RAII class that automatically cleanses its data on destruction */
+ class SafeDbt final
+ {
+ Dbt m_dbt;
+
+ 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;
+ u_int32_t get_size() const;
+
+ // conversion operator to access the underlying Dbt
+ operator Dbt*();
+ };
+
protected:
Db* pdb;
std::string strFile;
@@ -193,7 +248,6 @@ public:
/* verifies the database file */
static bool VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
-public:
template <typename K, typename T>
bool Read(const K& key, T& value)
{
@@ -204,13 +258,11 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
- Dbt datKey(ssKey.data(), ssKey.size());
+ SafeDbt datKey(ssKey.data(), ssKey.size());
// Read
- Dbt datValue;
- datValue.set_flags(DB_DBT_MALLOC);
- int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
- memory_cleanse(datKey.get_data(), datKey.get_size());
+ SafeDbt datValue;
+ int ret = pdb->get(activeTxn, datKey, datValue, 0);
bool success = false;
if (datValue.get_data() != nullptr) {
// Unserialize value
@@ -221,10 +273,6 @@ public:
} catch (const std::exception&) {
// In this case success remains 'false'
}
-
- // Clear and free memory
- memory_cleanse(datValue.get_data(), datValue.get_size());
- free(datValue.get_data());
}
return ret == 0 && success;
}
@@ -241,20 +289,16 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
- Dbt datKey(ssKey.data(), ssKey.size());
+ SafeDbt datKey(ssKey.data(), ssKey.size());
// Value
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
ssValue.reserve(10000);
ssValue << value;
- Dbt datValue(ssValue.data(), ssValue.size());
+ SafeDbt datValue(ssValue.data(), ssValue.size());
// Write
- int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
-
- // Clear memory in case it was a private key
- memory_cleanse(datKey.get_data(), datKey.get_size());
- memory_cleanse(datValue.get_data(), datValue.get_size());
+ int ret = pdb->put(activeTxn, datKey, datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
return (ret == 0);
}
@@ -270,13 +314,10 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
- Dbt datKey(ssKey.data(), ssKey.size());
+ SafeDbt datKey(ssKey.data(), ssKey.size());
// Erase
- int ret = pdb->del(activeTxn, &datKey, 0);
-
- // Clear memory
- memory_cleanse(datKey.get_data(), datKey.get_size());
+ int ret = pdb->del(activeTxn, datKey, 0);
return (ret == 0 || ret == DB_NOTFOUND);
}
@@ -290,13 +331,10 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
- Dbt datKey(ssKey.data(), ssKey.size());
+ SafeDbt datKey(ssKey.data(), ssKey.size());
// Exists
- int ret = pdb->exists(activeTxn, &datKey, 0);
-
- // Clear memory
- memory_cleanse(datKey.get_data(), datKey.get_size());
+ int ret = pdb->exists(activeTxn, datKey, 0);
return (ret == 0);
}
@@ -311,20 +349,12 @@ public:
return pcursor;
}
- int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, bool setRange = false)
+ int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue)
{
// Read at cursor
- Dbt datKey;
- unsigned int fFlags = DB_NEXT;
- if (setRange) {
- datKey.set_data(ssKey.data());
- datKey.set_size(ssKey.size());
- fFlags = DB_SET_RANGE;
- }
- Dbt datValue;
- datKey.set_flags(DB_DBT_MALLOC);
- datValue.set_flags(DB_DBT_MALLOC);
- int ret = pcursor->get(&datKey, &datValue, fFlags);
+ SafeDbt datKey;
+ SafeDbt datValue;
+ int ret = pcursor->get(datKey, datValue, DB_NEXT);
if (ret != 0)
return ret;
else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
@@ -337,16 +367,9 @@ public:
ssValue.SetType(SER_DISK);
ssValue.clear();
ssValue.write((char*)datValue.get_data(), datValue.get_size());
-
- // Clear and free memory
- memory_cleanse(datKey.get_data(), datKey.get_size());
- memory_cleanse(datValue.get_data(), datValue.get_size());
- free(datKey.get_data());
- free(datValue.get_data());
return 0;
}
-public:
bool TxnBegin()
{
if (!pdb || activeTxn)
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 0eb85a6e5c..15ddd5cb97 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -1,8 +1,9 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <consensus/validation.h>
+#include <interfaces/chain.h>
#include <wallet/coincontrol.h>
#include <wallet/feebumper.h>
#include <wallet/fees.h>
@@ -12,13 +13,15 @@
#include <policy/rbf.h>
#include <validation.h> //for mempool access
#include <txmempool.h>
-#include <utilmoneystr.h>
-#include <util.h>
+#include <util/moneystr.h>
+#include <util/rbf.h>
+#include <util/system.h>
+#include <util/validation.h>
#include <net.h>
//! Check whether transaction has descendant in wallet or mempool, or has been
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
-static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet)
+static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet)
{
if (wallet->HasWalletSpend(wtx.GetHash())) {
errors.push_back("Transaction has descendants in the wallet");
@@ -26,15 +29,13 @@ static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWallet
}
{
- LOCK(mempool.cs);
- auto it_mp = mempool.mapTx.find(wtx.GetHash());
- if (it_mp != mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1) {
+ if (wallet->chain().hasDescendantsInMempool(wtx.GetHash())) {
errors.push_back("Transaction has descendants in the mempool");
return feebumper::Result::INVALID_PARAMETER;
}
}
- if (wtx.GetDepthInMainChain() != 0) {
+ if (wtx.GetDepthInMainChain(locked_chain) != 0) {
errors.push_back("Transaction has been mined, or is conflicted with a mined transaction");
return feebumper::Result::WALLET_ERROR;
}
@@ -64,19 +65,23 @@ namespace feebumper {
bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid)
{
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
const CWalletTx* wtx = wallet->GetWalletTx(txid);
if (wtx == nullptr) return false;
std::vector<std::string> errors_dummy;
- feebumper::Result res = PreconditionChecks(wallet, *wtx, errors_dummy);
+ feebumper::Result res = PreconditionChecks(*locked_chain, wallet, *wtx, errors_dummy);
return res == feebumper::Result::OK;
}
-Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors,
- CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
+Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, CAmount total_fee, std::vector<std::string>& errors,
+ CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
{
- LOCK2(cs_main, wallet->cs_wallet);
+ new_fee = total_fee;
+
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
errors.clear();
auto it = wallet->mapWallet.find(txid);
if (it == wallet->mapWallet.end()) {
@@ -85,7 +90,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
}
const CWalletTx& wtx = it->second;
- Result result = PreconditionChecks(wallet, wtx, errors);
+ Result result = PreconditionChecks(*locked_chain, wallet, wtx, errors);
if (result != Result::OK) {
return result;
}
@@ -118,49 +123,33 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
// calculate the old fee and fee-rate
old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
CFeeRate nOldFeeRate(old_fee, txSize);
- CFeeRate nNewFeeRate;
// The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to
// future proof against changes to network wide policy for incremental relay
// fee that our node may not be aware of.
+ CFeeRate nodeIncrementalRelayFee = wallet->chain().relayIncrementalFee();
CFeeRate walletIncrementalRelayFee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
- if (::incrementalRelayFee > walletIncrementalRelayFee) {
- walletIncrementalRelayFee = ::incrementalRelayFee;
+ if (nodeIncrementalRelayFee > walletIncrementalRelayFee) {
+ walletIncrementalRelayFee = nodeIncrementalRelayFee;
}
- if (total_fee > 0) {
- CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + ::incrementalRelayFee.GetFee(maxNewTxSize);
- if (total_fee < minTotalFee) {
- errors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)",
- FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(::incrementalRelayFee.GetFee(maxNewTxSize))));
- return Result::INVALID_PARAMETER;
- }
- CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize);
- if (total_fee < requiredFee) {
- errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)",
- FormatMoney(requiredFee)));
- return Result::INVALID_PARAMETER;
- }
- new_fee = total_fee;
- nNewFeeRate = CFeeRate(total_fee, maxNewTxSize);
- } else {
- new_fee = GetMinimumFee(*wallet, maxNewTxSize, coin_control, mempool, ::feeEstimator, nullptr /* FeeCalculation */);
- nNewFeeRate = CFeeRate(new_fee, maxNewTxSize);
-
- // New fee rate must be at least old rate + minimum incremental relay rate
- // walletIncrementalRelayFee.GetFeePerK() should be exact, because it's initialized
- // in that unit (fee per kb).
- // However, nOldFeeRate is a calculated value from the tx fee/size, so
- // add 1 satoshi to the result, because it may have been rounded down.
- if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + 1 + walletIncrementalRelayFee.GetFeePerK()) {
- nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + 1 + walletIncrementalRelayFee.GetFeePerK());
- new_fee = nNewFeeRate.GetFee(maxNewTxSize);
- }
+ CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + nodeIncrementalRelayFee.GetFee(maxNewTxSize);
+ if (total_fee < minTotalFee) {
+ errors.push_back(strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)",
+ FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(nodeIncrementalRelayFee.GetFee(maxNewTxSize))));
+ return Result::INVALID_PARAMETER;
+ }
+ CAmount requiredFee = GetRequiredFee(*wallet, maxNewTxSize);
+ if (total_fee < requiredFee) {
+ errors.push_back(strprintf("Insufficient totalFee (cannot be less than required fee %s)",
+ FormatMoney(requiredFee)));
+ return Result::INVALID_PARAMETER;
}
// Check that in all cases the new fee doesn't violate maxTxFee
- if (new_fee > maxTxFee) {
- errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)",
- FormatMoney(new_fee), FormatMoney(maxTxFee)));
+ const CAmount max_tx_fee = wallet->m_default_max_tx_fee;
+ if (new_fee > max_tx_fee) {
+ errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)",
+ FormatMoney(new_fee), FormatMoney(max_tx_fee)));
return Result::WALLET_ERROR;
}
@@ -169,15 +158,15 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
// This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
// in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
// moment earlier. In this case, we report an error to the user, who may use total_fee to make an adjustment.
- CFeeRate minMempoolFeeRate = mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
+ CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee();
+ CFeeRate nNewFeeRate = CFeeRate(total_fee, maxNewTxSize);
if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
errors.push_back(strprintf(
"New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- "
- "the totalFee value should be at least %s or the settxfee value should be at least %s to add transaction",
+ "the totalFee value should be at least %s to add transaction",
FormatMoney(nNewFeeRate.GetFeePerK()),
FormatMoney(minMempoolFeeRate.GetFeePerK()),
- FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)),
- FormatMoney(minMempoolFeeRate.GetFeePerK())));
+ FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize))));
return Result::WALLET_ERROR;
}
@@ -194,8 +183,8 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
// If the output would become dust, discard it (converting the dust to fee)
poutput->nValue -= nDelta;
- if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet, ::feeEstimator))) {
- LogPrint(BCLog::RPC, "Bumping fee and discarding dust output\n");
+ if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet))) {
+ wallet->WalletLogPrintf("Bumping fee and discarding dust output\n");
new_fee += poutput->nValue;
mtx.vout.erase(mtx.vout.begin() + nOutput);
}
@@ -207,18 +196,123 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
}
}
+ return Result::OK;
+}
+
+
+Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors,
+ CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
+{
+ // We are going to modify coin control later, copy to re-use
+ CCoinControl new_coin_control(coin_control);
+
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
+ errors.clear();
+ auto it = wallet->mapWallet.find(txid);
+ if (it == wallet->mapWallet.end()) {
+ errors.push_back("Invalid or non-wallet transaction id");
+ return Result::INVALID_ADDRESS_OR_KEY;
+ }
+ const CWalletTx& wtx = it->second;
+
+ Result result = PreconditionChecks(*locked_chain, wallet, wtx, errors);
+ if (result != Result::OK) {
+ return result;
+ }
+
+ // Fill in recipients(and preserve a single change key if there is one)
+ std::vector<CRecipient> recipients;
+ for (const auto& output : wtx.tx->vout) {
+ if (!wallet->IsChange(output)) {
+ CRecipient recipient = {output.scriptPubKey, output.nValue, false};
+ recipients.push_back(recipient);
+ } else {
+ CTxDestination change_dest;
+ ExtractDestination(output.scriptPubKey, change_dest);
+ new_coin_control.destChange = change_dest;
+ }
+ }
+
+ // Get the fee rate of the original transaction. This is calculated from
+ // the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the
+ // result.
+ old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
+ int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
+ // Feerate of thing we are bumping
+ CFeeRate feerate(old_fee, txSize);
+ feerate += CFeeRate(1);
+
+ // The node has a configurable incremental relay fee. Increment the fee by
+ // the minimum of that and the wallet's conservative
+ // WALLET_INCREMENTAL_RELAY_FEE value to future proof against changes to
+ // network wide policy for incremental relay fee that our node may not be
+ // aware of. This ensures we're over the over the required relay fee rate
+ // (BIP 125 rule 4). The replacement tx will be at least as large as the
+ // original tx, so the total fee will be greater (BIP 125 rule 3)
+ CFeeRate node_incremental_relay_fee = wallet->chain().relayIncrementalFee();
+ CFeeRate wallet_incremental_relay_fee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
+ feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
+
+ // Fee rate must also be at least the wallet's GetMinimumFeeRate
+ CFeeRate min_feerate(GetMinimumFeeRate(*wallet, new_coin_control, /* feeCalc */ nullptr));
+
+ // Set the required fee rate for the replacement transaction in coin control.
+ new_coin_control.m_feerate = std::max(feerate, min_feerate);
+
+ // Fill in required inputs we are double-spending(all of them)
+ // N.B.: bip125 doesn't require all the inputs in the replaced transaction to be
+ // used in the replacement transaction, but it's very important for wallets to make
+ // sure that happens. If not, it would be possible to bump a transaction A twice to
+ // A2 and A3 where A2 and A3 don't conflict (or alternatively bump A to A2 and A2
+ // to A3 where A and A3 don't conflict). If both later get confirmed then the sender
+ // has accidentally double paid.
+ for (const auto& inputs : wtx.tx->vin) {
+ new_coin_control.Select(COutPoint(inputs.prevout));
+ }
+ new_coin_control.fAllowOtherInputs = true;
+
+ // We cannot source new unconfirmed inputs(bip125 rule 2)
+ new_coin_control.m_min_depth = 1;
+
+ CTransactionRef tx_new = MakeTransactionRef();
+ CReserveKey reservekey(wallet);
+ CAmount fee_ret;
+ int change_pos_in_out = -1; // No requested location for change
+ std::string fail_reason;
+ if (!wallet->CreateTransaction(*locked_chain, recipients, tx_new, reservekey, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) {
+ errors.push_back("Unable to create transaction: " + fail_reason);
+ return Result::WALLET_ERROR;
+ }
+
+ // If change key hasn't been ReturnKey'ed by this point, we take it out of keypool
+ reservekey.KeepKey();
+
+ // Write back new fee if successful
+ new_fee = fee_ret;
+
+ // Write back transaction
+ mtx = CMutableTransaction(*tx_new);
+ // Mark new tx not replaceable, if requested.
+ if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) {
+ for (auto& input : mtx.vin) {
+ if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe;
+ }
+ }
return Result::OK;
}
bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx) {
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
return wallet->SignTransaction(mtx);
}
Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid)
{
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = wallet->chain().lock();
+ LOCK(wallet->cs_wallet);
if (!errors.empty()) {
return Result::MISC_ERROR;
}
@@ -230,7 +324,7 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti
CWalletTx& oldWtx = it->second;
// make sure the transaction still has no descendants and hasn't been mined in the meantime
- Result result = PreconditionChecks(wallet, oldWtx, errors);
+ Result result = PreconditionChecks(*locked_chain, wallet, oldWtx, errors);
if (result != Result::OK) {
return result;
}
@@ -242,7 +336,7 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti
CReserveKey reservekey(wallet);
CValidationState state;
- if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, oldWtx.strFromAccount, reservekey, g_connman.get(), state)) {
+ if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, reservekey, state)) {
// NOTE: CommitTransaction never returns false, so this should never happen.
errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state)));
return Result::WALLET_ERROR;
diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
index 7e36a9766b..0c4e1cb7dd 100644
--- a/src/wallet/feebumper.h
+++ b/src/wallet/feebumper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -28,8 +28,8 @@ enum class Result
//! Return whether transaction can be bumped.
bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid);
-//! Create bumpfee transaction.
-Result CreateTransaction(const CWallet* wallet,
+//! Create bumpfee transaction based on total amount.
+Result CreateTotalBumpTransaction(const CWallet* wallet,
const uint256& txid,
const CCoinControl& coin_control,
CAmount total_fee,
@@ -38,6 +38,15 @@ Result CreateTransaction(const CWallet* wallet,
CAmount& new_fee,
CMutableTransaction& mtx);
+//! Create bumpfee transaction based on feerate estimates.
+Result CreateRateBumpTransaction(CWallet* wallet,
+ const uint256& txid,
+ const CCoinControl& coin_control,
+ std::vector<std::string>& errors,
+ CAmount& old_fee,
+ CAmount& new_fee,
+ CMutableTransaction& mtx);
+
//! Sign the new transaction,
//! @return false if the tx couldn't be found or if it was
//! impossible to create the signature(s)
diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp
index 8d576a6689..59d05a771a 100644
--- a/src/wallet/fees.cpp
+++ b/src/wallet/fees.cpp
@@ -1,13 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <wallet/fees.h>
#include <policy/policy.h>
-#include <txmempool.h>
-#include <util.h>
+#include <util/system.h>
#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
@@ -19,12 +18,13 @@ CAmount GetRequiredFee(const CWallet& wallet, unsigned int nTxBytes)
}
-CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc)
+CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, FeeCalculation* feeCalc)
{
- CAmount fee_needed = GetMinimumFeeRate(wallet, coin_control, pool, estimator, feeCalc).GetFee(nTxBytes);
+ CAmount fee_needed = GetMinimumFeeRate(wallet, coin_control, feeCalc).GetFee(nTxBytes);
// Always obey the maximum
- if (fee_needed > maxTxFee) {
- fee_needed = maxTxFee;
+ const CAmount max_tx_fee = wallet.m_default_max_tx_fee;
+ if (fee_needed > max_tx_fee) {
+ fee_needed = max_tx_fee;
if (feeCalc) feeCalc->reason = FeeReason::MAXTXFEE;
}
return fee_needed;
@@ -32,10 +32,10 @@ CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinC
CFeeRate GetRequiredFeeRate(const CWallet& wallet)
{
- return std::max(wallet.m_min_fee, ::minRelayTxFee);
+ return std::max(wallet.m_min_fee, wallet.chain().relayMinFee());
}
-CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc)
+CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, FeeCalculation* feeCalc)
{
/* User control of how to calculate fee uses the following parameter precedence:
1. coin_control.m_feerate
@@ -64,7 +64,7 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr
if (coin_control.m_fee_mode == FeeEstimateMode::CONSERVATIVE) conservative_estimate = true;
else if (coin_control.m_fee_mode == FeeEstimateMode::ECONOMICAL) conservative_estimate = false;
- feerate_needed = estimator.estimateSmartFee(target, feeCalc, conservative_estimate);
+ feerate_needed = wallet.chain().estimateSmartFee(target, conservative_estimate, feeCalc);
if (feerate_needed == CFeeRate(0)) {
// if we don't have enough data for estimateSmartFee, then use fallback fee
feerate_needed = wallet.m_fallback_fee;
@@ -74,7 +74,7 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr
if (wallet.m_fallback_fee == CFeeRate(0)) return feerate_needed;
}
// Obey mempool min fee when using smart fee estimation
- CFeeRate min_mempool_feerate = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
+ CFeeRate min_mempool_feerate = wallet.chain().mempoolMinFee();
if (feerate_needed < min_mempool_feerate) {
feerate_needed = min_mempool_feerate;
if (feeCalc) feeCalc->reason = FeeReason::MEMPOOL_MIN;
@@ -90,13 +90,13 @@ CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_contr
return feerate_needed;
}
-CFeeRate GetDiscardRate(const CWallet& wallet, const CBlockPolicyEstimator& estimator)
+CFeeRate GetDiscardRate(const CWallet& wallet)
{
- unsigned int highest_target = estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
- CFeeRate discard_rate = estimator.estimateSmartFee(highest_target, nullptr /* FeeCalculation */, false /* conservative */);
+ unsigned int highest_target = wallet.chain().estimateMaxBlocks();
+ CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, false /* conservative */);
// Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate
discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate);
// Discard rate must be at least dustRelayFee
- discard_rate = std::max(discard_rate, ::dustRelayFee);
+ discard_rate = std::max(discard_rate, wallet.chain().relayDustFee());
return discard_rate;
}
diff --git a/src/wallet/fees.h b/src/wallet/fees.h
index b3cd064abc..434f211dc2 100644
--- a/src/wallet/fees.h
+++ b/src/wallet/fees.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,10 +8,8 @@
#include <amount.h>
-class CBlockPolicyEstimator;
class CCoinControl;
class CFeeRate;
-class CTxMemPool;
class CWallet;
struct FeeCalculation;
@@ -25,7 +23,7 @@ CAmount GetRequiredFee(const CWallet& wallet, unsigned int nTxBytes);
* Estimate the minimum fee considering user set parameters
* and the required fee
*/
-CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc);
+CAmount GetMinimumFee(const CWallet& wallet, unsigned int nTxBytes, const CCoinControl& coin_control, FeeCalculation* feeCalc);
/**
* Return the minimum required feerate taking into account the
@@ -37,11 +35,11 @@ CFeeRate GetRequiredFeeRate(const CWallet& wallet);
* Estimate the minimum fee rate considering user set parameters
* and the required fee
*/
-CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation* feeCalc);
+CFeeRate GetMinimumFeeRate(const CWallet& wallet, const CCoinControl& coin_control, FeeCalculation* feeCalc);
/**
* Return the maximum feerate for discarding change.
*/
-CFeeRate GetDiscardRate(const CWallet& wallet, const CBlockPolicyEstimator& estimator);
+CFeeRate GetDiscardRate(const CWallet& wallet);
#endif // BITCOIN_WALLET_FEES_H
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 52c7e6c70f..0b8afd5a5d 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -1,15 +1,17 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
#include <init.h>
+#include <interfaces/chain.h>
#include <net.h>
#include <scheduler.h>
#include <outputtype.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/error.h>
+#include <util/system.h>
+#include <util/moneystr.h>
#include <validation.h>
#include <walletinitinterface.h>
#include <wallet/rpcwallet.h>
@@ -19,34 +21,17 @@
class WalletInit : public WalletInitInterface {
public:
+ //! Was the wallet component compiled in.
+ bool HasWalletSupport() const override {return true;}
+
//! Return the wallets help message.
void AddWalletOptions() const override;
//! Wallets parameter interaction
bool ParameterInteraction() const override;
- //! Register wallet RPCs.
- void RegisterRPC(CRPCTable &tableRPC) const override;
-
- //! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
- // This function will perform salvage on the wallet if requested, as long as only one wallet is
- // being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
- bool Verify() const override;
-
- //! Load wallet databases.
- bool Open() const override;
-
- //! Complete startup of wallets.
- void Start(CScheduler& scheduler) const override;
-
- //! Flush all wallets in preparation for shutdown.
- void Flush() const override;
-
- //! Stop all wallets. Wallets will be flushed first.
- void Stop() const override;
-
- //! Close all wallets.
- void Close() const override;
+ //! Add wallets that should be opened to list of init interfaces.
+ void Construct(InitInterfaces& interfaces) const override;
};
const WalletInitInterface& g_wallet_init_interface = WalletInit();
@@ -54,7 +39,7 @@ const WalletInitInterface& g_wallet_init_interface = WalletInit();
void WalletInit::AddWalletOptions() const
{
gArgs.AddArg("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)), false, OptionsCategory::WALLET);
- gArgs.AddArg("-avoidpartialspends", strprintf(_("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)"), DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-avoidpartialspends", strprintf("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)", DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
gArgs.AddArg("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)", false, OptionsCategory::WALLET);
gArgs.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", false, OptionsCategory::WALLET);
gArgs.AddArg("-discardfee=<amt>", strprintf("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
@@ -63,6 +48,8 @@ void WalletInit::AddWalletOptions() const
gArgs.AddArg("-fallbackfee=<amt>", strprintf("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)), false, OptionsCategory::WALLET);
gArgs.AddArg("-keypool=<n>", strprintf("Set key pool size to <n> (default: %u)", DEFAULT_KEYPOOL_SIZE), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-maxtxfee=<amt>", strprintf("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)",
+ CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-mintxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)), false, OptionsCategory::WALLET);
gArgs.AddArg("-paytxfee=<amt>", strprintf("Fee (in %s/kB) to add to transactions you send (default: %s)",
@@ -78,7 +65,7 @@ void WalletInit::AddWalletOptions() const
gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", false, OptionsCategory::WALLET);
gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), false, OptionsCategory::WALLET);
gArgs.AddArg("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup"
- " (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)", false, OptionsCategory::WALLET);
+ " (1 = keep tx meta data e.g. payment request information, 2 = drop tx meta data)", false, OptionsCategory::WALLET);
gArgs.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), true, OptionsCategory::WALLET_DEBUG_TEST);
gArgs.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), true, OptionsCategory::WALLET_DEBUG_TEST);
@@ -96,7 +83,6 @@ bool WalletInit::ParameterInteraction() const
return true;
}
- gArgs.SoftSetArg("-wallet", "");
const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
@@ -140,131 +126,15 @@ bool WalletInit::ParameterInteraction() const
if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false))
return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again."));
- if (::minRelayTxFee.GetFeePerK() > HIGH_TX_FEE_PER_KB)
- InitWarning(AmountHighWarn("-minrelaytxfee") + " " +
- _("The wallet will avoid paying less than the minimum relay fee."));
-
- if (gArgs.IsArgSet("-maxtxfee"))
- {
- CAmount nMaxFee = 0;
- if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee))
- return InitError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
- if (nMaxFee > HIGH_MAX_TX_FEE)
- InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
- maxTxFee = nMaxFee;
- if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
- {
- return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
- gArgs.GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString()));
- }
- }
-
return true;
}
-void WalletInit::RegisterRPC(CRPCTable &t) const
-{
- if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
- return;
- }
-
- RegisterWalletRPCCommands(t);
-}
-
-bool WalletInit::Verify() const
-{
- if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
- return true;
- }
-
- if (gArgs.IsArgSet("-walletdir")) {
- fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
- if (!fs::exists(wallet_dir)) {
- return InitError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
- } else if (!fs::is_directory(wallet_dir)) {
- return InitError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
- } else if (!wallet_dir.is_absolute()) {
- return InitError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
- }
- }
-
- LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
-
- uiInterface.InitMessage(_("Verifying wallet(s)..."));
-
- std::vector<std::string> wallet_files = gArgs.GetArgs("-wallet");
-
- // Parameter interaction code should have thrown an error if -salvagewallet
- // was enabled with more than wallet file, so the wallet_files size check
- // here should have no effect.
- bool salvage_wallet = gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1;
-
- // Keep track of each wallet absolute path to detect duplicates.
- std::set<fs::path> wallet_paths;
-
- for (const auto& wallet_file : wallet_files) {
- fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
-
- if (!wallet_paths.insert(wallet_path).second) {
- return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
- }
-
- std::string error_string;
- std::string warning_string;
- bool verify_success = CWallet::Verify(wallet_file, salvage_wallet, error_string, warning_string);
- if (!error_string.empty()) InitError(error_string);
- if (!warning_string.empty()) InitWarning(warning_string);
- if (!verify_success) return false;
- }
-
- return true;
-}
-
-bool WalletInit::Open() const
+void WalletInit::Construct(InitInterfaces& interfaces) const
{
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
LogPrintf("Wallet disabled!\n");
- return true;
- }
-
- for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
- std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
- if (!pwallet) {
- return false;
- }
- AddWallet(pwallet);
- }
-
- return true;
-}
-
-void WalletInit::Start(CScheduler& scheduler) const
-{
- for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
- pwallet->postInitProcess();
- }
-
- // Run a thread to flush wallet periodically
- scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
-}
-
-void WalletInit::Flush() const
-{
- for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
- pwallet->Flush(false);
- }
-}
-
-void WalletInit::Stop() const
-{
- for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
- pwallet->Flush(true);
- }
-}
-
-void WalletInit::Close() const
-{
- for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
- RemoveWallet(pwallet);
+ return;
}
+ gArgs.SoftSetArg("-wallet", "");
+ interfaces.chain_clients.emplace_back(interfaces::MakeWalletClient(*interfaces.chain, gArgs.GetArgs("-wallet")));
}
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
new file mode 100644
index 0000000000..54aa12dba8
--- /dev/null
+++ b/src/wallet/load.cpp
@@ -0,0 +1,112 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <wallet/load.h>
+
+#include <interfaces/chain.h>
+#include <scheduler.h>
+#include <util/system.h>
+#include <wallet/wallet.h>
+
+bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
+{
+ if (gArgs.IsArgSet("-walletdir")) {
+ fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
+ boost::system::error_code error;
+ // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
+ fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
+ if (error || !fs::exists(wallet_dir)) {
+ chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
+ return false;
+ } else if (!fs::is_directory(wallet_dir)) {
+ chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
+ return false;
+ // The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
+ } else if (!wallet_dir.is_absolute()) {
+ chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
+ return false;
+ }
+ gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string());
+ }
+
+ LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
+
+ chain.initMessage(_("Verifying wallet(s)..."));
+
+ // Parameter interaction code should have thrown an error if -salvagewallet
+ // was enabled with more than wallet file, so the wallet_files size check
+ // here should have no effect.
+ bool salvage_wallet = gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1;
+
+ // Keep track of each wallet absolute path to detect duplicates.
+ std::set<fs::path> wallet_paths;
+
+ for (const auto& wallet_file : wallet_files) {
+ WalletLocation location(wallet_file);
+
+ if (!wallet_paths.insert(location.GetPath()).second) {
+ chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
+ return false;
+ }
+
+ std::string error_string;
+ std::string warning_string;
+ bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warning_string);
+ if (!error_string.empty()) chain.initError(error_string);
+ if (!warning_string.empty()) chain.initWarning(warning_string);
+ if (!verify_success) return false;
+ }
+
+ return true;
+}
+
+bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
+{
+ for (const std::string& walletFile : wallet_files) {
+ std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile));
+ if (!pwallet) {
+ return false;
+ }
+ AddWallet(pwallet);
+ }
+
+ return true;
+}
+
+void StartWallets(CScheduler& scheduler)
+{
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
+ pwallet->postInitProcess();
+ }
+
+ // Schedule periodic wallet flushes and tx rebroadcasts
+ scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
+ scheduler.scheduleEvery(MaybeResendWalletTxs, 1000);
+}
+
+void FlushWallets()
+{
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
+ pwallet->Flush(false);
+ }
+}
+
+void StopWallets()
+{
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
+ pwallet->Flush(true);
+ }
+}
+
+void UnloadWallets()
+{
+ auto wallets = GetWallets();
+ while (!wallets.empty()) {
+ auto wallet = wallets.back();
+ wallets.pop_back();
+ RemoveWallet(wallet);
+ UnloadWallet(std::move(wallet));
+ }
+}
diff --git a/src/wallet/load.h b/src/wallet/load.h
new file mode 100644
index 0000000000..81f078fd10
--- /dev/null
+++ b/src/wallet/load.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_WALLET_LOAD_H
+#define BITCOIN_WALLET_LOAD_H
+
+#include <string>
+#include <vector>
+
+class CScheduler;
+
+namespace interfaces {
+class Chain;
+} // namespace interfaces
+
+//! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
+//! This function will perform salvage on the wallet if requested, as long as only one wallet is
+//! being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
+bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
+
+//! Load wallet databases.
+bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
+
+//! Complete startup of wallets.
+void StartWallets(CScheduler& scheduler);
+
+//! Flush all wallets in preparation for shutdown.
+void FlushWallets();
+
+//! Stop all wallets. Wallets will be flushed first.
+void StopWallets();
+
+//! Close all wallets.
+void UnloadWallets();
+
+#endif // BITCOIN_WALLET_LOAD_H
diff --git a/src/wallet/psbtwallet.cpp b/src/wallet/psbtwallet.cpp
new file mode 100644
index 0000000000..ce4788dee1
--- /dev/null
+++ b/src/wallet/psbtwallet.cpp
@@ -0,0 +1,60 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <wallet/psbtwallet.h>
+
+TransactionError FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs)
+{
+ LOCK(pwallet->cs_wallet);
+ // Get all of the previous transactions
+ complete = true;
+ for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
+ const CTxIn& txin = psbtx.tx->vin[i];
+ PSBTInput& input = psbtx.inputs.at(i);
+
+ if (PSBTInputSigned(input)) {
+ continue;
+ }
+
+ // Verify input looks sane. This will check that we have at most one uxto, witness or non-witness.
+ if (!input.IsSane()) {
+ return TransactionError::INVALID_PSBT;
+ }
+
+ // If we have no utxo, grab it from the wallet.
+ if (!input.non_witness_utxo && input.witness_utxo.IsNull()) {
+ const uint256& txhash = txin.prevout.hash;
+ const auto it = pwallet->mapWallet.find(txhash);
+ if (it != pwallet->mapWallet.end()) {
+ const CWalletTx& wtx = it->second;
+ // We only need the non_witness_utxo, which is a superset of the witness_utxo.
+ // The signing code will switch to the smaller witness_utxo if this is ok.
+ input.non_witness_utxo = wtx.tx;
+ }
+ }
+
+ // Get the Sighash type
+ if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
+ return TransactionError::SIGHASH_MISMATCH;
+ }
+
+ complete &= SignPSBTInput(HidingSigningProvider(pwallet, !sign, !bip32derivs), psbtx, i, sighash_type);
+ }
+
+ // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
+ for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
+ const CTxOut& out = psbtx.tx->vout.at(i);
+ PSBTOutput& psbt_out = psbtx.outputs.at(i);
+
+ // Fill a SignatureData with output info
+ SignatureData sigdata;
+ psbt_out.FillSignatureData(sigdata);
+
+ MutableTransactionSignatureCreator creator(psbtx.tx.get_ptr(), 0, out.nValue, 1);
+ ProduceSignature(HidingSigningProvider(pwallet, true, !bip32derivs), creator, out.scriptPubKey, sigdata);
+ psbt_out.FromSignatureData(sigdata);
+ }
+
+ return TransactionError::OK;
+}
diff --git a/src/wallet/psbtwallet.h b/src/wallet/psbtwallet.h
new file mode 100644
index 0000000000..a24a0967d2
--- /dev/null
+++ b/src/wallet/psbtwallet.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_WALLET_PSBTWALLET_H
+#define BITCOIN_WALLET_PSBTWALLET_H
+
+#include <node/transaction.h>
+#include <psbt.h>
+#include <primitives/transaction.h>
+#include <wallet/wallet.h>
+
+/**
+ * Fills out a PSBT with information from the wallet. Fills in UTXOs if we have
+ * them. Tries to sign if sign=true. Sets `complete` if the PSBT is now complete
+ * (i.e. has all required signatures or signature-parts, and is ready to
+ * finalize.) Sets `error` and returns false if something goes wrong.
+ *
+ * @param[in] pwallet pointer to a wallet
+ * @param[in] &psbtx reference to PartiallySignedTransaction to fill in
+ * @param[out] &complete indicates whether the PSBT is now complete
+ * @param[in] sighash_type the sighash type to use when signing (if PSBT does not specify)
+ * @param[in] sign whether to sign or not
+ * @param[in] bip32derivs whether to fill in bip32 derivation information if available
+ * return error
+ */
+NODISCARD TransactionError FillPSBT(const CWallet* pwallet,
+ PartiallySignedTransaction& psbtx,
+ bool& complete,
+ int sighash_type = 1 /* SIGHASH_ALL */,
+ bool sign = true,
+ bool bip32derivs = false);
+
+#endif // BITCOIN_WALLET_PSBTWALLET_H
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 3cb4050f01..3861b5524f 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1,24 +1,28 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
+#include <core_io.h>
+#include <interfaces/chain.h>
#include <key_io.h>
+#include <merkleblock.h>
#include <rpc/server.h>
-#include <validation.h>
+#include <rpc/util.h>
+#include <script/descriptor.h>
#include <script/script.h>
#include <script/standard.h>
#include <sync.h>
-#include <util.h>
-#include <utiltime.h>
+#include <util/bip32.h>
+#include <util/system.h>
+#include <util/time.h>
+#include <validation.h>
#include <wallet/wallet.h>
-#include <merkleblock.h>
-#include <core_io.h>
#include <wallet/rpcwallet.h>
-#include <fstream>
#include <stdint.h>
+#include <tuple>
#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
@@ -41,7 +45,7 @@ int64_t static DecodeDumpTime(const std::string &str) {
std::string static EncodeDumpString(const std::string &str) {
std::stringstream ret;
- for (unsigned char c : str) {
+ for (const unsigned char c : str) {
if (c <= 32 || c >= 128 || c == '%') {
ret << '%' << HexStr(&c, &c + 1);
} else {
@@ -65,7 +69,7 @@ static std::string DecodeDumpString(const std::string &str) {
return ret.str();
}
-static bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyid, std::string &strAddr, std::string &strLabel)
+static bool GetWalletAddressesForKey(CWallet* const pwallet, const CKeyID& keyid, std::string& strAddr, std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
bool fLabelFound = false;
CKey key;
@@ -108,16 +112,18 @@ UniValue importprivkey(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
- "importprivkey \"privkey\" ( \"label\" ) ( rescan )\n"
- "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n"
- "Hint: use importmulti to import more than one private key.\n"
- "\nArguments:\n"
- "1. \"privkey\" (string, required) The private key (see dumpprivkey)\n"
- "2. \"label\" (string, optional, default=\"\") An optional label\n"
- "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
- "may report that the imported key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
- "\nExamples:\n"
+ RPCHelpMan{"importprivkey",
+ "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n"
+ "Hint: use importmulti to import more than one private key.\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
+ "may report that the imported key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n",
+ {
+ {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key (see dumpprivkey)"},
+ {"label", RPCArg::Type::STR, /* default */ "current label if address exists, otherwise \"\"", "An optional label"},
+ {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"},
+ },
+ RPCResults{},
+ RPCExamples{
"\nDump a private key\n"
+ HelpExampleCli("dumpprivkey", "\"myaddress\"") +
"\nImport the private key with rescan\n"
@@ -128,13 +134,18 @@ UniValue importprivkey(const JSONRPCRequest& request)
+ HelpExampleCli("importprivkey", "\"mykey\" \"\" false") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
- );
+ },
+ }.ToString());
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
+ }
WalletRescanReserver reserver(pwallet);
bool fRescan = true;
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -147,8 +158,12 @@ UniValue importprivkey(const JSONRPCRequest& request)
if (!request.params[2].isNull())
fRescan = request.params[2].get_bool();
- if (fRescan && fPruneMode)
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
+ if (fRescan && 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, "Rescan is disabled when blocks are pruned");
+ }
if (fRescan && !reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
@@ -162,9 +177,14 @@ UniValue importprivkey(const JSONRPCRequest& request)
CKeyID vchAddress = pubkey.GetID();
{
pwallet->MarkDirty();
- // We don't know which corresponding address will be used; label them all
+
+ // We don't know which corresponding address will be used;
+ // label all new addresses, and label existing addresses if a
+ // label was passed.
for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
- pwallet->SetAddressBook(dest, strLabel, "receive");
+ if (!request.params[1].isNull() || pwallet->mapAddressBook.count(dest) == 0) {
+ pwallet->SetAddressBook(dest, strLabel, "receive");
+ }
}
// Don't throw error in case a key is already there
@@ -199,16 +219,19 @@ UniValue abortrescan(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 0)
throw std::runtime_error(
- "abortrescan\n"
- "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n"
- "\nExamples:\n"
+ RPCHelpMan{"abortrescan",
+ "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n",
+ {},
+ RPCResults{},
+ RPCExamples{
"\nImport a private key\n"
+ HelpExampleCli("importprivkey", "\"mykey\"") +
"\nAbort the running wallet rescan\n"
+ HelpExampleCli("abortrescan", "") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("abortrescan", "")
- );
+ },
+ }.ToString());
if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
pwallet->AbortRescan();
@@ -233,7 +256,7 @@ static void ImportScript(CWallet* const pwallet, const CScript& script, const st
if (!pwallet->HaveCScript(id) && !pwallet->AddCScript(script)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
- ImportAddress(pwallet, id, strLabel);
+ ImportAddress(pwallet, ScriptHash(id), strLabel);
} else {
CTxDestination destination;
if (ExtractDestination(script, destination)) {
@@ -261,26 +284,29 @@ UniValue importaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
- "importaddress \"address\" ( \"label\" rescan p2sh )\n"
- "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The Bitcoin address (or hex-encoded script)\n"
- "2. \"label\" (string, optional, default=\"\") An optional label\n"
- "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
- "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
+ RPCHelpMan{"importaddress",
+ "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported address exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
"If you have the full public key, you should call importpubkey instead of this.\n"
"\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
- "as change, and not show up in many RPCs.\n"
- "\nExamples:\n"
+ "as change, and not show up in many RPCs.\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The Bitcoin address (or hex-encoded script)"},
+ {"label", RPCArg::Type::STR, /* default */ "\"\"", "An optional label"},
+ {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"},
+ {"p2sh", RPCArg::Type::BOOL, /* default */ "false", "Add the P2SH version of the script as well"},
+ },
+ RPCResults{},
+ RPCExamples{
"\nImport an address with rescan\n"
+ HelpExampleCli("importaddress", "\"myaddress\"") +
"\nImport using a label without rescan\n"
+ HelpExampleCli("importaddress", "\"myaddress\" \"testing\" false") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false")
- );
+ },
+ }.ToString());
std::string strLabel;
@@ -292,8 +318,12 @@ UniValue importaddress(const JSONRPCRequest& request)
if (!request.params[2].isNull())
fRescan = request.params[2].get_bool();
- if (fRescan && fPruneMode)
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
+ if (fRescan && 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, "Rescan is disabled when blocks are pruned");
+ }
WalletRescanReserver reserver(pwallet);
if (fRescan && !reserver.reserve()) {
@@ -306,7 +336,8 @@ UniValue importaddress(const JSONRPCRequest& request)
fP2SH = request.params[3].get_bool();
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
CTxDestination dest = DecodeDestination(request.params[0].get_str());
if (IsValidDestination(dest)) {
@@ -324,7 +355,11 @@ UniValue importaddress(const JSONRPCRequest& request)
if (fRescan)
{
RescanWallet(*pwallet, reserver);
- pwallet->ReacceptWalletTransactions();
+ {
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
+ pwallet->ReacceptWalletTransactions(*locked_chain);
+ }
}
return NullUniValue;
@@ -340,11 +375,15 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 2)
throw std::runtime_error(
- "importprunedfunds\n"
- "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n"
- "\nArguments:\n"
- "1. \"rawtransaction\" (string, required) A raw transaction in hex funding an already-existing address in wallet\n"
- "2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n"
+ RPCHelpMan{"importprunedfunds",
+ "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n",
+ {
+ {"rawtransaction", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A raw transaction in hex funding an already-existing address in wallet"},
+ {"txoutproof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex output from gettxoutproof that contains the transaction"},
+ },
+ RPCResults{},
+ RPCExamples{""},
+ }.ToString()
);
CMutableTransaction tx;
@@ -363,9 +402,8 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
unsigned int txnIndex = 0;
if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) {
- LOCK(cs_main);
- const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash());
- if (!pindex || !chainActive.Contains(pindex)) {
+ auto locked_chain = pwallet->chain().lock();
+ if (locked_chain->getBlockHeight(merkleBlock.header.GetHash()) == nullopt) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
}
@@ -383,7 +421,8 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
wtx.nIndex = txnIndex;
wtx.hashBlock = merkleBlock.header.GetHash();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (pwallet->IsMine(*wtx.tx)) {
pwallet->AddToWallet(wtx, false);
@@ -403,20 +442,23 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "removeprunedfunds \"txid\"\n"
- "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n"
- "\nExamples:\n"
- + HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
+ RPCHelpMan{"removeprunedfunds",
+ "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded id of the transaction you are deleting"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
- );
+ },
+ }.ToString());
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- uint256 hash;
- hash.SetHex(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "txid"));
std::vector<uint256> vHash;
vHash.push_back(hash);
std::vector<uint256> vHashOut;
@@ -442,22 +484,25 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
- "importpubkey \"pubkey\" ( \"label\" rescan )\n"
- "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
- "\nArguments:\n"
- "1. \"pubkey\" (string, required) The hex-encoded public key\n"
- "2. \"label\" (string, optional, default=\"\") An optional label\n"
- "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
- "may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
- "\nExamples:\n"
+ RPCHelpMan{"importpubkey",
+ "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
+ "may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n",
+ {
+ {"pubkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The hex-encoded public key"},
+ {"label", RPCArg::Type::STR, /* default */ "\"\"", "An optional label"},
+ {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"},
+ },
+ RPCResults{},
+ RPCExamples{
"\nImport a public key with rescan\n"
+ HelpExampleCli("importpubkey", "\"mypubkey\"") +
"\nImport using a label without rescan\n"
+ HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false")
- );
+ },
+ }.ToString());
std::string strLabel;
@@ -469,8 +514,12 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (!request.params[2].isNull())
fRescan = request.params[2].get_bool();
- if (fRescan && fPruneMode)
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
+ if (fRescan && 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, "Rescan is disabled when blocks are pruned");
+ }
WalletRescanReserver reserver(pwallet);
if (fRescan && !reserver.reserve()) {
@@ -485,7 +534,8 @@ UniValue importpubkey(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
for (const auto& dest : GetAllDestinationsForKey(pubKey)) {
ImportAddress(pwallet, dest, strLabel);
@@ -496,7 +546,11 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (fRescan)
{
RescanWallet(*pwallet, reserver);
- pwallet->ReacceptWalletTransactions();
+ {
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
+ pwallet->ReacceptWalletTransactions(*locked_chain);
+ }
}
return NullUniValue;
@@ -513,21 +567,28 @@ UniValue importwallet(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "importwallet \"filename\"\n"
- "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n"
- "\nArguments:\n"
- "1. \"filename\" (string, required) The wallet file\n"
- "\nExamples:\n"
+ RPCHelpMan{"importwallet",
+ "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n",
+ {
+ {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet file"},
+ },
+ RPCResults{},
+ RPCExamples{
"\nDump the wallet\n"
+ HelpExampleCli("dumpwallet", "\"test\"") +
"\nImport the wallet\n"
+ HelpExampleCli("importwallet", "\"test\"") +
"\nImport using the json rpc call\n"
+ HelpExampleRpc("importwallet", "\"test\"")
- );
-
- if (fPruneMode)
- throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
+ },
+ }.ToString());
+
+ 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()) {
@@ -537,25 +598,29 @@ UniValue importwallet(const JSONRPCRequest& request)
int64_t nTimeBegin = 0;
bool fGood = true;
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
- std::ifstream file;
- file.open(request.params[0].get_str().c_str(), std::ios::in | std::ios::ate);
+ fsbridge::ifstream file;
+ file.open(request.params[0].get_str(), std::ios::in | std::ios::ate);
if (!file.is_open()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
}
- nTimeBegin = chainActive.Tip()->GetBlockTime();
+ Optional<int> tip_height = locked_chain->getHeight();
+ nTimeBegin = tip_height ? locked_chain->getBlockTime(*tip_height) : 0;
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg);
// Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
// we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
- uiInterface.ShowProgress(_("Importing..."), 0, false); // show progress dialog in GUI
+ pwallet->chain().showProgress(strprintf("%s " + _("Importing..."), pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI
+ std::vector<std::tuple<CKey, int64_t, bool, std::string>> keys;
+ std::vector<std::pair<CScript, int64_t>> scripts;
while (file.good()) {
- uiInterface.ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false);
+ pwallet->chain().showProgress("", std::max(1, std::min(50, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false);
std::string line;
std::getline(file, line);
if (line.empty() || line[0] == '#')
@@ -567,13 +632,6 @@ UniValue importwallet(const JSONRPCRequest& request)
continue;
CKey key = DecodeSecret(vstr[0]);
if (key.IsValid()) {
- CPubKey pubkey = key.GetPubKey();
- assert(key.VerifyPubKey(pubkey));
- CKeyID keyid = pubkey.GetID();
- if (pwallet->HaveKey(keyid)) {
- LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
- continue;
- }
int64_t nTime = DecodeDumpTime(vstr[1]);
std::string strLabel;
bool fLabel = true;
@@ -589,40 +647,71 @@ UniValue importwallet(const JSONRPCRequest& request)
fLabel = true;
}
}
- LogPrintf("Importing %s...\n", EncodeDestination(keyid));
- if (!pwallet->AddKeyPubKey(key, pubkey)) {
- fGood = false;
- continue;
- }
- pwallet->mapKeyMetadata[keyid].nCreateTime = nTime;
- if (fLabel)
- pwallet->SetAddressBook(keyid, strLabel, "receive");
- 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());
- CScriptID id(script);
- if (pwallet->HaveCScript(id)) {
- LogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
- continue;
- }
- if(!pwallet->AddCScript(script)) {
- LogPrintf("Error importing script %s\n", vstr[0]);
- fGood = false;
- continue;
- }
- int64_t birth_time = DecodeDumpTime(vstr[1]);
- if (birth_time > 0) {
- pwallet->m_script_metadata[id].nCreateTime = birth_time;
- nTimeBegin = std::min(nTimeBegin, birth_time);
- }
+ std::vector<unsigned char> vData(ParseHex(vstr[0]));
+ CScript script = CScript(vData.begin(), vData.end());
+ int64_t birth_time = DecodeDumpTime(vstr[1]);
+ scripts.push_back(std::pair<CScript, int64_t>(script, birth_time));
}
}
file.close();
- uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
+ // 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
+ throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled when private keys are disabled");
+ }
+ double total = (double)(keys.size() + scripts.size());
+ double progress = 0;
+ for (const auto& key_tuple : keys) {
+ pwallet->chain().showProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false);
+ const CKey& key = std::get<0>(key_tuple);
+ int64_t time = std::get<1>(key_tuple);
+ bool has_label = std::get<2>(key_tuple);
+ std::string label = std::get<3>(key_tuple);
+
+ CPubKey pubkey = key.GetPubKey();
+ assert(key.VerifyPubKey(pubkey));
+ CKeyID keyid = pubkey.GetID();
+ if (pwallet->HaveKey(keyid)) {
+ pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(PKHash(keyid)));
+ continue;
+ }
+ pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(PKHash(keyid)));
+ if (!pwallet->AddKeyPubKey(key, pubkey)) {
+ fGood = false;
+ continue;
+ }
+ pwallet->mapKeyMetadata[keyid].nCreateTime = time;
+ if (has_label)
+ pwallet->SetAddressBook(PKHash(keyid), label, "receive");
+ nTimeBegin = std::min(nTimeBegin, time);
+ progress++;
+ }
+ for (const auto& script_pair : scripts) {
+ pwallet->chain().showProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false);
+ const CScript& script = script_pair.first;
+ int64_t time = script_pair.second;
+ CScriptID id(script);
+ if (pwallet->HaveCScript(id)) {
+ pwallet->WalletLogPrintf("Skipping import of %s (script already present)\n", HexStr(script));
+ continue;
+ }
+ if(!pwallet->AddCScript(script)) {
+ pwallet->WalletLogPrintf("Error importing script %s\n", HexStr(script));
+ fGood = false;
+ continue;
+ }
+ if (time > 0) {
+ pwallet->m_script_metadata[id].nCreateTime = time;
+ nTimeBegin = std::min(nTimeBegin, time);
+ }
+ progress++;
+ }
+ pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI
pwallet->UpdateTimeFirstKey(nTimeBegin);
}
- uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
+ pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI
RescanWallet(*pwallet, reserver, nTimeBegin, false /* update */);
pwallet->MarkDirty();
@@ -642,20 +731,24 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "dumpprivkey \"address\"\n"
- "\nReveals the private key corresponding to 'address'.\n"
- "Then the importprivkey can be used with this output\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address for the private key\n"
- "\nResult:\n"
+ RPCHelpMan{"dumpprivkey",
+ "\nReveals the private key corresponding to 'address'.\n"
+ "Then the importprivkey can be used with this output\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for the private key"},
+ },
+ RPCResult{
"\"key\" (string) The private key\n"
- "\nExamples:\n"
- + HelpExampleCli("dumpprivkey", "\"myaddress\"")
+ },
+ RPCExamples{
+ HelpExampleCli("dumpprivkey", "\"myaddress\"")
+ HelpExampleCli("importprivkey", "\"mykey\"")
+ HelpExampleRpc("dumpprivkey", "\"myaddress\"")
- );
+ },
+ }.ToString());
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -686,56 +779,57 @@ UniValue dumpwallet(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "dumpwallet \"filename\"\n"
- "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n"
- "Imported scripts are included in the dumpfile, but corresponding BIP173 addresses, etc. may not be added automatically by importwallet.\n"
- "Note that if your wallet contains keys which are not derived from your HD seed (e.g. imported keys), these are not covered by\n"
- "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n"
- "\nArguments:\n"
- "1. \"filename\" (string, required) The filename with path (either absolute or relative to bitcoind)\n"
- "\nResult:\n"
+ RPCHelpMan{"dumpwallet",
+ "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n"
+ "Imported scripts are included in the dumpfile, but corresponding BIP173 addresses, etc. may not be added automatically by importwallet.\n"
+ "Note that if your wallet contains keys which are not derived from your HD seed (e.g. imported keys), these are not covered by\n"
+ "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n",
+ {
+ {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The filename with path (either absolute or relative to bitcoind)"},
+ },
+ RPCResult{
"{ (json object)\n"
" \"filename\" : { (string) The filename with full absolute path\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("dumpwallet", "\"test\"")
+ },
+ RPCExamples{
+ HelpExampleCli("dumpwallet", "\"test\"")
+ HelpExampleRpc("dumpwallet", "\"test\"")
- );
+ },
+ }.ToString());
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
- boost::filesystem::path filepath = request.params[0].get_str();
- filepath = boost::filesystem::absolute(filepath);
+ fs::path filepath = request.params[0].get_str();
+ filepath = fs::absolute(filepath);
/* Prevent arbitrary files from being overwritten. There have been reports
* that users have overwritten wallet files this way:
* https://github.com/bitcoin/bitcoin/issues/9934
* It may also avoid other security issues.
*/
- if (boost::filesystem::exists(filepath)) {
+ if (fs::exists(filepath)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " already exists. If you are sure this is what you want, move it out of the way first");
}
- std::ofstream file;
- file.open(filepath.string().c_str());
+ fsbridge::ofstream file;
+ file.open(filepath);
if (!file.is_open())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
- std::map<CTxDestination, int64_t> mapKeyBirth;
+ std::map<CKeyID, int64_t> mapKeyBirth;
const std::map<CKeyID, int64_t>& mapKeyPool = pwallet->GetAllReserveKeys();
- pwallet->GetKeyBirthTimes(mapKeyBirth);
+ pwallet->GetKeyBirthTimes(*locked_chain, mapKeyBirth);
std::set<CScriptID> scripts = pwallet->GetCScripts();
- // TODO: include scripts in GetKeyBirthTimes() output instead of separate
// sort time/key pairs
std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
for (const auto& entry : mapKeyBirth) {
- if (const CKeyID* keyID = boost::get<CKeyID>(&entry.first)) { // set and test
- vKeyBirth.push_back(std::make_pair(entry.second, *keyID));
- }
+ vKeyBirth.push_back(std::make_pair(entry.second, entry.first));
}
mapKeyBirth.clear();
std::sort(vKeyBirth.begin(), vKeyBirth.end());
@@ -743,8 +837,9 @@ UniValue dumpwallet(const JSONRPCRequest& request)
// produce output
file << strprintf("# Wallet dump created by Bitcoin %s\n", CLIENT_BUILD);
file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
- file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
- file << strprintf("# mined on %s\n", FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()));
+ const Optional<int> tip_height = locked_chain->getHeight();
+ file << strprintf("# * Best block at time of backup was %i (%s),\n", tip_height.get_value_or(-1), tip_height ? locked_chain->getBlockHash(*tip_height).ToString() : "(missing block hash)");
+ file << strprintf("# mined on %s\n", tip_height ? FormatISO8601DateTime(locked_chain->getBlockTime(*tip_height)) : "(missing block time)");
file << "\n";
// add the base58check encoded extended master if the wallet uses HD
@@ -778,14 +873,14 @@ UniValue dumpwallet(const JSONRPCRequest& request)
} else {
file << "change=1";
}
- file << strprintf(" # addr=%s%s\n", strAddr, (pwallet->mapKeyMetadata[keyid].hdKeypath.size() > 0 ? " hdkeypath="+pwallet->mapKeyMetadata[keyid].hdKeypath : ""));
+ file << strprintf(" # addr=%s%s\n", strAddr, (pwallet->mapKeyMetadata[keyid].has_key_origin ? " hdkeypath="+WriteHDKeypath(pwallet->mapKeyMetadata[keyid].key_origin.path) : ""));
}
}
file << "\n";
for (const CScriptID &scriptid : scripts) {
CScript script;
std::string create_time = "0";
- std::string address = EncodeDestination(scriptid);
+ std::string address = EncodeDestination(ScriptHash(scriptid));
// get birth times for scripts with metadata
auto it = pwallet->m_script_metadata.find(scriptid);
if (it != pwallet->m_script_metadata.end()) {
@@ -806,305 +901,433 @@ UniValue dumpwallet(const JSONRPCRequest& request)
return reply;
}
-
-static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
+struct ImportData
{
- try {
- bool success = false;
+ // Input data
+ std::unique_ptr<CScript> redeemscript; //!< Provided redeemScript; will be moved to `import_scripts` if relevant.
+ std::unique_ptr<CScript> witnessscript; //!< Provided witnessScript; will be moved to `import_scripts` if relevant.
- // Required fields.
- const UniValue& scriptPubKey = data["scriptPubKey"];
+ // Output data
+ std::set<CScript> import_scripts;
+ std::map<CKeyID, bool> used_keys; //!< Import these private keys if available (the value indicates whether if the key is required for solvability)
+ std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> key_origins;
+};
- // Should have script or JSON with "address".
- if (!(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address")) && !(scriptPubKey.getType() == UniValue::VSTR)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey");
+enum class ScriptContext
+{
+ TOP, //!< Top-level scriptPubKey
+ P2SH, //!< P2SH redeemScript
+ WITNESS_V0, //!< P2WSH witnessScript
+};
+
+// Analyse the provided scriptPubKey, determining which keys and which redeem scripts from the ImportData struct are needed to spend it, and mark them as used.
+// Returns an error string, or the empty string for success.
+static std::string RecurseImportData(const CScript& script, ImportData& import_data, const ScriptContext script_ctx)
+{
+ // Use Solver to obtain script type and parsed pubkeys or hashes:
+ std::vector<std::vector<unsigned char>> solverdata;
+ txnouttype script_type = Solver(script, solverdata);
+
+ switch (script_type) {
+ case TX_PUBKEY: {
+ CPubKey pubkey(solverdata[0].begin(), solverdata[0].end());
+ import_data.used_keys.emplace(pubkey.GetID(), false);
+ return "";
+ }
+ case TX_PUBKEYHASH: {
+ CKeyID id = CKeyID(uint160(solverdata[0]));
+ import_data.used_keys[id] = true;
+ return "";
+ }
+ case TX_SCRIPTHASH: {
+ if (script_ctx == ScriptContext::P2SH) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside another P2SH");
+ if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside a P2WSH");
+ assert(script_ctx == ScriptContext::TOP);
+ CScriptID id = CScriptID(uint160(solverdata[0]));
+ auto subscript = std::move(import_data.redeemscript); // Remove redeemscript from import_data to check for superfluous script later.
+ if (!subscript) return "missing redeemscript";
+ if (CScriptID(*subscript) != id) return "redeemScript does not match the scriptPubKey";
+ import_data.import_scripts.emplace(*subscript);
+ return RecurseImportData(*subscript, import_data, ScriptContext::P2SH);
+ }
+ case TX_MULTISIG: {
+ for (size_t i = 1; i + 1< solverdata.size(); ++i) {
+ CPubKey pubkey(solverdata[i].begin(), solverdata[i].end());
+ import_data.used_keys.emplace(pubkey.GetID(), false);
}
+ return "";
+ }
+ case TX_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());
+ 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";
+ if (script_ctx == ScriptContext::TOP) {
+ import_data.import_scripts.emplace(script); // Special rule for IsMine: native P2WSH requires the TOP script imported (see script/ismine.cpp)
+ }
+ import_data.import_scripts.emplace(*subscript);
+ return RecurseImportData(*subscript, import_data, ScriptContext::WITNESS_V0);
+ }
+ case TX_WITNESS_V0_KEYHASH: {
+ if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2WPKH inside P2WSH");
+ CKeyID id = CKeyID(uint160(solverdata[0]));
+ import_data.used_keys[id] = true;
+ if (script_ctx == ScriptContext::TOP) {
+ import_data.import_scripts.emplace(script); // Special rule for IsMine: native P2WPKH requires the TOP script imported (see script/ismine.cpp)
+ }
+ return "";
+ }
+ case TX_NULL_DATA:
+ return "unspendable script";
+ case TX_NONSTANDARD:
+ case TX_WITNESS_UNKNOWN:
+ default:
+ return "unrecognized script";
+ }
+}
- // Optional fields.
- const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : "";
- const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue();
- const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
- const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
- const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
- const std::string& label = data.exists("label") && !internal ? data["label"].get_str() : "";
+static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CPubKey>& pubkey_map, std::map<CKeyID, CKey>& privkey_map, std::set<CScript>& script_pub_keys, bool& have_solving_data, const UniValue& data, std::vector<CKeyID>& ordered_pubkeys)
+{
+ UniValue warnings(UniValue::VARR);
- bool isScript = scriptPubKey.getType() == UniValue::VSTR;
- bool isP2SH = strRedeemScript.length() > 0;
- const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str();
+ // First ensure scriptPubKey has either a script or JSON with "address" string
+ const UniValue& scriptPubKey = data["scriptPubKey"];
+ bool isScript = scriptPubKey.getType() == UniValue::VSTR;
+ if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string");
+ }
+ const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str();
+
+ // Optional fields.
+ const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : "";
+ const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : "";
+ const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue();
+ const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
+ const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
+ const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
+
+ if (data.exists("range")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for a non-descriptor import");
+ }
- // Parse the output.
- CScript script;
+ // Generate the script and destination for the scriptPubKey provided
+ CScript script;
+ if (!isScript) {
+ CTxDestination dest = DecodeDestination(output);
+ if (!IsValidDestination(dest)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address \"" + output + "\"");
+ }
+ script = GetScriptForDestination(dest);
+ } else {
+ if (!IsHex(output)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey \"" + output + "\"");
+ }
+ std::vector<unsigned char> vData(ParseHex(output));
+ script = CScript(vData.begin(), vData.end());
CTxDestination dest;
-
- if (!isScript) {
- dest = DecodeDestination(output);
- if (!IsValidDestination(dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
- }
- script = GetScriptForDestination(dest);
- } else {
- if (!IsHex(output)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey");
- }
-
- std::vector<unsigned char> vData(ParseHex(output));
- script = CScript(vData.begin(), vData.end());
+ if (!ExtractDestination(script, dest) && !internal) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports.");
}
+ }
+ script_pub_keys.emplace(script);
- // Watchonly and private keys
- if (watchOnly && keys.size()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between watchonly and keys");
+ // Parse all arguments
+ if (strRedeemScript.size()) {
+ if (!IsHex(strRedeemScript)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script \"" + strRedeemScript + "\": must be hex string");
}
-
- // Internal + Label
- if (internal && data.exists("label")) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label");
+ auto parsed_redeemscript = ParseHex(strRedeemScript);
+ import_data.redeemscript = MakeUnique<CScript>(parsed_redeemscript.begin(), parsed_redeemscript.end());
+ }
+ if (witness_script_hex.size()) {
+ if (!IsHex(witness_script_hex)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid witness script \"" + witness_script_hex + "\": must be hex string");
}
-
- // Not having Internal + Script
- if (!internal && isScript) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set for hex scriptPubKey");
+ auto parsed_witnessscript = ParseHex(witness_script_hex);
+ import_data.witnessscript = MakeUnique<CScript>(parsed_witnessscript.begin(), parsed_witnessscript.end());
+ }
+ for (size_t i = 0; i < pubKeys.size(); ++i) {
+ const auto& str = pubKeys[i].get_str();
+ if (!IsHex(str)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" must be a hex string");
}
-
- // Keys / PubKeys size check.
- if (!isP2SH && (keys.size() > 1 || pubKeys.size() > 1)) { // Address / scriptPubKey
- throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address");
+ auto parsed_pubkey = ParseHex(str);
+ CPubKey pubkey(parsed_pubkey.begin(), parsed_pubkey.end());
+ if (!pubkey.IsFullyValid()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key");
}
-
- // Invalid P2SH redeemScript
- if (isP2SH && !IsHex(strRedeemScript)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script");
+ pubkey_map.emplace(pubkey.GetID(), pubkey);
+ ordered_pubkeys.push_back(pubkey.GetID());
+ }
+ for (size_t i = 0; i < keys.size(); ++i) {
+ const auto& str = keys[i].get_str();
+ CKey key = DecodeSecret(str);
+ if (!key.IsValid()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
}
+ CPubKey pubkey = key.GetPubKey();
+ CKeyID id = pubkey.GetID();
+ if (pubkey_map.count(id)) {
+ pubkey_map.erase(id);
+ }
+ privkey_map.emplace(id, key);
+ }
- // Process. //
-
- // P2SH
- if (isP2SH) {
- // Import redeem script.
- std::vector<unsigned char> vData(ParseHex(strRedeemScript));
- CScript redeemScript = CScript(vData.begin(), vData.end());
-
- // Invalid P2SH address
- if (!script.IsPayToScriptHash()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script");
- }
-
- pwallet->MarkDirty();
-
- if (!pwallet->AddWatchOnly(redeemScript, timestamp)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
- }
-
- CScriptID redeem_id(redeemScript);
- if (!pwallet->HaveCScript(redeem_id) && !pwallet->AddCScript(redeemScript)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
- }
-
- CScript redeemDestination = GetScriptForDestination(redeem_id);
-
- if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
- }
-
- pwallet->MarkDirty();
-
- if (!pwallet->AddWatchOnly(redeemDestination, timestamp)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
- }
-
- // add to address book or update label
- if (IsValidDestination(dest)) {
- pwallet->SetAddressBook(dest, label, "receive");
- }
-
- // Import private keys.
- if (keys.size()) {
- for (size_t i = 0; i < keys.size(); i++) {
- const std::string& privkey = keys[i].get_str();
-
- CKey key = DecodeSecret(privkey);
-
- if (!key.IsValid()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
- }
-
- CPubKey pubkey = key.GetPubKey();
- assert(key.VerifyPubKey(pubkey));
-
- CKeyID vchAddress = pubkey.GetID();
- pwallet->MarkDirty();
- pwallet->SetAddressBook(vchAddress, label, "receive");
-
- if (pwallet->HaveKey(vchAddress)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key");
- }
- pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
+ // Verify and process input data
+ have_solving_data = import_data.redeemscript || import_data.witnessscript || pubkey_map.size() || privkey_map.size();
+ if (have_solving_data) {
+ // Match up data in import_data with the scriptPubKey in script.
+ auto error = RecurseImportData(script, import_data, ScriptContext::TOP);
- if (!pwallet->AddKeyPubKey(key, pubkey)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
- }
+ // Verify whether the watchonly option corresponds to the availability of private keys.
+ bool spendable = std::all_of(import_data.used_keys.begin(), import_data.used_keys.end(), [&](const std::pair<CKeyID, bool>& used_key){ return privkey_map.count(used_key.first) > 0; });
+ if (!watchOnly && !spendable) {
+ warnings.push_back("Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
+ }
+ if (watchOnly && spendable) {
+ warnings.push_back("All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag.");
+ }
- pwallet->UpdateTimeFirstKey(timestamp);
+ // Check that all required keys for solvability are provided.
+ if (error.empty()) {
+ for (const auto& require_key : import_data.used_keys) {
+ if (!require_key.second) continue; // Not a required key
+ if (pubkey_map.count(require_key.first) == 0 && privkey_map.count(require_key.first) == 0) {
+ error = "some required keys are missing";
}
}
+ }
- success = true;
+ if (!error.empty()) {
+ warnings.push_back("Importing as non-solvable: " + error + ". If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.");
+ import_data = ImportData();
+ pubkey_map.clear();
+ privkey_map.clear();
+ have_solving_data = false;
} else {
- // Import public keys.
- if (pubKeys.size() && keys.size() == 0) {
- const std::string& strPubKey = pubKeys[0].get_str();
-
- if (!IsHex(strPubKey)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
- }
-
- std::vector<unsigned char> vData(ParseHex(strPubKey));
- CPubKey pubKey(vData.begin(), vData.end());
-
- if (!pubKey.IsFullyValid()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
- }
-
- CTxDestination pubkey_dest = pubKey.GetID();
-
- // Consistency check.
- if (!isScript && !(pubkey_dest == dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
-
- // Consistency check.
- if (isScript) {
- CTxDestination destination;
-
- if (ExtractDestination(script, destination)) {
- if (!(destination == pubkey_dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
- }
+ // RecurseImportData() removes any relevant redeemscript/witnessscript from import_data, so we can use that to discover if a superfluous one was provided.
+ if (import_data.redeemscript) warnings.push_back("Ignoring redeemscript as this is not a P2SH script.");
+ if (import_data.witnessscript) warnings.push_back("Ignoring witnessscript as this is not a (P2SH-)P2WSH script.");
+ for (auto it = privkey_map.begin(); it != privkey_map.end(); ) {
+ auto oldit = it++;
+ if (import_data.used_keys.count(oldit->first) == 0) {
+ warnings.push_back("Ignoring irrelevant private key.");
+ privkey_map.erase(oldit);
}
-
- CScript pubKeyScript = GetScriptForDestination(pubkey_dest);
-
- if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
- }
-
- pwallet->MarkDirty();
-
- if (!pwallet->AddWatchOnly(pubKeyScript, timestamp)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
- }
-
- // add to address book or update label
- if (IsValidDestination(pubkey_dest)) {
- pwallet->SetAddressBook(pubkey_dest, label, "receive");
+ }
+ for (auto it = pubkey_map.begin(); it != pubkey_map.end(); ) {
+ auto oldit = it++;
+ auto key_data_it = import_data.used_keys.find(oldit->first);
+ if (key_data_it == import_data.used_keys.end() || !key_data_it->second) {
+ warnings.push_back("Ignoring public key \"" + HexStr(oldit->first) + "\" as it doesn't appear inside P2PKH or P2WPKH.");
+ pubkey_map.erase(oldit);
}
+ }
+ }
+ }
- // TODO Is this necessary?
- CScript scriptRawPubKey = GetScriptForRawPubKey(pubKey);
-
- if (::IsMine(*pwallet, scriptRawPubKey) == ISMINE_SPENDABLE) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
- }
+ return warnings;
+}
- pwallet->MarkDirty();
+static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID, CPubKey>& pubkey_map, std::map<CKeyID, CKey>& privkey_map, std::set<CScript>& script_pub_keys, bool& have_solving_data, const UniValue& data, std::vector<CKeyID>& ordered_pubkeys)
+{
+ UniValue warnings(UniValue::VARR);
- if (!pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
- }
+ const std::string& descriptor = data["desc"].get_str();
+ FlatSigningProvider keys;
+ auto parsed_desc = Parse(descriptor, keys, /* require_checksum = */ true);
+ if (!parsed_desc) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Descriptor is invalid");
+ }
- success = true;
- }
+ have_solving_data = parsed_desc->IsSolvable();
+ const bool watch_only = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
- // Import private keys.
- if (keys.size()) {
- const std::string& strPrivkey = keys[0].get_str();
+ int64_t range_start = 0, range_end = 0;
+ if (!parsed_desc->IsRange() && data.exists("range")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for an un-ranged descriptor");
+ } else if (parsed_desc->IsRange()) {
+ if (!data.exists("range")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Descriptor is ranged, please specify the range");
+ }
+ std::tie(range_start, range_end) = ParseDescriptorRange(data["range"]);
+ }
- // Checks.
- CKey key = DecodeSecret(strPrivkey);
+ const UniValue& priv_keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
+
+ // Expand all descriptors to get public keys and scripts.
+ // TODO: get private keys from descriptors too
+ for (int i = range_start; i <= range_end; ++i) {
+ FlatSigningProvider out_keys;
+ std::vector<CScript> scripts_temp;
+ parsed_desc->Expand(i, keys, scripts_temp, out_keys);
+ std::copy(scripts_temp.begin(), scripts_temp.end(), std::inserter(script_pub_keys, script_pub_keys.end()));
+ for (const auto& key_pair : out_keys.pubkeys) {
+ ordered_pubkeys.push_back(key_pair.first);
+ }
- if (!key.IsValid()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
- }
+ for (const auto& x : out_keys.scripts) {
+ import_data.import_scripts.emplace(x.second);
+ }
- CPubKey pubKey = key.GetPubKey();
- assert(key.VerifyPubKey(pubKey));
+ std::copy(out_keys.pubkeys.begin(), out_keys.pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end()));
+ import_data.key_origins.insert(out_keys.origins.begin(), out_keys.origins.end());
+ }
- CTxDestination pubkey_dest = pubKey.GetID();
+ for (size_t i = 0; i < priv_keys.size(); ++i) {
+ const auto& str = priv_keys[i].get_str();
+ CKey key = DecodeSecret(str);
+ if (!key.IsValid()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
+ }
+ CPubKey pubkey = key.GetPubKey();
+ CKeyID id = pubkey.GetID();
- // Consistency check.
- if (!isScript && !(pubkey_dest == dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
+ // Check if this private key corresponds to a public key from the descriptor
+ if (!pubkey_map.count(id)) {
+ warnings.push_back("Ignoring irrelevant private key.");
+ } else {
+ privkey_map.emplace(id, key);
+ }
+ }
- // Consistency check.
- if (isScript) {
- CTxDestination destination;
+ // Check if all the public keys have corresponding private keys in the import for spendability.
+ // This does not take into account threshold multisigs which could be spendable without all keys.
+ // Thus, threshold multisigs without all keys will be considered not spendable here, even if they are,
+ // perhaps triggering a false warning message. This is consistent with the current wallet IsMine check.
+ bool spendable = std::all_of(pubkey_map.begin(), pubkey_map.end(),
+ [&](const std::pair<CKeyID, CPubKey>& used_key) {
+ return privkey_map.count(used_key.first) > 0;
+ }) && std::all_of(import_data.key_origins.begin(), import_data.key_origins.end(),
+ [&](const std::pair<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& entry) {
+ return privkey_map.count(entry.first) > 0;
+ });
+ if (!watch_only && !spendable) {
+ warnings.push_back("Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
+ }
+ if (watch_only && spendable) {
+ warnings.push_back("All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag.");
+ }
- if (ExtractDestination(script, destination)) {
- if (!(destination == pubkey_dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
- }
- }
+ return warnings;
+}
- CKeyID vchAddress = pubKey.GetID();
- pwallet->MarkDirty();
- pwallet->SetAddressBook(vchAddress, label, "receive");
+static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
+{
+ UniValue warnings(UniValue::VARR);
+ UniValue result(UniValue::VOBJ);
- if (pwallet->HaveKey(vchAddress)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
- }
+ try {
+ const bool internal = data.exists("internal") ? data["internal"].get_bool() : false;
+ // Internal addresses should not have a label
+ 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 bool add_keypool = data.exists("keypool") ? data["keypool"].get_bool() : false;
- pwallet->mapKeyMetadata[vchAddress].nCreateTime = timestamp;
+ // Add to keypool only works with privkeys disabled
+ if (add_keypool && !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Keys can only be imported to the keypool when private keys are disabled");
+ }
- if (!pwallet->AddKeyPubKey(key, pubKey)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
- }
+ ImportData import_data;
+ std::map<CKeyID, CPubKey> pubkey_map;
+ std::map<CKeyID, CKey> privkey_map;
+ std::set<CScript> script_pub_keys;
+ std::vector<CKeyID> ordered_pubkeys;
+ bool have_solving_data;
+
+ if (data.exists("scriptPubKey") && data.exists("desc")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Both a descriptor and a scriptPubKey should not be provided.");
+ } else if (data.exists("scriptPubKey")) {
+ warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data, ordered_pubkeys);
+ } else if (data.exists("desc")) {
+ warnings = ProcessImportDescriptor(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data, ordered_pubkeys);
+ } else {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Either a descriptor or scriptPubKey must be provided.");
+ }
- pwallet->UpdateTimeFirstKey(timestamp);
+ // If private keys are disabled, abort if private keys are being imported
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !privkey_map.empty()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
+ }
- success = true;
+ // Check whether we have any work to do
+ for (const CScript& script : script_pub_keys) {
+ if (::IsMine(*pwallet, script) & ISMINE_SPENDABLE) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script (\"" + HexStr(script.begin(), script.end()) + "\")");
}
+ }
- // Import scriptPubKey only.
- if (pubKeys.size() == 0 && keys.size() == 0) {
- if (::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
- }
+ // All good, time to import
+ pwallet->MarkDirty();
+ for (const auto& entry : import_data.import_scripts) {
+ if (!pwallet->HaveCScript(CScriptID(entry)) && !pwallet->AddCScript(entry)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding script to wallet");
+ }
+ }
+ for (const auto& entry : privkey_map) {
+ const CKey& key = entry.second;
+ CPubKey pubkey = key.GetPubKey();
+ const CKeyID& id = entry.first;
+ assert(key.VerifyPubKey(pubkey));
+ pwallet->mapKeyMetadata[id].nCreateTime = timestamp;
+ // If the private key is not present in the wallet, insert it.
+ if (!pwallet->HaveKey(id) && !pwallet->AddKeyPubKey(key, pubkey)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
+ }
+ pwallet->UpdateTimeFirstKey(timestamp);
+ }
+ for (const auto& entry : import_data.key_origins) {
+ pwallet->AddKeyOrigin(entry.second.first, entry.second.second);
+ }
+ for (const CKeyID& id : ordered_pubkeys) {
+ auto entry = pubkey_map.find(id);
+ if (entry == pubkey_map.end()) {
+ continue;
+ }
+ const CPubKey& pubkey = entry->second;
+ CPubKey temp;
+ if (!pwallet->GetPubKey(id, temp) && !pwallet->AddWatchOnly(GetScriptForRawPubKey(pubkey), timestamp)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
+ }
+ pwallet->mapKeyMetadata[id].nCreateTime = timestamp;
- pwallet->MarkDirty();
+ // Add to keypool only works with pubkeys
+ if (add_keypool) {
+ pwallet->AddKeypoolPubkey(pubkey, internal);
+ }
+ }
+ for (const CScript& script : script_pub_keys) {
+ if (!have_solving_data || !::IsMine(*pwallet, script)) { // Always call AddWatchOnly for non-solvable watch-only, so that watch timestamp gets updated
if (!pwallet->AddWatchOnly(script, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
-
- if (scriptPubKey.getType() == UniValue::VOBJ) {
- // add to address book or update label
- if (IsValidDestination(dest)) {
- pwallet->SetAddressBook(dest, label, "receive");
- }
- }
-
- success = true;
+ }
+ CTxDestination dest;
+ ExtractDestination(script, dest);
+ if (!internal && IsValidDestination(dest)) {
+ pwallet->SetAddressBook(dest, label, "receive");
}
}
- UniValue result = UniValue(UniValue::VOBJ);
- result.pushKV("success", UniValue(success));
- return result;
+ result.pushKV("success", UniValue(true));
} catch (const UniValue& e) {
- UniValue result = UniValue(UniValue::VOBJ);
result.pushKV("success", UniValue(false));
result.pushKV("error", e);
- return result;
} catch (...) {
- UniValue result = UniValue(UniValue::VOBJ);
result.pushKV("success", UniValue(false));
+
result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, "Missing required fields"));
- return result;
}
+ if (warnings.size()) result.pushKV("warnings", warnings);
+ return result;
}
static int64_t GetImportTimestamp(const UniValue& data, int64_t now)
@@ -1129,46 +1352,70 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
return NullUniValue;
}
- // clang-format off
if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
throw std::runtime_error(
- "importmulti \"requests\" ( \"options\" )\n\n"
- "Import addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options). Requires a new wallet backup.\n\n"
- "Arguments:\n"
- "1. requests (array, required) Data to be imported\n"
- " [ (array of json objects)\n"
- " {\n"
- " \"scriptPubKey\": \"<script>\" | { \"address\":\"<address>\" }, (string / json, required) Type of scriptPubKey (string for script, json for address)\n"
- " \"timestamp\": timestamp | \"now\" , (integer / string, required) Creation time of the key in seconds since epoch (Jan 1 1970 GMT),\n"
- " or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n"
- " key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n"
- " \"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n"
- " 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n"
- " creation time of all keys being imported by the importmulti call will be scanned.\n"
- " \"redeemscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH address or a P2SH scriptPubKey\n"
- " \"pubkeys\": [\"<pubKey>\", ... ] , (array, optional) Array of strings giving pubkeys that must occur in the output or redeemscript\n"
- " \"keys\": [\"<key>\", ... ] , (array, optional) Array of strings giving private keys whose corresponding public keys must occur in the output or redeemscript\n"
- " \"internal\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be treated as not incoming payments\n"
- " \"watchonly\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be considered watched even when they're not spendable, only allowed if keys are empty\n"
- " \"label\": <label> , (string, optional, default: '') Label to assign to the address (aka account name, for now), only allowed with internal=false\n"
- " }\n"
- " ,...\n"
- " ]\n"
- "2. options (json, optional)\n"
- " {\n"
- " \"rescan\": <false>, (boolean, optional, default: true) Stating if should rescan the blockchain after all imports\n"
- " }\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
- "may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n"
- "\nExamples:\n" +
- HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
- "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
- HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'") +
-
+ RPCHelpMan{"importmulti",
+ "\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), optionally rescanning the blockchain from the earliest creation time of the imported scripts. Requires a new wallet backup.\n"
+ "If an address/script is imported without all of the private keys required to spend from that address, it will be watchonly. The 'watchonly' option must be set to true in this case or a warning will be returned.\n"
+ "Conversely, if all the private keys are provided and the address/script is spendable, the watchonly option must be set to false, or a warning will be returned.\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
+ "may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n",
+ {
+ {"requests", RPCArg::Type::ARR, RPCArg::Optional::NO, "Data to be imported",
+ {
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"desc", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Descriptor to import. If using descriptor, do not also provide address/scriptPubKey, scripts, or pubkeys"},
+ {"scriptPubKey", RPCArg::Type::STR, RPCArg::Optional::NO, "Type of scriptPubKey (string for script, json for address). Should not be provided if using a descriptor",
+ /* oneline_description */ "", {"\"<script>\" | { \"address\":\"<address>\" }", "string / json"}
+ },
+ {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Creation time of the key in seconds since epoch (Jan 1 1970 GMT),\n"
+ " or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n"
+ " key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n"
+ " \"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n"
+ " 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n"
+ " creation time of all keys being imported by the importmulti call will be scanned.",
+ /* oneline_description */ "", {"timestamp | \"now\"", "integer / string"}
+ },
+ {"redeemscript", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Allowed only if the scriptPubKey is a P2SH or P2SH-P2WSH address/scriptPubKey"},
+ {"witnessscript", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Allowed only if the scriptPubKey is a P2SH-P2WSH or P2WSH address/scriptPubKey"},
+ {"pubkeys", RPCArg::Type::ARR, /* default */ "empty array", "Array of strings giving pubkeys to import. They must occur in P2PKH or P2WPKH scripts. They are not required when the private key is also provided (see the \"keys\" argument).",
+ {
+ {"pubKey", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
+ }
+ },
+ {"keys", RPCArg::Type::ARR, /* default */ "empty array", "Array of strings giving private keys to import. The corresponding public keys must occur in the output or redeemscript.",
+ {
+ {"key", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
+ }
+ },
+ {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the end or the range (in the form [begin,end]) to import"},
+ {"internal", RPCArg::Type::BOOL, /* default */ "false", "Stating whether matching outputs should be treated as not incoming payments (also known as change)"},
+ {"watchonly", RPCArg::Type::BOOL, /* default */ "false", "Stating whether matching outputs should be considered watchonly."},
+ {"label", RPCArg::Type::STR, /* default */ "''", "Label to assign to the address, only allowed with internal=false"},
+ {"keypool", RPCArg::Type::BOOL, /* default */ "false", "Stating whether imported public keys should be added to the keypool for when users request new addresses. Only allowed when wallet private keys are disabled"},
+ },
+ },
+ },
+ "\"requests\""},
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ {
+ {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Stating if should rescan the blockchain after all imports"},
+ },
+ "\"options\""},
+ },
+ RPCResult{
"\nResponse is an array with the same size as the input that has the execution result :\n"
- " [{ \"success\": true } , { \"success\": false, \"error\": { \"code\": -1, \"message\": \"Internal Server Error\"} }, ... ]\n");
+ " [{\"success\": true}, {\"success\": true, \"warnings\": [\"Ignoring irrelevant private key\"]}, {\"success\": false, \"error\": {\"code\": -1, \"message\": \"Internal Server Error\"}}, ...]\n"
+ },
+ RPCExamples{
+ HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
+ "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
+ HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'")
+ },
+ }.ToString()
+ );
- // clang-format on
RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
@@ -1195,19 +1442,21 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
int64_t nLowestTimestamp = 0;
UniValue response(UniValue::VARR);
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
// Verify all timestamps are present before importing any keys.
- now = chainActive.Tip() ? chainActive.Tip()->GetMedianTimePast() : 0;
+ const Optional<int> tip_height = locked_chain->getHeight();
+ now = tip_height ? locked_chain->getBlockMedianTimePast(*tip_height) : 0;
for (const UniValue& data : requests.getValues()) {
GetImportTimestamp(data, now);
}
const int64_t minimumTimestamp = 1;
- if (fRescan && chainActive.Tip()) {
- nLowestTimestamp = chainActive.Tip()->GetBlockTime();
+ if (fRescan && tip_height) {
+ nLowestTimestamp = locked_chain->getBlockTime(*tip_height);
} else {
fRescan = false;
}
@@ -1234,7 +1483,11 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
}
if (fRescan && fRunScan && requests.size()) {
int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */);
- pwallet->ReacceptWalletTransactions();
+ {
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
+ pwallet->ReacceptWalletTransactions(*locked_chain);
+ }
if (pwallet->IsAbortingRescan()) {
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 73dfebf114..96a74a338a 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,26 +7,33 @@
#include <chain.h>
#include <consensus/validation.h>
#include <core_io.h>
-#include <httpserver.h>
-#include <validation.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <key_io.h>
#include <net.h>
+#include <node/transaction.h>
#include <outputtype.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/rbf.h>
-#include <rpc/mining.h>
-#include <rpc/rawtransaction.h>
+#include <rpc/rawtransaction_util.h>
#include <rpc/server.h>
#include <rpc/util.h>
+#include <script/descriptor.h>
#include <script/sign.h>
#include <shutdown.h>
#include <timedata.h>
-#include <util.h>
-#include <utilmoneystr.h>
+#include <util/bip32.h>
+#include <util/fees.h>
+#include <util/moneystr.h>
+#include <util/system.h>
+#include <util/url.h>
+#include <util/validation.h>
+#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/feebumper.h>
+#include <wallet/psbtwallet.h>
#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
#include <wallet/walletdb.h>
@@ -63,14 +70,14 @@ std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& reques
return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr;
}
-std::string HelpRequiringPassphrase(CWallet * const pwallet)
+std::string HelpRequiringPassphrase(const CWallet* pwallet)
{
return pwallet && pwallet->IsCrypted()
? "\nRequires wallet passphrase to be set with walletpassphrase call."
: "";
}
-bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
+bool EnsureWalletIsAvailable(const CWallet* pwallet, bool avoidException)
{
if (pwallet) return true;
if (avoidException) return false;
@@ -82,16 +89,16 @@ bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
"Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
}
-void EnsureWalletIsUnlocked(CWallet * const pwallet)
+void EnsureWalletIsUnlocked(const CWallet* pwallet)
{
if (pwallet->IsLocked()) {
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
}
}
-static void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
+static void WalletTxToJSON(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx, UniValue& entry)
{
- int confirms = wtx.GetDepthInMainChain();
+ int confirms = wtx.GetDepthInMainChain(locked_chain);
entry.pushKV("confirmations", confirms);
if (wtx.IsCoinBase())
entry.pushKV("generated", true);
@@ -99,9 +106,12 @@ static void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{
entry.pushKV("blockhash", wtx.hashBlock.GetHex());
entry.pushKV("blockindex", wtx.nIndex);
- entry.pushKV("blocktime", LookupBlockIndex(wtx.hashBlock)->GetBlockTime());
+ int64_t block_time;
+ bool found_block = chain.findBlock(wtx.hashBlock, nullptr /* block */, &block_time);
+ assert(found_block);
+ entry.pushKV("blocktime", block_time);
} else {
- entry.pushKV("trusted", wtx.IsTrusted());
+ entry.pushKV("trusted", wtx.IsTrusted(locked_chain));
}
uint256 hash = wtx.GetHash();
entry.pushKV("txid", hash.GetHex());
@@ -115,8 +125,7 @@ static void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
// Add opt-in RBF status
std::string rbfStatus = "no";
if (confirms <= 0) {
- LOCK(mempool.cs);
- RBFTransactionState rbfState = IsRBFOptIn(*wtx.tx, mempool);
+ RBFTransactionState rbfState = chain.isRBFOptIn(*wtx.tx);
if (rbfState == RBFTransactionState::UNKNOWN)
rbfStatus = "unknown";
else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125)
@@ -147,25 +156,28 @@ static UniValue getnewaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 2)
throw std::runtime_error(
- "getnewaddress ( \"label\" \"address_type\" )\n"
- "\nReturns a new Bitcoin address for receiving payments.\n"
- "If 'label' is specified, it is added to the address book \n"
- "so payments received with the address will be associated with 'label'.\n"
- "\nArguments:\n"
- "1. \"label\" (string, optional) The label name for the address to be linked to. If not provided, the default label \"\" is used. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name.\n"
- "2. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n"
- "\nResult:\n"
+ RPCHelpMan{"getnewaddress",
+ "\nReturns a new Bitcoin address for receiving payments.\n"
+ "If 'label' is specified, it is added to the address book \n"
+ "so payments received with the address will be associated with 'label'.\n",
+ {
+ {"label", RPCArg::Type::STR, /* default */ "\"\"", "The label name for the address to be linked to. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name."},
+ {"address_type", RPCArg::Type::STR, /* default */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ },
+ RPCResult{
"\"address\" (string) The new bitcoin address\n"
- "\nExamples:\n"
- + HelpExampleCli("getnewaddress", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getnewaddress", "")
+ HelpExampleRpc("getnewaddress", "")
- );
+ },
+ }.ToString());
- if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
- }
+ LOCK(pwallet->cs_wallet);
- LOCK2(cs_main, pwallet->cs_wallet);
+ if (!pwallet->CanGetAddresses()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
+ }
// Parse the label first so we don't generate a key if there's an error
std::string label;
@@ -196,59 +208,6 @@ static UniValue getnewaddress(const JSONRPCRequest& request)
return EncodeDestination(dest);
}
-CTxDestination GetLabelDestination(CWallet* const pwallet, const std::string& label, bool bForceNew=false)
-{
- CTxDestination dest;
- if (!pwallet->GetLabelDestination(dest, label, bForceNew)) {
- throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
- }
-
- return dest;
-}
-
-static UniValue getaccountaddress(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (!IsDeprecatedRPCEnabled("accounts")) {
- if (request.fHelp) {
- throw std::runtime_error("getaccountaddress (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "getaccountaddress is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
- "getaccountaddress \"account\"\n"
- "\n\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
- "\nArguments:\n"
- "1. \"account\" (string, required) The account for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created if there is no account by the given name.\n"
- "\nResult:\n"
- "\"address\" (string) The account bitcoin address\n"
- "\nExamples:\n"
- + HelpExampleCli("getaccountaddress", "")
- + HelpExampleCli("getaccountaddress", "\"\"")
- + HelpExampleCli("getaccountaddress", "\"myaccount\"")
- + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
- );
-
- LOCK2(cs_main, pwallet->cs_wallet);
-
- // Parse the account first so we don't generate a key if there's an error
- std::string account = LabelFromValue(request.params[0]);
-
- UniValue ret(UniValue::VSTR);
-
- ret = EncodeDestination(GetLabelDestination(pwallet, account));
- return ret;
-}
-
-
static UniValue getrawchangeaddress(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -260,23 +219,26 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
- "getrawchangeaddress ( \"address_type\" )\n"
- "\nReturns a new Bitcoin address, for receiving change.\n"
- "This is for use with raw transactions, NOT normal use.\n"
- "\nArguments:\n"
- "1. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -changetype.\n"
- "\nResult:\n"
+ RPCHelpMan{"getrawchangeaddress",
+ "\nReturns a new Bitcoin address, for receiving change.\n"
+ "This is for use with raw transactions, NOT normal use.\n",
+ {
+ {"address_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ },
+ RPCResult{
"\"address\" (string) The address\n"
- "\nExamples:\n"
- + HelpExampleCli("getrawchangeaddress", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getrawchangeaddress", "")
+ HelpExampleRpc("getrawchangeaddress", "")
- );
+ },
+ }.ToString());
- if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
- }
+ LOCK(pwallet->cs_wallet);
- LOCK2(cs_main, pwallet->cs_wallet);
+ if (!pwallet->CanGetAddresses(true)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
+ }
if (!pwallet->IsLocked()) {
pwallet->TopUpKeyPool();
@@ -312,159 +274,43 @@ static UniValue setlabel(const JSONRPCRequest& request)
return NullUniValue;
}
- if (!IsDeprecatedRPCEnabled("accounts") && request.strMethod == "setaccount") {
- if (request.fHelp) {
- throw std::runtime_error("setaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "setaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
if (request.fHelp || request.params.size() != 2)
throw std::runtime_error(
- "setlabel \"address\" \"label\"\n"
- "\nSets the label associated with the given address.\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address to be associated with a label.\n"
- "2. \"label\" (string, required) The label to assign to the address.\n"
- "\nExamples:\n"
- + HelpExampleCli("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
+ RPCHelpMan{"setlabel",
+ "\nSets the label associated with the given address.\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to be associated with a label."},
+ {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label to assign to the address."},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
+ HelpExampleRpc("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
- );
+ },
+ }.ToString());
- LOCK2(cs_main, pwallet->cs_wallet);
+ LOCK(pwallet->cs_wallet);
CTxDestination dest = DecodeDestination(request.params[0].get_str());
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
}
- std::string old_label = pwallet->mapAddressBook[dest].name;
std::string label = LabelFromValue(request.params[1]);
if (IsMine(*pwallet, dest)) {
pwallet->SetAddressBook(dest, label, "receive");
- if (request.strMethod == "setaccount" && old_label != label && dest == GetLabelDestination(pwallet, old_label)) {
- // for setaccount, call GetLabelDestination so a new receive address is created for the old account
- GetLabelDestination(pwallet, old_label, true);
- }
} else {
pwallet->SetAddressBook(dest, label, "send");
}
- // Detect when there are no addresses using this label.
- // If so, delete the account record for it. Labels, unlike addresses, can be deleted,
- // and if we wouldn't do this, the record would stick around forever.
- bool found_address = false;
- for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
- if (item.second.name == label) {
- found_address = true;
- break;
- }
- }
- if (!found_address) {
- pwallet->DeleteLabel(old_label);
- }
-
return NullUniValue;
}
-static UniValue getaccount(const JSONRPCRequest& request)
+static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue)
{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (!IsDeprecatedRPCEnabled("accounts")) {
- if (request.fHelp) {
- throw std::runtime_error("getaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "getaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
- "getaccount \"address\"\n"
- "\nDEPRECATED. Returns the account associated with the given address.\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address for account lookup.\n"
- "\nResult:\n"
- "\"accountname\" (string) the account address\n"
- "\nExamples:\n"
- + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")
- + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")
- );
-
- LOCK2(cs_main, pwallet->cs_wallet);
-
- CTxDestination dest = DecodeDestination(request.params[0].get_str());
- if (!IsValidDestination(dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- }
-
- std::string strAccount;
- std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(dest);
- if (mi != pwallet->mapAddressBook.end() && !(*mi).second.name.empty()) {
- strAccount = (*mi).second.name;
- }
- return strAccount;
-}
-
-
-static UniValue getaddressesbyaccount(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (!IsDeprecatedRPCEnabled("accounts")) {
- if (request.fHelp) {
- throw std::runtime_error("getaddressbyaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "getaddressesbyaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
- "getaddressesbyaccount \"account\"\n"
- "\nDEPRECATED. Returns the list of addresses for the given account.\n"
- "\nArguments:\n"
- "1. \"account\" (string, required) The account name.\n"
- "\nResult:\n"
- "[ (json array of string)\n"
- " \"address\" (string) a bitcoin address associated with the given account\n"
- " ,...\n"
- "]\n"
- "\nExamples:\n"
- + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
- + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
- );
-
- LOCK2(cs_main, pwallet->cs_wallet);
-
- std::string strAccount = LabelFromValue(request.params[0]);
-
- // Find all addresses that have the given account
- UniValue ret(UniValue::VARR);
- for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
- const CTxDestination& dest = item.first;
- const std::string& strName = item.second.name;
- if (strName == strAccount) {
- ret.push_back(EncodeDestination(dest));
- }
- }
- return ret;
-}
-
-static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue, std::string fromAccount)
-{
- CAmount curBalance = pwallet->GetBalance();
+ CAmount curBalance = pwallet->GetBalance().m_mine_trusted;
// Check amount
if (nValue <= 0)
@@ -473,7 +319,7 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
if (nValue > curBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
- if (pwallet->GetBroadcastTransactions() && !g_connman) {
+ if (pwallet->GetBroadcastTransactions() && !pwallet->chain().p2pEnabled()) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
}
@@ -489,13 +335,13 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
CTransactionRef tx;
- if (!pwallet->CreateTransaction(vecSend, tx, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
+ if (!pwallet->CreateTransaction(locked_chain, vecSend, tx, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
CValidationState state;
- if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, std::move(fromAccount), reservekey, g_connman.get(), state)) {
+ if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, reservekey, state)) {
strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state));
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
@@ -513,39 +359,43 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 2 || request.params.size() > 8)
throw std::runtime_error(
- "sendtoaddress \"address\" amount ( \"comment\" \"comment_to\" subtractfeefromamount replaceable conf_target \"estimate_mode\")\n"
- "\nSend an amount to a given address.\n"
- + HelpRequiringPassphrase(pwallet) +
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address to send to.\n"
- "2. \"amount\" (numeric or string, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
- "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
- " This is not part of the transaction, just kept in your wallet.\n"
- "4. \"comment_to\" (string, optional) A comment to store the name of the person or organization \n"
+ RPCHelpMan{"sendtoaddress",
+ "\nSend an amount to a given address." +
+ HelpRequiringPassphrase(pwallet) + "\n",
+ {
+ {"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"
+ " 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"
" to which you're sending the transaction. This is not part of the \n"
- " transaction, just kept in your wallet.\n"
- "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
- " The recipient will receive less bitcoins than you enter in the amount field.\n"
- "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
- "7. conf_target (numeric, optional) Confirmation target (in blocks)\n"
- "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
+ " transaction, just kept in your wallet."},
+ {"subtractfeefromamount", RPCArg::Type::BOOL, /* default */ "false", "The fee will be deducted from the amount being sent.\n"
+ " The recipient will receive less bitcoins than you enter in the amount field."},
+ {"replaceable", RPCArg::Type::BOOL, /* default */ "fallback to wallet's default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "fallback to wallet's default", "Confirmation target (in blocks)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
" \"UNSET\"\n"
" \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\"\n"
- "\nResult:\n"
+ " \"CONSERVATIVE\""},
+ },
+ RPCResult{
"\"txid\" (string) The transaction id.\n"
- "\nExamples:\n"
- + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
+ },
+ RPCExamples{
+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
+ HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
CTxDestination dest = DecodeDestination(request.params[0].get_str());
if (!IsValidDestination(dest)) {
@@ -575,7 +425,7 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
}
if (!request.params[6].isNull()) {
- coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]);
+ coin_control.m_confirm_target = ParseConfirmTarget(request.params[6], pwallet->chain().estimateMaxBlocks());
}
if (!request.params[7].isNull()) {
@@ -587,7 +437,7 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
- CTransactionRef tx = SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue), {} /* fromAccount */);
+ CTransactionRef tx = SendMoney(*locked_chain, pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue));
return tx->GetHash().GetHex();
}
@@ -602,11 +452,12 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "listaddressgroupings\n"
- "\nLists groups of addresses which have had their common ownership\n"
- "made public by common use as inputs or as the resulting change\n"
- "in past transactions\n"
- "\nResult:\n"
+ RPCHelpMan{"listaddressgroupings",
+ "\nLists groups of addresses which have had their common ownership\n"
+ "made public by common use as inputs or as the resulting change\n"
+ "in past transactions\n",
+ {},
+ RPCResult{
"[\n"
" [\n"
" [\n"
@@ -618,19 +469,22 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
" ]\n"
" ,...\n"
"]\n"
- "\nExamples:\n"
- + HelpExampleCli("listaddressgroupings", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listaddressgroupings", "")
+ HelpExampleRpc("listaddressgroupings", "")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
UniValue jsonGroupings(UniValue::VARR);
- std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
+ std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances(*locked_chain);
for (const std::set<CTxDestination>& grouping : pwallet->GetAddressGroupings()) {
UniValue jsonGrouping(UniValue::VARR);
for (const CTxDestination& address : grouping)
@@ -661,26 +515,30 @@ static UniValue signmessage(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 2)
throw std::runtime_error(
- "signmessage \"address\" \"message\"\n"
- "\nSign a message with the private key of an address"
- + HelpRequiringPassphrase(pwallet) + "\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address to use for the private key.\n"
- "2. \"message\" (string, required) The message to create a signature of.\n"
- "\nResult:\n"
+ RPCHelpMan{"signmessage",
+ "\nSign a message with the private key of an address" +
+ HelpRequiringPassphrase(pwallet) + "\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the private key."},
+ {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
+ },
+ RPCResult{
"\"signature\" (string) The signature of the message encoded in base 64\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nUnlock the wallet for 30 seconds\n"
+ HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
"\nCreate the signature\n"
+ HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
"\nVerify the signature\n"
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
- "\nAs json rpc\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")
- );
+ },
+ }.ToString());
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -692,13 +550,14 @@ static UniValue signmessage(const JSONRPCRequest& request)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
}
- const CKeyID *keyID = boost::get<CKeyID>(&dest);
- if (!keyID) {
+ const PKHash *pkhash = boost::get<PKHash>(&dest);
+ if (!pkhash) {
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
}
CKey key;
- if (!pwallet->GetKey(*keyID, key)) {
+ CKeyID keyID(*pkhash);
+ if (!pwallet->GetKey(keyID, key)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
}
@@ -724,29 +583,33 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "getreceivedbyaddress \"address\" ( minconf )\n"
- "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address for transactions.\n"
- "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
- "\nResult:\n"
+ RPCHelpMan{"getreceivedbyaddress",
+ "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for transactions."},
+ {"minconf", RPCArg::Type::NUM, /* default */ "1", "Only include transactions confirmed at least this many times."},
+ },
+ RPCResult{
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nThe amount from transactions with at least 1 confirmation\n"
+ HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") +
"\nThe amount including unconfirmed transactions, zero confirmations\n"
+ HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 0") +
"\nThe amount with at least 6 confirmations\n"
+ HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
// Bitcoin address
CTxDestination dest = DecodeDestination(request.params[0].get_str());
@@ -767,12 +630,13 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
CAmount nAmount = 0;
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
- if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
+ if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) {
continue;
+ }
for (const CTxOut& txout : wtx.tx->vout)
if (txout.scriptPubKey == scriptPubKey)
- if (wtx.GetDepthInMainChain() >= nMinDepth)
+ if (wtx.GetDepthInMainChain(*locked_chain) >= nMinDepth)
nAmount += txout.nValue;
}
@@ -789,38 +653,35 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
return NullUniValue;
}
- if (!IsDeprecatedRPCEnabled("accounts") && request.strMethod == "getreceivedbyaccount") {
- if (request.fHelp) {
- throw std::runtime_error("getreceivedbyaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "getreceivedbyaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "getreceivedbylabel \"label\" ( minconf )\n"
- "\nReturns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.\n"
- "\nArguments:\n"
- "1. \"label\" (string, required) The selected label, may be the default label using \"\".\n"
- "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
- "\nResult:\n"
+ RPCHelpMan{"getreceivedbylabel",
+ "\nReturns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.\n",
+ {
+ {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The selected label, may be the default label using \"\"."},
+ {"minconf", RPCArg::Type::NUM, /* default */ "1", "Only include transactions confirmed at least this many times."},
+ },
+ RPCResult{
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this label.\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nAmount received by the default label with at least 1 confirmation\n"
+ HelpExampleCli("getreceivedbylabel", "\"\"") +
"\nAmount received at the tabby label including unconfirmed amounts with zero confirmations\n"
+ HelpExampleCli("getreceivedbylabel", "\"tabby\" 0") +
"\nThe amount with at least 6 confirmations\n"
+ HelpExampleCli("getreceivedbylabel", "\"tabby\" 6") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
// Minimum confirmations
int nMinDepth = 1;
@@ -835,14 +696,15 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
CAmount nAmount = 0;
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
- if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
+ if (wtx.IsCoinBase() || !locked_chain->checkFinalTx(*wtx.tx)) {
continue;
+ }
for (const CTxOut& txout : wtx.tx->vout)
{
CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwallet, address) && setAddress.count(address)) {
- if (wtx.GetDepthInMainChain() >= nMinDepth)
+ if (wtx.GetDepthInMainChain(*locked_chain) >= nMinDepth)
nAmount += txout.nValue;
}
}
@@ -863,85 +725,53 @@ static UniValue getbalance(const JSONRPCRequest& request)
if (request.fHelp || (request.params.size() > 3 ))
throw std::runtime_error(
- (IsDeprecatedRPCEnabled("accounts") ? std::string(
- "getbalance ( \"account\" minconf include_watchonly )\n"
- "\nIf account is not specified, returns the server's total available balance.\n"
- "The available balance is what the wallet considers currently spendable, and is\n"
- "thus affected by options which limit spendability such as -spendzeroconfchange.\n"
- "If account is specified (DEPRECATED), returns the balance in the account.\n"
- "Note that the account \"\" is not the same as leaving the parameter out.\n"
- "The server total may be different to the balance in the default \"\" account.\n"
- "\nArguments:\n"
- "1. \"account\" (string, optional) DEPRECATED. This argument will be removed in V0.18. \n"
- " To use this deprecated argument, start bitcoind with -deprecatedrpc=accounts. The account string may be given as a\n"
- " specific account name to find the balance associated with wallet keys in\n"
- " a named account, or as the empty string (\"\") to find the balance\n"
- " associated with wallet keys not in any named account, or as \"*\" to find\n"
- " the balance associated with all wallet keys regardless of account.\n"
- " When this option is specified, it calculates the balance in a different\n"
- " way than when it is not specified, and which can count spends twice when\n"
- " there are conflicting pending transactions (such as those created by\n"
- " the bumpfee command), temporarily resulting in low or even negative\n"
- " balances. In general, account balance calculation is not considered\n"
- " reliable and has resulted in confusing outcomes, so it is recommended to\n"
- " avoid passing this argument.\n"
- "2. minconf (numeric, optional) Only include transactions confirmed at least this many times. \n"
- " The default is 1 if an account is provided or 0 if no account is provided\n")
- : std::string(
- "getbalance ( \"(dummy)\" minconf include_watchonly )\n"
- "\nReturns the total available balance.\n"
- "The available balance is what the wallet considers currently spendable, and is\n"
- "thus affected by options which limit spendability such as -spendzeroconfchange.\n"
- "\nArguments:\n"
- "1. (dummy) (string, optional) Remains for backward compatibility. Must be excluded or set to \"*\".\n"
- "2. minconf (numeric, optional, default=0) Only include transactions confirmed at least this many times.\n")) +
- "3. include_watchonly (bool, optional, default=false) Also include balance in watch-only addresses (see 'importaddress')\n"
- "\nResult:\n"
- "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
- "\nExamples:\n"
+ RPCHelpMan{"getbalance",
+ "\nReturns the total available balance.\n"
+ "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 \"*\"."},
+ {"minconf", RPCArg::Type::NUM, /* default */ "0", "Only include transactions confirmed at least this many times."},
+ {"include_watchonly", RPCArg::Type::BOOL, /* default */ "false", "Also include balance in watch-only addresses (see 'importaddress')"},
+ },
+ RPCResult{
+ "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this wallet.\n"
+ },
+ RPCExamples{
"\nThe total amount in the wallet with 1 or more confirmations\n"
+ HelpExampleCli("getbalance", "") +
"\nThe total amount in the wallet at least 6 blocks confirmed\n"
+ HelpExampleCli("getbalance", "\"*\" 6") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("getbalance", "\"*\", 6")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- const UniValue& account_value = request.params[0];
+ const UniValue& dummy_value = request.params[0];
+ if (!dummy_value.isNull() && dummy_value.get_str() != "*") {
+ throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\".");
+ }
int min_depth = 0;
- if (IsDeprecatedRPCEnabled("accounts") && !account_value.isNull()) {
- // Default min_depth to 1 when an account is provided.
- min_depth = 1;
- }
if (!request.params[1].isNull()) {
min_depth = request.params[1].get_int();
}
- isminefilter filter = ISMINE_SPENDABLE;
+ bool include_watchonly = false;
if (!request.params[2].isNull() && request.params[2].get_bool()) {
- filter = filter | ISMINE_WATCH_ONLY;
+ include_watchonly = true;
}
- if (!account_value.isNull()) {
-
- const std::string& account_param = account_value.get_str();
- const std::string* account = account_param != "*" ? &account_param : nullptr;
+ const auto bal = pwallet->GetBalance(min_depth);
- if (!IsDeprecatedRPCEnabled("accounts") && account_param != "*") {
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\".");
- } else if (IsDeprecatedRPCEnabled("accounts")) {
- return ValueFromAmount(pwallet->GetLegacyBalance(filter, min_depth, account));
- }
- }
-
- return ValueFromAmount(pwallet->GetBalance(filter, min_depth));
+ return ValueFromAmount(bal.m_mine_trusted + (include_watchonly ? bal.m_watchonly_trusted : 0));
}
static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
@@ -955,158 +785,21 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
if (request.fHelp || request.params.size() > 0)
throw std::runtime_error(
- "getunconfirmedbalance\n"
- "Returns the server's total unconfirmed balance\n");
+ RPCHelpMan{"getunconfirmedbalance",
+ "DEPRECATED\nIdentical to getbalances().mine.untrusted_pending\n",
+ {},
+ RPCResults{},
+ RPCExamples{""},
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
-
- return ValueFromAmount(pwallet->GetUnconfirmedBalance());
-}
-
-
-static UniValue movecmd(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (!IsDeprecatedRPCEnabled("accounts")) {
- if (request.fHelp) {
- throw std::runtime_error("move (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "move is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
- if (request.fHelp || request.params.size() < 3 || request.params.size() > 5)
- throw std::runtime_error(
- "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
- "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
- "\nArguments:\n"
- "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
- "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
- "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n"
- "4. (dummy) (numeric, optional) Ignored. Remains for backward compatibility.\n"
- "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
- "\nResult:\n"
- "true|false (boolean) true if successful.\n"
- "\nExamples:\n"
- "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
- + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
- "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n"
- + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
- "\nAs a json rpc call\n"
- + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
- );
-
- LOCK2(cs_main, pwallet->cs_wallet);
-
- std::string strFrom = LabelFromValue(request.params[0]);
- std::string strTo = LabelFromValue(request.params[1]);
- CAmount nAmount = AmountFromValue(request.params[2]);
- if (nAmount <= 0)
- throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
- if (!request.params[3].isNull())
- // unused parameter, used to be nMinDepth, keep type-checking it though
- (void)request.params[3].get_int();
- std::string strComment;
- if (!request.params[4].isNull())
- strComment = request.params[4].get_str();
-
- if (!pwallet->AccountMove(strFrom, strTo, nAmount, strComment)) {
- throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
- }
-
- return true;
-}
-
-
-static UniValue sendfrom(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (!IsDeprecatedRPCEnabled("accounts")) {
- if (request.fHelp) {
- throw std::runtime_error("sendfrom (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "sendfrom is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
-
- if (request.fHelp || request.params.size() < 3 || request.params.size() > 6)
- throw std::runtime_error(
- "sendfrom \"fromaccount\" \"toaddress\" amount ( minconf \"comment\" \"comment_to\" )\n"
- "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address."
- + HelpRequiringPassphrase(pwallet) + "\n"
- "\nArguments:\n"
- "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
- " Specifying an account does not influence coin selection, but it does associate the newly created\n"
- " transaction with the account, so the account's balance computation and transaction history can reflect\n"
- " the spend.\n"
- "2. \"toaddress\" (string, required) The bitcoin address to send funds to.\n"
- "3. amount (numeric or string, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
- "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
- "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
- " This is not part of the transaction, just kept in your wallet.\n"
- "6. \"comment_to\" (string, optional) An optional comment to store the name of the person or organization \n"
- " to which you're sending the transaction. This is not part of the transaction, \n"
- " it is just kept in your wallet.\n"
- "\nResult:\n"
- "\"txid\" (string) The transaction id.\n"
- "\nExamples:\n"
- "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n"
- + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
- "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
- + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
- "\nAs a json rpc call\n"
- + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
- );
-
- // Make sure the results are valid at least up to the most recent block
- // the user could have gotten from another RPC command prior to now
- pwallet->BlockUntilSyncedToCurrentChain();
-
- LOCK2(cs_main, pwallet->cs_wallet);
-
- std::string strAccount = LabelFromValue(request.params[0]);
- CTxDestination dest = DecodeDestination(request.params[1].get_str());
- if (!IsValidDestination(dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- }
- CAmount nAmount = AmountFromValue(request.params[2]);
- if (nAmount <= 0)
- throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
- int nMinDepth = 1;
- if (!request.params[3].isNull())
- nMinDepth = request.params[3].get_int();
-
- mapValue_t mapValue;
- if (!request.params[4].isNull() && !request.params[4].get_str().empty())
- mapValue["comment"] = request.params[4].get_str();
- if (!request.params[5].isNull() && !request.params[5].get_str().empty())
- mapValue["to"] = request.params[5].get_str();
-
- EnsureWalletIsUnlocked(pwallet);
-
- // Check funds
- CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount);
- if (nAmount > nBalance)
- throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- CCoinControl no_coin_control; // This is a deprecated API
- CTransactionRef tx = SendMoney(pwallet, dest, nAmount, false, no_coin_control, std::move(mapValue), std::move(strAccount));
- return tx->GetHash().GetHex();
+ return ValueFromAmount(pwallet->GetBalance().m_mine_untrusted_pending);
}
@@ -1119,109 +812,68 @@ static UniValue sendmany(const JSONRPCRequest& request)
return NullUniValue;
}
- std::string help_text;
- if (!IsDeprecatedRPCEnabled("accounts")) {
- help_text = "sendmany \"\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] replaceable conf_target \"estimate_mode\")\n"
- "\nSend multiple times. Amounts are double-precision floating point numbers.\n"
- "Note that the \"fromaccount\" argument has been removed in V0.17. To use this RPC with a \"fromaccount\" argument, restart\n"
- "bitcoind with -deprecatedrpc=accounts\n"
- + HelpRequiringPassphrase(pwallet) + "\n"
- "\nArguments:\n"
- "1. \"dummy\" (string, required) Must be set to \"\" for backwards compatibility.\n"
- "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
- " {\n"
- " \"address\":amount (numeric or string) The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n"
- " ,...\n"
- " }\n"
- "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
- "4. \"comment\" (string, optional) A comment\n"
- "5. subtractfeefrom (array, optional) A json array with 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.\n"
- " [\n"
- " \"address\" (string) Subtract fee from this address\n"
- " ,...\n"
- " ]\n"
- "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
- "7. conf_target (numeric, optional) Confirmation target (in blocks)\n"
- "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
- " \"UNSET\"\n"
- " \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\"\n"
- "\nResult:\n"
- "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
- " the number of addresses.\n"
- "\nExamples:\n"
- "\nSend two amounts to two different addresses:\n"
- + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
- "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
- + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
- "\nSend two amounts to two different addresses, subtract fee from amount:\n"
- + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
- "\nAs a json rpc call\n"
- + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"");
- } else {
- help_text = "sendmany \"\" \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] replaceable conf_target \"estimate_mode\")\n"
- "\nSend multiple times. Amounts are double-precision floating point numbers."
- + HelpRequiringPassphrase(pwallet) + "\n"
- "\nArguments:\n"
- "1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
- "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
- " {\n"
- " \"address\":amount (numeric or string) The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n"
- " ,...\n"
- " }\n"
- "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
- "4. \"comment\" (string, optional) A comment\n"
- "5. subtractfeefrom (array, optional) A json array with addresses.\n"
+ const RPCHelpMan help{"sendmany",
+ "\nSend multiple times. Amounts are double-precision floating point numbers." +
+ HelpRequiringPassphrase(pwallet) + "\n",
+ {
+ {"dummy", RPCArg::Type::STR, RPCArg::Optional::NO, "Must be set to \"\" for backwards compatibility.", "\"\""},
+ {"amounts", RPCArg::Type::OBJ, RPCArg::Optional::NO, "A json object with 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, "A json array with 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.\n"
- " [\n"
- " \"address\" (string) Subtract fee from this address\n"
- " ,...\n"
- " ]\n"
- "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
- "7. conf_target (numeric, optional) Confirmation target (in blocks)\n"
- "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
+ " If no addresses are specified here, the sender pays the fee.",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Subtract fee from this address"},
+ },
+ },
+ {"replaceable", RPCArg::Type::BOOL, /* default */ "fallback to wallet's default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "fallback to wallet's default", "Confirmation target (in blocks)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
" \"UNSET\"\n"
" \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\"\n"
- "\nResult:\n"
+ " \"CONSERVATIVE\""},
+ },
+ RPCResult{
"\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
" the number of addresses.\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nSend two amounts to two different addresses:\n"
+ HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
"\nSend two amounts to two different addresses setting the confirmation and comment:\n"
+ HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
"\nSend two amounts to two different addresses, subtract fee from amount:\n"
+ HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
- "\nAs a json rpc call\n"
- + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"");
- }
+ "\nAs a JSON-RPC call\n"
+ + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"")
+ },
+ };
- if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) throw std::runtime_error(help_text);
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
+ }
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- if (pwallet->GetBroadcastTransactions() && !g_connman) {
+ if (pwallet->GetBroadcastTransactions() && !pwallet->chain().p2pEnabled()) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
}
- if (!IsDeprecatedRPCEnabled("accounts") && !request.params[0].get_str().empty()) {
+ if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\"");
}
- std::string strAccount = LabelFromValue(request.params[0]);
UniValue sendTo = request.params[1].get_obj();
- int nMinDepth = 1;
- if (!request.params[2].isNull())
- nMinDepth = request.params[2].get_int();
mapValue_t mapValue;
if (!request.params[3].isNull() && !request.params[3].get_str().empty())
@@ -1237,7 +889,7 @@ static UniValue sendmany(const JSONRPCRequest& request)
}
if (!request.params[6].isNull()) {
- coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]);
+ coin_control.m_confirm_target = ParseConfirmTarget(request.params[6], pwallet->chain().estimateMaxBlocks());
}
if (!request.params[7].isNull()) {
@@ -1249,7 +901,6 @@ static UniValue sendmany(const JSONRPCRequest& request)
std::set<CTxDestination> destinations;
std::vector<CRecipient> vecSend;
- CAmount totalAmount = 0;
std::vector<std::string> keys = sendTo.getKeys();
for (const std::string& name_ : keys) {
CTxDestination dest = DecodeDestination(name_);
@@ -1266,7 +917,6 @@ static UniValue sendmany(const JSONRPCRequest& request)
CAmount nAmount = AmountFromValue(sendTo[name_]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
- totalAmount += nAmount;
bool fSubtractFeeFromAmount = false;
for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
@@ -1281,13 +931,6 @@ static UniValue sendmany(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
- // Check funds
- if (IsDeprecatedRPCEnabled("accounts") && totalAmount > pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount)) {
- throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
- } else if (!IsDeprecatedRPCEnabled("accounts") && totalAmount > pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, nullptr)) {
- throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Wallet has insufficient funds");
- }
-
// Shuffle recipient list
std::shuffle(vecSend.begin(), vecSend.end(), FastRandomContext());
@@ -1297,11 +940,11 @@ static UniValue sendmany(const JSONRPCRequest& request)
int nChangePosRet = -1;
std::string strFailReason;
CTransactionRef tx;
- bool fCreated = pwallet->CreateTransaction(vecSend, tx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
+ bool fCreated = pwallet->CreateTransaction(*locked_chain, vecSend, tx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
CValidationState state;
- if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, std::move(strAccount), keyChange, g_connman.get(), state)) {
+ if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, keyChange, state)) {
strFailReason = strprintf("Transaction commit failed:: %s", FormatStateMessage(state));
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
}
@@ -1319,38 +962,41 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
}
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
- std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"label\" \"address_type\" )\n"
- "\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
- "Each key is a Bitcoin address or hex-encoded public key.\n"
- "This functionality is only intended for use with non-watchonly addresses.\n"
- "See `importaddress` for watchonly p2sh address support.\n"
- "If 'label' is specified, assign address to that label.\n"
-
- "\nArguments:\n"
- "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
- "2. \"keys\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
- " [\n"
- " \"address\" (string) bitcoin address or hex-encoded public key\n"
- " ...,\n"
- " ]\n"
- "3. \"label\" (string, optional) A label to assign the addresses to.\n"
- "4. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n"
-
- "\nResult:\n"
+ std::string msg =
+ RPCHelpMan{"addmultisigaddress",
+ "\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
+ "Each key is a Bitcoin address or hex-encoded public key.\n"
+ "This functionality is only intended for use with non-watchonly addresses.\n"
+ "See `importaddress` for watchonly p2sh address support.\n"
+ "If 'label' is specified, assign address to that label.\n",
+ {
+ {"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys or addresses."},
+ {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of bitcoin addresses or hex-encoded public keys",
+ {
+ {"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."},
+ {"address_type", RPCArg::Type::STR, /* default */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ },
+ RPCResult{
"{\n"
" \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
" \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
"}\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nAdd a multisig address from 2 addresses\n"
+ HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
- "\nAs json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
- ;
+ },
+ }.ToString();
throw std::runtime_error(msg);
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
std::string label;
if (!request.params[2].isNull())
@@ -1387,146 +1033,18 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
return result;
}
-class Witnessifier : public boost::static_visitor<bool>
-{
-public:
- CWallet * const pwallet;
- CTxDestination result;
- bool already_witness;
-
- explicit Witnessifier(CWallet *_pwallet) : pwallet(_pwallet), already_witness(false) {}
-
- bool operator()(const CKeyID &keyID) {
- if (pwallet) {
- CScript basescript = GetScriptForDestination(keyID);
- CScript witscript = GetScriptForWitness(basescript);
- if (!IsSolvable(*pwallet, witscript)) {
- return false;
- }
- return ExtractDestination(witscript, result);
- }
- return false;
- }
-
- bool operator()(const CScriptID &scriptID) {
- CScript subscript;
- if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
- int witnessversion;
- std::vector<unsigned char> witprog;
- if (subscript.IsWitnessProgram(witnessversion, witprog)) {
- ExtractDestination(subscript, result);
- already_witness = true;
- return true;
- }
- CScript witscript = GetScriptForWitness(subscript);
- if (!IsSolvable(*pwallet, witscript)) {
- return false;
- }
- return ExtractDestination(witscript, result);
- }
- return false;
- }
-
- bool operator()(const WitnessV0KeyHash& id)
- {
- already_witness = true;
- result = id;
- return true;
- }
-
- bool operator()(const WitnessV0ScriptHash& id)
- {
- already_witness = true;
- result = id;
- return true;
- }
-
- template<typename T>
- bool operator()(const T& dest) { return false; }
-};
-
-static UniValue addwitnessaddress(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
- {
- std::string msg = "addwitnessaddress \"address\" ( p2sh )\n"
- "\nDEPRECATED: set the address_type argument of getnewaddress, or option -addresstype=[bech32|p2sh-segwit] instead.\n"
- "Add a witness address for a script (with pubkey or redeemscript known). Requires a new wallet backup.\n"
- "It returns the witness script.\n"
-
- "\nArguments:\n"
- "1. \"address\" (string, required) An address known to the wallet\n"
- "2. p2sh (bool, optional, default=true) Embed inside P2SH\n"
-
- "\nResult:\n"
- "\"witnessaddress\", (string) The value of the new address (P2SH or BIP173).\n"
- "}\n"
- ;
- throw std::runtime_error(msg);
- }
-
- if (!IsDeprecatedRPCEnabled("addwitnessaddress")) {
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "addwitnessaddress is deprecated and will be fully removed in v0.17. "
- "To use addwitnessaddress in v0.16, restart bitcoind with -deprecatedrpc=addwitnessaddress.\n"
- "Projects should transition to using the address_type argument of getnewaddress, or option -addresstype=[bech32|p2sh-segwit] instead.\n");
- }
-
- CTxDestination dest = DecodeDestination(request.params[0].get_str());
- if (!IsValidDestination(dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
- }
-
- bool p2sh = true;
- if (!request.params[1].isNull()) {
- p2sh = request.params[1].get_bool();
- }
-
- Witnessifier w(pwallet);
- bool ret = boost::apply_visitor(w, dest);
- if (!ret) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
- }
-
- CScript witprogram = GetScriptForDestination(w.result);
-
- if (p2sh) {
- w.result = CScriptID(witprogram);
- }
-
- if (w.already_witness) {
- if (!(dest == w.result)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Cannot convert between witness address types");
- }
- } else {
- pwallet->AddCScript(witprogram); // Implicit for single-key now, but necessary for multisig and for compatibility with older software
- pwallet->SetAddressBook(w.result, "", "receive");
- }
-
- return EncodeDestination(w.result);
-}
-
struct tallyitem
{
- CAmount nAmount;
- int nConf;
+ CAmount nAmount{0};
+ int nConf{std::numeric_limits<int>::max()};
std::vector<uint256> txids;
- bool fIsWatchonly;
+ bool fIsWatchonly{false};
tallyitem()
{
- nAmount = 0;
- nConf = std::numeric_limits<int>::max();
- fIsWatchonly = false;
}
};
-static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label)
+static UniValue ListReceived(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
// Minimum confirmations
int nMinDepth = 1;
@@ -1558,10 +1076,11 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
const CWalletTx& wtx = pairWtx.second;
- if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
+ if (wtx.IsCoinBase() || !locked_chain.checkFinalTx(*wtx.tx)) {
continue;
+ }
- int nDepth = wtx.GetDepthInMainChain();
+ int nDepth = wtx.GetDepthInMainChain(locked_chain);
if (nDepth < nMinDepth)
continue;
@@ -1635,7 +1154,6 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
if(fIsWatchonly)
obj.pushKV("involvesWatchonly", true);
obj.pushKV("address", EncodeDestination(address));
- obj.pushKV("account", label);
obj.pushKV("amount", ValueFromAmount(nAmount));
obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
obj.pushKV("label", label);
@@ -1661,7 +1179,6 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
UniValue obj(UniValue::VOBJ);
if (entry.second.fIsWatchonly)
obj.pushKV("involvesWatchonly", true);
- obj.pushKV("account", entry.first);
obj.pushKV("amount", ValueFromAmount(nAmount));
obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
obj.pushKV("label", entry.first);
@@ -1683,19 +1200,19 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 4)
throw std::runtime_error(
- "listreceivedbyaddress ( minconf include_empty include_watchonly address_filter )\n"
- "\nList balances by receiving address.\n"
- "\nArguments:\n"
- "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
- "2. include_empty (bool, optional, default=false) Whether to include addresses that haven't received any payments.\n"
- "3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
- "4. address_filter (string, optional) If present, only return information on this address.\n"
- "\nResult:\n"
+ RPCHelpMan{"listreceivedbyaddress",
+ "\nList balances by receiving address.\n",
+ {
+ {"minconf", RPCArg::Type::NUM, /* default */ "1", "The minimum number of confirmations before payments are included."},
+ {"include_empty", RPCArg::Type::BOOL, /* default */ "false", "Whether to include addresses that haven't received any payments."},
+ {"include_watchonly", RPCArg::Type::BOOL, /* default */ "false", "Whether to include watch-only addresses (see 'importaddress')."},
+ {"address_filter", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If present, only return information on this address."},
+ },
+ RPCResult{
"[\n"
" {\n"
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
" \"address\" : \"receivingaddress\", (string) The receiving address\n"
- " \"account\" : \"accountname\", (string) DEPRECATED. Backwards compatible alias for label.\n"
" \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
" \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
" \"label\" : \"label\", (string) The label of the receiving address. The default label is \"\".\n"
@@ -1706,21 +1223,23 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
" }\n"
" ,...\n"
"]\n"
-
- "\nExamples:\n"
- + HelpExampleCli("listreceivedbyaddress", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listreceivedbyaddress", "")
+ HelpExampleCli("listreceivedbyaddress", "6 true")
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true")
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- return ListReceived(pwallet, request.params, false);
+ return ListReceived(*locked_chain, pwallet, request.params, false);
}
static UniValue listreceivedbylabel(const JSONRPCRequest& request)
@@ -1732,47 +1251,41 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request)
return NullUniValue;
}
- if (!IsDeprecatedRPCEnabled("accounts") && request.strMethod == "listreceivedbyaccount") {
- if (request.fHelp) {
- throw std::runtime_error("listreceivedbyaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "listreceivedbyaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
if (request.fHelp || request.params.size() > 3)
throw std::runtime_error(
- "listreceivedbylabel ( minconf include_empty include_watchonly)\n"
- "\nList received transactions by label.\n"
- "\nArguments:\n"
- "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
- "2. include_empty (bool, optional, default=false) Whether to include labels that haven't received any payments.\n"
- "3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
-
- "\nResult:\n"
+ RPCHelpMan{"listreceivedbylabel",
+ "\nList received transactions by label.\n",
+ {
+ {"minconf", RPCArg::Type::NUM, /* default */ "1", "The minimum number of confirmations before payments are included."},
+ {"include_empty", RPCArg::Type::BOOL, /* default */ "false", "Whether to include labels that haven't received any payments."},
+ {"include_watchonly", RPCArg::Type::BOOL, /* default */ "false", "Whether to include watch-only addresses (see 'importaddress')."},
+ },
+ RPCResult{
"[\n"
" {\n"
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
- " \"account\" : \"accountname\", (string) DEPRECATED. Backwards compatible alias for label.\n"
" \"amount\" : x.xxx, (numeric) The total amount received by addresses with this label\n"
" \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
" \"label\" : \"label\" (string) The label of the receiving address. The default label is \"\".\n"
" }\n"
" ,...\n"
"]\n"
-
- "\nExamples:\n"
- + HelpExampleCli("listreceivedbylabel", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listreceivedbylabel", "")
+ HelpExampleCli("listreceivedbylabel", "6 true")
+ HelpExampleRpc("listreceivedbylabel", "6, true, true")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- return ListReceived(pwallet, request.params, true);
+ return ListReceived(*locked_chain, pwallet, request.params, true);
}
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
@@ -1785,28 +1298,26 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
/**
* List transactions based on the given criteria.
*
- * @param pwallet The wallet.
- * @param wtx The wallet transaction.
- * @param strAccount The account, if any, or "*" for all.
- * @param nMinDepth The minimum confirmation depth.
- * @param fLong Whether to include the JSON version of the transaction.
- * @param ret The UniValue into which the result is stored.
- * @param filter The "is mine" filter bool.
+ * @param pwallet The wallet.
+ * @param wtx The wallet transaction.
+ * @param nMinDepth The minimum confirmation depth.
+ * @param fLong Whether to include the JSON version of the transaction.
+ * @param ret The UniValue into which the result is stored.
+ * @param filter_ismine The "is mine" filter flags.
+ * @param filter_label Optional label string to filter incoming transactions.
*/
-static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
+static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
CAmount nFee;
- std::string strSentAccount;
std::list<COutputEntry> listReceived;
std::list<COutputEntry> listSent;
- wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
+ wtx.GetAmounts(listReceived, listSent, nFee, filter_ismine);
- bool fAllAccounts = (strAccount == std::string("*"));
bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
// Sent
- if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
+ if (!filter_label)
{
for (const COutputEntry& s : listSent)
{
@@ -1814,7 +1325,6 @@ static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const
if (involvesWatchonly || (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY)) {
entry.pushKV("involvesWatchonly", true);
}
- if (IsDeprecatedRPCEnabled("accounts")) entry.pushKV("account", strSentAccount);
MaybePushAddress(entry, s.destination);
entry.pushKV("category", "send");
entry.pushKV("amount", ValueFromAmount(-s.amount));
@@ -1824,72 +1334,54 @@ static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const
entry.pushKV("vout", s.vout);
entry.pushKV("fee", ValueFromAmount(-nFee));
if (fLong)
- WalletTxToJSON(wtx, entry);
+ WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry);
entry.pushKV("abandoned", wtx.isAbandoned());
ret.push_back(entry);
}
}
// Received
- if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+ if (listReceived.size() > 0 && wtx.GetDepthInMainChain(locked_chain) >= nMinDepth)
{
for (const COutputEntry& r : listReceived)
{
- std::string account;
+ std::string label;
if (pwallet->mapAddressBook.count(r.destination)) {
- account = pwallet->mapAddressBook[r.destination].name;
+ label = pwallet->mapAddressBook[r.destination].name;
}
- if (fAllAccounts || (account == strAccount))
+ if (filter_label && label != *filter_label) {
+ continue;
+ }
+ UniValue entry(UniValue::VOBJ);
+ if (involvesWatchonly || (::IsMine(*pwallet, r.destination) & ISMINE_WATCH_ONLY)) {
+ entry.pushKV("involvesWatchonly", true);
+ }
+ MaybePushAddress(entry, r.destination);
+ if (wtx.IsCoinBase())
{
- UniValue entry(UniValue::VOBJ);
- if (involvesWatchonly || (::IsMine(*pwallet, r.destination) & ISMINE_WATCH_ONLY)) {
- entry.pushKV("involvesWatchonly", true);
- }
- if (IsDeprecatedRPCEnabled("accounts")) entry.pushKV("account", account);
- MaybePushAddress(entry, r.destination);
- if (wtx.IsCoinBase())
- {
- if (wtx.GetDepthInMainChain() < 1)
- entry.pushKV("category", "orphan");
- else if (wtx.GetBlocksToMaturity() > 0)
- entry.pushKV("category", "immature");
- else
- entry.pushKV("category", "generate");
- }
+ if (wtx.GetDepthInMainChain(locked_chain) < 1)
+ entry.pushKV("category", "orphan");
+ else if (wtx.IsImmatureCoinBase(locked_chain))
+ entry.pushKV("category", "immature");
else
- {
- entry.pushKV("category", "receive");
- }
- entry.pushKV("amount", ValueFromAmount(r.amount));
- if (pwallet->mapAddressBook.count(r.destination)) {
- entry.pushKV("label", account);
- }
- entry.pushKV("vout", r.vout);
- if (fLong)
- WalletTxToJSON(wtx, entry);
- ret.push_back(entry);
+ entry.pushKV("category", "generate");
}
+ else
+ {
+ entry.pushKV("category", "receive");
+ }
+ entry.pushKV("amount", ValueFromAmount(r.amount));
+ if (pwallet->mapAddressBook.count(r.destination)) {
+ entry.pushKV("label", label);
+ }
+ entry.pushKV("vout", r.vout);
+ if (fLong)
+ WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry);
+ ret.push_back(entry);
}
}
}
-static void AcentryToJSON(const CAccountingEntry& acentry, const std::string& strAccount, UniValue& ret)
-{
- bool fAllAccounts = (strAccount == std::string("*"));
-
- if (fAllAccounts || acentry.strAccount == strAccount)
- {
- UniValue entry(UniValue::VOBJ);
- entry.pushKV("account", acentry.strAccount);
- entry.pushKV("category", "move");
- entry.pushKV("time", acentry.nTime);
- entry.pushKV("amount", ValueFromAmount(acentry.nCreditDebit));
- if (IsDeprecatedRPCEnabled("accounts")) entry.pushKV("otheraccount", acentry.strOtherAccount);
- entry.pushKV("comment", acentry.strComment);
- ret.push_back(entry);
- }
-}
-
UniValue listtransactions(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -1899,24 +1391,30 @@ UniValue listtransactions(const JSONRPCRequest& request)
return NullUniValue;
}
- std::string help_text {};
- if (!IsDeprecatedRPCEnabled("accounts")) {
- help_text = "listtransactions (dummy count skip include_watchonly)\n"
- "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
- "Note that the \"account\" argument and \"otheraccount\" return value have been removed in V0.17. To use this RPC with an \"account\" argument, restart\n"
- "bitcoind with -deprecatedrpc=accounts\n"
- "\nArguments:\n"
- "1. \"dummy\" (string, optional) If set, should be \"*\" for backwards compatibility.\n"
- "2. count (numeric, optional, default=10) The number of transactions to return\n"
- "3. skip (numeric, optional, default=0) The number of transactions to skip\n"
- "4. include_watchonly (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
- "\nResult:\n"
+ if (request.fHelp || request.params.size() > 4)
+ throw std::runtime_error(
+ 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", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "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, /* default */ "10", "The number of transactions to return"},
+ {"skip", RPCArg::Type::NUM, /* default */ "0", "The number of transactions to skip"},
+ {"include_watchonly", RPCArg::Type::BOOL, /* default */ "false", "Include transactions to watch-only addresses (see 'importaddress')"},
+ },
+ RPCResult{
"[\n"
" {\n"
" \"address\":\"address\", (string) The bitcoin address of the transaction.\n"
- " \"category\":\"send|receive\", (string) The transaction category.\n"
+ " \"category\": (string) The transaction category.\n"
+ " \"send\" Transactions sent.\n"
+ " \"receive\" Non-coinbase transactions received.\n"
+ " \"generate\" Coinbase transactions received with more than 100 confirmations.\n"
+ " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
+ " \"orphan\" Orphaned coinbase transactions received.\n"
" \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
- " for the 'receive' category,\n"
+ " for all other categories\n"
" \"label\": \"label\", (string) A comment for the address/transaction, if any\n"
" \"vout\": n, (numeric) the vout value\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
@@ -1937,83 +1435,26 @@ UniValue listtransactions(const JSONRPCRequest& request)
" 'send' category of transactions.\n"
" }\n"
"]\n"
-
- "\nExamples:\n"
- "\nList the most recent 10 transactions in the systems\n"
- + HelpExampleCli("listtransactions", "") +
- "\nList transactions 100 to 120\n"
- + HelpExampleCli("listtransactions", "\"*\" 20 100") +
- "\nAs a json rpc call\n"
- + HelpExampleRpc("listtransactions", "\"*\", 20, 100");
- } else {
- help_text = "listtransactions ( \"account\" count skip include_watchonly)\n"
- "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
- "\nArguments:\n"
- "1. \"account\" (string, optional) DEPRECATED. This argument will be removed in V0.18. The account name. Should be \"*\".\n"
- "2. count (numeric, optional, default=10) The number of transactions to return\n"
- "3. skip (numeric, optional, default=0) The number of transactions to skip\n"
- "4. include_watchonly (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
- "\nResult:\n"
- "[\n"
- " {\n"
- " \"account\":\"accountname\", (string) DEPRECATED. This field will be removed in V0.18. The account name associated with the transaction. \n"
- " It will be \"\" for the default account.\n"
- " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for \n"
- " move transactions (category = move).\n"
- " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
- " transaction between accounts, and not associated with an address,\n"
- " transaction id or block. 'send' and 'receive' transactions are \n"
- " associated with an address, transaction id and block details\n"
- " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
- " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
- " and for the 'move' category for inbound funds.\n"
- " \"label\": \"label\", (string) A comment for the address/transaction, if any\n"
- " \"vout\": n, (numeric) the vout value\n"
- " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
- " 'send' category of transactions.\n"
- " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
- " 'receive' category of transactions. Negative confirmations indicate the\n"
- " transaction conflicts with the block chain\n"
- " \"trusted\": xxx, (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
- " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
- " category of transactions.\n"
- " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive'\n"
- " category of transactions.\n"
- " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
- " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
- " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
- " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
- " for 'send' and 'receive' category of transactions.\n"
- " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
- " \"otheraccount\": \"accountname\", (string) DEPRECATED. This field will be removed in V0.18. For the 'move' category of transactions, the account the funds came \n"
- " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
- " negative amounts).\n"
- " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
- " may be unknown for unconfirmed transactions not in the mempool\n"
- " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
- " 'send' category of transactions.\n"
- " }\n"
- "]\n"
-
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nList the most recent 10 transactions in the systems\n"
+ HelpExampleCli("listtransactions", "") +
"\nList transactions 100 to 120\n"
+ HelpExampleCli("listtransactions", "\"*\" 20 100") +
- "\nAs a json rpc call\n"
- + HelpExampleRpc("listtransactions", "\"*\", 20, 100");
- }
- if (request.fHelp || request.params.size() > 4) throw std::runtime_error(help_text);
+ "\nAs a JSON-RPC call\n"
+ + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- std::string strAccount = "*";
- if (!request.params[0].isNull()) {
- strAccount = request.params[0].get_str();
- if (!IsDeprecatedRPCEnabled("accounts") && strAccount != "*") {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"*\"");
+ const std::string* filter_label = nullptr;
+ if (!request.params[0].isNull() && request.params[0].get_str() != "*") {
+ filter_label = &request.params[0].get_str();
+ if (filter_label->empty()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Label argument must be a valid label name or \"*\".");
}
}
int nCount = 10;
@@ -2035,21 +1476,16 @@ UniValue listtransactions(const JSONRPCRequest& request)
UniValue ret(UniValue::VARR);
{
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
// iterate backwards until we have nCount items to return:
for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
- CWalletTx *const pwtx = (*it).second.first;
- if (pwtx != nullptr)
- ListTransactions(pwallet, *pwtx, strAccount, 0, true, ret, filter);
- if (IsDeprecatedRPCEnabled("accounts")) {
- CAccountingEntry *const pacentry = (*it).second.second;
- if (pacentry != nullptr) AcentryToJSON(*pacentry, strAccount, ret);
- }
-
+ CWalletTx *const pwtx = (*it).second;
+ ListTransactions(*locked_chain, pwallet, *pwtx, 0, true, ret, filter, filter_label);
if ((int)ret.size() >= (nCount+nFrom)) break;
}
}
@@ -2080,101 +1516,6 @@ UniValue listtransactions(const JSONRPCRequest& request)
return ret;
}
-static UniValue listaccounts(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (!IsDeprecatedRPCEnabled("accounts")) {
- if (request.fHelp) {
- throw std::runtime_error("listaccounts (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
- }
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "listaccounts is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
- }
-
- if (request.fHelp || request.params.size() > 2)
- throw std::runtime_error(
- "listaccounts ( minconf include_watchonly)\n"
- "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
- "\nArguments:\n"
- "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
- "2. include_watchonly (bool, optional, default=false) Include balances in watch-only addresses (see 'importaddress')\n"
- "\nResult:\n"
- "{ (json object where keys are account names, and values are numeric balances\n"
- " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
- " ...\n"
- "}\n"
- "\nExamples:\n"
- "\nList account balances where there at least 1 confirmation\n"
- + HelpExampleCli("listaccounts", "") +
- "\nList account balances including zero confirmation transactions\n"
- + HelpExampleCli("listaccounts", "0") +
- "\nList account balances for 6 or more confirmations\n"
- + HelpExampleCli("listaccounts", "6") +
- "\nAs json rpc call\n"
- + HelpExampleRpc("listaccounts", "6")
- );
-
- // Make sure the results are valid at least up to the most recent block
- // the user could have gotten from another RPC command prior to now
- pwallet->BlockUntilSyncedToCurrentChain();
-
- LOCK2(cs_main, pwallet->cs_wallet);
-
- int nMinDepth = 1;
- if (!request.params[0].isNull())
- nMinDepth = request.params[0].get_int();
- isminefilter includeWatchonly = ISMINE_SPENDABLE;
- if(!request.params[1].isNull())
- if(request.params[1].get_bool())
- includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
-
- std::map<std::string, CAmount> mapAccountBalances;
- for (const std::pair<const CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
- if (IsMine(*pwallet, entry.first) & includeWatchonly) { // This address belongs to me
- mapAccountBalances[entry.second.name] = 0;
- }
- }
-
- for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
- const CWalletTx& wtx = pairWtx.second;
- CAmount nFee;
- std::string strSentAccount;
- std::list<COutputEntry> listReceived;
- std::list<COutputEntry> listSent;
- int nDepth = wtx.GetDepthInMainChain();
- if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
- continue;
- wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
- mapAccountBalances[strSentAccount] -= nFee;
- for (const COutputEntry& s : listSent)
- mapAccountBalances[strSentAccount] -= s.amount;
- if (nDepth >= nMinDepth)
- {
- for (const COutputEntry& r : listReceived)
- if (pwallet->mapAddressBook.count(r.destination)) {
- mapAccountBalances[pwallet->mapAddressBook[r.destination].name] += r.amount;
- }
- else
- mapAccountBalances[""] += r.amount;
- }
- }
-
- const std::list<CAccountingEntry>& acentries = pwallet->laccentries;
- for (const CAccountingEntry& entry : acentries)
- mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
-
- UniValue ret(UniValue::VOBJ);
- for (const std::pair<const std::string, CAmount>& accountBalance : mapAccountBalances) {
- ret.pushKV(accountBalance.first, ValueFromAmount(accountBalance.second));
- }
- return ret;
-}
-
static UniValue listsinceblock(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -2186,34 +1527,39 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 4)
throw std::runtime_error(
- "listsinceblock ( \"blockhash\" target_confirmations include_watchonly include_removed )\n"
- "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n"
- "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"
- "\nArguments:\n"
- "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
- "2. target_confirmations: (numeric, optional, 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\n"
- "3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
- "4. include_removed: (bool, optional, default=true) Show transactions that were removed due to a reorg in the \"removed\" array\n"
- " (not guaranteed to work on pruned nodes)\n"
- "\nResult:\n"
+ RPCHelpMan{"listsinceblock",
+ "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n"
+ "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."},
+ {"target_confirmations", RPCArg::Type::NUM, /* 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, /* default */ "false", "Include transactions to watch-only addresses (see 'importaddress')"},
+ {"include_removed", RPCArg::Type::BOOL, /* default */ "true", "Show transactions that were removed due to a reorg in the \"removed\" array\n"
+ " (not guaranteed to work on pruned nodes)"},
+ },
+ RPCResult{
"{\n"
" \"transactions\": [\n"
- " \"account\":\"accountname\", (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account name associated with the transaction. Will be \"\" for the default account.\n"
- " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
- " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
- " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
- " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
+ " \"address\":\"address\", (string) The bitcoin address of the transaction.\n"
+ " \"category\": (string) The transaction category.\n"
+ " \"send\" Transactions sent.\n"
+ " \"receive\" Non-coinbase transactions received.\n"
+ " \"generate\" Coinbase transactions received with more than 100 confirmations.\n"
+ " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
+ " \"orphan\" Orphaned coinbase transactions received.\n"
+ " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"
+ " for all other categories\n"
" \"vout\" : n, (numeric) the vout value\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n"
- " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
+ " \"confirmations\": n, (numeric) The number of confirmations for the transaction.\n"
" When it's < 0, it means the transaction conflicted that many blocks ago.\n"
- " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
- " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive' category of transactions.\n"
+ " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction.\n"
+ " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it.\n"
" \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
- " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
+ " \"txid\": \"transactionid\", (string) The transaction id.\n"
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
- " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
+ " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT).\n"
" \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
" may be unknown for unconfirmed transactions not in the mempool\n"
" \"abandoned\": xxx, (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.\n"
@@ -2227,37 +1573,34 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
" ],\n"
" \"lastblock\": \"lastblockhash\" (string) The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("listsinceblock", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listsinceblock", "")
+ HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
+ HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- const CBlockIndex* pindex = nullptr; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
- const CBlockIndex* paltindex = nullptr; // Block index of the specified block, even if it's in a deactivated chain.
+ // The way the 'height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
+ Optional<int> height = MakeOptional(false, int()); // Height of the specified block or the common ancestor, if the block provided was in a deactivated chain.
+ Optional<int> altheight; // Height of the specified block, even if it's in a deactivated chain.
int target_confirms = 1;
isminefilter filter = ISMINE_SPENDABLE;
+ uint256 blockId;
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
- uint256 blockId;
-
- blockId.SetHex(request.params[0].get_str());
- paltindex = pindex = LookupBlockIndex(blockId);
- if (!pindex) {
+ blockId = ParseHashV(request.params[0], "blockhash");
+ height = locked_chain->findFork(blockId, &altheight);
+ if (!height) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
- if (chainActive[pindex->nHeight] != pindex) {
- // the block being asked for is a part of a deactivated chain;
- // we don't want to depend on its perceived height in the block
- // chain, we want to instead use the last common ancestor
- pindex = chainActive.FindFork(pindex);
- }
}
if (!request.params[1].isNull()) {
@@ -2274,24 +1617,25 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
- int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
+ const Optional<int> tip_height = locked_chain->getHeight();
+ int depth = tip_height && height ? (1 + *tip_height - *height) : -1;
UniValue transactions(UniValue::VARR);
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
CWalletTx tx = pairWtx.second;
- if (depth == -1 || tx.GetDepthInMainChain() < depth) {
- ListTransactions(pwallet, tx, "*", 0, true, transactions, filter);
+ if (depth == -1 || tx.GetDepthInMainChain(*locked_chain) < depth) {
+ ListTransactions(*locked_chain, pwallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
}
}
// when a reorg'd block is requested, we also list any relevant transactions
// in the blocks of the chain that was detached
UniValue removed(UniValue::VARR);
- while (include_removed && paltindex && paltindex != pindex) {
+ while (include_removed && altheight && *altheight > *height) {
CBlock block;
- if (!ReadBlockFromDisk(block, paltindex, Params().GetConsensus())) {
+ if (!pwallet->chain().findBlock(blockId, &block) || block.IsNull()) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
}
for (const CTransactionRef& tx : block.vtx) {
@@ -2299,14 +1643,15 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
if (it != pwallet->mapWallet.end()) {
// We want all transactions regardless of confirmation count to appear here,
// even negative confirmation ones, hence the big negative.
- ListTransactions(pwallet, it->second, "*", -100000000, true, removed, filter);
+ ListTransactions(*locked_chain, pwallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
}
}
- paltindex = paltindex->pprev;
+ blockId = block.hashPrevBlock;
+ --*altheight;
}
- CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
- uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
+ int last_height = tip_height ? *tip_height + 1 - target_confirms : -1;
+ uint256 lastblock = last_height >= 0 ? locked_chain->getBlockHash(last_height) : uint256();
UniValue ret(UniValue::VOBJ);
ret.pushKV("transactions", transactions);
@@ -2327,12 +1672,13 @@ static UniValue gettransaction(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "gettransaction \"txid\" ( include_watchonly )\n"
- "\nGet detailed information about in-wallet transaction <txid>\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The transaction id\n"
- "2. \"include_watchonly\" (bool, optional, default=false) Whether to include watch-only addresses in balance calculation and details[]\n"
- "\nResult:\n"
+ RPCHelpMan{"gettransaction",
+ "\nGet detailed information about in-wallet transaction <txid>\n",
+ {
+ {"txid", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction id"},
+ {"include_watchonly", RPCArg::Type::BOOL, /* default */ "false", "Whether to include watch-only addresses in balance calculation and details[]"},
+ },
+ RPCResult{
"{\n"
" \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
@@ -2348,9 +1694,13 @@ static UniValue gettransaction(const JSONRPCRequest& request)
" may be unknown for unconfirmed transactions not in the mempool\n"
" \"details\" : [\n"
" {\n"
- " \"account\" : \"accountname\", (string) DEPRECATED. This field will be removed in a V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account name involved in the transaction, can be \"\" for the default account.\n"
" \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n"
- " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
+ " \"category\" : (string) The transaction category.\n"
+ " \"send\" Transactions sent.\n"
+ " \"receive\" Non-coinbase transactions received.\n"
+ " \"generate\" Coinbase transactions received with more than 100 confirmations.\n"
+ " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"
+ " \"orphan\" Orphaned coinbase transactions received.\n"
" \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n"
" \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
" \"vout\" : n, (numeric) the vout value\n"
@@ -2363,21 +1713,22 @@ static UniValue gettransaction(const JSONRPCRequest& request)
" ],\n"
" \"hex\" : \"data\" (string) Raw data for transaction\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ },
+ RPCExamples{
+ HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
+ HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- uint256 hash;
- hash.SetHex(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "txid"));
isminefilter filter = ISMINE_SPENDABLE;
if(!request.params[1].isNull())
@@ -2391,7 +1742,7 @@ static UniValue gettransaction(const JSONRPCRequest& request)
}
const CWalletTx& wtx = it->second;
- CAmount nCredit = wtx.GetCredit(filter);
+ CAmount nCredit = wtx.GetCredit(*locked_chain, filter);
CAmount nDebit = wtx.GetDebit(filter);
CAmount nNet = nCredit - nDebit;
CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
@@ -2400,13 +1751,13 @@ static UniValue gettransaction(const JSONRPCRequest& request)
if (wtx.IsFromMe(filter))
entry.pushKV("fee", ValueFromAmount(nFee));
- WalletTxToJSON(wtx, entry);
+ WalletTxToJSON(pwallet->chain(), *locked_chain, wtx, entry);
UniValue details(UniValue::VARR);
- ListTransactions(pwallet, wtx, "*", 0, false, details, filter);
+ ListTransactions(*locked_chain, pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */);
entry.pushKV("details", details);
- std::string strHex = EncodeHexTx(*wtx.tx, RPCSerializationFlags());
+ std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
entry.pushKV("hex", strHex);
return entry;
@@ -2423,34 +1774,36 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
- "abandontransaction \"txid\"\n"
- "\nMark in-wallet transaction <txid> as abandoned\n"
- "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
- "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
- "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
- "It has no effect on transactions which are already abandoned.\n"
- "\nArguments:\n"
- "1. \"txid\" (string, required) The transaction id\n"
- "\nResult:\n"
- "\nExamples:\n"
- + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ RPCHelpMan{"abandontransaction",
+ "\nMark in-wallet transaction <txid> as abandoned\n"
+ "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
+ "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
+ "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
+ "It has no effect on transactions which are already abandoned.\n",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
- );
+ },
+ }.ToString());
}
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
- uint256 hash;
- hash.SetHex(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "txid"));
if (!pwallet->mapWallet.count(hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
}
- if (!pwallet->AbandonTransaction(hash)) {
+ if (!pwallet->AbandonTransaction(*locked_chain, hash)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
}
@@ -2469,20 +1822,24 @@ static UniValue backupwallet(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "backupwallet \"destination\"\n"
- "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n"
- "\nArguments:\n"
- "1. \"destination\" (string) The destination directory or file\n"
- "\nExamples:\n"
- + HelpExampleCli("backupwallet", "\"backup.dat\"")
+ RPCHelpMan{"backupwallet",
+ "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n",
+ {
+ {"destination", RPCArg::Type::STR, RPCArg::Optional::NO, "The destination directory or file"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("backupwallet", "\"backup.dat\"")
+ HelpExampleRpc("backupwallet", "\"backup.dat\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
std::string strDest = request.params[0].get_str();
if (!pwallet->BackupWallet(strDest)) {
@@ -2504,21 +1861,25 @@ static UniValue keypoolrefill(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
- "keypoolrefill ( newsize )\n"
- "\nFills the keypool."
- + HelpRequiringPassphrase(pwallet) + "\n"
- "\nArguments\n"
- "1. newsize (numeric, optional, default=100) The new keypool size\n"
- "\nExamples:\n"
- + HelpExampleCli("keypoolrefill", "")
+ RPCHelpMan{"keypoolrefill",
+ "\nFills the keypool."+
+ HelpRequiringPassphrase(pwallet) + "\n",
+ {
+ {"newsize", RPCArg::Type::NUM, /* default */ "100", "The new keypool size"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("keypoolrefill", "")
+ HelpExampleRpc("keypoolrefill", "")
- );
+ },
+ }.ToString());
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
// 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
unsigned int kpSize = 0;
@@ -2539,13 +1900,6 @@ static UniValue keypoolrefill(const JSONRPCRequest& request)
}
-static void LockWallet(CWallet* pWallet)
-{
- LOCK(pWallet->cs_wallet);
- pWallet->nRelockTime = 0;
- pWallet->Lock();
-}
-
static UniValue walletpassphrase(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -2557,26 +1911,30 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 2) {
throw std::runtime_error(
- "walletpassphrase \"passphrase\" timeout\n"
- "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
- "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
- "\nArguments:\n"
- "1. \"passphrase\" (string, required) The wallet passphrase\n"
- "2. timeout (numeric, required) The time to keep the decryption key in seconds; capped at 100000000 (~3 years).\n"
+ RPCHelpMan{"walletpassphrase",
+ "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
+ "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
"\nNote:\n"
"Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
- "time that overrides the old one.\n"
- "\nExamples:\n"
+ "time that overrides the old one.\n",
+ {
+ {"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet passphrase"},
+ {"timeout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The time to keep the decryption key in seconds; capped at 100000000 (~3 years)."},
+ },
+ RPCResults{},
+ RPCExamples{
"\nUnlock the wallet for 60 seconds\n"
+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
"\nLock the wallet again (before 60 seconds)\n"
+ HelpExampleCli("walletlock", "") +
- "\nAs json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
- );
+ },
+ }.ToString());
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
@@ -2601,21 +1959,29 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
nSleepTime = MAX_SLEEP_TIME;
}
- if (strWalletPass.length() > 0)
- {
- if (!pwallet->Unlock(strWalletPass)) {
- throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
- }
+ if (strWalletPass.empty()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
+ }
+
+ if (!pwallet->Unlock(strWalletPass)) {
+ throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
}
- else
- throw std::runtime_error(
- "walletpassphrase <passphrase> <timeout>\n"
- "Stores the wallet decryption key in memory for <timeout> seconds.");
pwallet->TopUpKeyPool();
pwallet->nRelockTime = GetTime() + nSleepTime;
- RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), std::bind(LockWallet, pwallet), nSleepTime);
+
+ // Keep a weak pointer to the wallet so that it is possible to unload the
+ // wallet before the following callback is called. If a valid shared pointer
+ // is acquired in the callback then the wallet is still loaded.
+ std::weak_ptr<CWallet> weak_wallet = wallet;
+ pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
+ if (auto shared_wallet = weak_wallet.lock()) {
+ LOCK(shared_wallet->cs_wallet);
+ shared_wallet->Lock();
+ shared_wallet->nRelockTime = 0;
+ }
+ }, nSleepTime);
return NullUniValue;
}
@@ -2632,18 +1998,22 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 2) {
throw std::runtime_error(
- "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
- "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
- "\nArguments:\n"
- "1. \"oldpassphrase\" (string) The current passphrase\n"
- "2. \"newpassphrase\" (string) The new passphrase\n"
- "\nExamples:\n"
- + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
+ RPCHelpMan{"walletpassphrasechange",
+ "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n",
+ {
+ {"oldpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The current passphrase"},
+ {"newpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The new passphrase"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
+ HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
- );
+ },
+ }.ToString());
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
@@ -2659,10 +2029,9 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request)
strNewWalletPass.reserve(100);
strNewWalletPass = request.params[1].get_str().c_str();
- if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
- throw std::runtime_error(
- "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
- "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
+ if (strOldWalletPass.empty() || strNewWalletPass.empty()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
+ }
if (!pwallet->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) {
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
@@ -2683,23 +2052,27 @@ static UniValue walletlock(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
- "walletlock\n"
- "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
- "After calling this method, you will need to call walletpassphrase again\n"
- "before being able to call any methods which require the wallet to be unlocked.\n"
- "\nExamples:\n"
+ RPCHelpMan{"walletlock",
+ "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
+ "After calling this method, you will need to call walletpassphrase again\n"
+ "before being able to call any methods which require the wallet to be unlocked.\n",
+ {},
+ RPCResults{},
+ RPCExamples{
"\nSet the passphrase for 2 minutes to perform a transaction\n"
+ HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
"\nPerform a send (requires passphrase set)\n"
+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
"\nClear the passphrase since we are done before 2 minutes is up\n"
+ HelpExampleCli("walletlock", "") +
- "\nAs json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("walletlock", "")
- );
+ },
+ }.ToString());
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (!pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
@@ -2723,16 +2096,17 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
- "encryptwallet \"passphrase\"\n"
- "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
- "After this, any calls that interact with private keys such as sending or signing \n"
- "will require the passphrase to be set prior the making these calls.\n"
- "Use the walletpassphrase call for this, and then walletlock call.\n"
- "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
- "Note that this will shutdown the server.\n"
- "\nArguments:\n"
- "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
- "\nExamples:\n"
+ RPCHelpMan{"encryptwallet",
+ "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
+ "After this, any calls that interact with private keys such as sending or signing \n"
+ "will require the passphrase to be set prior the making these calls.\n"
+ "Use the walletpassphrase call for this, and then walletlock call.\n"
+ "If the wallet is already encrypted, use the walletpassphrasechange call.\n",
+ {
+ {"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long."},
+ },
+ RPCResults{},
+ RPCExamples{
"\nEncrypt your wallet\n"
+ HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
"\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
@@ -2741,12 +2115,14 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
+ HelpExampleCli("signmessage", "\"address\" \"test message\"") +
"\nNow lock the wallet again by removing the passphrase\n"
+ HelpExampleCli("walletlock", "") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
- );
+ },
+ }.ToString());
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
if (pwallet->IsCrypted()) {
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
@@ -2758,20 +2134,15 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
strWalletPass.reserve(100);
strWalletPass = request.params[0].get_str().c_str();
- if (strWalletPass.length() < 1)
- throw std::runtime_error(
- "encryptwallet <passphrase>\n"
- "Encrypts the wallet with <passphrase>.");
+ if (strWalletPass.empty()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "passphrase can not be empty");
+ }
if (!pwallet->EncryptWallet(strWalletPass)) {
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
}
- // BDB seems to have a bad habit of writing old data into
- // slack space in .dat files; that is bad if the old data is
- // unencrypted private keys. So:
- StartShutdown();
- return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.";
+ return "wallet encrypted; The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.";
}
static UniValue lockunspent(const JSONRPCRequest& request)
@@ -2785,29 +2156,31 @@ static UniValue lockunspent(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n"
- "\nUpdates list of temporarily unspendable outputs.\n"
- "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
- "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
- "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
- "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
- "is always cleared (by virtue of process exit) when a node stops or fails.\n"
- "Also see the listunspent call\n"
- "\nArguments:\n"
- "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
- "2. \"transactions\" (string, optional) A json array of objects. Each object the txid (string) vout (numeric)\n"
- " [ (json array of json objects)\n"
- " {\n"
- " \"txid\":\"id\", (string) The transaction id\n"
- " \"vout\": n (numeric) The output number\n"
- " }\n"
- " ,...\n"
- " ]\n"
-
- "\nResult:\n"
+ RPCHelpMan{"lockunspent",
+ "\nUpdates list of temporarily unspendable outputs.\n"
+ "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
+ "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
+ "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
+ "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
+ "is always cleared (by virtue of process exit) when a node stops or fails.\n"
+ "Also see the listunspent call\n",
+ {
+ {"unlock", RPCArg::Type::BOOL, RPCArg::Optional::NO, "Whether to unlock (true) or lock (false) the specified transactions"},
+ {"transactions", RPCArg::Type::ARR, /* default */ "empty array", "A json array of objects. Each object the txid (string) vout (numeric).",
+ {
+ {"", 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 number"},
+ },
+ },
+ },
+ },
+ },
+ RPCResult{
"true|false (boolean) Whether the command was successful or not\n"
-
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nList the unspent transactions\n"
+ HelpExampleCli("listunspent", "") +
"\nLock an unspent transaction\n"
@@ -2816,15 +2189,17 @@ static UniValue lockunspent(const JSONRPCRequest& request)
+ HelpExampleCli("listlockunspent", "") +
"\nUnlock the transaction again\n"
+ HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
- );
+ },
+ }.ToString());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
RPCTypeCheckArgument(request.params[0], UniValue::VBOOL);
@@ -2854,17 +2229,13 @@ static UniValue lockunspent(const JSONRPCRequest& request)
{"vout", UniValueType(UniValue::VNUM)},
});
- const std::string& txid = find_value(o, "txid").get_str();
- if (!IsHex(txid)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
- }
-
+ const uint256 txid(ParseHashO(o, "txid"));
const int nOutput = find_value(o, "vout").get_int();
if (nOutput < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
}
- const COutPoint outpt(uint256S(txid), nOutput);
+ const COutPoint outpt(txid, nOutput);
const auto it = pwallet->mapWallet.find(outpt.hash);
if (it == pwallet->mapWallet.end()) {
@@ -2877,7 +2248,7 @@ static UniValue lockunspent(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
}
- if (pwallet->IsSpent(outpt.hash, outpt.n)) {
+ if (pwallet->IsSpent(*locked_chain, outpt.hash, outpt.n)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
}
@@ -2914,10 +2285,11 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 0)
throw std::runtime_error(
- "listlockunspent\n"
- "\nReturns list of temporarily unspendable outputs.\n"
- "See the lockunspent call to lock and unlock transactions for spending.\n"
- "\nResult:\n"
+ RPCHelpMan{"listlockunspent",
+ "\nReturns list of temporarily unspendable outputs.\n"
+ "See the lockunspent call to lock and unlock transactions for spending.\n",
+ {},
+ RPCResult{
"[\n"
" {\n"
" \"txid\" : \"transactionid\", (string) The transaction id locked\n"
@@ -2925,7 +2297,8 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
" }\n"
" ,...\n"
"]\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nList the unspent transactions\n"
+ HelpExampleCli("listunspent", "") +
"\nLock an unspent transaction\n"
@@ -2934,18 +2307,20 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
+ HelpExampleCli("listlockunspent", "") +
"\nUnlock the transaction again\n"
+ HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("listlockunspent", "")
- );
+ },
+ }.ToString());
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
std::vector<COutPoint> vOutpts;
pwallet->ListLockedCoins(vOutpts);
UniValue ret(UniValue::VARR);
- for (COutPoint &outpt : vOutpts) {
+ for (const COutPoint& outpt : vOutpts) {
UniValue o(UniValue::VOBJ);
o.pushKV("txid", outpt.hash.GetHex());
@@ -2967,26 +2342,100 @@ static UniValue settxfee(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 1) {
throw std::runtime_error(
- "settxfee amount\n"
- "\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n"
- "\nArguments:\n"
- "1. amount (numeric or string, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n"
- "\nResult\n"
+ RPCHelpMan{"settxfee",
+ "\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n",
+ {
+ {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kB"},
+ },
+ RPCResult{
"true|false (boolean) Returns true if successful\n"
- "\nExamples:\n"
- + HelpExampleCli("settxfee", "0.00001")
+ },
+ RPCExamples{
+ HelpExampleCli("settxfee", "0.00001")
+ HelpExampleRpc("settxfee", "0.00001")
- );
+ },
+ }.ToString());
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
CAmount nAmount = AmountFromValue(request.params[0]);
+ CFeeRate tx_fee_rate(nAmount, 1000);
+ if (tx_fee_rate == 0) {
+ // automatic selection
+ } else if (tx_fee_rate < pwallet->chain().relayMinFee()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", pwallet->chain().relayMinFee().ToString()));
+ } else if (tx_fee_rate < pwallet->m_min_fee) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than wallet min fee (%s)", pwallet->m_min_fee.ToString()));
+ }
- pwallet->m_pay_tx_fee = CFeeRate(nAmount, 1000);
+ pwallet->m_pay_tx_fee = tx_fee_rate;
return true;
}
+static UniValue getbalances(const JSONRPCRequest& request)
+{
+ std::shared_ptr<CWallet> const rpc_wallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(rpc_wallet.get(), request.fHelp)) {
+ return NullUniValue;
+ }
+ CWallet& wallet = *rpc_wallet;
+
+ const RPCHelpMan help{
+ "getbalances",
+ "Returns an object with all balances in " + CURRENCY_UNIT + ".\n",
+ {},
+ RPCResult{
+ "{\n"
+ " \"mine\": { (object) balances from outputs that the wallet can sign\n"
+ " \"trusted\": xxx (numeric) trusted balance (outputs created by the wallet or confirmed outputs)\n"
+ " \"untrusted_pending\": xxx (numeric) untrusted pending balance (outputs created by others that are in the mempool)\n"
+ " \"immature\": xxx (numeric) balance from immature coinbase outputs\n"
+ " },\n"
+ " \"watchonly\": { (object) watchonly balances (not present if wallet does not watch anything)\n"
+ " \"trusted\": xxx (numeric) trusted balance (outputs created by the wallet or confirmed outputs)\n"
+ " \"untrusted_pending\": xxx (numeric) untrusted pending balance (outputs created by others that are in the mempool)\n"
+ " \"immature\": xxx (numeric) balance from immature coinbase outputs\n"
+ " },\n"
+ "}\n"},
+ RPCExamples{
+ HelpExampleCli("getbalances", "") +
+ HelpExampleRpc("getbalances", "")},
+ };
+
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
+ }
+
+ // Make sure the results are valid at least up to the most recent block
+ // the user could have gotten from another RPC command prior to now
+ wallet.BlockUntilSyncedToCurrentChain();
+
+ auto locked_chain = wallet.chain().lock();
+ LOCK(wallet.cs_wallet);
+
+ UniValue obj(UniValue::VOBJ);
+
+ const auto bal = wallet.GetBalance();
+ UniValue balances{UniValue::VOBJ};
+ {
+ UniValue balances_mine{UniValue::VOBJ};
+ balances_mine.pushKV("trusted", ValueFromAmount(bal.m_mine_trusted));
+ balances_mine.pushKV("untrusted_pending", ValueFromAmount(bal.m_mine_untrusted_pending));
+ balances_mine.pushKV("immature", ValueFromAmount(bal.m_mine_immature));
+ balances.pushKV("mine", balances_mine);
+ }
+ if (wallet.HaveWatchOnly()) {
+ UniValue balances_watchonly{UniValue::VOBJ};
+ balances_watchonly.pushKV("trusted", ValueFromAmount(bal.m_watchonly_trusted));
+ balances_watchonly.pushKV("untrusted_pending", ValueFromAmount(bal.m_watchonly_untrusted_pending));
+ balances_watchonly.pushKV("immature", ValueFromAmount(bal.m_watchonly_immature));
+ balances.pushKV("watchonly", balances_watchonly);
+ }
+ return balances;
+}
+
static UniValue getwalletinfo(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -2996,17 +2445,16 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
- "getwalletinfo\n"
- "Returns an object containing various wallet state info.\n"
- "\nResult:\n"
+ const RPCHelpMan help{"getwalletinfo",
+ "Returns an object containing various wallet state info.\n",
+ {},
+ RPCResult{
"{\n"
" \"walletname\": xxxxx, (string) the wallet name\n"
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
- " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
- " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
- " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
+ " \"balance\": xxxxxxx, (numeric) DEPRECATED. Identical to getbalances().mine.trusted\n"
+ " \"unconfirmed_balance\": xxx, (numeric) DEPRECATED. Identical to getbalances().mine.untrusted_pending\n"
+ " \"immature_balance\": xxxxxx, (numeric) DEPRECATED. Identical to getbalances().mine.immature\n"
" \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated (only counts external keys)\n"
@@ -3014,33 +2462,45 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
" \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
" \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
" \"hdseedid\": \"<hash160>\" (string, optional) the Hash160 of the HD seed (only present when HD is enabled)\n"
- " \"hdmasterkeyid\": \"<hash160>\" (string, optional) alias for hdseedid retained for backwards-compatibility. Will be removed in V0.18.\n"
" \"private_keys_enabled\": true|false (boolean) false if privatekeys are disabled for this wallet (enforced watch-only wallet)\n"
+ " \"scanning\": (json object) current scanning details, or false if no scan is in progress\n"
+ " {\n"
+ " \"duration\" : xxxx (numeric) elapsed seconds since scan start\n"
+ " \"progress\" : x.xxxx, (numeric) scanning progress percentage [0.0, 1.0]\n"
+ " }\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getwalletinfo", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getwalletinfo", "")
+ HelpExampleRpc("getwalletinfo", "")
- );
+ },
+ };
+
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
+ }
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
UniValue obj(UniValue::VOBJ);
size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
+ const auto bal = pwallet->GetBalance();
obj.pushKV("walletname", pwallet->GetName());
obj.pushKV("walletversion", pwallet->GetVersion());
- obj.pushKV("balance", ValueFromAmount(pwallet->GetBalance()));
- obj.pushKV("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance()));
- obj.pushKV("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance()));
+ obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
+ obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
+ obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
obj.pushKV("txcount", (int)pwallet->mapWallet.size());
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
CKeyID seed_id = pwallet->GetHDChain().seed_id;
- if (!seed_id.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
+ if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
}
if (pwallet->IsCrypted()) {
@@ -3049,28 +2509,74 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
if (!seed_id.IsNull()) {
obj.pushKV("hdseedid", seed_id.GetHex());
- obj.pushKV("hdmasterkeyid", seed_id.GetHex());
}
obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
+ if (pwallet->IsScanning()) {
+ UniValue scanning(UniValue::VOBJ);
+ scanning.pushKV("duration", pwallet->ScanningDuration() / 1000);
+ scanning.pushKV("progress", pwallet->ScanningProgress());
+ obj.pushKV("scanning", scanning);
+ } else {
+ obj.pushKV("scanning", false);
+ }
return obj;
}
+static UniValue listwalletdir(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 0) {
+ throw std::runtime_error(
+ RPCHelpMan{"listwalletdir",
+ "Returns a list of wallets in the wallet directory.\n",
+ {},
+ RPCResult{
+ "{\n"
+ " \"wallets\" : [ (json array of objects)\n"
+ " {\n"
+ " \"name\" : \"name\" (string) The wallet name\n"
+ " }\n"
+ " ,...\n"
+ " ]\n"
+ "}\n"
+ },
+ RPCExamples{
+ HelpExampleCli("listwalletdir", "")
+ + HelpExampleRpc("listwalletdir", "")
+ },
+ }.ToString());
+ }
+
+ UniValue wallets(UniValue::VARR);
+ for (const auto& path : ListWalletDir()) {
+ UniValue wallet(UniValue::VOBJ);
+ wallet.pushKV("name", path.string());
+ wallets.push_back(wallet);
+ }
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("wallets", wallets);
+ return result;
+}
+
static UniValue listwallets(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
- "listwallets\n"
- "Returns a list of currently loaded wallets.\n"
- "For full information on the wallet, use \"getwalletinfo\"\n"
- "\nResult:\n"
+ RPCHelpMan{"listwallets",
+ "Returns a list of currently loaded wallets.\n"
+ "For full information on the wallet, use \"getwalletinfo\"\n",
+ {},
+ RPCResult{
"[ (json array of strings)\n"
" \"walletname\" (string) the wallet name\n"
" ...\n"
"]\n"
- "\nExamples:\n"
- + HelpExampleCli("listwallets", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listwallets", "")
+ HelpExampleRpc("listwallets", "")
- );
+ },
+ }.ToString());
UniValue obj(UniValue::VARR);
@@ -3091,47 +2597,40 @@ static UniValue loadwallet(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "loadwallet \"filename\"\n"
- "\nLoads a wallet from a wallet file or directory."
- "\nNote that all wallet command-line options used when starting bitcoind will be"
- "\napplied to the new wallet (eg -zapwallettxes, upgradewallet, rescan, etc).\n"
- "\nArguments:\n"
- "1. \"filename\" (string, required) The wallet directory or .dat file.\n"
- "\nResult:\n"
+ RPCHelpMan{"loadwallet",
+ "\nLoads a wallet from a wallet file or directory."
+ "\nNote that all wallet command-line options used when starting bitcoind will be"
+ "\napplied to the new wallet (eg -zapwallettxes, upgradewallet, rescan, etc).\n",
+ {
+ {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet directory or .dat file."},
+ },
+ RPCResult{
"{\n"
" \"name\" : <wallet_name>, (string) The wallet name if loaded successfully.\n"
" \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("loadwallet", "\"test.dat\"")
+ },
+ RPCExamples{
+ HelpExampleCli("loadwallet", "\"test.dat\"")
+ HelpExampleRpc("loadwallet", "\"test.dat\"")
- );
- std::string wallet_file = request.params[0].get_str();
- std::string error;
+ },
+ }.ToString());
- fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
- if (fs::symlink_status(wallet_path).type() == fs::file_not_found) {
- throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Wallet " + wallet_file + " not found.");
- } else if (fs::is_directory(wallet_path)) {
+ WalletLocation location(request.params[0].get_str());
+
+ if (!location.Exists()) {
+ throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Wallet " + location.GetName() + " not found.");
+ } else if (fs::is_directory(location.GetPath())) {
// The given filename is a directory. Check that there's a wallet.dat file.
- fs::path wallet_dat_file = wallet_path / "wallet.dat";
+ fs::path wallet_dat_file = location.GetPath() / "wallet.dat";
if (fs::symlink_status(wallet_dat_file).type() == fs::file_not_found) {
- throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Directory " + wallet_file + " does not contain a wallet.dat file.");
+ throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Directory " + location.GetName() + " does not contain a wallet.dat file.");
}
}
- std::string warning;
- if (!CWallet::Verify(wallet_file, false, error, warning)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
- }
-
- std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(wallet_file, fs::absolute(wallet_file, GetWalletDir()));
- if (!wallet) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Wallet loading failed.");
- }
- AddWallet(wallet);
-
- wallet->postInitProcess();
+ std::string error, warning;
+ std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_interfaces->chain, location, error, warning);
+ if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error);
UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName());
@@ -3142,46 +2641,92 @@ static UniValue loadwallet(const JSONRPCRequest& request)
static UniValue createwallet(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
- throw std::runtime_error(
- "createwallet \"wallet_name\" ( disable_private_keys )\n"
- "\nCreates and loads a new wallet.\n"
- "\nArguments:\n"
- "1. \"wallet_name\" (string, required) The name for the new wallet. If this is a path, the wallet will be created at the path location.\n"
- "2. disable_private_keys (boolean, optional, default: false) Disable the possibility of private keys (only watchonlys are possible in this mode).\n"
- "\nResult:\n"
+ const RPCHelpMan help{
+ "createwallet",
+ "\nCreates and loads a new wallet.\n",
+ {
+ {"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, /* default */ "false", "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
+ {"blank", RPCArg::Type::BOOL, /* 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, "Encrypt the wallet with this passphrase."},
+ },
+ RPCResult{
"{\n"
" \"name\" : <wallet_name>, (string) The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path.\n"
" \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("createwallet", "\"testwallet\"")
+ },
+ RPCExamples{
+ HelpExampleCli("createwallet", "\"testwallet\"")
+ HelpExampleRpc("createwallet", "\"testwallet\"")
- );
+ },
+ };
+
+ if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
+ throw std::runtime_error(help.ToString());
}
- std::string wallet_name = request.params[0].get_str();
std::string error;
std::string warning;
- bool disable_privatekeys = false;
- if (!request.params[1].isNull()) {
- disable_privatekeys = request.params[1].get_bool();
+ uint64_t flags = 0;
+ if (!request.params[1].isNull() && request.params[1].get_bool()) {
+ flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
+ }
+
+ bool create_blank = false; // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
+ if (!request.params[2].isNull() && request.params[2].get_bool()) {
+ create_blank = true;
+ flags |= WALLET_FLAG_BLANK_WALLET;
+ }
+ SecureString passphrase;
+ passphrase.reserve(100);
+ if (!request.params[3].isNull()) {
+ passphrase = request.params[3].get_str().c_str();
+ if (passphrase.empty()) {
+ // Empty string is invalid
+ throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Cannot encrypt a wallet with a blank password");
+ }
+ // Born encrypted wallets need to be blank first so that wallet creation doesn't make any unencrypted keys
+ flags |= WALLET_FLAG_BLANK_WALLET;
}
- fs::path wallet_path = fs::absolute(wallet_name, GetWalletDir());
- if (fs::symlink_status(wallet_path).type() != fs::file_not_found) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Wallet " + wallet_name + " already exists.");
+ WalletLocation location(request.params[0].get_str());
+ if (location.Exists()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Wallet " + location.GetName() + " already exists.");
}
// Wallet::Verify will check if we're trying to create a wallet with a duplication name.
- if (!CWallet::Verify(wallet_name, false, error, warning)) {
+ if (!CWallet::Verify(*g_rpc_interfaces->chain, location, false, error, warning)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
}
- std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(wallet_name, fs::absolute(wallet_name, GetWalletDir()), (disable_privatekeys ? (uint64_t)WALLET_FLAG_DISABLE_PRIVATE_KEYS : 0));
+ std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(*g_rpc_interfaces->chain, location, flags);
if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed.");
}
+
+ // Encrypt the wallet if there's a passphrase
+ if (!passphrase.empty() && !(flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ if (!wallet->EncryptWallet(passphrase)) {
+ throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Wallet created but failed to encrypt.");
+ }
+
+ if (!create_blank) {
+ // Unlock the wallet
+ if (!wallet->Unlock(passphrase)) {
+ throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Wallet was encrypted but could not be unlocked");
+ }
+
+ // Set a seed for the wallet
+ CPubKey master_pub_key = wallet->GenerateNewSeed();
+ wallet->SetHDSeed(master_pub_key);
+ wallet->NewKeyPool();
+
+ // Relock the wallet
+ wallet->Lock();
+ }
+ }
+
AddWallet(wallet);
wallet->postInitProcess();
@@ -3197,15 +2742,18 @@ static UniValue unloadwallet(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1) {
throw std::runtime_error(
- "unloadwallet ( \"wallet_name\" )\n"
- "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
- "Specifying the wallet name on a wallet endpoint is invalid."
- "\nArguments:\n"
- "1. \"wallet_name\" (string, optional) The name of the wallet to unload.\n"
- "\nExamples:\n"
- + HelpExampleCli("unloadwallet", "wallet_name")
+ RPCHelpMan{"unloadwallet",
+ "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
+ "Specifying the wallet name on a wallet endpoint is invalid.",
+ {
+ {"wallet_name", RPCArg::Type::STR, /* default */ "the wallet name from the RPC request", "The name of the wallet to unload."},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("unloadwallet", "wallet_name")
+ HelpExampleRpc("unloadwallet", "wallet_name")
- );
+ },
+ }.ToString());
}
std::string wallet_name;
@@ -3228,57 +2776,12 @@ static UniValue unloadwallet(const JSONRPCRequest& request)
if (!RemoveWallet(wallet)) {
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
}
- UnregisterValidationInterface(wallet.get());
- // The wallet can be in use so it's not possible to explicitly unload here.
- // Just notify the unload intent so that all shared pointers are released.
- // The wallet will be destroyed once the last shared pointer is released.
- wallet->NotifyUnload();
-
- // There's no point in waiting for the wallet to unload.
- // At this point this method should never fail. The unloading could only
- // fail due to an unexpected error which would cause a process termination.
+ UnloadWallet(std::move(wallet));
return NullUniValue;
}
-static UniValue resendwallettransactions(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
- "resendwallettransactions\n"
- "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
- "Intended only for testing; the wallet code periodically re-broadcasts\n"
- "automatically.\n"
- "Returns an RPC error if -walletbroadcast is set to false.\n"
- "Returns array of transaction ids that were re-broadcast.\n"
- );
-
- if (!g_connman)
- throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
-
- LOCK2(cs_main, pwallet->cs_wallet);
-
- if (!pwallet->GetBroadcastTransactions()) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet transaction broadcasting is disabled with -walletbroadcast");
- }
-
- std::vector<uint256> txids = pwallet->ResendWalletTransactionsBefore(GetTime(), g_connman.get());
- UniValue result(UniValue::VARR);
- for (const uint256& txid : txids)
- {
- result.push_back(txid.ToString());
- }
- return result;
-}
-
static UniValue listunspent(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -3290,55 +2793,59 @@ static UniValue listunspent(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 5)
throw std::runtime_error(
- "listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] [query_options])\n"
- "\nReturns array of unspent transaction outputs\n"
- "with between minconf and maxconf (inclusive) confirmations.\n"
- "Optionally filter to only include txouts paid to specified addresses.\n"
- "\nArguments:\n"
- "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
- "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
- "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
- " [\n"
- " \"address\" (string) bitcoin address\n"
- " ,...\n"
- " ]\n"
- "4. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend\n"
- " See description of \"safe\" attribute below.\n"
- "5. query_options (json, optional) JSON with query options\n"
- " {\n"
- " \"minimumAmount\" (numeric or string, default=0) Minimum value of each UTXO in " + CURRENCY_UNIT + "\n"
- " \"maximumAmount\" (numeric or string, default=unlimited) Maximum value of each UTXO in " + CURRENCY_UNIT + "\n"
- " \"maximumCount\" (numeric or string, default=unlimited) Maximum number of UTXOs\n"
- " \"minimumSumAmount\" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in " + CURRENCY_UNIT + "\n"
- " }\n"
- "\nResult\n"
+ RPCHelpMan{"listunspent",
+ "\nReturns array of unspent transaction outputs\n"
+ "with between minconf and maxconf (inclusive) confirmations.\n"
+ "Optionally filter to only include txouts paid to specified addresses.\n",
+ {
+ {"minconf", RPCArg::Type::NUM, /* default */ "1", "The minimum confirmations to filter"},
+ {"maxconf", RPCArg::Type::NUM, /* default */ "9999999", "The maximum confirmations to filter"},
+ {"addresses", RPCArg::Type::ARR, /* default */ "empty array", "A json array of bitcoin addresses to filter",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address"},
+ },
+ },
+ {"include_unsafe", RPCArg::Type::BOOL, /* 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",
+ {
+ {"minimumAmount", RPCArg::Type::AMOUNT, /* default */ "0", "Minimum value of each UTXO in " + CURRENCY_UNIT + ""},
+ {"maximumAmount", RPCArg::Type::AMOUNT, /* default */ "unlimited", "Maximum value of each UTXO in " + CURRENCY_UNIT + ""},
+ {"maximumCount", RPCArg::Type::NUM, /* default */ "unlimited", "Maximum number of UTXOs"},
+ {"minimumSumAmount", RPCArg::Type::AMOUNT, /* default */ "unlimited", "Minimum sum value of all UTXOs in " + CURRENCY_UNIT + ""},
+ },
+ "query_options"},
+ },
+ RPCResult{
"[ (array of json object)\n"
" {\n"
" \"txid\" : \"txid\", (string) the transaction id \n"
" \"vout\" : n, (numeric) the vout value\n"
" \"address\" : \"address\", (string) the bitcoin address\n"
" \"label\" : \"label\", (string) The associated label, or \"\" for the default label\n"
- " \"account\" : \"account\", (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The associated account, or \"\" for the default account\n"
" \"scriptPubKey\" : \"key\", (string) the script key\n"
" \"amount\" : x.xxx, (numeric) the transaction output amount in " + CURRENCY_UNIT + "\n"
" \"confirmations\" : n, (numeric) The number of confirmations\n"
- " \"redeemScript\" : n (string) The redeemScript if scriptPubKey is P2SH\n"
+ " \"redeemScript\" : \"script\" (string) The redeemScript if scriptPubKey is P2SH\n"
+ " \"witnessScript\" : \"script\" (string) witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH\n"
" \"spendable\" : xxx, (bool) Whether we have the private keys to spend this output\n"
" \"solvable\" : xxx, (bool) Whether we know how to spend this output, ignoring the lack of keys\n"
+ " \"desc\" : xxx, (string, only when solvable) A descriptor for spending this output\n"
" \"safe\" : xxx (bool) Whether this output is considered safe to spend. Unconfirmed transactions\n"
" from outside keys and unconfirmed replacement transactions are considered unsafe\n"
" and are not eligible for spending by fundrawtransaction and sendtoaddress.\n"
" }\n"
" ,...\n"
"]\n"
-
- "\nExamples\n"
- + HelpExampleCli("listunspent", "")
+ },
+ RPCExamples{
+ HelpExampleCli("listunspent", "")
+ HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
+ HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
+ HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
+ HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
- );
+ },
+ }.ToString());
int nMinDepth = 1;
if (!request.params[0].isNull()) {
@@ -3402,8 +2909,9 @@ static UniValue listunspent(const JSONRPCRequest& request)
UniValue results(UniValue::VARR);
std::vector<COutput> vecOutputs;
{
- LOCK2(cs_main, pwallet->cs_wallet);
- pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
+ pwallet->AvailableCoins(*locked_chain, vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
}
LOCK(pwallet->cs_wallet);
@@ -3426,16 +2934,35 @@ static UniValue listunspent(const JSONRPCRequest& request)
auto i = pwallet->mapAddressBook.find(address);
if (i != pwallet->mapAddressBook.end()) {
entry.pushKV("label", i->second.name);
- if (IsDeprecatedRPCEnabled("accounts")) {
- entry.pushKV("account", i->second.name);
- }
}
if (scriptPubKey.IsPayToScriptHash()) {
- const CScriptID& hash = boost::get<CScriptID>(address);
+ const CScriptID& hash = CScriptID(boost::get<ScriptHash>(address));
CScript redeemScript;
if (pwallet->GetCScript(hash, redeemScript)) {
entry.pushKV("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()));
+ // Now check if the redeemScript is actually a P2WSH script
+ CTxDestination witness_destination;
+ if (redeemScript.IsPayToWitnessScriptHash()) {
+ bool extracted = ExtractDestination(redeemScript, witness_destination);
+ assert(extracted);
+ // Also return the witness script
+ const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(witness_destination);
+ CScriptID id;
+ CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
+ CScript witnessScript;
+ if (pwallet->GetCScript(id, witnessScript)) {
+ entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end()));
+ }
+ }
+ }
+ } else if (scriptPubKey.IsPayToWitnessScriptHash()) {
+ const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(address);
+ CScriptID id;
+ CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
+ CScript witnessScript;
+ if (pwallet->GetCScript(id, witnessScript)) {
+ entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end()));
}
}
}
@@ -3445,6 +2972,10 @@ static UniValue listunspent(const JSONRPCRequest& request)
entry.pushKV("confirmations", out.nDepth);
entry.pushKV("spendable", out.fSpendable);
entry.pushKV("solvable", out.fSolvable);
+ if (out.fSolvable) {
+ auto descriptor = InferDescriptor(scriptPubKey, *pwallet);
+ entry.pushKV("desc", descriptor->ToString());
+ }
entry.pushKV("safe", out.fSafe);
results.push_back(entry);
}
@@ -3531,7 +3062,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
if (options.exists("feeRate")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate");
}
- coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"]);
+ coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"], pwallet->chain().estimateMaxBlocks());
}
if (options.exists("estimate_mode")) {
if (options.exists("feeRate")) {
@@ -3579,61 +3110,66 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
- "fundrawtransaction \"hexstring\" ( options iswitness )\n"
- "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
- "This will not modify existing inputs, and will add at most one change output to the outputs.\n"
- "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
- "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
- "The inputs added will not be signed, use signrawtransaction for that.\n"
- "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
- "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
- "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
- "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
- "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
- "\nArguments:\n"
- "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
- "2. options (object, optional)\n"
- " {\n"
- " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
- " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
- " \"change_type\" (string, optional) The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -changetype.\n"
- " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
- " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
- " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific fee rate in " + CURRENCY_UNIT + "/kB\n"
- " \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
+ RPCHelpMan{"fundrawtransaction",
+ "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
+ "This will not modify existing inputs, and will add at most one change output to the outputs.\n"
+ "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
+ "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
+ "The inputs added will not be signed, use signrawtransactionwithkey\n"
+ " or signrawtransactionwithwallet for that.\n"
+ "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
+ "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
+ "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
+ "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
+ "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}",
+ {
+ {"changeAddress", RPCArg::Type::STR, /* default */ "pool address", "The bitcoin address to receive the change"},
+ {"changePosition", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"},
+ {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"includeWatching", RPCArg::Type::BOOL, /* default */ "false", "Also select inputs which are watch only"},
+ {"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"},
+ {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"},
+ {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "A json array of integers.\n"
" The fee will be equally deducted from the amount of each specified output.\n"
- " The outputs are specified by their zero-based index, before any change output is added.\n"
" Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
- " If no outputs are specified here, the sender pays the fee.\n"
- " [vout_index,...]\n"
- " \"replaceable\" (boolean, optional) Marks this transaction as BIP125 replaceable.\n"
- " Allows this transaction to be replaced by a transaction with higher fees\n"
- " \"conf_target\" (numeric, optional) Confirmation target (in blocks)\n"
- " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
+ " If no outputs are specified here, the sender pays the fee.",
+ {
+ {"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
+ },
+ },
+ {"replaceable", RPCArg::Type::BOOL, /* default */ "fallback to wallet's default", "Marks this transaction as BIP125 replaceable.\n"
+ " Allows this transaction to be replaced by a transaction with higher fees"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "fallback to wallet's default", "Confirmation target (in blocks)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
" \"UNSET\"\n"
" \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\"\n"
- " }\n"
- " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
- "3. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction \n"
- " If iswitness is not present, heuristic tests will be used in decoding\n"
-
- "\nResult:\n"
+ " \"CONSERVATIVE\""},
+ },
+ "options"},
+ {"iswitness", RPCArg::Type::BOOL, /* default */ "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"},
+ },
+ RPCResult{
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
" \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
" \"changepos\": n (numeric) The position of the added change output, or -1\n"
"}\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate a transaction with no inputs\n"
+ HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
"\nAdd sufficient unsigned inputs to meet the output value\n"
+ HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
"\nSign the transaction\n"
- + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
+ + HelpExampleCli("signrawtransactionwithwallet", "\"fundedtransactionhex\"") +
"\nSend the transaction\n"
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
- );
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType(), UniValue::VBOOL});
@@ -3650,7 +3186,7 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
FundTransaction(pwallet, tx, fee, change_position, request.params[1]);
UniValue result(UniValue::VOBJ);
- result.pushKV("hex", EncodeHexTx(tx));
+ result.pushKV("hex", EncodeHexTx(CTransaction(tx)));
result.pushKV("fee", ValueFromAmount(fee));
result.pushKV("changepos", change_position);
@@ -3668,34 +3204,36 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
- "signrawtransactionwithwallet \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] sighashtype )\n"
- "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
- "The second optional argument (may be null) is an array of previous transaction outputs that\n"
- "this transaction depends on but may not yet be in the block chain.\n"
- + HelpRequiringPassphrase(pwallet) + "\n"
-
- "\nArguments:\n"
- "1. \"hexstring\" (string, required) The transaction hex string\n"
- "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n"
- " [ (json array of json objects, or 'null' if none provided)\n"
- " {\n"
- " \"txid\":\"id\", (string, required) The transaction id\n"
- " \"vout\":n, (numeric, required) The output number\n"
- " \"scriptPubKey\": \"hex\", (string, required) script key\n"
- " \"redeemScript\": \"hex\", (string, required for P2SH or P2WSH) redeem script\n"
- " \"amount\": value (numeric, required) The amount spent\n"
- " }\n"
- " ,...\n"
- " ]\n"
- "3. \"sighashtype\" (string, optional, default=ALL) The signature hash type. Must be one of\n"
+ RPCHelpMan{"signrawtransactionwithwallet",
+ "\nSign inputs for raw transaction (serialized, hex-encoded).\n"
+ "The second optional argument (may be null) is an array of previous transaction outputs that\n"
+ "this transaction depends on but may not yet be in the block chain." +
+ HelpRequiringPassphrase(pwallet) + "\n",
+ {
+ {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"},
+ {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of previous dependent transaction outputs",
+ {
+ {"", 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 number"},
+ {"scriptPubKey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "script key"},
+ {"redeemScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2SH) redeem script"},
+ {"witnessScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2WSH or P2SH-P2WSH) witness script"},
+ {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::OMITTED, "(required for Segwit inputs) the amount spent"},
+ },
+ },
+ },
+ },
+ {"sighashtype", RPCArg::Type::STR, /* default */ "ALL", "The signature hash type. Must be one of\n"
" \"ALL\"\n"
" \"NONE\"\n"
" \"SINGLE\"\n"
" \"ALL|ANYONECANPAY\"\n"
" \"NONE|ANYONECANPAY\"\n"
- " \"SINGLE|ANYONECANPAY\"\n"
-
- "\nResult:\n"
+ " \"SINGLE|ANYONECANPAY\""},
+ },
+ RPCResult{
"{\n"
" \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
@@ -3710,11 +3248,12 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
" ,...\n"
" ]\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"")
+ },
+ RPCExamples{
+ HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"")
+ HelpExampleRpc("signrawtransactionwithwallet", "\"myhex\"")
- );
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true);
@@ -3724,8 +3263,18 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
}
// Sign the transaction
- LOCK2(cs_main, pwallet->cs_wallet);
- return SignTransaction(mtx, request.params[1], pwallet, false, request.params[2]);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
+ EnsureWalletIsUnlocked(pwallet);
+
+ // Fetch previous transactions (inputs):
+ std::map<COutPoint, Coin> coins;
+ for (const CTxIn& txin : mtx.vin) {
+ coins[txin.prevout]; // Create empty map entry keyed by prevout.
+ }
+ pwallet->chain().findCoins(coins);
+
+ return SignTransaction(mtx, request.params[1], pwallet, coins, false, request.params[2]);
}
static UniValue bumpfee(const JSONRPCRequest& request)
@@ -3739,54 +3288,58 @@ static UniValue bumpfee(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
- "bumpfee \"txid\" ( options ) \n"
- "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
- "An opt-in RBF transaction with the given txid must be in the wallet.\n"
- "The command will pay the additional fee by decreasing (or perhaps removing) its change output.\n"
- "If the change output is not big enough to cover the increased fee, the command will currently fail\n"
- "instead of adding new inputs to compensate. (A future implementation could improve this.)\n"
- "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
- "By default, the new fee will be calculated automatically using estimatesmartfee.\n"
- "The user can specify a confirmation target for estimatesmartfee.\n"
- "Alternatively, the user can specify totalFee, or use RPC settxfee to set a higher fee rate.\n"
- "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
- "returned by getnetworkinfo) to enter the node's mempool.\n"
- "\nArguments:\n"
- "1. txid (string, required) The txid to be bumped\n"
- "2. options (object, optional)\n"
- " {\n"
- " \"confTarget\" (numeric, optional) Confirmation target (in blocks)\n"
- " \"totalFee\" (numeric, optional) Total fee (NOT feerate) to pay, in satoshis.\n"
+ RPCHelpMan{"bumpfee",
+ "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
+ "An opt-in RBF transaction with the given txid must be in the wallet.\n"
+ "The command will 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.\n"
+ "If `totalFee` is given, adding inputs is not supported, so there must be a single change output that is big enough or it will fail.\n"
+ "All inputs in the original transaction will be included in the replacement transaction.\n"
+ "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
+ "By default, the new fee will be calculated automatically using estimatesmartfee.\n"
+ "The user can specify a confirmation target for estimatesmartfee.\n"
+ "Alternatively, the user can specify totalFee, or use RPC settxfee to set a higher fee rate.\n"
+ "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
+ "returned by getnetworkinfo) to enter the node's mempool.\n",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"},
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ {
+ {"confTarget", RPCArg::Type::NUM, /* default */ "fallback to wallet's default", "Confirmation target (in blocks)"},
+ {"totalFee", RPCArg::Type::NUM, /* default */ "fallback to 'confTarget'", "Total fee (NOT feerate) to pay, in satoshis.\n"
" In rare cases, the actual fee paid might be slightly higher than the specified\n"
" totalFee if the tx change output has to be removed because it is too close to\n"
- " the dust threshold.\n"
- " \"replaceable\" (boolean, optional, default true) Whether the new transaction should still be\n"
+ " the dust threshold."},
+ {"replaceable", RPCArg::Type::BOOL, /* default */ "true", "Whether the new transaction should still be\n"
" marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
" be left unchanged from the original. If false, any input sequence numbers in the\n"
" original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
" so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
" still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
- " are replaceable).\n"
- " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
+ " are replaceable)."},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
" \"UNSET\"\n"
" \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\"\n"
- " }\n"
- "\nResult:\n"
+ " \"CONSERVATIVE\""},
+ },
+ "options"},
+ },
+ RPCResult{
"{\n"
" \"txid\": \"value\", (string) The id of the new transaction\n"
" \"origfee\": n, (numeric) Fee of the replaced transaction\n"
" \"fee\": n, (numeric) Fee of the new transaction\n"
" \"errors\": [ str... ] (json array of strings) Errors encountered during processing (may be empty)\n"
"}\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nBump the fee, get the new transaction\'s txid\n" +
- HelpExampleCli("bumpfee", "<txid>"));
+ HelpExampleCli("bumpfee", "<txid>")
+ },
+ }.ToString());
}
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
- uint256 hash;
- hash.SetHex(request.params[0].get_str());
+ uint256 hash(ParseHashV(request.params[0], "txid"));
// optional parameters
CAmount totalFee = 0;
@@ -3806,7 +3359,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
if (options.exists("confTarget") && options.exists("totalFee")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction.");
} else if (options.exists("confTarget")) { // TODO: alias this to conf_target
- coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"]);
+ coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"], pwallet->chain().estimateMaxBlocks());
} else if (options.exists("totalFee")) {
totalFee = options["totalFee"].get_int64();
if (totalFee <= 0) {
@@ -3828,7 +3381,8 @@ static UniValue bumpfee(const JSONRPCRequest& request)
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- LOCK2(cs_main, pwallet->cs_wallet);
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
@@ -3836,7 +3390,14 @@ static UniValue bumpfee(const JSONRPCRequest& request)
CAmount old_fee;
CAmount new_fee;
CMutableTransaction mtx;
- feebumper::Result res = feebumper::CreateTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx);
+ feebumper::Result res;
+ if (totalFee > 0) {
+ // Targeting total fee bump. Requires a change output of sufficient size.
+ res = feebumper::CreateTotalBumpTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx);
+ } else {
+ // Targeting feerate bump.
+ res = feebumper::CreateRateBumpTransaction(pwallet, hash, coin_control, errors, old_fee, new_fee, mtx);
+ }
if (res != feebumper::Result::OK) {
switch(res) {
case feebumper::Result::INVALID_ADDRESS_OR_KEY:
@@ -3879,53 +3440,6 @@ static UniValue bumpfee(const JSONRPCRequest& request)
return result;
}
-UniValue generate(const JSONRPCRequest& request)
-{
- std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- CWallet* const pwallet = wallet.get();
-
-
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
- return NullUniValue;
- }
-
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
- throw std::runtime_error(
- "generate nblocks ( maxtries )\n"
- "\nMine up to nblocks blocks immediately (before the RPC call returns) to an address in the wallet.\n"
- "\nArguments:\n"
- "1. nblocks (numeric, required) How many blocks are generated immediately.\n"
- "2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
- "\nResult:\n"
- "[ blockhashes ] (array) hashes of blocks generated\n"
- "\nExamples:\n"
- "\nGenerate 11 blocks\n"
- + HelpExampleCli("generate", "11")
- );
- }
-
- int num_generate = request.params[0].get_int();
- uint64_t max_tries = 1000000;
- if (!request.params[1].isNull()) {
- max_tries = request.params[1].get_int();
- }
-
- std::shared_ptr<CReserveScript> coinbase_script;
- pwallet->GetScriptForMining(coinbase_script);
-
- // If the keypool is exhausted, no script is returned at all. Catch this.
- if (!coinbase_script) {
- throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
- }
-
- //throw an error if no script was provided
- if (coinbase_script->reserveScript.empty()) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available");
- }
-
- return generateBlocks(coinbase_script, num_generate, max_tries, true);
-}
-
UniValue rescanblockchain(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -3937,20 +3451,23 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 2) {
throw std::runtime_error(
- "rescanblockchain (\"start_height\") (\"stop_height\")\n"
- "\nRescan the local blockchain for wallet related transactions.\n"
- "\nArguments:\n"
- "1. \"start_height\" (numeric, optional) block height where the rescan should start\n"
- "2. \"stop_height\" (numeric, optional) the last block height that should be scanned\n"
- "\nResult:\n"
+ RPCHelpMan{"rescanblockchain",
+ "\nRescan the local blockchain for wallet related transactions.\n",
+ {
+ {"start_height", RPCArg::Type::NUM, /* 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."},
+ },
+ RPCResult{
"{\n"
- " \"start_height\" (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n"
- " \"stop_height\" (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n"
+ " \"start_height\" (numeric) The block height where the rescan started (the requested height or 0)\n"
+ " \"stop_height\" (numeric) The height of the last rescanned block. May be null in rare cases if there was a reorg and the call didn't scan any blocks because they were already scanned in the background.\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("rescanblockchain", "100000 120000")
+ },
+ RPCExamples{
+ HelpExampleCli("rescanblockchain", "100000 120000")
+ HelpExampleRpc("rescanblockchain", "100000, 120000")
- );
+ },
+ }.ToString());
}
WalletRescanReserver reserver(pwallet);
@@ -3958,58 +3475,62 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}
- CBlockIndex *pindexStart = nullptr;
- CBlockIndex *pindexStop = nullptr;
- CBlockIndex *pChainTip = nullptr;
+ int start_height = 0;
+ uint256 start_block, stop_block;
{
- LOCK(cs_main);
- pindexStart = chainActive.Genesis();
- pChainTip = chainActive.Tip();
+ auto locked_chain = pwallet->chain().lock();
+ Optional<int> tip_height = locked_chain->getHeight();
if (!request.params[0].isNull()) {
- pindexStart = chainActive[request.params[0].get_int()];
- if (!pindexStart) {
+ start_height = request.params[0].get_int();
+ if (start_height < 0 || !tip_height || start_height > *tip_height) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
}
}
+ Optional<int> stop_height;
if (!request.params[1].isNull()) {
- pindexStop = chainActive[request.params[1].get_int()];
- if (!pindexStop) {
+ stop_height = request.params[1].get_int();
+ if (*stop_height < 0 || !tip_height || *stop_height > *tip_height) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
}
- else if (pindexStop->nHeight < pindexStart->nHeight) {
+ else if (*stop_height < start_height) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater than start_height");
}
}
- }
- // We can't rescan beyond non-pruned blocks, stop and throw an error
- if (fPruneMode) {
- LOCK(cs_main);
- CBlockIndex *block = pindexStop ? pindexStop : pChainTip;
- while (block && block->nHeight >= pindexStart->nHeight) {
- if (!(block->nStatus & BLOCK_HAVE_DATA)) {
- throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
- }
- block = block->pprev;
+ // We can't rescan beyond non-pruned blocks, stop and throw an error
+ if (locked_chain->findPruned(start_height, stop_height)) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
}
- }
- CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions(pindexStart, pindexStop, reserver, true);
- if (!stopBlock) {
- if (pwallet->IsAbortingRescan()) {
- throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
+ if (tip_height) {
+ start_block = locked_chain->getBlockHash(start_height);
+ // If called with a stop_height, set the stop_height here to
+ // trigger a rescan to that height.
+ // If called without a stop height, leave stop_height as null here
+ // so rescan continues to the tip (even if the tip advances during
+ // rescan).
+ if (stop_height) {
+ stop_block = locked_chain->getBlockHash(*stop_height);
+ }
}
- // if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex
- stopBlock = pindexStop ? pindexStop : pChainTip;
}
- else {
+
+ CWallet::ScanResult result =
+ pwallet->ScanForWalletTransactions(start_block, stop_block, reserver, true /* fUpdate */);
+ switch (result.status) {
+ case CWallet::ScanResult::SUCCESS:
+ break;
+ case CWallet::ScanResult::FAILURE:
throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
+ case CWallet::ScanResult::USER_ABORT:
+ throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
+ // no default case, so the compiler can warn about missing cases
}
UniValue response(UniValue::VOBJ);
- response.pushKV("start_height", pindexStart->nHeight);
- response.pushKV("stop_height", stopBlock->nHeight);
+ response.pushKV("start_height", start_height);
+ response.pushKV("stop_height", result.last_scanned_height ? *result.last_scanned_height : UniValue());
return response;
}
@@ -4018,17 +3539,15 @@ class DescribeWalletAddressVisitor : public boost::static_visitor<UniValue>
public:
CWallet * const pwallet;
- void ProcessSubScript(const CScript& subscript, UniValue& obj, bool include_addresses = false) const
+ void ProcessSubScript(const CScript& subscript, UniValue& obj) const
{
// Always present: script type and redeemscript
- txnouttype which_type;
std::vector<std::vector<unsigned char>> solutions_data;
- Solver(subscript, which_type, solutions_data);
+ txnouttype which_type = Solver(subscript, solutions_data);
obj.pushKV("script", GetTxnOutputType(which_type));
obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
CTxDestination embedded;
- UniValue a(UniValue::VARR);
if (ExtractDestination(subscript, embedded)) {
// Only when the script corresponds to an address.
UniValue subobj(UniValue::VOBJ);
@@ -4041,7 +3560,6 @@ public:
// Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
obj.pushKV("embedded", std::move(subobj));
- if (include_addresses) a.push_back(EncodeDestination(embedded));
} else if (which_type == TX_MULTISIG) {
// Also report some information on multisig scripts (which do not have a corresponding address).
// TODO: abstract out the common functionality between this logic and ExtractDestinations.
@@ -4049,25 +3567,19 @@ public:
UniValue pubkeys(UniValue::VARR);
for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
- if (include_addresses) a.push_back(EncodeDestination(key.GetID()));
pubkeys.push_back(HexStr(key.begin(), key.end()));
}
obj.pushKV("pubkeys", std::move(pubkeys));
}
-
- // The "addresses" field is confusing because it refers to public keys using their P2PKH address.
- // For that reason, only add the 'addresses' field when needed for backward compatibility. New applications
- // can use the 'embedded'->'address' field for P2SH or P2WSH wrapped addresses, and 'pubkeys' for
- // inspecting multisig participants.
- if (include_addresses) obj.pushKV("addresses", std::move(a));
}
explicit DescribeWalletAddressVisitor(CWallet* _pwallet) : pwallet(_pwallet) {}
UniValue operator()(const CNoDestination& dest) const { return UniValue(UniValue::VOBJ); }
- UniValue operator()(const CKeyID& keyID) const
+ UniValue operator()(const PKHash& pkhash) const
{
+ CKeyID keyID(pkhash);
UniValue obj(UniValue::VOBJ);
CPubKey vchPubKey;
if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
@@ -4077,12 +3589,13 @@ public:
return obj;
}
- UniValue operator()(const CScriptID& scriptID) const
+ UniValue operator()(const ScriptHash& scripthash) const
{
+ CScriptID scriptID(scripthash);
UniValue obj(UniValue::VOBJ);
CScript subscript;
if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
- ProcessSubScript(subscript, obj, IsDeprecatedRPCEnabled("validateaddress"));
+ ProcessSubScript(subscript, obj);
}
return obj;
}
@@ -4144,18 +3657,22 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
- "getaddressinfo \"address\"\n"
- "\nReturn information about the given bitcoin address. Some information requires the address\n"
- "to be in the wallet.\n"
- "\nArguments:\n"
- "1. \"address\" (string, required) The bitcoin address to get the information of.\n"
- "\nResult:\n"
+ RPCHelpMan{"getaddressinfo",
+ "\nReturn information about the given bitcoin address. Some information requires the address\n"
+ "to be in the wallet.\n",
+ {
+ {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to get the information of."},
+ },
+ RPCResult{
"{\n"
" \"address\" : \"address\", (string) The bitcoin address validated\n"
- " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n"
+ " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n"
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
+ " \"solvable\" : true|false, (boolean) Whether we know how to spend coins sent to this address, ignoring the possible lack of private keys\n"
+ " \"desc\" : \"desc\", (string, optional) A descriptor for spending coins sent to this address (only when solvable)\n"
" \"isscript\" : true|false, (boolean) If the key is a script\n"
+ " \"ischange\" : true|false, (boolean) If the address was used for change output\n"
" \"iswitness\" : true|false, (boolean) If the address is a witness address\n"
" \"witness_version\" : version (numeric, optional) The version number of the witness program\n"
" \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n"
@@ -4168,14 +3685,13 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
" ]\n"
" \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n"
" \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH)\n"
- " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdseedid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n"
- " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
- " \"label\" : \"label\" (string) The label associated with the address, \"\" is the default account\n"
- " \"account\" : \"account\" (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account associated with the address, \"\" is the default account\n"
+ " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdseedid\") and relation to the wallet (\"ismine\", \"iswatchonly\").\n"
+ " \"iscompressed\" : true|false, (boolean, optional) If the pubkey is compressed\n"
+ " \"label\" : \"label\" (string) The label associated with the address, \"\" is the default label\n"
" \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
" \"hdseedid\" : \"<hash160>\" (string, optional) The Hash160 of the HD seed\n"
- " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) alias for hdseedid maintained for backwards compatibility. Will be removed in V0.18.\n"
+ " \"hdmasterfingerprint\" : \"<hash160>\" (string, optional) The fingperint of the master key.\n"
" \"labels\" (object) Array of labels associated with the address.\n"
" [\n"
" { (json object of label data)\n"
@@ -4184,10 +3700,12 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
" },...\n"
" ]\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ },
+ RPCExamples{
+ HelpExampleCli("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ HelpExampleRpc("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
- );
+ },
+ }.ToString());
}
LOCK(pwallet->cs_wallet);
@@ -4208,15 +3726,18 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
isminetype mine = IsMine(*pwallet, dest);
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
+ bool solvable = IsSolvable(*pwallet, scriptPubKey);
+ ret.pushKV("solvable", solvable);
+ if (solvable) {
+ ret.pushKV("desc", InferDescriptor(scriptPubKey, *pwallet)->ToString());
+ }
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
UniValue detail = DescribeWalletAddress(pwallet, dest);
ret.pushKVs(detail);
if (pwallet->mapAddressBook.count(dest)) {
ret.pushKV("label", pwallet->mapAddressBook[dest].name);
- if (IsDeprecatedRPCEnabled("accounts")) {
- ret.pushKV("account", pwallet->mapAddressBook[dest].name);
- }
}
+ ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
const CKeyMetadata* meta = nullptr;
CKeyID key_id = GetKeyForDestination(*pwallet, dest);
if (!key_id.IsNull()) {
@@ -4233,10 +3754,10 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
}
if (meta) {
ret.pushKV("timestamp", meta->nCreateTime);
- if (!meta->hdKeypath.empty()) {
- ret.pushKV("hdkeypath", meta->hdKeypath);
+ if (meta->has_key_origin) {
+ ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
- ret.pushKV("hdmasterkeyid", meta->hd_seed_id.GetHex());
+ ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint, meta->key_origin.fingerprint + 4));
}
}
@@ -4264,20 +3785,23 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "getaddressesbylabel \"label\"\n"
- "\nReturns the list of addresses assigned the specified label.\n"
- "\nArguments:\n"
- "1. \"label\" (string, required) The label.\n"
- "\nResult:\n"
+ RPCHelpMan{"getaddressesbylabel",
+ "\nReturns the list of addresses assigned the specified label.\n",
+ {
+ {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
+ },
+ RPCResult{
"{ (json object with addresses as keys)\n"
" \"address\": { (json object with information about address)\n"
" \"purpose\": \"string\" (string) Purpose of address (\"send\" for sending address, \"receive\" for receiving address)\n"
" },...\n"
"}\n"
- "\nExamples:\n"
- + HelpExampleCli("getaddressesbylabel", "\"tabby\"")
+ },
+ RPCExamples{
+ HelpExampleCli("getaddressesbylabel", "\"tabby\"")
+ HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
- );
+ },
+ }.ToString());
LOCK(pwallet->cs_wallet);
@@ -4285,9 +3809,20 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
// Find all addresses that have the given label
UniValue ret(UniValue::VOBJ);
+ std::set<std::string> addresses;
for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
if (item.second.name == label) {
- ret.pushKV(EncodeDestination(item.first), AddressBookDataToJSON(item.second, false));
+ std::string address = EncodeDestination(item.first);
+ // CWallet::mapAddressBook is not expected to contain duplicate
+ // address strings, but build a separate set as a precaution just in
+ // case it does.
+ bool unique = addresses.emplace(address).second;
+ assert(unique);
+ // UniValue::pushKV checks if the key exists in O(N)
+ // and since duplicate addresses are unexpected (checked with
+ // std::set in O(log(N))), UniValue::__pushKV is used instead,
+ // which currently is O(1).
+ ret.__pushKV(address, AddressBookDataToJSON(item.second, false));
}
}
@@ -4309,25 +3844,28 @@ static UniValue listlabels(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
- "listlabels ( \"purpose\" )\n"
- "\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n"
- "\nArguments:\n"
- "1. \"purpose\" (string, optional) Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument.\n"
- "\nResult:\n"
+ 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."},
+ },
+ RPCResult{
"[ (json array of string)\n"
" \"label\", (string) Label name\n"
" ...\n"
"]\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nList all labels\n"
+ HelpExampleCli("listlabels", "") +
"\nList labels that have receiving addresses\n"
+ HelpExampleCli("listlabels", "receive") +
"\nList labels that have sending addresses\n"
+ HelpExampleCli("listlabels", "send") +
- "\nAs json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("listlabels", "receive")
- );
+ },
+ }.ToString());
LOCK(pwallet->cs_wallet);
@@ -4363,34 +3901,42 @@ UniValue sethdseed(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 2) {
throw std::runtime_error(
- "sethdseed ( \"newkeypool\" \"seed\" )\n"
- "\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
- "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
- "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed.\n"
- + HelpRequiringPassphrase(pwallet) +
- "\nArguments:\n"
- "1. \"newkeypool\" (boolean, optional, default=true) Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
+ RPCHelpMan{"sethdseed",
+ "\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
+ "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
+ "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." +
+ HelpRequiringPassphrase(pwallet) + "\n",
+ {
+ {"newkeypool", RPCArg::Type::BOOL, /* default */ "true", "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
" If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
" If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
- " keypool will be used until it has been depleted.\n"
- "2. \"seed\" (string, optional) The WIF private key to use as the new HD seed; if not provided a random seed will be used.\n"
- " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1\n"
- "\nExamples:\n"
- + HelpExampleCli("sethdseed", "")
+ " keypool will be used until it has been depleted."},
+ {"seed", RPCArg::Type::STR, /* default */ "random seed", "The WIF private key to use as the new HD seed.\n"
+ " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
+ },
+ RPCResults{},
+ RPCExamples{
+ HelpExampleCli("sethdseed", "")
+ HelpExampleCli("sethdseed", "false")
+ HelpExampleCli("sethdseed", "true \"wifkey\"")
+ HelpExampleRpc("sethdseed", "true, \"wifkey\"")
- );
+ },
+ }.ToString());
}
- if (IsInitialBlockDownload()) {
+ if (pwallet->chain().isInitialBlockDownload()) {
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set a new HD seed while still in Initial Block Download");
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
+ }
+
+ auto locked_chain = pwallet->chain().lock();
+ LOCK(pwallet->cs_wallet);
// Do not do anything to non-HD wallets
- if (!pwallet->IsHDEnabled()) {
+ if (!pwallet->CanSupportFeature(FEATURE_HD)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed on a non-HD wallet. Start with -upgradewallet in order to upgrade a non-HD wallet to HD");
}
@@ -4423,150 +3969,6 @@ UniValue sethdseed(const JSONRPCRequest& request)
return NullUniValue;
}
-bool ParseHDKeypath(std::string keypath_str, std::vector<uint32_t>& keypath)
-{
- std::stringstream ss(keypath_str);
- std::string item;
- bool first = true;
- while (std::getline(ss, item, '/')) {
- if (item.compare("m") == 0) {
- if (first) {
- first = false;
- continue;
- }
- return false;
- }
- // Finds whether it is hardened
- uint32_t path = 0;
- size_t pos = item.find("'");
- if (pos != std::string::npos) {
- // The hardened tick can only be in the last index of the string
- if (pos != item.size() - 1) {
- return false;
- }
- path |= 0x80000000;
- item = item.substr(0, item.size() - 1); // Drop the last character which is the hardened tick
- }
-
- // Ensure this is only numbers
- if (item.find_first_not_of( "0123456789" ) != std::string::npos) {
- return false;
- }
- uint32_t number;
- if (!ParseUInt32(item, &number)) {
- return false;
- }
- path |= number;
-
- keypath.push_back(path);
- first = false;
- }
- return true;
-}
-
-void AddKeypathToMap(const CWallet* pwallet, const CKeyID& keyID, std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths)
-{
- CPubKey vchPubKey;
- if (!pwallet->GetPubKey(keyID, vchPubKey)) {
- return;
- }
- CKeyMetadata meta;
- auto it = pwallet->mapKeyMetadata.find(keyID);
- if (it != pwallet->mapKeyMetadata.end()) {
- meta = it->second;
- }
- std::vector<uint32_t> keypath;
- if (!meta.hdKeypath.empty()) {
- if (!ParseHDKeypath(meta.hdKeypath, keypath)) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Internal keypath is broken");
- }
- // Get the proper master key id
- CKey key;
- pwallet->GetKey(meta.hd_seed_id, key);
- CExtKey masterKey;
- masterKey.SetSeed(key.begin(), key.size());
- // Add to map
- keypath.insert(keypath.begin(), ReadLE32(masterKey.key.GetPubKey().GetID().begin()));
- } else { // Single pubkeys get the master fingerprint of themselves
- keypath.insert(keypath.begin(), ReadLE32(vchPubKey.GetID().begin()));
- }
- hd_keypaths.emplace(vchPubKey, keypath);
-}
-
-bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const CTransaction* txConst, int sighash_type, bool sign, bool bip32derivs)
-{
- LOCK(pwallet->cs_wallet);
- // Get all of the previous transactions
- bool complete = true;
- for (unsigned int i = 0; i < txConst->vin.size(); ++i) {
- const CTxIn& txin = txConst->vin[i];
- PSBTInput& input = psbtx.inputs.at(i);
-
- // If we don't know about this input, skip it and let someone else deal with it
- const uint256& txhash = txin.prevout.hash;
- const auto& it = pwallet->mapWallet.find(txhash);
- if (it != pwallet->mapWallet.end()) {
- const CWalletTx& wtx = it->second;
- CTxOut utxo = wtx.tx->vout[txin.prevout.n];
- input.non_witness_utxo = wtx.tx;
- input.witness_utxo = utxo;
- }
-
- // Get the Sighash type
- if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Specified Sighash and sighash in PSBT do not match.");
- }
-
- SignatureData sigdata;
- if (sign) {
- complete &= SignPSBTInput(*pwallet, *psbtx.tx, input, sigdata, i, sighash_type);
- } else {
- complete &= SignPSBTInput(PublicOnlySigningProvider(pwallet), *psbtx.tx, input, sigdata, i, sighash_type);
- }
-
- // Drop the unnecessary UTXO
- if (sigdata.witness) {
- input.non_witness_utxo = nullptr;
- } else {
- input.witness_utxo.SetNull();
- }
-
- // Get public key paths
- if (bip32derivs) {
- for (const auto& pubkey_it : sigdata.misc_pubkeys) {
- AddKeypathToMap(pwallet, pubkey_it.first, input.hd_keypaths);
- }
- }
- }
-
- // Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
- for (unsigned int i = 0; i < txConst->vout.size(); ++i) {
- const CTxOut& out = txConst->vout.at(i);
- PSBTOutput& psbt_out = psbtx.outputs.at(i);
-
- // Dummy tx so we can use ProduceSignature to get stuff out
- CMutableTransaction dummy_tx;
- dummy_tx.vin.push_back(CTxIn());
- dummy_tx.vout.push_back(CTxOut());
-
- // Fill a SignatureData with output info
- SignatureData sigdata;
- psbt_out.FillSignatureData(sigdata);
-
- MutableTransactionSignatureCreator creator(psbtx.tx.get_ptr(), 0, out.nValue, 1);
- ProduceSignature(*pwallet, creator, out.scriptPubKey, sigdata);
- psbt_out.FromSignatureData(sigdata);
-
- // Get public key paths
- if (bip32derivs) {
- for (const auto& pubkey_it : sigdata.misc_pubkeys) {
- AddKeypathToMap(pwallet, pubkey_it.first, psbt_out.hd_keypaths);
- }
- }
- }
- return complete;
-}
-
UniValue walletprocesspsbt(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -4578,60 +3980,60 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
- "walletprocesspsbt \"psbt\" ( sign \"sighashtype\" bip32derivs )\n"
- "\nUpdate a PSBT with input information from our wallet and then sign inputs\n"
- "that we can sign for.\n"
- + HelpRequiringPassphrase(pwallet) + "\n"
-
- "\nArguments:\n"
- "1. \"psbt\" (string, required) The transaction base64 string\n"
- "2. sign (boolean, optional, default=true) Also sign the transaction when updating\n"
- "3. \"sighashtype\" (string, optional, default=ALL) The signature hash type to sign with if not specified by the PSBT. Must be one of\n"
+ RPCHelpMan{"walletprocesspsbt",
+ "\nUpdate a PSBT with input information from our wallet and then sign inputs\n"
+ "that we can sign for." +
+ HelpRequiringPassphrase(pwallet) + "\n",
+ {
+ {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction base64 string"},
+ {"sign", RPCArg::Type::BOOL, /* default */ "true", "Also sign the transaction when updating"},
+ {"sighashtype", RPCArg::Type::STR, /* default */ "ALL", "The signature hash type to sign with if not specified by the PSBT. Must be one of\n"
" \"ALL\"\n"
" \"NONE\"\n"
" \"SINGLE\"\n"
" \"ALL|ANYONECANPAY\"\n"
" \"NONE|ANYONECANPAY\"\n"
- " \"SINGLE|ANYONECANPAY\"\n"
- "4. bip32derivs (boolean, optiona, default=false) If true, includes the BIP 32 derivation paths for public keys if we know them\n"
-
- "\nResult:\n"
+ " \"SINGLE|ANYONECANPAY\""},
+ {"bip32derivs", RPCArg::Type::BOOL, /* default */ "false", "If true, includes the BIP 32 derivation paths for public keys if we know them"},
+ },
+ RPCResult{
"{\n"
" \"psbt\" : \"value\", (string) The base64-encoded partially signed transaction\n"
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
" ]\n"
"}\n"
-
- "\nExamples:\n"
- + HelpExampleCli("walletprocesspsbt", "\"psbt\"")
- );
+ },
+ RPCExamples{
+ HelpExampleCli("walletprocesspsbt", "\"psbt\"")
+ },
+ }.ToString());
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VSTR});
// Unserialize the transaction
PartiallySignedTransaction psbtx;
std::string error;
- if (!DecodePSBT(psbtx, request.params[0].get_str(), error)) {
+ if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}
// Get the sighash type
int nHashType = ParseSighashString(request.params[2]);
- // Use CTransaction for the constant parts of the
- // transaction to avoid rehashing.
- const CTransaction txConst(*psbtx.tx);
-
// Fill transaction with our data and also sign
bool sign = request.params[1].isNull() ? true : request.params[1].get_bool();
bool bip32derivs = request.params[3].isNull() ? false : request.params[3].get_bool();
- bool complete = FillPSBT(pwallet, psbtx, &txConst, nHashType, sign, bip32derivs);
+ bool complete = true;
+ const TransactionError err = FillPSBT(pwallet, psbtx, complete, nHashType, sign, bip32derivs);
+ if (err != TransactionError::OK) {
+ throw JSONRPCTransactionError(err);
+ }
UniValue result(UniValue::VOBJ);
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
- result.push_back(Pair("psbt", EncodeBase64((unsigned char*)ssTx.data(), ssTx.size())));
- result.push_back(Pair("complete", complete));
+ result.pushKV("psbt", EncodeBase64(ssTx.str()));
+ result.pushKV("complete", complete);
return result;
}
@@ -4645,201 +4047,192 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 2 || request.params.size() > 6)
+ if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
throw std::runtime_error(
- "walletcreatefundedpsbt [{\"txid\":\"id\",\"vout\":n},...] [{\"address\":amount},{\"data\":\"hex\"},...] ( locktime ) ( replaceable ) ( options bip32derivs )\n"
- "\nCreates and funds a transaction in the Partially Signed Transaction format. Inputs will be added if supplied inputs are not enough\n"
- "Implements the Creator and Updater roles.\n"
- "\nArguments:\n"
- "1. \"inputs\" (array, required) A json array of json objects\n"
- " [\n"
- " {\n"
- " \"txid\":\"id\", (string, required) The transaction id\n"
- " \"vout\":n, (numeric, required) The output number\n"
- " \"sequence\":n (numeric, optional) The sequence number\n"
- " } \n"
- " ,...\n"
- " ]\n"
- "2. \"outputs\" (array, required) a json array with outputs (key-value pairs)\n"
- " [\n"
- " {\n"
- " \"address\": x.xxx, (obj, optional) A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + "\n"
- " },\n"
- " {\n"
- " \"data\": \"hex\" (obj, optional) A key-value pair. The key must be \"data\", the value is hex encoded data\n"
- " }\n"
- " ,... More key-value pairs of the above form. For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
- " accepted as second parameter.\n"
- " ]\n"
- "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
- "4. replaceable (boolean, optional, default=false) 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.\n"
- "5. options (object, optional)\n"
- " {\n"
- " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
- " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
- " \"change_type\" (string, optional) The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -changetype.\n"
- " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
- " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
- " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific fee rate in " + CURRENCY_UNIT + "/kB\n"
- " \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
+ RPCHelpMan{"walletcreatefundedpsbt",
+ "\nCreates and funds a transaction in the Partially Signed Transaction format. Inputs will be added if supplied inputs are not enough\n"
+ "Implements the Creator and Updater roles.\n",
+ {
+ {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects",
+ {
+ {"", 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 number"},
+ {"sequence", RPCArg::Type::NUM, RPCArg::Optional::NO, "The sequence number"},
+ },
+ },
+ },
+ },
+ {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n"
+ "That is, each address can only appear once and there can only be one 'data' object.\n"
+ "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"
+ " accepted as second parameter.",
+ {
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + ""},
+ },
+ },
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"},
+ },
+ },
+ },
+ },
+ {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ {
+ {"changeAddress", RPCArg::Type::STR_HEX, /* default */ "pool address", "The bitcoin address to receive the change"},
+ {"changePosition", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"},
+ {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"includeWatching", RPCArg::Type::BOOL, /* default */ "false", "Also select inputs which are watch only"},
+ {"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"},
+ {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"},
+ {"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "A json array of integers.\n"
" The fee will be equally deducted from the amount of each specified output.\n"
- " The outputs are specified by their zero-based index, before any change output is added.\n"
" Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
- " If no outputs are specified here, the sender pays the fee.\n"
- " [vout_index,...]\n"
- " \"replaceable\" (boolean, optional) Marks this transaction as BIP125 replaceable.\n"
- " Allows this transaction to be replaced by a transaction with higher fees\n"
- " \"conf_target\" (numeric, optional) Confirmation target (in blocks)\n"
- " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
+ " If no outputs are specified here, the sender pays the fee.",
+ {
+ {"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
+ },
+ },
+ {"replaceable", RPCArg::Type::BOOL, /* default */ "false", "Marks this transaction as BIP125 replaceable.\n"
+ " Allows this transaction to be replaced by a transaction with higher fees"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "Fallback to wallet's confirmation target", "Confirmation target (in blocks)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
" \"UNSET\"\n"
" \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\"\n"
- " }\n"
- "6. bip32derivs (boolean, optiona, default=false) If true, includes the BIP 32 derivation paths for public keys if we know them\n"
- "\nResult:\n"
+ " \"CONSERVATIVE\""},
+ },
+ "options"},
+ {"bip32derivs", RPCArg::Type::BOOL, /* default */ "false", "If true, includes the BIP 32 derivation paths for public keys if we know them"},
+ },
+ RPCResult{
"{\n"
" \"psbt\": \"value\", (string) The resulting raw transaction (base64-encoded string)\n"
" \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
" \"changepos\": n (numeric) The position of the added change output, or -1\n"
"}\n"
- "\nExamples:\n"
+ },
+ RPCExamples{
"\nCreate a transaction with no inputs\n"
+ HelpExampleCli("walletcreatefundedpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
- );
+ },
+ }.ToString());
RPCTypeCheck(request.params, {
UniValue::VARR,
UniValueType(), // ARR or OBJ, checked later
UniValue::VNUM,
- UniValue::VBOOL,
- UniValue::VOBJ
+ UniValue::VOBJ,
+ UniValue::VBOOL
}, true
);
CAmount fee;
int change_position;
- CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3]);
- FundTransaction(pwallet, rawTx, fee, change_position, request.params[4]);
+ CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3]["replaceable"]);
+ FundTransaction(pwallet, rawTx, fee, change_position, request.params[3]);
// Make a blank psbt
- PartiallySignedTransaction psbtx;
- psbtx.tx = rawTx;
- for (unsigned int i = 0; i < rawTx.vin.size(); ++i) {
- psbtx.inputs.push_back(PSBTInput());
- }
- for (unsigned int i = 0; i < rawTx.vout.size(); ++i) {
- psbtx.outputs.push_back(PSBTOutput());
- }
-
- // Use CTransaction for the constant parts of the
- // transaction to avoid rehashing.
- const CTransaction txConst(*psbtx.tx);
+ PartiallySignedTransaction psbtx(rawTx);
// Fill transaction with out data but don't sign
- bool bip32derivs = request.params[5].isNull() ? false : request.params[5].get_bool();
- FillPSBT(pwallet, psbtx, &txConst, 1, false, bip32derivs);
+ bool bip32derivs = request.params[4].isNull() ? false : request.params[4].get_bool();
+ bool complete = true;
+ const TransactionError err = FillPSBT(pwallet, psbtx, complete, 1, false, bip32derivs);
+ if (err != TransactionError::OK) {
+ throw JSONRPCTransactionError(err);
+ }
// Serialize the PSBT
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
UniValue result(UniValue::VOBJ);
- result.pushKV("psbt", EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()));
+ result.pushKV("psbt", EncodeBase64(ssTx.str()));
result.pushKV("fee", ValueFromAmount(fee));
result.pushKV("changepos", change_position);
return result;
}
-extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
-extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
-extern UniValue importprivkey(const JSONRPCRequest& request);
-extern UniValue importaddress(const JSONRPCRequest& request);
-extern UniValue importpubkey(const JSONRPCRequest& request);
-extern UniValue dumpwallet(const JSONRPCRequest& request);
-extern UniValue importwallet(const JSONRPCRequest& request);
-extern UniValue importprunedfunds(const JSONRPCRequest& request);
-extern UniValue removeprunedfunds(const JSONRPCRequest& request);
-extern UniValue importmulti(const JSONRPCRequest& request);
-extern UniValue rescanblockchain(const JSONRPCRequest& request);
-
+UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
+UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
+UniValue importprivkey(const JSONRPCRequest& request);
+UniValue importaddress(const JSONRPCRequest& request);
+UniValue importpubkey(const JSONRPCRequest& request);
+UniValue dumpwallet(const JSONRPCRequest& request);
+UniValue importwallet(const JSONRPCRequest& request);
+UniValue importprunedfunds(const JSONRPCRequest& request);
+UniValue removeprunedfunds(const JSONRPCRequest& request);
+UniValue importmulti(const JSONRPCRequest& request);
+
+// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} },
- { "wallet", "walletprocesspsbt", &walletprocesspsbt, {"psbt","sign","sighashtype","bip32derivs"} },
- { "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","replaceable","options","bip32derivs"} },
- { "hidden", "resendwallettransactions", &resendwallettransactions, {} },
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
{ "wallet", "abortrescan", &abortrescan, {} },
- { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label|account","address_type"} },
- { "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
+ { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label","address_type"} },
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
- { "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys"} },
+ { "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase"} },
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
{ "wallet", "dumpwallet", &dumpwallet, {"filename"} },
{ "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
+ { "wallet", "getaddressesbylabel", &getaddressesbylabel, {"label"} },
{ "wallet", "getaddressinfo", &getaddressinfo, {"address"} },
- { "wallet", "getbalance", &getbalance, {"account|dummy","minconf","include_watchonly"} },
- { "wallet", "getnewaddress", &getnewaddress, {"label|account","address_type"} },
+ { "wallet", "getbalance", &getbalance, {"dummy","minconf","include_watchonly"} },
+ { "wallet", "getnewaddress", &getnewaddress, {"label","address_type"} },
{ "wallet", "getrawchangeaddress", &getrawchangeaddress, {"address_type"} },
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} },
+ { "wallet", "getreceivedbylabel", &getreceivedbylabel, {"label","minconf"} },
{ "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} },
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
+ { "wallet", "getbalances", &getbalances, {} },
{ "wallet", "getwalletinfo", &getwalletinfo, {} },
+ { "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
{ "wallet", "importmulti", &importmulti, {"requests","options"} },
{ "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} },
- { "wallet", "importwallet", &importwallet, {"filename"} },
- { "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
{ "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} },
{ "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} },
+ { "wallet", "importwallet", &importwallet, {"filename"} },
{ "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} },
{ "wallet", "listaddressgroupings", &listaddressgroupings, {} },
+ { "wallet", "listlabels", &listlabels, {"purpose"} },
{ "wallet", "listlockunspent", &listlockunspent, {} },
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly","address_filter"} },
+ { "wallet", "listreceivedbylabel", &listreceivedbylabel, {"minconf","include_empty","include_watchonly"} },
{ "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} },
- { "wallet", "listtransactions", &listtransactions, {"account|dummy","count","skip","include_watchonly"} },
+ { "wallet", "listtransactions", &listtransactions, {"label|dummy","count","skip","include_watchonly"} },
{ "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
+ { "wallet", "listwalletdir", &listwalletdir, {} },
{ "wallet", "listwallets", &listwallets, {} },
{ "wallet", "loadwallet", &loadwallet, {"filename"} },
{ "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
- { "wallet", "sendmany", &sendmany, {"fromaccount|dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
+ { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
+ { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
+ { "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
{ "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} },
+ { "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
+ { "wallet", "setlabel", &setlabel, {"address","label"} },
{ "wallet", "settxfee", &settxfee, {"amount"} },
{ "wallet", "signmessage", &signmessage, {"address","message"} },
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
{ "wallet", "unloadwallet", &unloadwallet, {"wallet_name"} },
+ { "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","options","bip32derivs"} },
{ "wallet", "walletlock", &walletlock, {} },
- { "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
- { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
- { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
- { "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
-
- /** Account functions (deprecated) */
- { "wallet", "getaccountaddress", &getaccountaddress, {"account"} },
- { "wallet", "getaccount", &getaccount, {"address"} },
- { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} },
- { "wallet", "getreceivedbyaccount", &getreceivedbylabel, {"account","minconf"} },
- { "wallet", "listaccounts", &listaccounts, {"minconf","include_watchonly"} },
- { "wallet", "listreceivedbyaccount", &listreceivedbylabel, {"minconf","include_empty","include_watchonly"} },
- { "wallet", "setaccount", &setlabel, {"address","account"} },
- { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
- { "wallet", "move", &movecmd, {"fromaccount","toaccount","amount","minconf","comment"} },
-
- /** Label functions (to replace non-balance account functions) */
- { "wallet", "getaddressesbylabel", &getaddressesbylabel, {"label"} },
- { "wallet", "getreceivedbylabel", &getreceivedbylabel, {"label","minconf"} },
- { "wallet", "listlabels", &listlabels, {"purpose"} },
- { "wallet", "listreceivedbylabel", &listreceivedbylabel, {"minconf","include_empty","include_watchonly"} },
- { "wallet", "setlabel", &setlabel, {"address","label"} },
-
- { "generating", "generate", &generate, {"nblocks","maxtries"} },
+ { "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
+ { "wallet", "walletprocesspsbt", &walletprocesspsbt, {"psbt","sign","sighashtype","bip32derivs"} },
};
+// clang-format on
-void RegisterWalletRPCCommands(CRPCTable &t)
+void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique_ptr<interfaces::Handler>>& handlers)
{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
- t.appendCommand(commands[vcidx].name, &commands[vcidx]);
+ handlers.emplace_back(chain.handleRpc(commands[vcidx]));
}
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index 64556b5824..1c0523c90b 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -1,11 +1,13 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_RPCWALLET_H
#define BITCOIN_WALLET_RPCWALLET_H
+#include <memory>
#include <string>
+#include <vector>
class CRPCTable;
class CWallet;
@@ -14,7 +16,12 @@ class UniValue;
struct PartiallySignedTransaction;
class CTransaction;
-void RegisterWalletRPCCommands(CRPCTable &t);
+namespace interfaces {
+class Chain;
+class Handler;
+}
+
+void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique_ptr<interfaces::Handler>>& handlers);
/**
* Figures out what wallet, if any, to use for a JSONRPCRequest.
@@ -24,11 +31,10 @@ void RegisterWalletRPCCommands(CRPCTable &t);
*/
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
-std::string HelpRequiringPassphrase(CWallet *);
-void EnsureWalletIsUnlocked(CWallet *);
-bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
+std::string HelpRequiringPassphrase(const CWallet*);
+void EnsureWalletIsUnlocked(const CWallet*);
+bool EnsureWalletIsAvailable(const CWallet*, bool avoidException);
UniValue getaddressinfo(const JSONRPCRequest& request);
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request);
-bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const CTransaction* txConst, int sighash_type = 1, bool sign = true, bool bip32derivs = false);
#endif //BITCOIN_WALLET_RPCWALLET_H
diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp
deleted file mode 100644
index cc6e491f53..0000000000
--- a/src/wallet/test/accounting_tests.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <wallet/wallet.h>
-
-#include <wallet/test/wallet_test_fixture.h>
-
-#include <stdint.h>
-
-#include <boost/test/unit_test.hpp>
-
-BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup)
-
-static void
-GetResults(CWallet& wallet, std::map<CAmount, CAccountingEntry>& results)
-{
- std::list<CAccountingEntry> aes;
-
- results.clear();
- BOOST_CHECK(wallet.ReorderTransactions() == DBErrors::LOAD_OK);
- wallet.ListAccountCreditDebit("", aes);
- for (CAccountingEntry& ae : aes)
- {
- results[ae.nOrderPos] = ae;
- }
-}
-
-BOOST_AUTO_TEST_CASE(acc_orderupgrade)
-{
- std::vector<CWalletTx*> vpwtx;
- CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
- CAccountingEntry ae;
- std::map<CAmount, CAccountingEntry> results;
-
- LOCK(m_wallet.cs_wallet);
-
- ae.strAccount = "";
- ae.nCreditDebit = 1;
- ae.nTime = 1333333333;
- ae.strOtherAccount = "b";
- ae.strComment = "";
- m_wallet.AddAccountingEntry(ae);
-
- wtx.mapValue["comment"] = "z";
- m_wallet.AddToWallet(wtx);
- vpwtx.push_back(&m_wallet.mapWallet.at(wtx.GetHash()));
- vpwtx[0]->nTimeReceived = (unsigned int)1333333335;
- vpwtx[0]->nOrderPos = -1;
-
- ae.nTime = 1333333336;
- ae.strOtherAccount = "c";
- m_wallet.AddAccountingEntry(ae);
-
- GetResults(m_wallet, results);
-
- BOOST_CHECK(m_wallet.nOrderPosNext == 3);
- BOOST_CHECK(2 == results.size());
- BOOST_CHECK(results[0].nTime == 1333333333);
- BOOST_CHECK(results[0].strComment.empty());
- BOOST_CHECK(1 == vpwtx[0]->nOrderPos);
- BOOST_CHECK(results[2].nTime == 1333333336);
- BOOST_CHECK(results[2].strOtherAccount == "c");
-
-
- ae.nTime = 1333333330;
- ae.strOtherAccount = "d";
- ae.nOrderPos = m_wallet.IncOrderPosNext();
- m_wallet.AddAccountingEntry(ae);
-
- GetResults(m_wallet, results);
-
- BOOST_CHECK(results.size() == 3);
- BOOST_CHECK(m_wallet.nOrderPosNext == 4);
- BOOST_CHECK(results[0].nTime == 1333333333);
- BOOST_CHECK(1 == vpwtx[0]->nOrderPos);
- BOOST_CHECK(results[2].nTime == 1333333336);
- BOOST_CHECK(results[3].nTime == 1333333330);
- BOOST_CHECK(results[3].strComment.empty());
-
-
- wtx.mapValue["comment"] = "y";
- {
- CMutableTransaction tx(*wtx.tx);
- ++tx.nLockTime; // Just to change the hash :)
- wtx.SetTx(MakeTransactionRef(std::move(tx)));
- }
- m_wallet.AddToWallet(wtx);
- vpwtx.push_back(&m_wallet.mapWallet.at(wtx.GetHash()));
- vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
-
- wtx.mapValue["comment"] = "x";
- {
- CMutableTransaction tx(*wtx.tx);
- ++tx.nLockTime; // Just to change the hash :)
- wtx.SetTx(MakeTransactionRef(std::move(tx)));
- }
- m_wallet.AddToWallet(wtx);
- vpwtx.push_back(&m_wallet.mapWallet.at(wtx.GetHash()));
- vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
- vpwtx[2]->nOrderPos = -1;
-
- GetResults(m_wallet, results);
-
- BOOST_CHECK(results.size() == 3);
- BOOST_CHECK(m_wallet.nOrderPosNext == 6);
- BOOST_CHECK(0 == vpwtx[2]->nOrderPos);
- BOOST_CHECK(results[1].nTime == 1333333333);
- BOOST_CHECK(2 == vpwtx[0]->nOrderPos);
- BOOST_CHECK(results[3].nTime == 1333333336);
- BOOST_CHECK(results[4].nTime == 1333333330);
- BOOST_CHECK(results[4].strComment.empty());
- BOOST_CHECK(5 == vpwtx[1]->nOrderPos);
-
-
- ae.nTime = 1333333334;
- ae.strOtherAccount = "e";
- ae.nOrderPos = -1;
- m_wallet.AddAccountingEntry(ae);
-
- GetResults(m_wallet, results);
-
- BOOST_CHECK(results.size() == 4);
- BOOST_CHECK(m_wallet.nOrderPosNext == 7);
- BOOST_CHECK(0 == vpwtx[2]->nOrderPos);
- BOOST_CHECK(results[1].nTime == 1333333333);
- BOOST_CHECK(2 == vpwtx[0]->nOrderPos);
- BOOST_CHECK(results[3].nTime == 1333333336);
- BOOST_CHECK(results[3].strComment.empty());
- BOOST_CHECK(results[4].nTime == 1333333330);
- BOOST_CHECK(results[4].strComment.empty());
- BOOST_CHECK(results[5].nTime == 1333333334);
- BOOST_CHECK(6 == vpwtx[1]->nOrderPos);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 1561760577..9e7f0ed773 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,7 +8,7 @@
#include <amount.h>
#include <primitives/transaction.h>
#include <random.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <wallet/test/wallet_test_fixture.h>
#include <boost/test/unit_test.hpp>
@@ -28,7 +28,8 @@ std::vector<std::unique_ptr<CWalletTx>> wtxn;
typedef std::set<CInputCoin> CoinSet;
static std::vector<COutput> vCoins;
-static CWallet testWallet("dummy", WalletDatabase::CreateDummy());
+static auto testChain = interfaces::MakeChain();
+static CWallet testWallet(testChain.get(), WalletLocation(), WalletDatabase::CreateDummy());
static CAmount balance = 0;
CoinEligibilityFilter filter_standard(1, 6, 0);
@@ -65,11 +66,10 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa
// so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
tx.vin.resize(1);
}
- std::unique_ptr<CWalletTx> wtx(new CWalletTx(&testWallet, MakeTransactionRef(std::move(tx))));
+ std::unique_ptr<CWalletTx> wtx = MakeUnique<CWalletTx>(&testWallet, MakeTransactionRef(std::move(tx)));
if (fIsFromMe)
{
- wtx->fDebitCached = true;
- wtx->nDebitCached = 1;
+ wtx->m_amounts[CWalletTx::DEBIT].Set(ISMINE_SPENDABLE, 1);
}
COutput output(wtx.get(), nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
vCoins.push_back(output);
@@ -114,7 +114,7 @@ inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& coins)
{
static std::vector<OutputGroup> static_groups;
static_groups.clear();
- for (auto& coin : coins) static_groups.emplace_back(coin.GetInputCoin(), coin.nDepth, coin.tx->fDebitCached && coin.tx->nDebitCached == 1 /* HACK: we can't figure out the is_me flag so we use the conditions defined above; perhaps set safe to false for !fIsFromMe in add_coin() */, 0, 0);
+ for (auto& coin : coins) static_groups.emplace_back(coin.GetInputCoin(), coin.nDepth, coin.tx->m_amounts[CWalletTx::DEBIT].m_cached[ISMINE_SPENDABLE] && coin.tx->m_amounts[CWalletTx::DEBIT].m_value[ISMINE_SPENDABLE] == 1 /* HACK: we can't figure out the is_me flag so we use the conditions defined above; perhaps set safe to false for !fIsFromMe in add_coin() */, 0, 0);
return static_groups;
}
@@ -134,7 +134,6 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
/////////////////////////
// Known Outcome tests //
/////////////////////////
- BOOST_TEST_MESSAGE("Testing known outcomes");
// Empty utxo pool
BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), 1 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
@@ -150,6 +149,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
add_coin(1 * CENT, 1, actual_selection);
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 1 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
BOOST_CHECK(equal_sets(selection, actual_selection));
+ BOOST_CHECK_EQUAL(value_ret, 1 * CENT);
actual_selection.clear();
selection.clear();
@@ -157,6 +157,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
add_coin(2 * CENT, 2, actual_selection);
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 2 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
BOOST_CHECK(equal_sets(selection, actual_selection));
+ BOOST_CHECK_EQUAL(value_ret, 2 * CENT);
actual_selection.clear();
selection.clear();
@@ -165,6 +166,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
add_coin(2 * CENT, 2, actual_selection);
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 5 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
BOOST_CHECK(equal_sets(selection, actual_selection));
+ BOOST_CHECK_EQUAL(value_ret, 5 * CENT);
actual_selection.clear();
selection.clear();
@@ -181,6 +183,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
add_coin(1 * CENT, 1, actual_selection);
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 10 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
BOOST_CHECK(equal_sets(selection, actual_selection));
+ BOOST_CHECK_EQUAL(value_ret, 10 * CENT);
actual_selection.clear();
selection.clear();
@@ -190,6 +193,9 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
add_coin(3 * CENT, 3, actual_selection);
add_coin(2 * CENT, 2, actual_selection);
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 10 * CENT, 5000, selection, value_ret, not_input_fees));
+ BOOST_CHECK_EQUAL(value_ret, 10 * CENT);
+ // FIXME: this test is redundant with the above, because 1 Cent is selected, not "too small"
+ // BOOST_CHECK(equal_sets(selection, actual_selection));
// Select 0.25 Cent, not possible
BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), 0.25 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
@@ -203,6 +209,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), target, 0, selection, value_ret, not_input_fees)); // Should not exhaust
// Test same value early bailout optimization
+ utxo_pool.clear();
add_coin(7 * CENT, 7, actual_selection);
add_coin(7 * CENT, 7, actual_selection);
add_coin(7 * CENT, 7, actual_selection);
@@ -217,6 +224,8 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
add_coin(5 * CENT, 7, utxo_pool);
}
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 30 * CENT, 5000, selection, value_ret, not_input_fees));
+ BOOST_CHECK_EQUAL(value_ret, 30 * CENT);
+ BOOST_CHECK(equal_sets(selection, actual_selection));
////////////////////
// Behavior tests //
@@ -452,14 +461,19 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
BOOST_CHECK(testWallet.SelectCoinsMinConf(MIN_CHANGE * 9990 / 100, filter_confirmed, GroupCoins(vCoins), setCoinsRet, nValueRet, coin_selection_params, bnb_used));
BOOST_CHECK_EQUAL(nValueRet, 101 * MIN_CHANGE);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U);
+ }
+
+ // test with many inputs
+ for (CAmount amt=1500; amt < COIN; amt*=10) {
+ empty_wallet();
+ // Create 676 inputs (= (old MAX_STANDARD_TX_SIZE == 100000) / 148 bytes per input)
+ for (uint16_t j = 0; j < 676; j++)
+ add_coin(amt);
- // test with many inputs
- for (CAmount amt=1500; amt < COIN; amt*=10) {
- empty_wallet();
- // Create 676 inputs (= (old MAX_STANDARD_TX_SIZE == 100000) / 148 bytes per input)
- for (uint16_t j = 0; j < 676; j++)
- add_coin(amt);
+ // We only create the wallet once to save time, but we still run the coin selection RUN_TESTS times.
+ for (int i = 0; i < RUN_TESTS; i++) {
BOOST_CHECK(testWallet.SelectCoinsMinConf(2000, filter_confirmed, GroupCoins(vCoins), setCoinsRet, nValueRet, coin_selection_params, bnb_used));
+
if (amt - 2000 < MIN_CHANGE) {
// needs more than one input:
uint16_t returnSize = std::ceil((2000.0 + MIN_CHANGE)/amt);
@@ -471,14 +485,17 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
BOOST_CHECK_EQUAL(nValueRet, amt);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
}
- }
+ }
+ }
- // test randomness
- {
- empty_wallet();
- for (int i2 = 0; i2 < 100; i2++)
- add_coin(COIN);
+ // test randomness
+ {
+ empty_wallet();
+ for (int i2 = 0; i2 < 100; i2++)
+ add_coin(COIN);
+ // Again, we only create the wallet once to save time, but we still run the coin selection RUN_TESTS times.
+ for (int i = 0; i < RUN_TESTS; i++) {
// picking 50 from 100 coins doesn't depend on the shuffle,
// but does depend on randomness in the stochastic approximation code
BOOST_CHECK(testWallet.SelectCoinsMinConf(50 * COIN, filter_standard, GroupCoins(vCoins), setCoinsRet , nValueRet, coin_selection_params, bnb_used));
@@ -496,17 +513,19 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
fails++;
}
BOOST_CHECK_NE(fails, RANDOM_REPEATS);
-
- // add 75 cents in small change. not enough to make 90 cents,
- // then try making 90 cents. there are multiple competing "smallest bigger" coins,
- // one of which should be picked at random
- add_coin(5 * CENT);
- add_coin(10 * CENT);
- add_coin(15 * CENT);
- add_coin(20 * CENT);
- add_coin(25 * CENT);
-
- fails = 0;
+ }
+
+ // add 75 cents in small change. not enough to make 90 cents,
+ // then try making 90 cents. there are multiple competing "smallest bigger" coins,
+ // one of which should be picked at random
+ add_coin(5 * CENT);
+ add_coin(10 * CENT);
+ add_coin(15 * CENT);
+ add_coin(20 * CENT);
+ add_coin(25 * CENT);
+
+ for (int i = 0; i < RUN_TESTS; i++) {
+ int fails = 0;
for (int j = 0; j < RANDOM_REPEATS; j++)
{
// selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
@@ -517,8 +536,9 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
fails++;
}
BOOST_CHECK_NE(fails, RANDOM_REPEATS);
- }
- }
+ }
+ }
+
empty_wallet();
}
diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp
new file mode 100644
index 0000000000..e4950af4e5
--- /dev/null
+++ b/src/wallet/test/db_tests.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <memory>
+
+#include <boost/test/unit_test.hpp>
+
+#include <fs.h>
+#include <test/setup_common.h>
+#include <wallet/db.h>
+
+
+BOOST_FIXTURE_TEST_SUITE(db_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(getwalletenv_file)
+{
+ std::string test_name = "test_name.dat";
+ fs::path datadir = SetDataDir("tempdir");
+ fs::path file_path = datadir / test_name;
+ std::ofstream f(file_path.BOOST_FILESYSTEM_C_STR);
+ f.close();
+
+ std::string filename;
+ std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, filename);
+ BOOST_CHECK(filename == test_name);
+ BOOST_CHECK(env->Directory() == datadir);
+}
+
+BOOST_AUTO_TEST_CASE(getwalletenv_directory)
+{
+ std::string expected_name = "wallet.dat";
+ fs::path datadir = SetDataDir("tempdir");
+
+ std::string filename;
+ std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(datadir, filename);
+ BOOST_CHECK(filename == expected_name);
+ BOOST_CHECK(env->Directory() == datadir);
+}
+
+BOOST_AUTO_TEST_CASE(getwalletenv_g_dbenvs_multiple)
+{
+ fs::path datadir = SetDataDir("tempdir");
+ fs::path datadir_2 = SetDataDir("tempdir_2");
+ std::string filename;
+
+ std::shared_ptr<BerkeleyEnvironment> env_1 = GetWalletEnv(datadir, filename);
+ std::shared_ptr<BerkeleyEnvironment> env_2 = GetWalletEnv(datadir, filename);
+ std::shared_ptr<BerkeleyEnvironment> env_3 = GetWalletEnv(datadir_2, filename);
+
+ BOOST_CHECK(env_1 == env_2);
+ BOOST_CHECK(env_2 != env_3);
+}
+
+BOOST_AUTO_TEST_CASE(getwalletenv_g_dbenvs_free_instance)
+{
+ fs::path datadir = SetDataDir("tempdir");
+ fs::path datadir_2 = SetDataDir("tempdir_2");
+ std::string filename;
+
+ std::shared_ptr <BerkeleyEnvironment> env_1_a = GetWalletEnv(datadir, filename);
+ std::shared_ptr <BerkeleyEnvironment> env_2_a = GetWalletEnv(datadir_2, filename);
+ env_1_a.reset();
+
+ std::shared_ptr<BerkeleyEnvironment> env_1_b = GetWalletEnv(datadir, filename);
+ std::shared_ptr<BerkeleyEnvironment> env_2_b = GetWalletEnv(datadir_2, filename);
+
+ BOOST_CHECK(env_1_a != env_1_b);
+ BOOST_CHECK(env_2_a == env_2_b);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/test/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp
new file mode 100644
index 0000000000..3b828d57f9
--- /dev/null
+++ b/src/wallet/test/init_test_fixture.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <fs.h>
+
+#include <wallet/test/init_test_fixture.h>
+
+InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName): BasicTestingSetup(chainName)
+{
+ m_chain_client = MakeWalletClient(*m_chain, {});
+
+ std::string sep;
+ sep += fs::path::preferred_separator;
+
+ m_datadir = SetDataDir("tempdir");
+ m_cwd = fs::current_path();
+
+ m_walletdir_path_cases["default"] = m_datadir / "wallets";
+ m_walletdir_path_cases["custom"] = m_datadir / "my_wallets";
+ m_walletdir_path_cases["nonexistent"] = m_datadir / "path_does_not_exist";
+ m_walletdir_path_cases["file"] = m_datadir / "not_a_directory.dat";
+ m_walletdir_path_cases["trailing"] = m_datadir / "wallets" / sep;
+ m_walletdir_path_cases["trailing2"] = m_datadir / "wallets" / sep / sep;
+
+ fs::current_path(m_datadir);
+ m_walletdir_path_cases["relative"] = "wallets";
+
+ fs::create_directories(m_walletdir_path_cases["default"]);
+ fs::create_directories(m_walletdir_path_cases["custom"]);
+ fs::create_directories(m_walletdir_path_cases["relative"]);
+ std::ofstream f(m_walletdir_path_cases["file"].BOOST_FILESYSTEM_C_STR);
+ f.close();
+}
+
+InitWalletDirTestingSetup::~InitWalletDirTestingSetup()
+{
+ fs::current_path(m_cwd);
+}
+
+void InitWalletDirTestingSetup::SetWalletDir(const fs::path& walletdir_path)
+{
+ gArgs.ForceSetArg("-walletdir", walletdir_path.string());
+} \ No newline at end of file
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
new file mode 100644
index 0000000000..e2b7075085
--- /dev/null
+++ b/src/wallet/test/init_test_fixture.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
+#define BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
+
+#include <interfaces/chain.h>
+#include <test/setup_common.h>
+
+
+struct InitWalletDirTestingSetup: public BasicTestingSetup {
+ explicit InitWalletDirTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ ~InitWalletDirTestingSetup();
+ void SetWalletDir(const fs::path& walletdir_path);
+
+ fs::path m_datadir;
+ fs::path m_cwd;
+ std::map<std::string, fs::path> m_walletdir_path_cases;
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
+ std::unique_ptr<interfaces::ChainClient> m_chain_client;
+};
+
+#endif // BITCOIN_WALLET_TEST_INIT_TEST_FIXTURE_H
diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp
new file mode 100644
index 0000000000..9e5208b453
--- /dev/null
+++ b/src/wallet/test/init_tests.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2018-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <boost/test/unit_test.hpp>
+
+#include <test/setup_common.h>
+#include <wallet/test/init_test_fixture.h>
+
+#include <init.h>
+#include <walletinitinterface.h>
+#include <wallet/wallet.h>
+
+
+BOOST_FIXTURE_TEST_SUITE(init_tests, InitWalletDirTestingSetup)
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default)
+{
+ SetWalletDir(m_walletdir_path_cases["default"]);
+ bool result = m_chain_client->verify();
+ BOOST_CHECK(result == true);
+ fs::path walletdir = gArgs.GetArg("-walletdir", "");
+ fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
+ BOOST_CHECK(walletdir == expected_path);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom)
+{
+ SetWalletDir(m_walletdir_path_cases["custom"]);
+ bool result = m_chain_client->verify();
+ BOOST_CHECK(result == true);
+ fs::path walletdir = gArgs.GetArg("-walletdir", "");
+ fs::path expected_path = fs::canonical(m_walletdir_path_cases["custom"]);
+ BOOST_CHECK(walletdir == expected_path);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_does_not_exist)
+{
+ SetWalletDir(m_walletdir_path_cases["nonexistent"]);
+ bool result = m_chain_client->verify();
+ BOOST_CHECK(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_directory)
+{
+ SetWalletDir(m_walletdir_path_cases["file"]);
+ bool result = m_chain_client->verify();
+ BOOST_CHECK(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_relative)
+{
+ SetWalletDir(m_walletdir_path_cases["relative"]);
+ bool result = m_chain_client->verify();
+ BOOST_CHECK(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing)
+{
+ SetWalletDir(m_walletdir_path_cases["trailing"]);
+ bool result = m_chain_client->verify();
+ BOOST_CHECK(result == true);
+ fs::path walletdir = gArgs.GetArg("-walletdir", "");
+ fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
+ BOOST_CHECK(walletdir == expected_path);
+}
+
+BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing2)
+{
+ SetWalletDir(m_walletdir_path_cases["trailing2"]);
+ bool result = m_chain_client->verify();
+ BOOST_CHECK(result == true);
+ fs::path walletdir = gArgs.GetArg("-walletdir", "");
+ fs::path expected_path = fs::canonical(m_walletdir_path_cases["default"]);
+ BOOST_CHECK(walletdir == expected_path);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
index 2cc995bf04..4753c7f313 100644
--- a/src/wallet/test/psbt_wallet_tests.cpp
+++ b/src/wallet/test/psbt_wallet_tests.cpp
@@ -1,24 +1,26 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <key_io.h>
#include <script/sign.h>
-#include <utilstrencodings.h>
+#include <util/bip32.h>
+#include <util/strencodings.h>
+#include <wallet/psbtwallet.h>
#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
#include <univalue.h>
#include <boost/test/unit_test.hpp>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <wallet/test/wallet_test_fixture.h>
-extern bool ParseHDKeypath(std::string keypath_str, std::vector<uint32_t>& keypath);
-
BOOST_FIXTURE_TEST_SUITE(psbt_wallet_tests, WalletTestingSetup)
BOOST_AUTO_TEST_CASE(psbt_updater_test)
{
+ LOCK(m_wallet.cs_wallet);
+
// Create prevtxs and add to wallet
CDataStream s_prev_tx1(ParseHex("0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7501000000171600145f275f436b09a8cc9a2eb2a2f528485c68a56323feffffff02d8231f1b0100000017a914aed962d6654f9a2b36608eb9d64d2b260db4f1118700c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88702483045022100a22edcc6e5bc511af4cc4ae0de0fcd75c7e04d8c1c3a8aa9d820ed4b967384ec02200642963597b9b1bc22c75e9f3e117284a962188bf5e8a74c895089046a20ad770121035509a48eb623e10aace8bfd0212fdb8a8e5af3c94b0b133b95e114cab89e4f7965000000"), SER_NETWORK, PROTOCOL_VERSION);
CTransactionRef prev_tx1;
@@ -59,12 +61,9 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test)
CDataStream ssData(ParseHex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000"), SER_NETWORK, PROTOCOL_VERSION);
ssData >> psbtx;
- // Use CTransaction for the constant parts of the
- // transaction to avoid rehashing.
- const CTransaction txConst(*psbtx.tx);
-
// Fill transaction with our data
- FillPSBT(&m_wallet, psbtx, &txConst, 1, false, true);
+ bool complete = true;
+ BOOST_REQUIRE_EQUAL(TransactionError::OK, FillPSBT(&m_wallet, psbtx, complete, SIGHASH_ALL, false, true));
// Get the final tx
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
diff --git a/src/wallet/test/wallet_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp
index e04c0af1dd..2f41813234 100644
--- a/src/wallet/test/wallet_crypto_tests.cpp
+++ b/src/wallet/test/wallet_crypto_tests.cpp
@@ -1,9 +1,9 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <test/test_bitcoin.h>
-#include <utilstrencodings.h>
+#include <test/setup_common.h>
+#include <util/strencodings.h>
#include <wallet/crypter.h>
#include <vector>
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index 6129e337ce..e352c81519 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -6,18 +6,15 @@
#include <rpc/server.h>
#include <wallet/db.h>
+#include <wallet/rpcwallet.h>
-WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
- TestingSetup(chainName), m_wallet("mock", WalletDatabase::CreateMock())
+WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
+ : TestingSetup(chainName),
+ m_wallet(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock())
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
- RegisterValidationInterface(&m_wallet);
+ m_wallet.handleNotifications();
- RegisterWalletRPCCommands(tableRPC);
-}
-
-WalletTestingSetup::~WalletTestingSetup()
-{
- UnregisterValidationInterface(&m_wallet);
+ m_chain_client->registerRpcs();
}
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index b328b3543b..c1dbecdf8c 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -1,12 +1,14 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H
#define BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
+#include <interfaces/chain.h>
+#include <interfaces/wallet.h>
#include <wallet/wallet.h>
#include <memory>
@@ -15,8 +17,9 @@
*/
struct WalletTestingSetup: public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
- ~WalletTestingSetup();
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
+ std::unique_ptr<interfaces::ChainClient> m_chain_client = interfaces::MakeWalletClient(*m_chain, {});
CWallet m_wallet;
};
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index c89b8f252f..62630c011a 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,8 +11,10 @@
#include <vector>
#include <consensus/validation.h>
+#include <interfaces/chain.h>
+#include <policy/policy.h>
#include <rpc/server.h>
-#include <test/test_bitcoin.h>
+#include <test/setup_common.h>
#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/test/wallet_test_fixture.h>
@@ -32,26 +34,45 @@ static void AddKey(CWallet& wallet, const CKey& key)
wallet.AddKeyPubKey(key, key.GetPubKey());
}
-BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
+BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
{
// Cap last block file size, and mine new block in a new block file.
- CBlockIndex* const nullBlock = nullptr;
- CBlockIndex* oldTip = chainActive.Tip();
+ CBlockIndex* oldTip = ::ChainActive().Tip();
GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- CBlockIndex* newTip = chainActive.Tip();
+ CBlockIndex* newTip = ::ChainActive().Tip();
- LOCK(cs_main);
+ auto chain = interfaces::MakeChain();
+ auto locked_chain = chain->lock();
+ LockAnnotation lock(::cs_main);
+
+ // Verify ScanForWalletTransactions accommodates a null start block.
+ {
+ CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
+ AddKey(wallet, coinbaseKey);
+ WalletRescanReserver reserver(&wallet);
+ reserver.reserve();
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions({} /* start_block */, {} /* stop_block */, reserver, false /* update */);
+ BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
+ BOOST_CHECK(result.last_failed_block.IsNull());
+ BOOST_CHECK(result.last_scanned_block.IsNull());
+ BOOST_CHECK(!result.last_scanned_height);
+ BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 0);
+ }
// Verify ScanForWalletTransactions picks up transactions in both the old
// and new block files.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet);
reserver.reserve();
- BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip, nullptr, reserver));
- BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), {} /* stop_block */, reserver, false /* update */);
+ BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
+ BOOST_CHECK(result.last_failed_block.IsNull());
+ BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
+ BOOST_CHECK_EQUAL(*result.last_scanned_height, newTip->nHeight);
+ BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 100 * COIN);
}
// Prune the older block file.
@@ -61,19 +82,58 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// Verify ScanForWalletTransactions only picks transactions in the new block
// file.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(&wallet);
reserver.reserve();
- BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip, nullptr, reserver));
- BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), {} /* stop_block */, reserver, false /* update */);
+ BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::FAILURE);
+ BOOST_CHECK_EQUAL(result.last_failed_block, oldTip->GetBlockHash());
+ BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
+ BOOST_CHECK_EQUAL(*result.last_scanned_height, newTip->nHeight);
+ BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 50 * COIN);
}
+ // Prune the remaining block file.
+ PruneOneBlockFile(newTip->GetBlockPos().nFile);
+ UnlinkPrunedFiles({newTip->GetBlockPos().nFile});
+
+ // Verify ScanForWalletTransactions scans no blocks.
+ {
+ CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
+ AddKey(wallet, coinbaseKey);
+ WalletRescanReserver reserver(&wallet);
+ reserver.reserve();
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), {} /* stop_block */, reserver, false /* update */);
+ BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::FAILURE);
+ BOOST_CHECK_EQUAL(result.last_failed_block, newTip->GetBlockHash());
+ BOOST_CHECK(result.last_scanned_block.IsNull());
+ BOOST_CHECK(!result.last_scanned_height);
+ BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 0);
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
+{
+ // Cap last block file size, and mine new block in a new block file.
+ CBlockIndex* oldTip = ::ChainActive().Tip();
+ GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE;
+ CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+ CBlockIndex* newTip = ::ChainActive().Tip();
+
+ auto chain = interfaces::MakeChain();
+ auto locked_chain = chain->lock();
+ LockAnnotation lock(::cs_main);
+
+ // Prune the older block file.
+ PruneOneBlockFile(oldTip->GetBlockPos().nFile);
+ UnlinkPrunedFiles({oldTip->GetBlockPos().nFile});
+
// Verify importmulti RPC returns failure for a key whose creation time is
// before the missing block, and success for a key whose creation time is
// after.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
AddWallet(wallet);
UniValue keys;
keys.setArray();
@@ -117,7 +177,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
{
// Create two blocks with same timestamp to verify that importwallet rescan
// will pick up both blocks, not just the first.
- const int64_t BLOCK_TIME = chainActive.Tip()->GetBlockTimeMax() + 5;
+ const int64_t BLOCK_TIME = ::ChainActive().Tip()->GetBlockTimeMax() + 5;
SetMockTime(BLOCK_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
@@ -128,13 +188,15 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(KEY_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
- LOCK(cs_main);
+ auto chain = interfaces::MakeChain();
+ auto locked_chain = chain->lock();
+ LockAnnotation lock(::cs_main);
std::string backup_file = (SetDataDir("importwallet_rescan") / "wallet.backup").string();
// Import key into wallet and call dumpwallet to create backup file.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
LOCK(wallet->cs_wallet);
wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
@@ -150,7 +212,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
// were scanned, and no prior blocks were scanned.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
JSONRPCRequest request;
request.params.setArray();
@@ -180,21 +242,27 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// debit functions.
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ auto chain = interfaces::MakeChain();
+
+ CWallet wallet(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
CWalletTx wtx(&wallet, m_coinbase_txns.back());
- LOCK2(cs_main, wallet.cs_wallet);
- wtx.hashBlock = chainActive.Tip()->GetBlockHash();
+
+ auto locked_chain = chain->lock();
+ LockAnnotation lock(::cs_main);
+ LOCK(wallet.cs_wallet);
+
+ wtx.hashBlock = ::ChainActive().Tip()->GetBlockHash();
wtx.nIndex = 0;
// Call GetImmatureCredit() once before adding the key to the wallet to
// cache the current immature credit amount, which is 0.
- BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 0);
+ BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 0);
// Invalidate the cached value, add the key, and make sure a new immature
// credit amount is calculated.
wtx.MarkDirty();
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
- BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 50*COIN);
+ BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(*locked_chain), 50*COIN);
}
static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)
@@ -204,7 +272,8 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
SetMockTime(mockTime);
CBlockIndex* block = nullptr;
if (blockTime > 0) {
- LOCK(cs_main);
+ LockAnnotation lock(::cs_main);
+ auto locked_chain = wallet.chain().lock();
auto inserted = mapBlockIndex.emplace(GetRandHash(), new CBlockIndex);
assert(inserted.second);
const uint256& hash = inserted.first->first;
@@ -215,7 +284,7 @@ static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64
CWalletTx wtx(&wallet, MakeTransactionRef(tx));
if (block) {
- wtx.SetMerkleBranch(block, 0);
+ wtx.SetMerkleBranch(block->GetBlockHash(), 0);
}
{
LOCK(cs_main);
@@ -255,7 +324,7 @@ BOOST_AUTO_TEST_CASE(ComputeTimeSmart)
BOOST_AUTO_TEST_CASE(LoadReceiveRequests)
{
- CTxDestination dest = CKeyID();
+ CTxDestination dest = PKHash();
LOCK(m_wallet.cs_wallet);
m_wallet.AddDestData(dest, "misc", "val_misc");
m_wallet.AddDestData(dest, "rr0", "val_rr0");
@@ -273,13 +342,17 @@ public:
ListCoinsTestingSetup()
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- wallet = MakeUnique<CWallet>("mock", WalletDatabase::CreateMock());
+ wallet = MakeUnique<CWallet>(m_chain.get(), WalletLocation(), WalletDatabase::CreateMock());
bool firstRun;
wallet->LoadWallet(firstRun);
AddKey(*wallet, coinbaseKey);
WalletRescanReserver reserver(wallet.get());
reserver.reserve();
- wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver);
+ CWallet::ScanResult result = wallet->ScanForWalletTransactions(::ChainActive().Genesis()->GetBlockHash(), {} /* stop_block */, reserver, false /* update */);
+ BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
+ BOOST_CHECK_EQUAL(result.last_scanned_block, ::ChainActive().Tip()->GetBlockHash());
+ BOOST_CHECK_EQUAL(*result.last_scanned_height, ::ChainActive().Height());
+ BOOST_CHECK(result.last_failed_block.IsNull());
}
~ListCoinsTestingSetup()
@@ -295,22 +368,28 @@ public:
int changePos = -1;
std::string error;
CCoinControl dummy;
- BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, reservekey, fee, changePos, error, dummy));
+ {
+ auto locked_chain = m_chain->lock();
+ BOOST_CHECK(wallet->CreateTransaction(*locked_chain, {recipient}, tx, reservekey, fee, changePos, error, dummy));
+ }
CValidationState state;
- BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, {}, reservekey, nullptr, state));
+ BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, reservekey, state));
CMutableTransaction blocktx;
{
LOCK(wallet->cs_wallet);
blocktx = CMutableTransaction(*wallet->mapWallet.at(tx->GetHash()).tx);
}
CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+
+ LOCK(cs_main);
LOCK(wallet->cs_wallet);
auto it = wallet->mapWallet.find(tx->GetHash());
BOOST_CHECK(it != wallet->mapWallet.end());
- it->second.SetMerkleBranch(chainActive.Tip(), 1);
+ it->second.SetMerkleBranch(::ChainActive().Tip()->GetBlockHash(), 1);
return it->second;
}
+ std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain();
std::unique_ptr<CWallet> wallet;
};
@@ -320,9 +399,14 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
// Confirm ListCoins initially returns 1 coin grouped under coinbaseKey
// address.
- auto list = wallet->ListCoins();
+ std::map<CTxDestination, std::vector<COutput>> list;
+ {
+ auto locked_chain = m_chain->lock();
+ LOCK(wallet->cs_wallet);
+ list = wallet->ListCoins(*locked_chain);
+ }
BOOST_CHECK_EQUAL(list.size(), 1U);
- BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(), coinbaseAddress);
+ BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
BOOST_CHECK_EQUAL(list.begin()->second.size(), 1U);
// Check initial balance from one mature coinbase transaction.
@@ -333,16 +417,21 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
// coinbaseKey pubkey, even though the change address has a different
// pubkey.
AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN, false /* subtract fee */});
- list = wallet->ListCoins();
+ {
+ auto locked_chain = m_chain->lock();
+ LOCK(wallet->cs_wallet);
+ list = wallet->ListCoins(*locked_chain);
+ }
BOOST_CHECK_EQUAL(list.size(), 1U);
- BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(), coinbaseAddress);
+ BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
BOOST_CHECK_EQUAL(list.begin()->second.size(), 2U);
// Lock both coins. Confirm number of available coins drops to 0.
{
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = m_chain->lock();
+ LOCK(wallet->cs_wallet);
std::vector<COutput> available;
- wallet->AvailableCoins(available);
+ wallet->AvailableCoins(*locked_chain, available);
BOOST_CHECK_EQUAL(available.size(), 2U);
}
for (const auto& group : list) {
@@ -352,26 +441,76 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
}
}
{
- LOCK2(cs_main, wallet->cs_wallet);
+ auto locked_chain = m_chain->lock();
+ LOCK(wallet->cs_wallet);
std::vector<COutput> available;
- wallet->AvailableCoins(available);
+ wallet->AvailableCoins(*locked_chain, available);
BOOST_CHECK_EQUAL(available.size(), 0U);
}
// Confirm ListCoins still returns same result as before, despite coins
// being locked.
- list = wallet->ListCoins();
+ {
+ auto locked_chain = m_chain->lock();
+ LOCK(wallet->cs_wallet);
+ list = wallet->ListCoins(*locked_chain);
+ }
BOOST_CHECK_EQUAL(list.size(), 1U);
- BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(), coinbaseAddress);
+ BOOST_CHECK_EQUAL(boost::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
BOOST_CHECK_EQUAL(list.begin()->second.size(), 2U);
}
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ auto chain = interfaces::MakeChain();
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), WalletLocation(), WalletDatabase::CreateDummy());
+ wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
BOOST_CHECK(!wallet->TopUpKeyPool(1000));
CPubKey pubkey;
BOOST_CHECK(!wallet->GetKeyFromPool(pubkey, false));
}
+// Explicit calculation which is used to test the wallet constant
+// We get the same virtual size due to rounding(weight/4) for both use_max_sig values
+static size_t CalculateNestedKeyhashInputSize(bool use_max_sig)
+{
+ // Generate ephemeral valid pubkey
+ CKey key;
+ key.MakeNewKey(true);
+ CPubKey pubkey = key.GetPubKey();
+
+ // Generate pubkey hash
+ uint160 key_hash(Hash160(pubkey.begin(), pubkey.end()));
+
+ // Create inner-script to enter into keystore. Key hash can't be 0...
+ CScript inner_script = CScript() << OP_0 << std::vector<unsigned char>(key_hash.begin(), key_hash.end());
+
+ // Create outer P2SH script for the output
+ uint160 script_id(Hash160(inner_script.begin(), inner_script.end()));
+ CScript script_pubkey = CScript() << OP_HASH160 << std::vector<unsigned char>(script_id.begin(), script_id.end()) << OP_EQUAL;
+
+ // Add inner-script to key store and key to watchonly
+ CBasicKeyStore keystore;
+ keystore.AddCScript(inner_script);
+ keystore.AddKeyPubKey(key, pubkey);
+
+ // Fill in dummy signatures for fee calculation.
+ SignatureData sig_data;
+
+ if (!ProduceSignature(keystore, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, script_pubkey, sig_data)) {
+ // We're hand-feeding it correct arguments; shouldn't happen
+ assert(false);
+ }
+
+ CTxIn tx_in;
+ UpdateInput(tx_in, sig_data);
+ return (size_t)GetVirtualTransactionInputSize(tx_in);
+}
+
+BOOST_FIXTURE_TEST_CASE(dummy_input_size_test, TestChain100Setup)
+{
+ BOOST_CHECK_EQUAL(CalculateNestedKeyhashInputSize(false), DUMMY_NESTED_P2WPKH_INPUT_SIZE);
+ BOOST_CHECK_EQUAL(CalculateNestedKeyhashInputSize(true), DUMMY_NESTED_P2WPKH_INPUT_SIZE);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 218684fdf1..260617c666 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1,33 +1,39 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <wallet/wallet.h>
-#include <checkpoints.h>
#include <chain.h>
-#include <wallet/coincontrol.h>
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <fs.h>
+#include <interfaces/chain.h>
+#include <interfaces/wallet.h>
#include <key.h>
#include <key_io.h>
#include <keystore.h>
-#include <validation.h>
#include <net.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/rbf.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
+#include <script/descriptor.h>
#include <script/script.h>
#include <shutdown.h>
#include <timedata.h>
#include <txmempool.h>
-#include <utilmoneystr.h>
+#include <util/bip32.h>
+#include <util/error.h>
+#include <util/fees.h>
+#include <util/moneystr.h>
+#include <util/rbf.h>
+#include <util/validation.h>
+#include <validation.h>
+#include <wallet/coincontrol.h>
#include <wallet/fees.h>
-#include <wallet/walletutil.h>
#include <algorithm>
#include <assert.h>
@@ -35,6 +41,8 @@
#include <boost/algorithm/string/replace.hpp>
+static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10;
+
static CCriticalSection cs_wallets;
static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
@@ -79,13 +87,74 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
return nullptr;
}
+static Mutex g_wallet_release_mutex;
+static std::condition_variable g_wallet_release_cv;
+static std::set<CWallet*> g_unloading_wallet_set;
+
// Custom deleter for shared_ptr<CWallet>.
static void ReleaseWallet(CWallet* wallet)
{
- LogPrintf("Releasing wallet %s\n", wallet->GetName());
+ // Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain
+ // so that it's in sync with the current chainstate.
+ wallet->WalletLogPrintf("Releasing wallet\n");
wallet->BlockUntilSyncedToCurrentChain();
wallet->Flush();
+ wallet->m_chain_notifications_handler.reset();
delete wallet;
+ // Wallet is now released, notify UnloadWallet, if any.
+ {
+ LOCK(g_wallet_release_mutex);
+ if (g_unloading_wallet_set.erase(wallet) == 0) {
+ // UnloadWallet was not called for this wallet, all done.
+ return;
+ }
+ }
+ g_wallet_release_cv.notify_all();
+}
+
+void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
+{
+ // Mark wallet for unloading.
+ CWallet* pwallet = wallet.get();
+ {
+ LOCK(g_wallet_release_mutex);
+ auto it = g_unloading_wallet_set.insert(pwallet);
+ assert(it.second);
+ }
+ // The wallet can be in use so it's not possible to explicitly unload here.
+ // Notify the unload intent so that all remaining shared pointers are
+ // released.
+ pwallet->NotifyUnload();
+ // Time to ditch our shared_ptr and wait for ReleaseWallet call.
+ wallet.reset();
+ {
+ WAIT_LOCK(g_wallet_release_mutex, lock);
+ while (g_unloading_wallet_set.count(pwallet) == 1) {
+ g_wallet_release_cv.wait(lock);
+ }
+ }
+}
+
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning)
+{
+ if (!CWallet::Verify(chain, location, false, error, warning)) {
+ error = "Wallet file verification failed: " + error;
+ return nullptr;
+ }
+
+ std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location);
+ if (!wallet) {
+ error = "Wallet loading failed.";
+ return nullptr;
+ }
+ AddWallet(wallet);
+ wallet->postInitProcess();
+ return wallet;
+}
+
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning)
+{
+ return LoadWallet(chain, WalletLocation(name), error, warning);
}
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
@@ -102,56 +171,17 @@ std::string COutput::ToString() const
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
}
-class CAffectedKeysVisitor : public boost::static_visitor<void> {
-private:
- const CKeyStore &keystore;
- std::vector<CKeyID> &vKeys;
-
-public:
- CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
-
- void Process(const CScript &script) {
- txnouttype type;
- std::vector<CTxDestination> vDest;
- int nRequired;
- if (ExtractDestinations(script, type, vDest, nRequired)) {
- for (const CTxDestination &dest : vDest)
- boost::apply_visitor(*this, dest);
- }
- }
-
- void operator()(const CKeyID &keyId) {
- if (keystore.HaveKey(keyId))
- vKeys.push_back(keyId);
- }
-
- void operator()(const CScriptID &scriptId) {
- CScript script;
- if (keystore.GetCScript(scriptId, script))
- Process(script);
- }
-
- void operator()(const WitnessV0ScriptHash& scriptID)
- {
- CScriptID id;
- CRIPEMD160().Write(scriptID.begin(), 32).Finalize(id.begin());
- CScript script;
- if (keystore.GetCScript(id, script)) {
- Process(script);
- }
- }
-
- void operator()(const WitnessV0KeyHash& keyid)
- {
- CKeyID id(keyid);
- if (keystore.HaveKey(id)) {
- vKeys.push_back(id);
- }
+std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider)
+{
+ std::vector<CScript> dummy;
+ FlatSigningProvider out;
+ InferDescriptor(spk, provider)->Expand(0, DUMMY_SIGNING_PROVIDER, dummy, out);
+ std::vector<CKeyID> ret;
+ for (const auto& entry : out.pubkeys) {
+ ret.push_back(entry.first);
}
-
- template<typename X>
- void operator()(const X &none) {}
-};
+ return ret;
+}
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
{
@@ -165,7 +195,8 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal)
{
assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
- AssertLockHeld(cs_wallet); // mapKeyMetadata
+ assert(!IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
+ AssertLockHeld(cs_wallet);
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
CKey secret;
@@ -174,7 +205,7 @@ CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal)
int64_t nCreationTime = GetTime();
CKeyMetadata metadata(nCreationTime);
- // use HD key derivation if HD was enabled during wallet creation
+ // use HD key derivation if HD was enabled during wallet creation and a seed is present
if (IsHDEnabled()) {
DeriveNewChildKey(batch, metadata, secret, (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false));
} else {
@@ -229,24 +260,36 @@ void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey
if (internal) {
chainChildKey.Derive(childKey, hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
metadata.hdKeypath = "m/0'/1'/" + std::to_string(hdChain.nInternalChainCounter) + "'";
+ metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
+ metadata.key_origin.path.push_back(1 | BIP32_HARDENED_KEY_LIMIT);
+ metadata.key_origin.path.push_back(hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
hdChain.nInternalChainCounter++;
}
else {
chainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
metadata.hdKeypath = "m/0'/0'/" + std::to_string(hdChain.nExternalChainCounter) + "'";
+ metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
+ metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
+ metadata.key_origin.path.push_back(hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
hdChain.nExternalChainCounter++;
}
} while (HaveKey(childKey.key.GetPubKey().GetID()));
secret = childKey.key;
metadata.hd_seed_id = hdChain.seed_id;
+ CKeyID master_id = masterKey.key.GetPubKey().GetID();
+ std::copy(master_id.begin(), master_id.begin() + 4, metadata.key_origin.fingerprint);
+ metadata.has_key_origin = true;
// update the chain model in the database
if (!batch.WriteHDChain(hdChain))
throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed");
}
-bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& secret, const CPubKey &pubkey)
+bool CWallet::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& secret, const CPubKey& pubkey)
{
- AssertLockHeld(cs_wallet); // mapKeyMetadata
+ AssertLockHeld(cs_wallet);
+
+ // Make sure we aren't adding private keys to private key disabled wallets
+ assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
// CCryptoKeyStore has no concept of wallet databases, but calls AddCryptedKey
// which is overridden below. To avoid flushes, the database handle is
@@ -263,7 +306,7 @@ bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& secret, const C
// check if we need to remove from watch-only
CScript script;
- script = GetScriptForDestination(pubkey.GetID());
+ script = GetScriptForDestination(PKHash(pubkey));
if (HaveWatchOnly(script)) {
RemoveWatchOnly(script);
}
@@ -277,6 +320,7 @@ bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& secret, const C
secret.GetPrivKey(),
mapKeyMetadata[pubkey.GetID()]);
}
+ UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
return true;
}
@@ -304,20 +348,68 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
}
}
-void CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta)
+void CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata& meta)
{
- AssertLockHeld(cs_wallet); // mapKeyMetadata
+ AssertLockHeld(cs_wallet);
UpdateTimeFirstKey(meta.nCreateTime);
mapKeyMetadata[keyID] = meta;
}
-void CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta)
+void CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata& meta)
{
- AssertLockHeld(cs_wallet); // m_script_metadata
+ AssertLockHeld(cs_wallet);
UpdateTimeFirstKey(meta.nCreateTime);
m_script_metadata[script_id] = meta;
}
+// Writes a keymetadata for a public key. overwrite specifies whether to overwrite an existing metadata for that key if there exists one.
+bool CWallet::WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite)
+{
+ return WalletBatch(*database).WriteKeyMetadata(meta, pubkey, overwrite);
+}
+
+void CWallet::UpgradeKeyMetadata()
+{
+ AssertLockHeld(cs_wallet);
+ if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
+ return;
+ }
+
+ std::unique_ptr<WalletBatch> batch = MakeUnique<WalletBatch>(*database);
+ size_t cnt = 0;
+ for (auto& meta_pair : mapKeyMetadata) {
+ CKeyMetadata& meta = meta_pair.second;
+ if (!meta.hd_seed_id.IsNull() && !meta.has_key_origin && meta.hdKeypath != "s") { // If the hdKeypath is "s", that's the seed and it doesn't have a key origin
+ CKey key;
+ GetKey(meta.hd_seed_id, key);
+ CExtKey masterKey;
+ masterKey.SetSeed(key.begin(), key.size());
+ // Add to map
+ CKeyID master_id = masterKey.key.GetPubKey().GetID();
+ std::copy(master_id.begin(), master_id.begin() + 4, meta.key_origin.fingerprint);
+ if (!ParseHDKeypath(meta.hdKeypath, meta.key_origin.path)) {
+ throw std::runtime_error("Invalid stored hdKeypath");
+ }
+ meta.has_key_origin = true;
+ if (meta.nVersion < CKeyMetadata::VERSION_WITH_KEY_ORIGIN) {
+ meta.nVersion = CKeyMetadata::VERSION_WITH_KEY_ORIGIN;
+ }
+
+ // Write meta to wallet
+ CPubKey pubkey;
+ if (GetPubKey(meta_pair.first, pubkey)) {
+ batch->WriteKeyMetadata(meta, pubkey, true);
+ if (++cnt % 1000 == 0) {
+ // avoid creating overlarge in-memory batches in case the wallet contains large amounts of keys
+ batch.reset(new WalletBatch(*database));
+ }
+ }
+ }
+ }
+ batch.reset(); //write before setting the flag
+ SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
+}
+
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
@@ -343,7 +435,11 @@ bool CWallet::AddCScript(const CScript& redeemScript)
{
if (!CCryptoKeyStore::AddCScript(redeemScript))
return false;
- return WalletBatch(*database).WriteCScript(Hash160(redeemScript), redeemScript);
+ if (WalletBatch(*database).WriteCScript(Hash160(redeemScript), redeemScript)) {
+ UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
+ return true;
+ }
+ return false;
}
bool CWallet::LoadCScript(const CScript& redeemScript)
@@ -353,9 +449,8 @@ bool CWallet::LoadCScript(const CScript& redeemScript)
* these. Do not add them to the wallet and warn. */
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
{
- std::string strAddr = EncodeDestination(CScriptID(redeemScript));
- LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
- __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
+ std::string strAddr = EncodeDestination(ScriptHash(redeemScript));
+ WalletLogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
return true;
}
@@ -369,7 +464,11 @@ bool CWallet::AddWatchOnly(const CScript& dest)
const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)];
UpdateTimeFirstKey(meta.nCreateTime);
NotifyWatchonlyChanged(true);
- return WalletBatch(*database).WriteWatchOnly(dest, meta);
+ if (WalletBatch(*database).WriteWatchOnly(dest, meta)) {
+ UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
+ return true;
+ }
+ return false;
}
bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
@@ -396,7 +495,7 @@ bool CWallet::LoadWatchOnly(const CScript &dest)
return CCryptoKeyStore::AddWatchOnly(dest);
}
-bool CWallet::Unlock(const SecureString& strWalletPassphrase)
+bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
{
CCrypter crypter;
CKeyingMaterial _vMasterKey;
@@ -409,8 +508,11 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
return false;
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
continue; // try another master key
- if (CCryptoKeyStore::Unlock(_vMasterKey))
+ if (CCryptoKeyStore::Unlock(_vMasterKey, accept_no_keys)) {
+ // Now that we've unlocked, upgrade the key metadata
+ UpgradeKeyMetadata();
return true;
+ }
}
}
return false;
@@ -445,7 +547,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
if (pMasterKey.second.nDeriveIterations < 25000)
pMasterKey.second.nDeriveIterations = 25000;
- LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
+ WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
@@ -470,7 +572,7 @@ void CWallet::ChainStateFlushed(const CBlockLocator& loc)
void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
{
- LOCK(cs_wallet); // nWalletVersion
+ LOCK(cs_wallet);
if (nWalletVersion >= nVersion)
return;
@@ -494,7 +596,7 @@ void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in,
bool CWallet::SetMaxVersion(int nVersion)
{
- LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion
+ LOCK(cs_wallet);
// cannot downgrade below current version
if (nWalletVersion > nVersion)
return false;
@@ -573,7 +675,6 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
// nTimeReceived not copied on purpose
copyTo->nTimeSmart = copyFrom->nTimeSmart;
copyTo->fFromMe = copyFrom->fFromMe;
- copyTo->strFromAccount = copyFrom->strFromAccount;
// nOrderPos not copied on purpose
// cached members not copied on purpose
}
@@ -583,7 +684,7 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
* Outpoint is spent if any non-conflicted transaction
* spends it:
*/
-bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
+bool CWallet::IsSpent(interfaces::Chain::Lock& locked_chain, const uint256& hash, unsigned int n) const
{
const COutPoint outpoint(hash, n);
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
@@ -594,7 +695,7 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
const uint256& wtxid = it->second;
std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
if (mit != mapWallet.end()) {
- int depth = mit->second.GetDepthInMainChain();
+ int depth = mit->second.GetDepthInMainChain(locked_chain);
if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
return true; // Spent
}
@@ -653,7 +754,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
- LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
+ WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
return false;
@@ -676,6 +777,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
{
encrypted_batch->TxnAbort();
delete encrypted_batch;
+ encrypted_batch = nullptr;
// We now probably have half of our keys encrypted in memory, and half not...
// die and let the user reload the unencrypted wallet.
assert(false);
@@ -686,6 +788,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (!encrypted_batch->TxnCommit()) {
delete encrypted_batch;
+ encrypted_batch = nullptr;
// We now have keys encrypted in memory, but not on disk...
// die to avoid confusion and let the user reload the unencrypted wallet.
assert(false);
@@ -709,6 +812,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
// bits of the unencrypted private key in slack space in the database file.
database->Rewrite();
+ // BDB seems to have a bad habit of writing old data into
+ // slack space in .dat files; that is bad if the old data is
+ // unencrypted private keys. So:
+ database->ReloadDbEnv();
+
}
NotifyStatusChanged(this);
@@ -723,44 +831,30 @@ DBErrors CWallet::ReorderTransactions()
// Old wallets didn't have any defined order for transactions
// Probably a bad idea to change the output of this
- // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
- typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
- typedef std::multimap<int64_t, TxPair > TxItems;
+ // First: get all CWalletTx into a sorted-by-time multimap.
+ typedef std::multimap<int64_t, CWalletTx*> TxItems;
TxItems txByTime;
for (auto& entry : mapWallet)
{
CWalletTx* wtx = &entry.second;
- txByTime.insert(std::make_pair(wtx->nTimeReceived, TxPair(wtx, nullptr)));
- }
- std::list<CAccountingEntry> acentries;
- batch.ListAccountCreditDebit("", acentries);
- for (CAccountingEntry& entry : acentries)
- {
- txByTime.insert(std::make_pair(entry.nTime, TxPair(nullptr, &entry)));
+ txByTime.insert(std::make_pair(wtx->nTimeReceived, wtx));
}
nOrderPosNext = 0;
std::vector<int64_t> nOrderPosOffsets;
for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it)
{
- CWalletTx *const pwtx = (*it).second.first;
- CAccountingEntry *const pacentry = (*it).second.second;
- int64_t& nOrderPos = (pwtx != nullptr) ? pwtx->nOrderPos : pacentry->nOrderPos;
+ CWalletTx *const pwtx = (*it).second;
+ int64_t& nOrderPos = pwtx->nOrderPos;
if (nOrderPos == -1)
{
nOrderPos = nOrderPosNext++;
nOrderPosOffsets.push_back(nOrderPos);
- if (pwtx)
- {
- if (!batch.WriteTx(*pwtx))
- return DBErrors::LOAD_FAIL;
- }
- else
- if (!batch.WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
- return DBErrors::LOAD_FAIL;
+ if (!batch.WriteTx(*pwtx))
+ return DBErrors::LOAD_FAIL;
}
else
{
@@ -777,14 +871,8 @@ DBErrors CWallet::ReorderTransactions()
continue;
// Since we're changing the order, write it back
- if (pwtx)
- {
- if (!batch.WriteTx(*pwtx))
- return DBErrors::LOAD_FAIL;
- }
- else
- if (!batch.WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
- return DBErrors::LOAD_FAIL;
+ if (!batch.WriteTx(*pwtx))
+ return DBErrors::LOAD_FAIL;
}
}
batch.WriteOrderPosNext(nOrderPosNext);
@@ -792,9 +880,9 @@ DBErrors CWallet::ReorderTransactions()
return DBErrors::LOAD_OK;
}
-int64_t CWallet::IncOrderPosNext(WalletBatch *batch)
+int64_t CWallet::IncOrderPosNext(WalletBatch* batch)
{
- AssertLockHeld(cs_wallet); // nOrderPosNext
+ AssertLockHeld(cs_wallet);
int64_t nRet = nOrderPosNext++;
if (batch) {
batch->WriteOrderPosNext(nOrderPosNext);
@@ -804,80 +892,6 @@ int64_t CWallet::IncOrderPosNext(WalletBatch *batch)
return nRet;
}
-bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment)
-{
- WalletBatch batch(*database);
- if (!batch.TxnBegin())
- return false;
-
- int64_t nNow = GetAdjustedTime();
-
- // Debit
- CAccountingEntry debit;
- debit.nOrderPos = IncOrderPosNext(&batch);
- debit.strAccount = strFrom;
- debit.nCreditDebit = -nAmount;
- debit.nTime = nNow;
- debit.strOtherAccount = strTo;
- debit.strComment = strComment;
- AddAccountingEntry(debit, &batch);
-
- // Credit
- CAccountingEntry credit;
- credit.nOrderPos = IncOrderPosNext(&batch);
- credit.strAccount = strTo;
- credit.nCreditDebit = nAmount;
- credit.nTime = nNow;
- credit.strOtherAccount = strFrom;
- credit.strComment = strComment;
- AddAccountingEntry(credit, &batch);
-
- if (!batch.TxnCommit())
- return false;
-
- return true;
-}
-
-bool CWallet::GetLabelDestination(CTxDestination &dest, const std::string& label, bool bForceNew)
-{
- WalletBatch batch(*database);
-
- CAccount account;
- batch.ReadAccount(label, account);
-
- if (!bForceNew) {
- if (!account.vchPubKey.IsValid())
- bForceNew = true;
- else {
- // Check if the current key has been used (TODO: check other addresses with the same key)
- CScript scriptPubKey = GetScriptForDestination(GetDestinationForKey(account.vchPubKey, m_default_address_type));
- for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin();
- it != mapWallet.end() && account.vchPubKey.IsValid();
- ++it)
- for (const CTxOut& txout : (*it).second.tx->vout)
- if (txout.scriptPubKey == scriptPubKey) {
- bForceNew = true;
- break;
- }
- }
- }
-
- // Generate a new key
- if (bForceNew) {
- if (!GetKeyFromPool(account.vchPubKey, false))
- return false;
-
- LearnRelatedScripts(account.vchPubKey, m_default_address_type);
- dest = GetDestinationForKey(account.vchPubKey, m_default_address_type);
- SetAddressBook(dest, label, "receive");
- batch.WriteAccount(label, account);
- } else {
- dest = GetDestinationForKey(account.vchPubKey, m_default_address_type);
- }
-
- return true;
-}
-
void CWallet::MarkDirty()
{
{
@@ -907,7 +921,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
bool success = true;
if (!batch.WriteTx(wtx)) {
- LogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
+ WalletLogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
success = false;
}
@@ -930,9 +944,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
wtx.BindWallet(this);
bool fInsertedNew = ret.second;
if (fInsertedNew) {
- wtx.nTimeReceived = GetAdjustedTime();
+ wtx.nTimeReceived = chain().getAdjustedTime();
wtx.nOrderPos = IncOrderPosNext(&batch);
- wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
+ wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
wtx.nTimeSmart = ComputeTimeSmart(wtx);
AddToSpends(hash);
}
@@ -974,7 +988,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
}
//// debug print
- LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+ WalletLogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
// Write to disk
if (fInsertedNew || fUpdated)
@@ -1007,7 +1021,7 @@ void CWallet::LoadToWallet(const CWalletTx& wtxIn)
CWalletTx& wtx = ins.first->second;
wtx.BindWallet(this);
if (/* insertion took place */ ins.second) {
- wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, nullptr)));
+ wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
}
AddToSpends(hash);
for (const CTxIn& txin : wtx.tx->vin) {
@@ -1021,19 +1035,19 @@ void CWallet::LoadToWallet(const CWalletTx& wtxIn)
}
}
-bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate)
+bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const uint256& block_hash, int posInBlock, bool fUpdate)
{
const CTransaction& tx = *ptx;
{
AssertLockHeld(cs_wallet);
- if (pIndex != nullptr) {
+ if (!block_hash.IsNull()) {
for (const CTxIn& txin : tx.vin) {
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
while (range.first != range.second) {
if (range.first->second != tx.GetHash()) {
- LogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pIndex->GetBlockHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
- MarkConflicted(pIndex->GetBlockHash(), range.first->second);
+ WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), block_hash.ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
+ MarkConflicted(block_hash, range.first->second);
}
range.first++;
}
@@ -1053,16 +1067,14 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
// loop though all outputs
for (const CTxOut& txout: tx.vout) {
// extract addresses and check if they match with an unused keypool key
- std::vector<CKeyID> vAffected;
- CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
- for (const CKeyID &keyid : vAffected) {
+ for (const auto& keyid : GetAffectedKeys(txout.scriptPubKey, *this)) {
std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
if (mi != m_pool_key_to_index.end()) {
- LogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__);
+ WalletLogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__);
MarkReserveKeysAsUsed(mi->second);
if (!TopUpKeyPool()) {
- LogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
+ WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
}
}
}
@@ -1071,8 +1083,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
CWalletTx wtx(this, ptx);
// Get merkle branch if transaction was found in a block
- if (pIndex != nullptr)
- wtx.SetMerkleBranch(pIndex, posInBlock);
+ if (!block_hash.IsNull())
+ wtx.SetMerkleBranch(block_hash, posInBlock);
return AddToWallet(wtx, false);
}
@@ -1082,9 +1094,10 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
bool CWallet::TransactionCanBeAbandoned(const uint256& hashTx) const
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
const CWalletTx* wtx = GetWalletTx(hashTx);
- return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain() == 0 && !wtx->InMempool();
+ return wtx && !wtx->isAbandoned() && wtx->GetDepthInMainChain(*locked_chain) == 0 && !wtx->InMempool();
}
void CWallet::MarkInputsDirty(const CTransactionRef& tx)
@@ -1097,9 +1110,10 @@ void CWallet::MarkInputsDirty(const CTransactionRef& tx)
}
}
-bool CWallet::AbandonTransaction(const uint256& hashTx)
+bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const uint256& hashTx)
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain_recursive = chain().lock(); // Temporary. Removed in upcoming lock cleanup
+ LOCK(cs_wallet);
WalletBatch batch(*database, "r+");
@@ -1110,7 +1124,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
auto it = mapWallet.find(hashTx);
assert(it != mapWallet.end());
CWalletTx& origtx = it->second;
- if (origtx.GetDepthInMainChain() != 0 || origtx.InMempool()) {
+ if (origtx.GetDepthInMainChain(locked_chain) != 0 || origtx.InMempool()) {
return false;
}
@@ -1123,7 +1137,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
auto it = mapWallet.find(now);
assert(it != mapWallet.end());
CWalletTx& wtx = it->second;
- int currentconfirm = wtx.GetDepthInMainChain();
+ int currentconfirm = wtx.GetDepthInMainChain(locked_chain);
// If the orig tx was not in block, none of its spends can be
assert(currentconfirm <= 0);
// if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
@@ -1154,13 +1168,10 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
- int conflictconfirms = 0;
- CBlockIndex* pindex = LookupBlockIndex(hashBlock);
- if (pindex && chainActive.Contains(pindex)) {
- conflictconfirms = -(chainActive.Height() - pindex->nHeight + 1);
- }
+ int conflictconfirms = -locked_chain->getBlockDepth(hashBlock);
// If number of conflict confirms cannot be determined, this means
// that the block is still unknown or not yet part of the main chain,
// for example when loading the wallet during a reindex. Do nothing in that
@@ -1183,7 +1194,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
auto it = mapWallet.find(now);
assert(it != mapWallet.end());
CWalletTx& wtx = it->second;
- int currentconfirm = wtx.GetDepthInMainChain();
+ int currentconfirm = wtx.GetDepthInMainChain(*locked_chain);
if (conflictconfirms < currentconfirm) {
// Block is 'more conflicted' than current confirm; update.
// Mark transaction as conflicted with this block.
@@ -1206,8 +1217,8 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
}
}
-void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindex, int posInBlock, bool update_tx) {
- if (!AddToWalletIfInvolvingMe(ptx, pindex, posInBlock, update_tx))
+void CWallet::SyncTransaction(const CTransactionRef& ptx, const uint256& block_hash, int posInBlock, bool update_tx) {
+ if (!AddToWalletIfInvolvingMe(ptx, block_hash, posInBlock, update_tx))
return; // Not one of ours
// If a transaction changes 'conflicted' state, that changes the balance
@@ -1217,8 +1228,9 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pin
}
void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) {
- LOCK2(cs_main, cs_wallet);
- SyncTransaction(ptx);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
+ SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */);
auto it = mapWallet.find(ptx->GetHash());
if (it != mapWallet.end()) {
@@ -1234,8 +1246,10 @@ void CWallet::TransactionRemovedFromMempool(const CTransactionRef &ptx) {
}
}
-void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) {
- LOCK2(cs_main, cs_wallet);
+void CWallet::BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& vtxConflicted) {
+ const uint256& block_hash = block.GetHash();
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
// TODO: Temporarily ensure that mempool removals are notified before
// connected transactions. This shouldn't matter, but the abandoned
// state of transactions in our wallet is currently cleared when we
@@ -1245,49 +1259,40 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const
// the notification that the conflicted transaction was evicted.
for (const CTransactionRef& ptx : vtxConflicted) {
- SyncTransaction(ptx);
+ SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */);
TransactionRemovedFromMempool(ptx);
}
- for (size_t i = 0; i < pblock->vtx.size(); i++) {
- SyncTransaction(pblock->vtx[i], pindex, i);
- TransactionRemovedFromMempool(pblock->vtx[i]);
+ for (size_t i = 0; i < block.vtx.size(); i++) {
+ SyncTransaction(block.vtx[i], block_hash, i);
+ TransactionRemovedFromMempool(block.vtx[i]);
}
- m_last_block_processed = pindex;
+ m_last_block_processed = block_hash;
}
-void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
- LOCK2(cs_main, cs_wallet);
+void CWallet::BlockDisconnected(const CBlock& block) {
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
- for (const CTransactionRef& ptx : pblock->vtx) {
- SyncTransaction(ptx);
+ for (const CTransactionRef& ptx : block.vtx) {
+ SyncTransaction(ptx, {} /* block hash */, 0 /* position in block */);
}
}
+void CWallet::UpdatedBlockTip()
+{
+ m_best_block_time = GetTime();
+}
void CWallet::BlockUntilSyncedToCurrentChain() {
- AssertLockNotHeld(cs_main);
AssertLockNotHeld(cs_wallet);
-
- {
- // Skip the queue-draining stuff if we know we're caught up with
- // chainActive.Tip()...
- // We could also take cs_wallet here, and call m_last_block_processed
- // protected by cs_wallet instead of cs_main, but as long as we need
- // cs_main here anyway, it's easier to just call it cs_main-protected.
- LOCK(cs_main);
- const CBlockIndex* initialChainTip = chainActive.Tip();
-
- if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
- return;
- }
- }
-
- // ...otherwise put a callback in the validation interface queue and wait
+ // Skip the queue-draining stuff if we know we're caught up with
+ // ::ChainActive().Tip(), otherwise put a callback in the validation interface queue and wait
// for the queue to drain enough to execute it (indicating we are caught up
// at least with the time we entered this function).
- SyncWithValidationInterfaceQueue();
+ uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed);
+ chain().waitForNotificationsIfNewBlocksConnected(last_block_hash);
}
@@ -1338,6 +1343,11 @@ CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) cons
bool CWallet::IsChange(const CTxOut& txout) const
{
+ return IsChange(txout.scriptPubKey);
+}
+
+bool CWallet::IsChange(const CScript& script) const
+{
// TODO: fix handling of 'change' outputs. The assumption is that any
// payment to a script that is ours, but is not in the address book
// is change. That assumption is likely to break when we implement multisignature
@@ -1345,10 +1355,10 @@ bool CWallet::IsChange(const CTxOut& txout) const
// a better way of identifying which outputs are 'the send' and which are
// 'the change' will need to be implemented (maybe extend CWalletTx to remember
// which output, if any, was change).
- if (::IsMine(*this, txout.scriptPubKey))
+ if (::IsMine(*this, script))
{
CTxDestination address;
- if (!ExtractDestination(txout.scriptPubKey, address))
+ if (!ExtractDestination(script, address))
return true;
LOCK(cs_wallet);
@@ -1454,6 +1464,7 @@ CPubKey CWallet::DeriveNewSeed(const CKey& key)
// set the hd keypath to "s" -> Seed, refers the seed to itself
metadata.hdKeypath = "s";
+ metadata.has_key_origin = false;
metadata.hd_seed_id = seed.GetID();
{
@@ -1480,6 +1491,8 @@ void CWallet::SetHDSeed(const CPubKey& seed)
newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
newHdChain.seed_id = seed.GetID();
SetHDChain(newHdChain, false);
+ NotifyCanGetAddressesChanged();
+ UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
}
void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
@@ -1496,6 +1509,30 @@ bool CWallet::IsHDEnabled() const
return !hdChain.seed_id.IsNull();
}
+bool CWallet::CanGenerateKeys()
+{
+ // A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a non-HD wallet (pre FEATURE_HD)
+ LOCK(cs_wallet);
+ return IsHDEnabled() || !CanSupportFeature(FEATURE_HD);
+}
+
+bool CWallet::CanGetAddresses(bool internal)
+{
+ LOCK(cs_wallet);
+ // Check if the keypool has keys
+ bool keypool_has_keys;
+ if (internal && CanSupportFeature(FEATURE_HD_SPLIT)) {
+ keypool_has_keys = setInternalKeyPool.size() > 0;
+ } else {
+ keypool_has_keys = KeypoolCountExternalKeys() > 0;
+ }
+ // If the keypool doesn't have keys, check if we can generate them
+ if (!keypool_has_keys) {
+ return CanGenerateKeys();
+ }
+ return keypool_has_keys;
+}
+
void CWallet::SetWalletFlag(uint64_t flags)
{
LOCK(cs_wallet);
@@ -1504,6 +1541,14 @@ void CWallet::SetWalletFlag(uint64_t flags)
throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
}
+void CWallet::UnsetWalletFlag(uint64_t flag)
+{
+ LOCK(cs_wallet);
+ m_wallet_flags &= ~flag;
+ if (!WalletBatch(*database).WriteWalletFlags(m_wallet_flags))
+ throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
+}
+
bool CWallet::IsWalletFlagSet(uint64_t flag)
{
return (m_wallet_flags & flag);
@@ -1530,30 +1575,29 @@ int64_t CWalletTx::GetTxTime() const
return n ? n : nTimeReceived;
}
-// Helper for producing a max-sized low-S signature (eg 72 bytes)
-bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout) const
+// Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
+// or a max-sized low-S signature (e.g. 72 bytes) if use_max_sig is true
+bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig) const
{
// Fill in dummy signatures for fee calculation.
const CScript& scriptPubKey = txout.scriptPubKey;
SignatureData sigdata;
- if (!ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata))
- {
+ if (!ProduceSignature(*this, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
return false;
- } else {
- UpdateInput(tx_in, sigdata);
}
+ UpdateInput(tx_in, sigdata);
return true;
}
-// Helper for producing a bunch of max-sized low-S signatures (eg 72 bytes)
-bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts) const
+// Helper for producing a bunch of max-sized low-S low-R signatures (eg 71 bytes)
+bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig) const
{
// Fill in dummy signatures for fee calculation.
int nIn = 0;
for (const auto& txout : txouts)
{
- if (!DummySignInput(txNew.vin[nIn], txout)) {
+ if (!DummySignInput(txNew.vin[nIn], txout, use_max_sig)) {
return false;
}
@@ -1562,13 +1606,13 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut>
return true;
}
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet)
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig)
{
std::vector<CTxOut> txouts;
// Look up the inputs. We should have already checked that this transaction
// IsAllFromMe(ISMINE_SPENDABLE), so every input should already be in our
// wallet, with a valid index into the vout array, and the ability to sign.
- for (auto& input : tx.vin) {
+ for (const CTxIn& input : tx.vin) {
const auto mi = wallet->mapWallet.find(input.prevout.hash);
if (mi == wallet->mapWallet.end()) {
return -1;
@@ -1576,40 +1620,37 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wall
assert(input.prevout.n < mi->second.tx->vout.size());
txouts.emplace_back(mi->second.tx->vout[input.prevout.n]);
}
- return CalculateMaximumSignedTxSize(tx, wallet, txouts);
+ return CalculateMaximumSignedTxSize(tx, wallet, txouts, use_max_sig);
}
// txouts needs to be in the order of tx.vin
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts)
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig)
{
CMutableTransaction txNew(tx);
- if (!wallet->DummySignTx(txNew, txouts)) {
+ if (!wallet->DummySignTx(txNew, txouts, use_max_sig)) {
// This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
// implies that we can sign for every input.
return -1;
}
- return GetVirtualTransactionSize(txNew);
+ return GetVirtualTransactionSize(CTransaction(txNew));
}
-int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet)
+int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, bool use_max_sig)
{
CMutableTransaction txn;
txn.vin.push_back(CTxIn(COutPoint()));
- if (!wallet->DummySignInput(txn.vin[0], txout)) {
- // This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
- // implies that we can sign for every input.
+ if (!wallet->DummySignInput(txn.vin[0], txout, use_max_sig)) {
return -1;
}
return GetVirtualTransactionInputSize(txn.vin[0]);
}
void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
- std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const
+ std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter) const
{
nFee = 0;
listReceived.clear();
listSent.clear();
- strSentAccount = strFromAccount;
// Compute fee:
CAmount nDebit = GetDebit(filter);
@@ -1641,8 +1682,8 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable())
{
- LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
- this->GetHash().ToString());
+ pwallet->WalletLogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
+ this->GetHash().ToString());
address = CNoDestination();
}
@@ -1672,125 +1713,155 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
// Find starting block. May be null if nCreateTime is greater than the
// highest blockchain timestamp, in which case there is nothing that needs
// to be scanned.
- CBlockIndex* startBlock = nullptr;
+ uint256 start_block;
{
- LOCK(cs_main);
- startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW);
- LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
- }
-
- if (startBlock) {
- const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, nullptr, reserver, update);
- if (failedBlock) {
- return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1;
+ auto locked_chain = chain().lock();
+ const Optional<int> start_height = locked_chain->findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, &start_block);
+ const Optional<int> tip_height = locked_chain->getHeight();
+ WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0);
+ }
+
+ if (!start_block.IsNull()) {
+ // TODO: this should take into account failure by ScanResult::USER_ABORT
+ ScanResult result = ScanForWalletTransactions(start_block, {} /* stop_block */, reserver, update);
+ if (result.status == ScanResult::FAILURE) {
+ int64_t time_max;
+ if (!chain().findBlock(result.last_failed_block, nullptr /* block */, nullptr /* time */, &time_max)) {
+ throw std::logic_error("ScanForWalletTransactions returned invalid block hash");
+ }
+ return time_max + TIMESTAMP_WINDOW + 1;
}
}
return startTime;
}
/**
- * Scan the block chain (starting in pindexStart) for transactions
+ * Scan the block chain (starting in start_block) for transactions
* from or to us. If fUpdate is true, found transactions that already
* exist in the wallet will be updated.
*
- * Returns null if scan was successful. Otherwise, if a complete rescan was not
- * possible (due to pruning or corruption), returns pointer to the most recent
- * block that could not be scanned.
+ * @param[in] start_block Scan starting block. If block is not on the active
+ * chain, the scan will return SUCCESS immediately.
+ * @param[in] stop_block Scan ending block. If block is not on the active
+ * chain, the scan will continue until it reaches the
+ * chain tip.
*
- * If pindexStop is not a nullptr, the scan will stop at the block-index
- * defined by pindexStop
+ * @return ScanResult returning scan information and indicating success or
+ * failure. Return status will be set to SUCCESS if scan was
+ * successful. FAILURE if a complete rescan was not possible (due to
+ * pruning or corruption). USER_ABORT if the rescan was aborted before
+ * it could complete.
*
- * Caller needs to make sure pindexStop (and the optional pindexStart) are on
+ * @pre Caller needs to make sure start_block (and the optional stop_block) are on
* the main chain after to the addition of any new keys you want to detect
* transactions for.
*/
-CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver &reserver, bool fUpdate)
+CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, const uint256& stop_block, const WalletRescanReserver& reserver, bool fUpdate)
{
int64_t nNow = GetTime();
- const CChainParams& chainParams = Params();
+ int64_t start_time = GetTimeMillis();
assert(reserver.isReserved());
- if (pindexStop) {
- assert(pindexStop->nHeight >= pindexStart->nHeight);
- }
- CBlockIndex* pindex = pindexStart;
- CBlockIndex* ret = nullptr;
+ uint256 block_hash = start_block;
+ ScanResult result;
- if (pindex) LogPrintf("Rescan started from block %d...\n", pindex->nHeight);
+ WalletLogPrintf("Rescan started from block %s...\n", start_block.ToString());
+ fAbortRescan = false;
+ ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
+ uint256 tip_hash;
+ // The way the 'block_height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
+ Optional<int> block_height = MakeOptional(false, int());
+ double progress_begin;
+ double progress_end;
{
- fAbortRescan = false;
- ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
- CBlockIndex* tip = nullptr;
- double progress_begin;
- double progress_end;
- {
- LOCK(cs_main);
- progress_begin = GuessVerificationProgress(chainParams.TxData(), pindex);
- if (pindexStop == nullptr) {
- tip = chainActive.Tip();
- progress_end = GuessVerificationProgress(chainParams.TxData(), tip);
- } else {
- progress_end = GuessVerificationProgress(chainParams.TxData(), pindexStop);
- }
+ auto locked_chain = chain().lock();
+ if (Optional<int> tip_height = locked_chain->getHeight()) {
+ tip_hash = locked_chain->getBlockHash(*tip_height);
+ }
+ block_height = locked_chain->getBlockHeight(block_hash);
+ progress_begin = chain().guessVerificationProgress(block_hash);
+ progress_end = chain().guessVerificationProgress(stop_block.IsNull() ? tip_hash : stop_block);
+ }
+ double progress_current = progress_begin;
+ while (block_height && !fAbortRescan && !chain().shutdownRequested()) {
+ m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
+ if (*block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
+ ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
+ }
+ if (GetTime() >= nNow + 60) {
+ nNow = GetTime();
+ WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", *block_height, progress_current);
}
- double progress_current = progress_begin;
- while (pindex && !fAbortRescan && !ShutdownRequested())
- {
- if (pindex->nHeight % 100 == 0 && progress_end - progress_begin > 0.0) {
- ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((progress_current - progress_begin) / (progress_end - progress_begin) * 100))));
- }
- if (GetTime() >= nNow + 60) {
- nNow = GetTime();
- LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, progress_current);
- }
- CBlock block;
- if (ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
- LOCK2(cs_main, cs_wallet);
- if (pindex && !chainActive.Contains(pindex)) {
- // Abort scan if current block is no longer active, to prevent
- // marking transactions as coming from the wrong block.
- ret = pindex;
- break;
- }
- for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
- SyncTransaction(block.vtx[posInBlock], pindex, posInBlock, fUpdate);
- }
- } else {
- ret = pindex;
- }
- if (pindex == pindexStop) {
+ CBlock block;
+ if (chain().findBlock(block_hash, &block) && !block.IsNull()) {
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
+ if (!locked_chain->getBlockHeight(block_hash)) {
+ // Abort scan if current block is no longer active, to prevent
+ // marking transactions as coming from the wrong block.
+ // TODO: This should return success instead of failure, see
+ // https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518
+ result.last_failed_block = block_hash;
+ result.status = ScanResult::FAILURE;
break;
}
- {
- LOCK(cs_main);
- pindex = chainActive.Next(pindex);
- progress_current = GuessVerificationProgress(chainParams.TxData(), pindex);
- if (pindexStop == nullptr && tip != chainActive.Tip()) {
- tip = chainActive.Tip();
- // in case the tip has changed, update progress max
- progress_end = GuessVerificationProgress(chainParams.TxData(), tip);
- }
+ for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
+ SyncTransaction(block.vtx[posInBlock], block_hash, posInBlock, fUpdate);
}
+ // scan succeeded, record block as most recent successfully scanned
+ result.last_scanned_block = block_hash;
+ result.last_scanned_height = *block_height;
+ } else {
+ // could not scan block, keep scanning but record this block as the most recent failure
+ result.last_failed_block = block_hash;
+ result.status = ScanResult::FAILURE;
}
- if (pindex && fAbortRescan) {
- LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, progress_current);
- } else if (pindex && ShutdownRequested()) {
- LogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", pindex->nHeight, progress_current);
+ if (block_hash == stop_block) {
+ break;
+ }
+ {
+ auto locked_chain = chain().lock();
+ Optional<int> tip_height = locked_chain->getHeight();
+ if (!tip_height || *tip_height <= block_height || !locked_chain->getBlockHeight(block_hash)) {
+ // break successfully when rescan has reached the tip, or
+ // previous block is no longer on the chain due to a reorg
+ break;
+ }
+
+ // increment block and verification progress
+ block_hash = locked_chain->getBlockHash(++*block_height);
+ progress_current = chain().guessVerificationProgress(block_hash);
+
+ // handle updated tip hash
+ const uint256 prev_tip_hash = tip_hash;
+ tip_hash = locked_chain->getBlockHash(*tip_height);
+ if (stop_block.IsNull() && prev_tip_hash != tip_hash) {
+ // in case the tip has changed, update progress max
+ progress_end = chain().guessVerificationProgress(tip_hash);
+ }
}
- ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
}
- return ret;
+ ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 100); // hide progress dialog in GUI
+ if (block_height && fAbortRescan) {
+ WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", *block_height, progress_current);
+ result.status = ScanResult::USER_ABORT;
+ } else if (block_height && chain().shutdownRequested()) {
+ WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", *block_height, progress_current);
+ result.status = ScanResult::USER_ABORT;
+ } else {
+ WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - start_time);
+ }
+ return result;
}
-void CWallet::ReacceptWalletTransactions()
+void CWallet::ReacceptWalletTransactions(interfaces::Chain::Lock& locked_chain)
{
// If transactions aren't being broadcasted, don't let them into local mempool either
if (!fBroadcastTransactions)
return;
- LOCK2(cs_main, cs_wallet);
std::map<int64_t, CWalletTx*> mapSorted;
// Sort pending wallet transactions based on their initial wallet insertion order
@@ -1800,7 +1871,7 @@ void CWallet::ReacceptWalletTransactions()
CWalletTx& wtx = item.second;
assert(wtx.GetHash() == wtxid);
- int nDepth = wtx.GetDepthInMainChain();
+ int nDepth = wtx.GetDepthInMainChain(locked_chain);
if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
@@ -1808,33 +1879,34 @@ void CWallet::ReacceptWalletTransactions()
}
// Try to add wallet transactions to memory pool
- for (std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
+ for (const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
CWalletTx& wtx = *(item.second);
CValidationState state;
- wtx.AcceptToMemoryPool(maxTxFee, state);
+ wtx.AcceptToMemoryPool(locked_chain, state);
}
}
-bool CWalletTx::RelayWalletTransaction(CConnman* connman)
+bool CWalletTx::RelayWalletTransaction(interfaces::Chain::Lock& locked_chain)
{
- assert(pwallet->GetBroadcastTransactions());
- if (!IsCoinBase() && !isAbandoned() && GetDepthInMainChain() == 0)
- {
- CValidationState state;
- /* GetDepthInMainChain already catches known conflicts. */
- if (InMempool() || AcceptToMemoryPool(maxTxFee, state)) {
- LogPrintf("Relaying wtx %s\n", GetHash().ToString());
- if (connman) {
- CInv inv(MSG_TX, GetHash());
- connman->ForEachNode([&inv](CNode* pnode)
- {
- pnode->PushInventory(inv);
- });
- return true;
- }
- }
- }
- return false;
+ // Can't relay if wallet is not broadcasting
+ if (!pwallet->GetBroadcastTransactions()) return false;
+ // Don't relay coinbase transactions outside blocks
+ if (IsCoinBase()) return false;
+ // Don't relay abandoned transactions
+ if (isAbandoned()) return false;
+ // Don't relay conflicted or already confirmed transactions
+ if (GetDepthInMainChain(locked_chain) != 0) return false;
+ // Don't relay transactions that aren't accepted to the mempool
+ CValidationState unused_state;
+ if (!InMempool() && !AcceptToMemoryPool(locked_chain, unused_state)) return false;
+ // Don't try to relay if the node is not connected to the p2p network
+ if (!pwallet->chain().p2pEnabled()) return false;
+
+ // Try to relay the transaction
+ pwallet->WalletLogPrintf("Relaying wtx %s\n", GetHash().ToString());
+ pwallet->chain().relayTransaction(GetHash());
+
+ return true;
}
std::set<uint256> CWalletTx::GetConflicts() const
@@ -1849,113 +1921,77 @@ std::set<uint256> CWalletTx::GetConflicts() const
return result;
}
+CAmount CWalletTx::GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate) const
+{
+ auto& amount = m_amounts[type];
+ if (recalculate || !amount.m_cached[filter]) {
+ amount.Set(filter, type == DEBIT ? pwallet->GetDebit(*tx, filter) : pwallet->GetCredit(*tx, filter));
+ }
+ return amount.m_value[filter];
+}
+
CAmount CWalletTx::GetDebit(const isminefilter& filter) const
{
if (tx->vin.empty())
return 0;
CAmount debit = 0;
- if(filter & ISMINE_SPENDABLE)
- {
- if (fDebitCached)
- debit += nDebitCached;
- else
- {
- nDebitCached = pwallet->GetDebit(*tx, ISMINE_SPENDABLE);
- fDebitCached = true;
- debit += nDebitCached;
- }
+ if (filter & ISMINE_SPENDABLE) {
+ debit += GetCachableAmount(DEBIT, ISMINE_SPENDABLE);
}
- if(filter & ISMINE_WATCH_ONLY)
- {
- if(fWatchDebitCached)
- debit += nWatchDebitCached;
- else
- {
- nWatchDebitCached = pwallet->GetDebit(*tx, ISMINE_WATCH_ONLY);
- fWatchDebitCached = true;
- debit += nWatchDebitCached;
- }
+ if (filter & ISMINE_WATCH_ONLY) {
+ debit += GetCachableAmount(DEBIT, ISMINE_WATCH_ONLY);
}
return debit;
}
-CAmount CWalletTx::GetCredit(const isminefilter& filter) const
+CAmount CWalletTx::GetCredit(interfaces::Chain::Lock& locked_chain, const isminefilter& filter) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
- if (IsCoinBase() && GetBlocksToMaturity() > 0)
+ if (IsImmatureCoinBase(locked_chain))
return 0;
CAmount credit = 0;
- if (filter & ISMINE_SPENDABLE)
- {
+ if (filter & ISMINE_SPENDABLE) {
// GetBalance can assume transactions in mapWallet won't change
- if (fCreditCached)
- credit += nCreditCached;
- else
- {
- nCreditCached = pwallet->GetCredit(*tx, ISMINE_SPENDABLE);
- fCreditCached = true;
- credit += nCreditCached;
- }
+ credit += GetCachableAmount(CREDIT, ISMINE_SPENDABLE);
}
- if (filter & ISMINE_WATCH_ONLY)
- {
- if (fWatchCreditCached)
- credit += nWatchCreditCached;
- else
- {
- nWatchCreditCached = pwallet->GetCredit(*tx, ISMINE_WATCH_ONLY);
- fWatchCreditCached = true;
- credit += nWatchCreditCached;
- }
+ if (filter & ISMINE_WATCH_ONLY) {
+ credit += GetCachableAmount(CREDIT, ISMINE_WATCH_ONLY);
}
return credit;
}
-CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
+CAmount CWalletTx::GetImmatureCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache) const
{
- if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
- {
- if (fUseCache && fImmatureCreditCached)
- return nImmatureCreditCached;
- nImmatureCreditCached = pwallet->GetCredit(*tx, ISMINE_SPENDABLE);
- fImmatureCreditCached = true;
- return nImmatureCreditCached;
+ if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) {
+ return GetCachableAmount(IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache);
}
return 0;
}
-CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter) const
+CAmount CWalletTx::GetAvailableCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache, const isminefilter& filter) const
{
if (pwallet == nullptr)
return 0;
+ // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future).
+ bool allow_cache = filter == ISMINE_SPENDABLE || filter == ISMINE_WATCH_ONLY;
+
// Must wait until coinbase is safely deep enough in the chain before valuing it
- if (IsCoinBase() && GetBlocksToMaturity() > 0)
+ if (IsImmatureCoinBase(locked_chain))
return 0;
- CAmount* cache = nullptr;
- bool* cache_used = nullptr;
-
- if (filter == ISMINE_SPENDABLE) {
- cache = &nAvailableCreditCached;
- cache_used = &fAvailableCreditCached;
- } else if (filter == ISMINE_WATCH_ONLY) {
- cache = &nAvailableWatchCreditCached;
- cache_used = &fAvailableWatchCreditCached;
- }
-
- if (fUseCache && cache_used && *cache_used) {
- return *cache;
+ if (fUseCache && allow_cache && m_amounts[AVAILABLE_CREDIT].m_cached[filter]) {
+ return m_amounts[AVAILABLE_CREDIT].m_value[filter];
}
CAmount nCredit = 0;
uint256 hashTx = GetHash();
for (unsigned int i = 0; i < tx->vout.size(); i++)
{
- if (!pwallet->IsSpent(hashTx, i))
+ if (!pwallet->IsSpent(locked_chain, hashTx, i))
{
const CTxOut &txout = tx->vout[i];
nCredit += pwallet->GetCredit(txout, filter);
@@ -1964,23 +2000,17 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter
}
}
- if (cache) {
- *cache = nCredit;
- assert(cache_used);
- *cache_used = true;
+ if (allow_cache) {
+ m_amounts[AVAILABLE_CREDIT].Set(filter, nCredit);
}
+
return nCredit;
}
-CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const
+CAmount CWalletTx::GetImmatureWatchOnlyCredit(interfaces::Chain::Lock& locked_chain, const bool fUseCache) const
{
- if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
- {
- if (fUseCache && fImmatureWatchCreditCached)
- return nImmatureWatchCreditCached;
- nImmatureWatchCreditCached = pwallet->GetCredit(*tx, ISMINE_WATCH_ONLY);
- fImmatureWatchCreditCached = true;
- return nImmatureWatchCreditCached;
+ if (IsImmatureCoinBase(locked_chain) && IsInMainChain(locked_chain)) {
+ return GetCachableAmount(IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache);
}
return 0;
@@ -2000,12 +2030,13 @@ bool CWalletTx::InMempool() const
return fInMempool;
}
-bool CWalletTx::IsTrusted() const
+bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const
{
// Quick answer in most cases
- if (!CheckFinalTx(*tx))
+ if (!locked_chain.checkFinalTx(*tx)) {
return false;
- int nDepth = GetDepthInMainChain();
+ }
+ int nDepth = GetDepthInMainChain(locked_chain);
if (nDepth >= 1)
return true;
if (nDepth < 0)
@@ -2040,57 +2071,61 @@ bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
return CTransaction(tx1) == CTransaction(tx2);
}
-std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman)
+// Rebroadcast transactions from the wallet. We do this on a random timer
+// to slightly obfuscate which transactions come from our wallet.
+//
+// Ideally, we'd only resend transactions that we think should have been
+// mined in the most recent block. Any transaction that wasn't in the top
+// blockweight of transactions in the mempool shouldn't have been mined,
+// and so is probably just sitting in the mempool waiting to be confirmed.
+// Rebroadcasting does nothing to speed up confirmation and only damages
+// privacy.
+void CWallet::ResendWalletTransactions()
{
- std::vector<uint256> result;
-
- LOCK(cs_wallet);
+ // During reindex, importing and IBD, old wallet transactions become
+ // unconfirmed. Don't resend them as that would spam other nodes.
+ if (!chain().isReadyToBroadcast()) return;
- // Sort them in chronological order
- std::multimap<unsigned int, CWalletTx*> mapSorted;
- for (std::pair<const uint256, CWalletTx>& item : mapWallet)
- {
- CWalletTx& wtx = item.second;
- // Don't rebroadcast if newer than nTime:
- if (wtx.nTimeReceived > nTime)
- continue;
- mapSorted.insert(std::make_pair(wtx.nTimeReceived, &wtx));
- }
- for (std::pair<const unsigned int, CWalletTx*>& item : mapSorted)
- {
- CWalletTx& wtx = *item.second;
- if (wtx.RelayWalletTransaction(connman))
- result.push_back(wtx.GetHash());
- }
- return result;
-}
-
-void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman)
-{
// Do this infrequently and randomly to avoid giving away
// that these are our transactions.
- if (GetTime() < nNextResend || !fBroadcastTransactions)
- return;
+ if (GetTime() < nNextResend || !fBroadcastTransactions) return;
bool fFirst = (nNextResend == 0);
nNextResend = GetTime() + GetRand(30 * 60);
- if (fFirst)
- return;
+ if (fFirst) return;
// Only do it if there's been a new block since last time
- if (nBestBlockTime < nLastResend)
- return;
+ if (m_best_block_time < nLastResend) return;
nLastResend = GetTime();
- // Rebroadcast unconfirmed txes older than 5 minutes before the last
- // block was found:
- std::vector<uint256> relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60, connman);
- if (!relayed.empty())
- LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
+ int relayed_tx_count = 0;
+
+ { // locked_chain and cs_wallet scope
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
+
+ // Relay transactions
+ for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
+ CWalletTx& wtx = item.second;
+ // only rebroadcast unconfirmed txes older than 5 minutes before the
+ // last block was found
+ if (wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
+ if (wtx.RelayWalletTransaction(*locked_chain)) ++relayed_tx_count;
+ }
+ } // locked_chain and cs_wallet
+
+ if (relayed_tx_count > 0) {
+ WalletLogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed_tx_count);
+ }
}
/** @} */ // end of mapWallet
-
+void MaybeResendWalletTxs()
+{
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
+ pwallet->ResendWalletTransactions();
+ }
+}
/** @defgroup Actions
@@ -2099,131 +2134,42 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman
*/
-CAmount CWallet::GetBalance(const isminefilter& filter, const int min_depth) const
+CWallet::Balance CWallet::GetBalance(const int min_depth) const
{
- CAmount nTotal = 0;
+ Balance ret;
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
- const CWalletTx* pcoin = &entry.second;
- if (pcoin->IsTrusted() && pcoin->GetDepthInMainChain() >= min_depth) {
- nTotal += pcoin->GetAvailableCredit(true, filter);
+ const CWalletTx& wtx = entry.second;
+ const bool is_trusted{wtx.IsTrusted(*locked_chain)};
+ const int tx_depth{wtx.GetDepthInMainChain(*locked_chain)};
+ const CAmount tx_credit_mine{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_SPENDABLE)};
+ const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_WATCH_ONLY)};
+ if (is_trusted && tx_depth >= min_depth) {
+ ret.m_mine_trusted += tx_credit_mine;
+ ret.m_watchonly_trusted += tx_credit_watchonly;
}
- }
- }
-
- return nTotal;
-}
-
-CAmount CWallet::GetUnconfirmedBalance() const
-{
- CAmount nTotal = 0;
- {
- LOCK2(cs_main, cs_wallet);
- for (const auto& entry : mapWallet)
- {
- const CWalletTx* pcoin = &entry.second;
- if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool())
- nTotal += pcoin->GetAvailableCredit();
- }
- }
- return nTotal;
-}
-
-CAmount CWallet::GetImmatureBalance() const
-{
- CAmount nTotal = 0;
- {
- LOCK2(cs_main, cs_wallet);
- for (const auto& entry : mapWallet)
- {
- const CWalletTx* pcoin = &entry.second;
- nTotal += pcoin->GetImmatureCredit();
- }
- }
- return nTotal;
-}
-
-CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
-{
- CAmount nTotal = 0;
- {
- LOCK2(cs_main, cs_wallet);
- for (const auto& entry : mapWallet)
- {
- const CWalletTx* pcoin = &entry.second;
- if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool())
- nTotal += pcoin->GetAvailableCredit(true, ISMINE_WATCH_ONLY);
- }
- }
- return nTotal;
-}
-
-CAmount CWallet::GetImmatureWatchOnlyBalance() const
-{
- CAmount nTotal = 0;
- {
- LOCK2(cs_main, cs_wallet);
- for (const auto& entry : mapWallet)
- {
- const CWalletTx* pcoin = &entry.second;
- nTotal += pcoin->GetImmatureWatchOnlyCredit();
- }
- }
- return nTotal;
-}
-
-// Calculate total balance in a different way from GetBalance. The biggest
-// difference is that GetBalance sums up all unspent TxOuts paying to the
-// wallet, while this sums up both spent and unspent TxOuts paying to the
-// wallet, and then subtracts the values of TxIns spending from the wallet. This
-// also has fewer restrictions on which unconfirmed transactions are considered
-// trusted.
-CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const
-{
- LOCK2(cs_main, cs_wallet);
-
- CAmount balance = 0;
- for (const auto& entry : mapWallet) {
- const CWalletTx& wtx = entry.second;
- const int depth = wtx.GetDepthInMainChain();
- if (depth < 0 || !CheckFinalTx(*wtx.tx) || wtx.GetBlocksToMaturity() > 0) {
- continue;
- }
-
- // Loop through tx outputs and add incoming payments. For outgoing txs,
- // treat change outputs specially, as part of the amount debited.
- CAmount debit = wtx.GetDebit(filter);
- const bool outgoing = debit > 0;
- for (const CTxOut& out : wtx.tx->vout) {
- if (outgoing && IsChange(out)) {
- debit -= out.nValue;
- } else if (IsMine(out) & filter && depth >= minDepth && (!account || *account == GetLabelName(out.scriptPubKey))) {
- balance += out.nValue;
+ if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
+ ret.m_mine_untrusted_pending += tx_credit_mine;
+ ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
}
- }
-
- // For outgoing txs, subtract amount debited.
- if (outgoing && (!account || *account == wtx.strFromAccount)) {
- balance -= debit;
+ ret.m_mine_immature += wtx.GetImmatureCredit(*locked_chain);
+ ret.m_watchonly_immature += wtx.GetImmatureWatchOnlyCredit(*locked_chain);
}
}
-
- if (account) {
- balance += WalletBatch(*database).GetAccountCreditDebit(*account);
- }
-
- return balance;
+ return ret;
}
CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
CAmount balance = 0;
std::vector<COutput> vCoins;
- AvailableCoins(vCoins, true, coinControl);
+ AvailableCoins(*locked_chain, vCoins, true, coinControl);
for (const COutput& out : vCoins) {
if (out.fSpendable) {
balance += out.tx->tx->vout[out.i].nValue;
@@ -2232,9 +2178,8 @@ CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const
return balance;
}
-void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t nMaximumCount, const int nMinDepth, const int nMaxDepth) const
+void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t nMaximumCount, const int nMinDepth, const int nMaxDepth) const
{
- AssertLockHeld(cs_main);
AssertLockHeld(cs_wallet);
vCoins.clear();
@@ -2243,24 +2188,25 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
for (const auto& entry : mapWallet)
{
const uint256& wtxid = entry.first;
- const CWalletTx* pcoin = &entry.second;
+ const CWalletTx& wtx = entry.second;
- if (!CheckFinalTx(*pcoin->tx))
+ if (!locked_chain.checkFinalTx(*wtx.tx)) {
continue;
+ }
- if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+ if (wtx.IsImmatureCoinBase(locked_chain))
continue;
- int nDepth = pcoin->GetDepthInMainChain();
+ int nDepth = wtx.GetDepthInMainChain(locked_chain);
if (nDepth < 0)
continue;
// We should not consider coins which aren't at least in our mempool
// It's possible for these to be conflicted via ancestors which we may never be able to detect
- if (nDepth == 0 && !pcoin->InMempool())
+ if (nDepth == 0 && !wtx.InMempool())
continue;
- bool safeTx = pcoin->IsTrusted();
+ bool safeTx = wtx.IsTrusted(locked_chain);
// We should not consider coins from transactions that are replacing
// other transactions.
@@ -2277,7 +2223,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
// be a 1-block reorg away from the chain where transactions A and C
// were accepted to another chain where B, B', and C were all
// accepted.
- if (nDepth == 0 && pcoin->mapValue.count("replaces_txid")) {
+ if (nDepth == 0 && wtx.mapValue.count("replaces_txid")) {
safeTx = false;
}
@@ -2289,7 +2235,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
// intending to replace A', but potentially resulting in a scenario
// where A, A', and D could all be accepted (instead of just B and
// D, or just A and A' like the user would want).
- if (nDepth == 0 && pcoin->mapValue.count("replaced_by_txid")) {
+ if (nDepth == 0 && wtx.mapValue.count("replaced_by_txid")) {
safeTx = false;
}
@@ -2300,8 +2246,8 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
if (nDepth < nMinDepth || nDepth > nMaxDepth)
continue;
- for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
- if (pcoin->tx->vout[i].nValue < nMinimumAmount || pcoin->tx->vout[i].nValue > nMaximumAmount)
+ for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
+ if (wtx.tx->vout[i].nValue < nMinimumAmount || wtx.tx->vout[i].nValue > nMaximumAmount)
continue;
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(entry.first, i)))
@@ -2310,23 +2256,23 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
if (IsLockedCoin(entry.first, i))
continue;
- if (IsSpent(wtxid, i))
+ if (IsSpent(locked_chain, wtxid, i))
continue;
- isminetype mine = IsMine(pcoin->tx->vout[i]);
+ isminetype mine = IsMine(wtx.tx->vout[i]);
if (mine == ISMINE_NO) {
continue;
}
- bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
+ bool solvable = IsSolvable(*this, wtx.tx->vout[i].scriptPubKey);
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
- vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx));
+ vCoins.push_back(COutput(&wtx, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly)));
// Checks the sum amount of all UTXO's.
if (nMinimumSumAmount != MAX_MONEY) {
- nTotal += pcoin->tx->vout[i].nValue;
+ nTotal += wtx.tx->vout[i].nValue;
if (nTotal >= nMinimumSumAmount) {
return;
@@ -2341,25 +2287,16 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
}
}
-std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins() const
+std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins(interfaces::Chain::Lock& locked_chain) const
{
- // TODO: Add AssertLockHeld(cs_wallet) here.
- //
- // Because the return value from this function contains pointers to
- // CWalletTx objects, callers to this function really should acquire the
- // cs_wallet lock before calling it. However, the current caller doesn't
- // acquire this lock yet. There was an attempt to add the missing lock in
- // https://github.com/bitcoin/bitcoin/pull/10340, but that change has been
- // postponed until after https://github.com/bitcoin/bitcoin/pull/10244 to
- // avoid adding some extra complexity to the Qt code.
+ AssertLockHeld(cs_wallet);
std::map<CTxDestination, std::vector<COutput>> result;
std::vector<COutput> availableCoins;
- LOCK2(cs_main, cs_wallet);
- AvailableCoins(availableCoins);
+ AvailableCoins(locked_chain, availableCoins);
- for (auto& coin : availableCoins) {
+ for (const COutput& coin : availableCoins) {
CTxDestination address;
if (coin.fSpendable &&
ExtractDestination(FindNonChangeParentOutput(*coin.tx->tx, coin.i).scriptPubKey, address)) {
@@ -2369,10 +2306,10 @@ std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins() const
std::vector<COutPoint> lockedCoins;
ListLockedCoins(lockedCoins);
- for (const auto& output : lockedCoins) {
+ for (const COutPoint& output : lockedCoins) {
auto it = mapWallet.find(output.hash);
if (it != mapWallet.end()) {
- int depth = it->second.GetDepthInMainChain();
+ int depth = it->second.GetDepthInMainChain(locked_chain);
if (depth >= 0 && output.n < it->second.tx->vout.size() &&
IsMine(it->second.tx->vout[output.n]) == ISMINE_SPENDABLE) {
CTxDestination address;
@@ -2416,10 +2353,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
FeeCalculation feeCalc;
CCoinControl temp;
temp.m_confirm_target = 1008;
- CFeeRate long_term_feerate = GetMinimumFeeRate(*this, temp, ::mempool, ::feeEstimator, &feeCalc);
+ CFeeRate long_term_feerate = GetMinimumFeeRate(*this, temp, &feeCalc);
// Calculate cost of change
- CAmount cost_of_change = GetDiscardRate(*this, ::feeEstimator).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size);
+ CAmount cost_of_change = GetDiscardRate(*this).GetFee(coin_selection_params.change_spend_size) + coin_selection_params.effective_fee.GetFee(coin_selection_params.change_output_size);
// Filter by the min conf specs and add to utxo_pool and calculate effective value
for (OutputGroup& group : groups) {
@@ -2493,13 +2430,13 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
if (it != mapWallet.end())
{
- const CWalletTx* pcoin = &it->second;
+ const CWalletTx& wtx = it->second;
// Clearly invalid input, fail
- if (pcoin->tx->vout.size() <= outpoint.n)
+ if (wtx.tx->vout.size() <= outpoint.n)
return false;
// Just to calculate the marginal byte size
- nValueFromPresetInputs += pcoin->tx->vout[outpoint.n].nValue;
- setPresetCoins.insert(CInputCoin(pcoin->tx, outpoint.n));
+ nValueFromPresetInputs += wtx.tx->vout[outpoint.n].nValue;
+ setPresetCoins.insert(CInputCoin(wtx.tx, outpoint.n));
} else
return false; // TODO: Allow non-wallet inputs
}
@@ -2515,6 +2452,12 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
// form groups from remaining coins; note that preset coins will not
// automatically have their associated (same address) coins included
+ if (coin_control.m_avoid_partial_spends && vCoins.size() > OUTPUT_GROUP_MAX_ENTRIES) {
+ // Cases where we have 11+ outputs all pointing to the same destination may result in
+ // privacy leaks as they will potentially be deterministically sorted. We solve that by
+ // explicitly shuffling the outputs before processing
+ Shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
+ }
std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends);
size_t max_ancestors = (size_t)std::max<int64_t>(1, gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT));
@@ -2539,9 +2482,9 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
return res;
}
-bool CWallet::SignTransaction(CMutableTransaction &tx)
+bool CWallet::SignTransaction(CMutableTransaction& tx)
{
- AssertLockHeld(cs_wallet); // mapWallet
+ AssertLockHeld(cs_wallet);
// sign the new tx
int nIn = 0;
@@ -2581,11 +2524,12 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
// Acquire the locks to prevent races to the new locked unspents between the
// CreateTransaction call and LockCoin calls (when lockUnspents is true).
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
CReserveKey reservekey(this);
CTransactionRef tx_new;
- if (!CreateTransaction(vecSend, tx_new, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
+ if (!CreateTransaction(*locked_chain, vecSend, tx_new, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) {
return false;
}
@@ -2616,6 +2560,66 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
return true;
}
+static bool IsCurrentForAntiFeeSniping(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain)
+{
+ if (chain.isInitialBlockDownload()) {
+ return false;
+ }
+ constexpr int64_t MAX_ANTI_FEE_SNIPING_TIP_AGE = 8 * 60 * 60; // in seconds
+ if (locked_chain.getBlockTime(*locked_chain.getHeight()) < (GetTime() - MAX_ANTI_FEE_SNIPING_TIP_AGE)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Return a height-based locktime for new transactions (uses the height of the
+ * current chain tip unless we are not synced with the current chain
+ */
+static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain)
+{
+ uint32_t const height = locked_chain.getHeight().get_value_or(-1);
+ uint32_t locktime;
+ // Discourage fee sniping.
+ //
+ // For a large miner the value of the transactions in the best block and
+ // the mempool can exceed the cost of deliberately attempting to mine two
+ // blocks to orphan the current best block. By setting nLockTime such that
+ // only the next block can include the transaction, we discourage this
+ // practice as the height restricted and limited blocksize gives miners
+ // considering fee sniping fewer options for pulling off this attack.
+ //
+ // A simple way to think about this is from the wallet's point of view we
+ // always want the blockchain to move forward. By setting nLockTime this
+ // way we're basically making the statement that we only want this
+ // transaction to appear in the next block; we don't want to potentially
+ // encourage reorgs by allowing transactions to appear at lower heights
+ // than the next block in forks of the best chain.
+ //
+ // Of course, the subsidy is high enough, and transaction volume low
+ // enough, that fee sniping isn't a problem yet, but by implementing a fix
+ // now we ensure code won't be written that makes assumptions about
+ // nLockTime that preclude a fix later.
+ if (IsCurrentForAntiFeeSniping(chain, locked_chain)) {
+ locktime = height;
+
+ // Secondly occasionally randomly pick a nLockTime even further back, so
+ // that transactions that are delayed after signing for whatever reason,
+ // e.g. high-latency mix networks and some CoinJoin implementations, have
+ // better privacy.
+ if (GetRandInt(10) == 0)
+ locktime = std::max(0, (int)locktime - GetRandInt(100));
+ } else {
+ // If our chain is lagging behind, we can't discourage fee sniping nor help
+ // the privacy of high-latency transactions. To avoid leaking a potentially
+ // unique "nLockTime fingerprint", set nLockTime to a constant.
+ locktime = 0;
+ }
+ assert(locktime <= height);
+ assert(locktime < LOCKTIME_THRESHOLD);
+ return locktime;
+}
+
OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend)
{
// If -changetype is specified, always use that change type.
@@ -2644,7 +2648,7 @@ OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vec
return m_default_address_type;
}
-bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet,
+bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet,
int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
{
CAmount nValue = 0;
@@ -2670,46 +2674,18 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
CMutableTransaction txNew;
- // Discourage fee sniping.
- //
- // For a large miner the value of the transactions in the best block and
- // the mempool can exceed the cost of deliberately attempting to mine two
- // blocks to orphan the current best block. By setting nLockTime such that
- // only the next block can include the transaction, we discourage this
- // practice as the height restricted and limited blocksize gives miners
- // considering fee sniping fewer options for pulling off this attack.
- //
- // A simple way to think about this is from the wallet's point of view we
- // always want the blockchain to move forward. By setting nLockTime this
- // way we're basically making the statement that we only want this
- // transaction to appear in the next block; we don't want to potentially
- // encourage reorgs by allowing transactions to appear at lower heights
- // than the next block in forks of the best chain.
- //
- // Of course, the subsidy is high enough, and transaction volume low
- // enough, that fee sniping isn't a problem yet, but by implementing a fix
- // now we ensure code won't be written that makes assumptions about
- // nLockTime that preclude a fix later.
- txNew.nLockTime = chainActive.Height();
+ txNew.nLockTime = GetLocktimeForNewTransaction(chain(), locked_chain);
- // Secondly occasionally randomly pick a nLockTime even further back, so
- // that transactions that are delayed after signing for whatever reason,
- // e.g. high-latency mix networks and some CoinJoin implementations, have
- // better privacy.
- if (GetRandInt(10) == 0)
- txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
-
- assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
- assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
FeeCalculation feeCalc;
CAmount nFeeNeeded;
int nBytes;
{
std::set<CInputCoin> setCoins;
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
{
std::vector<COutput> vAvailableCoins;
- AvailableCoins(vAvailableCoins, true, &coin_control);
+ AvailableCoins(*locked_chain, vAvailableCoins, true, &coin_control, 1, MAX_MONEY, MAX_MONEY, 0, coin_control.m_min_depth);
CoinSelectionParams coin_selection_params; // Parameters for coin selection, init with dummy
// Create change script that will be used if we need change
@@ -2729,8 +2705,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
// post-backup change.
// Reserve a new key pair from key pool
- if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
- strFailReason = _("Can't generate a change-address key. Private keys are disabled for this wallet.");
+ if (!CanGetAddresses(true)) {
+ strFailReason = _("Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.");
return false;
}
CPubKey vchPubKey;
@@ -2748,12 +2724,12 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
scriptChange = GetScriptForDestination(GetDestinationForKey(vchPubKey, change_type));
}
CTxOut change_prototype_txout(0, scriptChange);
- coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout, SER_DISK, 0);
+ coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);
- CFeeRate discard_rate = GetDiscardRate(*this, ::feeEstimator);
+ CFeeRate discard_rate = GetDiscardRate(*this);
// Get the fee rate to use effective values in coin selection
- CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, ::mempool, ::feeEstimator, &feeCalc);
+ CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, &feeCalc);
nFeeRet = 0;
bool pick_new_inputs = true;
@@ -2792,9 +2768,9 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
}
}
// Include the fee cost for outputs. Note this is only used for BnB right now
- coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, SER_NETWORK, PROTOCOL_VERSION);
+ coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION);
- if (IsDust(txout, ::dustRelayFee))
+ if (IsDust(txout, chain().relayDustFee()))
{
if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
{
@@ -2815,7 +2791,14 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
if (pick_new_inputs) {
nValueIn = 0;
setCoins.clear();
- coin_selection_params.change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, this);
+ int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, this);
+ // If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh
+ // as lower-bound to allow BnB to do it's thing
+ if (change_spend_size == -1) {
+ coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE;
+ } else {
+ coin_selection_params.change_spend_size = (size_t)change_spend_size;
+ }
coin_selection_params.effective_fee = nFeeRateNeeded;
if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coin_control, coin_selection_params, bnb_used))
{
@@ -2829,6 +2812,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
return false;
}
}
+ } else {
+ bnb_used = false;
}
const CAmount nChange = nValueIn - nValueToSelect;
@@ -2871,13 +2856,13 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
txNew.vin.push_back(CTxIn(coin.outpoint,CScript()));
}
- nBytes = CalculateMaximumSignedTxSize(txNew, this);
+ nBytes = CalculateMaximumSignedTxSize(CTransaction(txNew), this, coin_control.fAllowWatchOnly);
if (nBytes < 0) {
strFailReason = _("Signing transaction failed");
return false;
}
- nFeeNeeded = GetMinimumFee(*this, nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc);
+ nFeeNeeded = GetMinimumFee(*this, nBytes, coin_control, &feeCalc);
if (feeCalc.reason == FeeReason::FALLBACK && !m_allow_fallback_fee) {
// eventually allow a fallback fee
strFailReason = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
@@ -2886,7 +2871,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
// If we made it here and we aren't even able to meet the relay fee on the next pass, give up
// because we must be at the maximum allowed fee.
- if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes))
+ if (nFeeNeeded < chain().relayMinFee().GetFee(nBytes))
{
strFailReason = _("Transaction too large for fee policy");
return false;
@@ -2905,7 +2890,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
// change output. Only try this once.
if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) {
unsigned int tx_size_with_change = nBytes + coin_selection_params.change_output_size + 2; // Add 2 as a buffer in case increasing # of outputs changes compact size
- CAmount fee_needed_with_change = GetMinimumFee(*this, tx_size_with_change, coin_control, ::mempool, ::feeEstimator, nullptr);
+ CAmount fee_needed_with_change = GetMinimumFee(*this, tx_size_with_change, coin_control, nullptr);
CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate);
if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) {
pick_new_inputs = false;
@@ -2962,7 +2947,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
// Shuffle selected coins and fill in final vin
txNew.vin.clear();
std::vector<CInputCoin> selected_coins(setCoins.begin(), setCoins.end());
- std::shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext());
+ Shuffle(selected_coins.begin(), selected_coins.end(), FastRandomContext());
// Note how the sequence number is set to non-maxint so that
// the nLockTime set above actually works.
@@ -3010,22 +2995,13 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) {
// Lastly, ensure this tx will pass the mempool's chain limits
- LockPoints lp;
- CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp);
- CTxMemPool::setEntries setAncestors;
- size_t nLimitAncestors = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
- size_t nLimitAncestorSize = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000;
- size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
- size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
- std::string errString;
- LOCK(::mempool.cs);
- if (!::mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
+ if (!chain().checkChainLimits(tx)) {
strFailReason = _("Transaction has too long of a mempool chain");
return false;
}
}
- LogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d 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",
+ WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d 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, nFeeNeeded, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
feeCalc.est.pass.start, feeCalc.est.pass.end,
100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool),
@@ -3039,19 +3015,19 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
/**
* Call after CreateTransaction unless you want to abort
*/
-bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, std::string fromAccount, CReserveKey& reservekey, CConnman* connman, CValidationState& state)
+bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CReserveKey& reservekey, CValidationState& state)
{
{
- LOCK2(cs_main, cs_wallet);
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
CWalletTx wtxNew(this, std::move(tx));
wtxNew.mapValue = std::move(mapValue);
wtxNew.vOrderForm = std::move(orderForm);
- wtxNew.strFromAccount = std::move(fromAccount);
wtxNew.fTimeReceivedIsTxTime = true;
wtxNew.fFromMe = true;
- LogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */
+ WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */
{
// Take key pair from key pool so it won't be used again
reservekey.KeepKey();
@@ -3076,45 +3052,20 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
if (fBroadcastTransactions)
{
// Broadcast
- if (!wtx.AcceptToMemoryPool(maxTxFee, state)) {
- LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", FormatStateMessage(state));
+ if (!wtx.AcceptToMemoryPool(*locked_chain, state)) {
+ WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", FormatStateMessage(state));
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
} else {
- wtx.RelayWalletTransaction(connman);
+ wtx.RelayWalletTransaction(*locked_chain);
}
}
}
return true;
}
-void CWallet::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries) {
- WalletBatch batch(*database);
- return batch.ListAccountCreditDebit(strAccount, entries);
-}
-
-bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry)
-{
- WalletBatch batch(*database);
-
- return AddAccountingEntry(acentry, &batch);
-}
-
-bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, WalletBatch *batch)
-{
- if (!batch->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) {
- return false;
- }
-
- laccentries.push_back(acentry);
- CAccountingEntry & entry = laccentries.back();
- wtxOrdered.insert(std::make_pair(entry.nOrderPos, TxPair(nullptr, &entry)));
-
- return true;
-}
-
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
- LOCK2(cs_main, cs_wallet);
+ LOCK(cs_wallet);
fFirstRunRet = false;
DBErrors nLoadWalletRet = WalletBatch(*database,"cr+").LoadWallet(this);
@@ -3134,7 +3085,8 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
LOCK(cs_KeyStore);
// This wallet is in its first run if all of these are empty
- fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty() && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
+ fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty()
+ && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
}
if (nLoadWalletRet != DBErrors::LOAD_OK)
@@ -3145,8 +3097,8 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut)
{
- AssertLockHeld(cs_wallet); // mapWallet
- DBErrors nZapSelectTxRet = WalletBatch(*database,"cr+").ZapSelectTx(vHashIn, vHashOut);
+ AssertLockHeld(cs_wallet);
+ DBErrors nZapSelectTxRet = WalletBatch(*database, "cr+").ZapSelectTx(vHashIn, vHashOut);
for (uint256 hash : vHashOut) {
const auto& it = mapWallet.find(hash);
wtxOrdered.erase(it->second.m_it_wtxOrdered);
@@ -3172,7 +3124,6 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
MarkDirty();
return DBErrors::LOAD_OK;
-
}
DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
@@ -3203,7 +3154,7 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s
{
bool fUpdated = false;
{
- LOCK(cs_wallet); // mapAddressBook
+ LOCK(cs_wallet);
std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
fUpdated = mi != mapAddressBook.end();
mapAddressBook[address].name = strName;
@@ -3220,7 +3171,7 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s
bool CWallet::DelAddressBook(const CTxDestination& address)
{
{
- LOCK(cs_wallet); // mapAddressBook
+ LOCK(cs_wallet);
// Delete destdata tuples associated with address
std::string strAddress = EncodeDestination(address);
@@ -3265,17 +3216,17 @@ bool CWallet::NewKeyPool()
LOCK(cs_wallet);
WalletBatch batch(*database);
- for (int64_t nIndex : setInternalKeyPool) {
+ for (const int64_t nIndex : setInternalKeyPool) {
batch.ErasePool(nIndex);
}
setInternalKeyPool.clear();
- for (int64_t nIndex : setExternalKeyPool) {
+ for (const int64_t nIndex : setExternalKeyPool) {
batch.ErasePool(nIndex);
}
setExternalKeyPool.clear();
- for (int64_t nIndex : set_pre_split_keypool) {
+ for (const int64_t nIndex : set_pre_split_keypool) {
batch.ErasePool(nIndex);
}
set_pre_split_keypool.clear();
@@ -3285,14 +3236,14 @@ bool CWallet::NewKeyPool()
if (!TopUpKeyPool()) {
return false;
}
- LogPrintf("CWallet::NewKeyPool rewrote keypool\n");
+ WalletLogPrintf("CWallet::NewKeyPool rewrote keypool\n");
}
return true;
}
size_t CWallet::KeypoolCountExternalKeys()
{
- AssertLockHeld(cs_wallet); // setExternalKeyPool
+ AssertLockHeld(cs_wallet);
return setExternalKeyPool.size() + set_pre_split_keypool.size();
}
@@ -3319,7 +3270,7 @@ void CWallet::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
bool CWallet::TopUpKeyPool(unsigned int kpSize)
{
- if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ if (!CanGenerateKeys()) {
return false;
}
{
@@ -3353,28 +3304,40 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
internal = true;
}
- assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys?
- int64_t index = ++m_max_keypool_index;
-
CPubKey pubkey(GenerateNewKey(batch, internal));
- if (!batch.WritePool(index, CKeyPool(pubkey, internal))) {
- throw std::runtime_error(std::string(__func__) + ": writing generated key failed");
- }
-
- if (internal) {
- setInternalKeyPool.insert(index);
- } else {
- setExternalKeyPool.insert(index);
- }
- m_pool_key_to_index[pubkey.GetID()] = index;
+ AddKeypoolPubkeyWithDB(pubkey, internal, batch);
}
if (missingInternal + missingExternal > 0) {
- LogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(), setInternalKeyPool.size());
+ WalletLogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(), setInternalKeyPool.size());
}
}
+ NotifyCanGetAddressesChanged();
return true;
}
+void CWallet::AddKeypoolPubkey(const CPubKey& pubkey, const bool internal)
+{
+ WalletBatch batch(*database);
+ AddKeypoolPubkeyWithDB(pubkey, internal, batch);
+ NotifyCanGetAddressesChanged();
+}
+
+void CWallet::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch)
+{
+ LOCK(cs_wallet);
+ assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys?
+ int64_t index = ++m_max_keypool_index;
+ if (!batch.WritePool(index, CKeyPool(pubkey, internal))) {
+ throw std::runtime_error(std::string(__func__) + ": writing imported pubkey failed");
+ }
+ if (internal) {
+ setInternalKeyPool.insert(index);
+ } else {
+ setExternalKeyPool.insert(index);
+ }
+ m_pool_key_to_index[pubkey.GetID()] = index;
+}
+
bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
{
nIndex = -1;
@@ -3385,7 +3348,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
if (!IsLocked())
TopUpKeyPool();
- bool fReturningInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && fRequestedInternal;
+ bool fReturningInternal = fRequestedInternal;
+ fReturningInternal &= (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) || IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
bool use_split_keypool = set_pre_split_keypool.empty();
std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
@@ -3402,7 +3366,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
if (!batch.ReadPool(nIndex, keypool)) {
throw std::runtime_error(std::string(__func__) + ": read failed");
}
- if (!HaveKey(keypool.vchPubKey.GetID())) {
+ CPubKey pk;
+ if (!GetPubKey(keypool.vchPubKey.GetID(), pk)) {
throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
}
// If the key was pre-split keypool, we don't care about what type it is
@@ -3414,8 +3379,9 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
}
m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
- LogPrintf("keypool reserve %d\n", nIndex);
+ WalletLogPrintf("keypool reserve %d\n", nIndex);
}
+ NotifyCanGetAddressesChanged();
return true;
}
@@ -3424,7 +3390,7 @@ void CWallet::KeepKey(int64_t nIndex)
// Remove from key pool
WalletBatch batch(*database);
batch.ErasePool(nIndex);
- LogPrintf("keypool keep %d\n", nIndex);
+ WalletLogPrintf("keypool keep %d\n", nIndex);
}
void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
@@ -3440,13 +3406,14 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
setExternalKeyPool.insert(nIndex);
}
m_pool_key_to_index[pubkey.GetID()] = nIndex;
+ NotifyCanGetAddressesChanged();
}
- LogPrintf("keypool return %d\n", nIndex);
+ WalletLogPrintf("keypool return %d\n", nIndex);
}
bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
{
- if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ if (!CanGetAddresses(internal)) {
return false;
}
@@ -3454,7 +3421,7 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
{
LOCK(cs_wallet);
int64_t nIndex;
- if (!ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
+ if (!ReserveKeyFromKeyPool(nIndex, keypool, internal) && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
if (IsLocked()) return false;
WalletBatch batch(*database);
result = GenerateNewKey(batch, internal);
@@ -3498,7 +3465,7 @@ int64_t CWallet::GetOldestKeyPoolTime()
return oldestKey;
}
-std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
+std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain::Lock& locked_chain)
{
std::map<CTxDestination, CAmount> balances;
@@ -3506,27 +3473,27 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
LOCK(cs_wallet);
for (const auto& walletEntry : mapWallet)
{
- const CWalletTx *pcoin = &walletEntry.second;
+ const CWalletTx& wtx = walletEntry.second;
- if (!pcoin->IsTrusted())
+ if (!wtx.IsTrusted(locked_chain))
continue;
- if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+ if (wtx.IsImmatureCoinBase(locked_chain))
continue;
- int nDepth = pcoin->GetDepthInMainChain();
- if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
+ int nDepth = wtx.GetDepthInMainChain(locked_chain);
+ if (nDepth < (wtx.IsFromMe(ISMINE_ALL) ? 0 : 1))
continue;
- for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++)
+ for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
{
CTxDestination addr;
- if (!IsMine(pcoin->tx->vout[i]))
+ if (!IsMine(wtx.tx->vout[i]))
continue;
- if(!ExtractDestination(pcoin->tx->vout[i].scriptPubKey, addr))
+ if(!ExtractDestination(wtx.tx->vout[i].scriptPubKey, addr))
continue;
- CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->tx->vout[i].nValue;
+ CAmount n = IsSpent(locked_chain, walletEntry.first, i) ? 0 : wtx.tx->vout[i].nValue;
if (!balances.count(addr))
balances[addr] = 0;
@@ -3540,19 +3507,19 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
{
- AssertLockHeld(cs_wallet); // mapWallet
+ AssertLockHeld(cs_wallet);
std::set< std::set<CTxDestination> > groupings;
std::set<CTxDestination> grouping;
for (const auto& walletEntry : mapWallet)
{
- const CWalletTx *pcoin = &walletEntry.second;
+ const CWalletTx& wtx = walletEntry.second;
- if (pcoin->tx->vin.size() > 0)
+ if (wtx.tx->vin.size() > 0)
{
bool any_mine = false;
// group all input addresses with each other
- for (CTxIn txin : pcoin->tx->vin)
+ for (const CTxIn& txin : wtx.tx->vin)
{
CTxDestination address;
if(!IsMine(txin)) /* If this input isn't mine, ignore it */
@@ -3566,7 +3533,7 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
// group change with input addresses
if (any_mine)
{
- for (CTxOut txout : pcoin->tx->vout)
+ for (const CTxOut& txout : wtx.tx->vout)
if (IsChange(txout))
{
CTxDestination txoutAddr;
@@ -3583,7 +3550,7 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
}
// group lone addrs by themselves
- for (const auto& txout : pcoin->tx->vout)
+ for (const auto& txout : wtx.tx->vout)
if (IsMine(txout))
{
CTxDestination address;
@@ -3602,7 +3569,7 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
// make a set of all the groups hit by this new group
std::set< std::set<CTxDestination>* > hits;
std::map< CTxDestination, std::set<CTxDestination>* >::iterator it;
- for (CTxDestination address : _grouping)
+ for (const CTxDestination& address : _grouping)
if ((it = setmap.find(address)) != setmap.end())
hits.insert((*it).second);
@@ -3617,12 +3584,12 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
uniqueGroupings.insert(merged);
// update setmap
- for (CTxDestination element : *merged)
+ for (const CTxDestination& element : *merged)
setmap[element] = merged;
}
std::set< std::set<CTxDestination> > ret;
- for (std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
+ for (const std::set<CTxDestination>* uniqueGrouping : uniqueGroupings)
{
ret.insert(*uniqueGrouping);
delete uniqueGrouping;
@@ -3645,14 +3612,12 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co
return result;
}
-void CWallet::DeleteLabel(const std::string& label)
-{
- WalletBatch batch(*database);
- batch.EraseAccount(label);
-}
-
bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool internal)
{
+ if (!pwallet->CanGetAddresses(internal)) {
+ return false;
+ }
+
if (nIndex == -1)
{
CKeyPool keypool;
@@ -3703,43 +3668,32 @@ void CWallet::MarkReserveKeysAsUsed(int64_t keypool_id)
}
LearnAllRelatedScripts(keypool.vchPubKey);
batch.ErasePool(index);
- LogPrintf("keypool index %d removed\n", index);
+ WalletLogPrintf("keypool index %d removed\n", index);
it = setKeyPool->erase(it);
}
}
-void CWallet::GetScriptForMining(std::shared_ptr<CReserveScript> &script)
-{
- std::shared_ptr<CReserveKey> rKey = std::make_shared<CReserveKey>(this);
- CPubKey pubkey;
- if (!rKey->GetReservedKey(pubkey))
- return;
-
- script = rKey;
- script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
-}
-
void CWallet::LockCoin(const COutPoint& output)
{
- AssertLockHeld(cs_wallet); // setLockedCoins
+ AssertLockHeld(cs_wallet);
setLockedCoins.insert(output);
}
void CWallet::UnlockCoin(const COutPoint& output)
{
- AssertLockHeld(cs_wallet); // setLockedCoins
+ AssertLockHeld(cs_wallet);
setLockedCoins.erase(output);
}
void CWallet::UnlockAllCoins()
{
- AssertLockHeld(cs_wallet); // setLockedCoins
+ AssertLockHeld(cs_wallet);
setLockedCoins.clear();
}
bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
{
- AssertLockHeld(cs_wallet); // setLockedCoins
+ AssertLockHeld(cs_wallet);
COutPoint outpt(hash, n);
return (setLockedCoins.count(outpt) > 0);
@@ -3747,7 +3701,7 @@ bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
{
- AssertLockHeld(cs_wallet); // setLockedCoins
+ AssertLockHeld(cs_wallet);
for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
it != setLockedCoins.end(); it++) {
COutPoint outpt = (*it);
@@ -3757,8 +3711,8 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
/** @} */ // end of Actions
-void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const {
- AssertLockHeld(cs_wallet); // mapKeyMetadata
+void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CKeyID, int64_t>& mapKeyBirth) const {
+ AssertLockHeld(cs_wallet);
mapKeyBirth.clear();
// get birth times for keys with metadata
@@ -3769,11 +3723,12 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c
}
// map in which we'll infer heights of other keys
- CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganized; use a 144-block safety margin
- std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
+ const Optional<int> tip_height = locked_chain.getHeight();
+ const int max_height = tip_height && *tip_height > 144 ? *tip_height - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
+ std::map<CKeyID, int> mapKeyFirstBlock;
for (const CKeyID &keyid : GetKeys()) {
if (mapKeyBirth.count(keyid) == 0)
- mapKeyFirstBlock[keyid] = pindexMax;
+ mapKeyFirstBlock[keyid] = max_height;
}
// if there are no such keys, we're done
@@ -3781,31 +3736,26 @@ void CWallet::GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) c
return;
// find first block that affects those keys, if there are any left
- std::vector<CKeyID> vAffected;
for (const auto& entry : mapWallet) {
// iterate over all wallet transactions...
const CWalletTx &wtx = entry.second;
- CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock);
- if (pindex && chainActive.Contains(pindex)) {
+ if (Optional<int> height = locked_chain.getBlockHeight(wtx.hashBlock)) {
// ... which are already in a block
- int nHeight = pindex->nHeight;
for (const CTxOut &txout : wtx.tx->vout) {
// iterate over all their outputs
- CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
- for (const CKeyID &keyid : vAffected) {
+ for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *this)) {
// ... and all their affected keys
- std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
- if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
- rit->second = pindex;
+ std::map<CKeyID, int>::iterator rit = mapKeyFirstBlock.find(keyid);
+ if (rit != mapKeyFirstBlock.end() && *height < rit->second)
+ rit->second = *height;
}
- vAffected.clear();
}
}
}
// Extract block timestamps for those keys
for (const auto& entry : mapKeyFirstBlock)
- mapKeyBirth[entry.first] = entry.second->GetBlockTime() - TIMESTAMP_WINDOW; // block times can be 2h off
+ mapKeyBirth[entry.first] = locked_chain.getBlockTime(entry.second) - TIMESTAMP_WINDOW; // block times can be 2h off
}
/**
@@ -3833,7 +3783,8 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
{
unsigned int nTimeSmart = wtx.nTimeReceived;
if (!wtx.hashUnset()) {
- if (const CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock)) {
+ int64_t blocktime;
+ if (chain().findBlock(wtx.hashBlock, nullptr /* block */, &blocktime)) {
int64_t latestNow = wtx.nTimeReceived;
int64_t latestEntry = 0;
@@ -3841,19 +3792,14 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
int64_t latestTolerated = latestNow + 300;
const TxItems& txOrdered = wtxOrdered;
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
- CWalletTx* const pwtx = it->second.first;
+ CWalletTx* const pwtx = it->second;
if (pwtx == &wtx) {
continue;
}
- CAccountingEntry* const pacentry = it->second.second;
int64_t nSmartTime;
- if (pwtx) {
- nSmartTime = pwtx->nTimeSmart;
- if (!nSmartTime) {
- nSmartTime = pwtx->nTimeReceived;
- }
- } else {
- nSmartTime = pacentry->nTime;
+ nSmartTime = pwtx->nTimeSmart;
+ if (!nSmartTime) {
+ nSmartTime = pwtx->nTimeReceived;
}
if (nSmartTime <= latestTolerated) {
latestEntry = nSmartTime;
@@ -3864,10 +3810,9 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
}
}
- int64_t blocktime = pindex->GetBlockTime();
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
} else {
- LogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.hashBlock.ToString());
+ WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.hashBlock.ToString());
}
}
return nTimeSmart;
@@ -3912,7 +3857,6 @@ bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, st
std::vector<std::string> CWallet::GetDestValues(const std::string& prefix) const
{
- LOCK(cs_wallet);
std::vector<std::string> values;
for (const auto& address : mapAddressBook) {
for (const auto& data : address.second.destdata) {
@@ -3942,7 +3886,7 @@ void CWallet::MarkPreSplitKeys()
}
}
-bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string& error_string, std::string& warning_string)
+bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string)
{
// Do some checking on wallet path. It should be either a:
//
@@ -3951,34 +3895,40 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
// 3. Path to a symlink to a directory.
// 4. For backwards compatibility, the name of a data file in -walletdir.
LOCK(cs_wallets);
- fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
+ const fs::path& wallet_path = location.GetPath();
fs::file_type path_type = fs::symlink_status(wallet_path).type();
if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
- (path_type == fs::regular_file && fs::path(wallet_file).filename() == wallet_file))) {
+ (path_type == fs::regular_file && fs::path(location.GetName()).filename() == location.GetName()))) {
error_string = strprintf(
"Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
"database/log.?????????? files can be stored, a location where such a directory could be created, "
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
- wallet_file, GetWalletDir());
+ location.GetName(), GetWalletDir());
return false;
}
// Make sure that the wallet path doesn't clash with an existing wallet path
- for (auto wallet : GetWallets()) {
- if (fs::absolute(wallet->GetName(), GetWalletDir()) == wallet_path) {
- error_string = strprintf("Error loading wallet %s. Duplicate -wallet filename specified.", wallet_file);
- return false;
- }
+ if (IsWalletLoaded(wallet_path)) {
+ error_string = strprintf("Error loading wallet %s. Duplicate -wallet filename specified.", location.GetName());
+ return false;
}
- if (!WalletBatch::VerifyEnvironment(wallet_path, error_string)) {
+ // Keep same database environment instance across Verify/Recover calls below.
+ std::unique_ptr<WalletDatabase> database = WalletDatabase::Create(wallet_path);
+
+ try {
+ if (!WalletBatch::VerifyEnvironment(wallet_path, error_string)) {
+ return false;
+ }
+ } catch (const fs::filesystem_error& e) {
+ error_string = strprintf("Error loading wallet %s. %s", location.GetName(), fsbridge::get_filesystem_error_message(e));
return false;
}
if (salvage_wallet) {
// Recover readable keypairs:
- CWallet dummyWallet("dummy", WalletDatabase::CreateDummy());
+ CWallet dummyWallet(&chain, WalletLocation(), WalletDatabase::CreateDummy());
std::string backup_filename;
if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
return false;
@@ -3988,74 +3938,74 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string);
}
-std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path, uint64_t wallet_creation_flags)
+std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags)
{
- const std::string& walletFile = name;
+ const std::string& walletFile = WalletDataFilePath(location.GetPath()).string();
// needed to restore wallet transaction meta data after -zapwallettxes
std::vector<CWalletTx> vWtx;
if (gArgs.GetBoolArg("-zapwallettxes", false)) {
- uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
+ chain.initMessage(_("Zapping all transactions from wallet..."));
- std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(name, WalletDatabase::Create(path));
+ std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(&chain, location, WalletDatabase::Create(location.GetPath()));
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DBErrors::LOAD_OK) {
- InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
+ chain.initError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
return nullptr;
}
}
- uiInterface.InitMessage(_("Loading wallet..."));
+ chain.initMessage(_("Loading wallet..."));
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
// TODO: Can't use std::make_shared because we need a custom deleter but
// should be possible to use std::allocate_shared.
- std::shared_ptr<CWallet> walletInstance(new CWallet(name, WalletDatabase::Create(path)), ReleaseWallet);
+ std::shared_ptr<CWallet> walletInstance(new CWallet(&chain, location, WalletDatabase::Create(location.GetPath())), ReleaseWallet);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
if (nLoadWalletRet == DBErrors::CORRUPT) {
- InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
+ chain.initError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
return nullptr;
}
else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
{
- InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
- " or address book entries might be missing or incorrect."),
+ chain.initWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
+ " or address book entries might be missing or incorrect."),
walletFile));
}
else if (nLoadWalletRet == DBErrors::TOO_NEW) {
- InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, _(PACKAGE_NAME)));
+ chain.initError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, _(PACKAGE_NAME)));
return nullptr;
}
else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
{
- InitError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)));
+ chain.initError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)));
return nullptr;
}
else {
- InitError(strprintf(_("Error loading %s"), walletFile));
+ chain.initError(strprintf(_("Error loading %s"), walletFile));
return nullptr;
}
}
- int prev_version = walletInstance->nWalletVersion;
+ int prev_version = walletInstance->GetVersion();
if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
{
int nMaxVersion = gArgs.GetArg("-upgradewallet", 0);
if (nMaxVersion == 0) // the -upgradewallet without argument case
{
- LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
+ walletInstance->WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
nMaxVersion = FEATURE_LATEST;
walletInstance->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
}
else
- LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
+ walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < walletInstance->GetVersion())
{
- InitError(_("Cannot downgrade wallet"));
+ chain.initError(_("Cannot downgrade wallet"));
return nullptr;
}
walletInstance->SetMaxVersion(nMaxVersion);
@@ -4066,16 +4016,16 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
LOCK(walletInstance->cs_wallet);
// Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
- int max_version = walletInstance->nWalletVersion;
- if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >=FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
- InitError(_("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified."));
+ int max_version = walletInstance->GetVersion();
+ if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
+ chain.initError(_("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified."));
return nullptr;
}
bool hd_upgrade = false;
bool split_upgrade = false;
if (walletInstance->CanSupportFeature(FEATURE_HD) && !walletInstance->IsHDEnabled()) {
- LogPrintf("Upgrading wallet to HD\n");
+ walletInstance->WalletLogPrintf("Upgrading wallet to HD\n");
walletInstance->SetMinVersion(FEATURE_HD);
// generate a new master key
@@ -4085,7 +4035,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
}
// Upgrade to HD chain split if necessary
if (walletInstance->CanSupportFeature(FEATURE_HD_SPLIT)) {
- LogPrintf("Upgrading wallet to use HD chain split\n");
+ walletInstance->WalletLogPrintf("Upgrading wallet to use HD chain split\n");
walletInstance->SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
split_upgrade = FEATURE_HD_SPLIT > prev_version;
}
@@ -4096,7 +4046,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
// Regenerate the keypool if upgraded to HD
if (hd_upgrade) {
if (!walletInstance->TopUpKeyPool()) {
- InitError(_("Unable to generate keys"));
+ chain.initError(_("Unable to generate keys"));
return nullptr;
}
}
@@ -4105,68 +4055,57 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
if (fFirstRun)
{
// ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
- if (!gArgs.GetBoolArg("-usehd", true)) {
- InitError(strprintf(_("Error creating %s: You can't create non-HD wallets with this version."), walletFile));
- return nullptr;
- }
walletInstance->SetMinVersion(FEATURE_LATEST);
if ((wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
//selective allow to set flags
walletInstance->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
+ } else if (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET) {
+ walletInstance->SetWalletFlag(WALLET_FLAG_BLANK_WALLET);
} else {
// generate a new seed
CPubKey seed = walletInstance->GenerateNewSeed();
walletInstance->SetHDSeed(seed);
- }
+ } // Otherwise, do not generate a new seed
// Top up the keypool
- if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !walletInstance->TopUpKeyPool()) {
- InitError(_("Unable to generate initial keys"));
+ if (walletInstance->CanGenerateKeys() && !walletInstance->TopUpKeyPool()) {
+ chain.initError(_("Unable to generate initial keys"));
return nullptr;
}
- walletInstance->ChainStateFlushed(chainActive.GetLocator());
+ auto locked_chain = chain.lock();
+ walletInstance->ChainStateFlushed(locked_chain->getTipLocator());
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
// Make it impossible to disable private keys after creation
- InitError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile));
+ chain.initError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile));
return NULL;
} else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
LOCK(walletInstance->cs_KeyStore);
if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) {
- InitWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
- }
- } else if (gArgs.IsArgSet("-usehd")) {
- bool useHD = gArgs.GetBoolArg("-usehd", true);
- if (walletInstance->IsHDEnabled() && !useHD) {
- InitError(strprintf(_("Error loading %s: You can't disable HD on an already existing HD wallet"), walletFile));
- return nullptr;
- }
- if (!walletInstance->IsHDEnabled() && useHD) {
- InitError(strprintf(_("Error loading %s: You can't enable HD on an already existing non-HD wallet"), walletFile));
- return nullptr;
+ chain.initWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
}
}
if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) {
- InitError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", "")));
+ chain.initError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", "")));
return nullptr;
}
if (!gArgs.GetArg("-changetype", "").empty() && !ParseOutputType(gArgs.GetArg("-changetype", ""), walletInstance->m_default_change_type)) {
- InitError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", "")));
+ chain.initError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", "")));
return nullptr;
}
if (gArgs.IsArgSet("-mintxfee")) {
CAmount n = 0;
if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) {
- InitError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
+ chain.initError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
return nullptr;
}
if (n > HIGH_TX_FEE_PER_KB) {
- InitWarning(AmountHighWarn("-mintxfee") + " " +
- _("This is the minimum transaction fee you pay on every transaction."));
+ chain.initWarning(AmountHighWarn("-mintxfee") + " " +
+ _("This is the minimum transaction fee you pay on every transaction."));
}
walletInstance->m_min_fee = CFeeRate(n);
}
@@ -4175,12 +4114,12 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
if (gArgs.IsArgSet("-fallbackfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
- InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", "")));
+ chain.initError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", "")));
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
- InitWarning(AmountHighWarn("-fallbackfee") + " " +
- _("This is the transaction fee you may pay when fee estimates are not available."));
+ chain.initWarning(AmountHighWarn("-fallbackfee") + " " +
+ _("This is the transaction fee you may pay when fee estimates are not available."));
}
walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
walletInstance->m_allow_fallback_fee = nFeePerK != 0; //disable fallback fee in case value was set to 0, enable if non-null value
@@ -4188,91 +4127,125 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
if (gArgs.IsArgSet("-discardfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
- InitError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", "")));
+ chain.initError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", "")));
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
- InitWarning(AmountHighWarn("-discardfee") + " " +
- _("This is the transaction fee you may discard if change is smaller than dust at this level"));
+ chain.initWarning(AmountHighWarn("-discardfee") + " " +
+ _("This is the transaction fee you may discard if change is smaller than dust at this level"));
}
walletInstance->m_discard_rate = CFeeRate(nFeePerK);
}
if (gArgs.IsArgSet("-paytxfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
- InitError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
+ chain.initError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
- InitWarning(AmountHighWarn("-paytxfee") + " " +
- _("This is the transaction fee you will pay if you send a transaction."));
+ chain.initWarning(AmountHighWarn("-paytxfee") + " " +
+ _("This is the transaction fee you will pay if you send a transaction."));
}
walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000);
- if (walletInstance->m_pay_tx_fee < ::minRelayTxFee) {
- InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
- gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString()));
+ if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) {
+ chain.initError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
+ gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString()));
return nullptr;
}
}
+
+ if (gArgs.IsArgSet("-maxtxfee"))
+ {
+ CAmount nMaxFee = 0;
+ if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) {
+ chain.initError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
+ return nullptr;
+ }
+ if (nMaxFee > HIGH_MAX_TX_FEE) {
+ chain.initWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
+ }
+ if (CFeeRate(nMaxFee, 1000) < chain.relayMinFee()) {
+ chain.initError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
+ gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString()));
+ return nullptr;
+ }
+ walletInstance->m_default_max_tx_fee = nMaxFee;
+ }
+
+ if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB)
+ chain.initWarning(AmountHighWarn("-minrelaytxfee") + " " +
+ _("The wallet will avoid paying less than the minimum relay fee."));
+
walletInstance->m_confirm_target = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
walletInstance->m_spend_zero_conf_change = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
walletInstance->m_signal_rbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
- LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
+ walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nStart);
// Try to top up keypool. No-op if the wallet is locked.
walletInstance->TopUpKeyPool();
- LOCK(cs_main);
+ auto locked_chain = chain.lock();
+ LOCK(walletInstance->cs_wallet);
- CBlockIndex *pindexRescan = chainActive.Genesis();
+ int rescan_height = 0;
if (!gArgs.GetBoolArg("-rescan", false))
{
WalletBatch batch(*walletInstance->database);
CBlockLocator locator;
- if (batch.ReadBestBlock(locator))
- pindexRescan = FindForkInGlobalIndex(chainActive, locator);
+ if (batch.ReadBestBlock(locator)) {
+ if (const Optional<int> fork_height = locked_chain->findLocatorFork(locator)) {
+ rescan_height = *fork_height;
+ }
+ }
}
- walletInstance->m_last_block_processed = chainActive.Tip();
+ const Optional<int> tip_height = locked_chain->getHeight();
+ if (tip_height) {
+ walletInstance->m_last_block_processed = locked_chain->getBlockHash(*tip_height);
+ } else {
+ walletInstance->m_last_block_processed.SetNull();
+ }
- if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
+ if (tip_height && *tip_height != rescan_height)
{
- //We can't rescan beyond non-pruned blocks, stop and throw an error
- //this might happen if a user uses an old wallet within a pruned node
- // or if he ran -disablewallet for a longer time, then decided to re-enable
- if (fPruneMode)
- {
- CBlockIndex *block = chainActive.Tip();
- while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block)
- block = block->pprev;
+ // We can't rescan beyond non-pruned blocks, stop and throw an error.
+ // This might happen if a user uses an old wallet within a pruned node
+ // or if they ran -disablewallet for a longer time, then decided to re-enable
+ if (chain.havePruned()) {
+ // Exit early and print an error.
+ // If a block is pruned after this check, we will load the wallet,
+ // but fail the rescan with a generic error.
+ int block_height = *tip_height;
+ while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
+ --block_height;
+ }
- if (pindexRescan != block) {
- InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
+ if (rescan_height != block_height) {
+ chain.initError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
return nullptr;
}
}
- uiInterface.InitMessage(_("Rescanning..."));
- LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
+ chain.initMessage(_("Rescanning..."));
+ 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)
- while (pindexRescan && walletInstance->nTimeFirstKey && (pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) {
- pindexRescan = chainActive.Next(pindexRescan);
+ if (walletInstance->nTimeFirstKey) {
+ if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
+ rescan_height = *first_block;
+ }
}
- nStart = GetTimeMillis();
{
WalletRescanReserver reserver(walletInstance.get());
- if (!reserver.reserve()) {
- InitError(_("Failed to rescan the wallet during initialization"));
+ if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) {
+ chain.initError(_("Failed to rescan the wallet during initialization"));
return nullptr;
}
- walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true);
}
- LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
- walletInstance->ChainStateFlushed(chainActive.GetLocator());
+ walletInstance->ChainStateFlushed(locked_chain->getTipLocator());
walletInstance->database->IncrementUpdateCounter();
// Restore wallet transaction metadata after -zapwallettxes=1
@@ -4293,7 +4266,6 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
copyTo->nTimeReceived = copyFrom->nTimeReceived;
copyTo->nTimeSmart = copyFrom->nTimeSmart;
copyTo->fFromMe = copyFrom->fFromMe;
- copyTo->strFromAccount = copyFrom->strFromAccount;
copyTo->nOrderPos = copyFrom->nOrderPos;
batch.WriteTx(*copyTo);
}
@@ -4301,28 +4273,38 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
}
}
- uiInterface.LoadWallet(walletInstance);
+ chain.loadWallet(interfaces::MakeWallet(walletInstance));
- // Register with the validation interface. It's ok to do this after rescan since we're still holding cs_main.
- RegisterValidationInterface(walletInstance.get());
+ // Register with the validation interface. It's ok to do this after rescan since we're still holding locked_chain.
+ walletInstance->handleNotifications();
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
{
- LOCK(walletInstance->cs_wallet);
- LogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
- LogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
- LogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size());
+ walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
+ walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
+ walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size());
}
return walletInstance;
}
+void CWallet::handleNotifications()
+{
+ m_chain_notifications_handler = m_chain->handleNotifications(*this);
+}
+
void CWallet::postInitProcess()
{
+ auto locked_chain = chain().lock();
+ LOCK(cs_wallet);
+
// Add wallet transactions that aren't already in a block to mempool
// Do this here as mempool requires genesis block to be loaded
- ReacceptWalletTransactions();
+ ReacceptWalletTransactions(*locked_chain);
+
+ // Update wallet transactions with current mempool transactions.
+ chain().requestMempoolTransactions(*this);
}
bool CWallet::BackupWallet(const std::string& strDest)
@@ -4351,47 +4333,46 @@ CWalletKey::CWalletKey(int64_t nExpires)
nTimeExpires = nExpires;
}
-void CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock)
+void CMerkleTx::SetMerkleBranch(const uint256& block_hash, int posInBlock)
{
// Update the tx's hashBlock
- hashBlock = pindex->GetBlockHash();
+ hashBlock = block_hash;
// set the position of the transaction in the block
nIndex = posInBlock;
}
-int CMerkleTx::GetDepthInMainChain() const
+int CMerkleTx::GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const
{
if (hashUnset())
return 0;
- AssertLockHeld(cs_main);
-
- // Find the block it claims to be in
- CBlockIndex* pindex = LookupBlockIndex(hashBlock);
- if (!pindex || !chainActive.Contains(pindex))
- return 0;
-
- return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1);
+ return locked_chain.getBlockDepth(hashBlock) * (nIndex == -1 ? -1 : 1);
}
-int CMerkleTx::GetBlocksToMaturity() const
+int CMerkleTx::GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const
{
if (!IsCoinBase())
return 0;
- return std::max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
+ int chain_depth = GetDepthInMainChain(locked_chain);
+ assert(chain_depth >= 0); // coinbase tx should not be conflicted
+ return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
}
+bool CMerkleTx::IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const
+{
+ // note GetBlocksToMaturity is 0 for non-coinbase tx
+ return GetBlocksToMaturity(locked_chain) > 0;
+}
-bool CWalletTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state)
+bool CWalletTx::AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, CValidationState& state)
{
// We must set fInMempool here - while it will be re-set to true by the
// entered-mempool callback, if we did not there would be a race where a
// user could call sendmoney in a loop and hit spurious out of funds errors
// because we think that this newly generated transaction's change is
// unavailable as we're not yet aware that it is in the mempool.
- bool ret = ::AcceptToMemoryPool(mempool, state, tx, nullptr /* pfMissingInputs */,
- nullptr /* plTxnReplaced */, false /* bypass_limits */, nAbsurdFee);
+ bool ret = locked_chain.submitToMemoryPool(tx, pwallet->m_default_max_tx_fee, state);
fInMempool |= ret;
return ret;
}
@@ -4422,12 +4403,12 @@ std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outpu
CInputCoin input_coin = output.GetInputCoin();
size_t ancestors, descendants;
- mempool.GetTransactionAncestry(output.tx->GetHash(), ancestors, descendants);
+ chain().getTransactionAncestry(output.tx->GetHash(), ancestors, descendants);
if (!single_coin && ExtractDestination(output.tx->tx->vout[output.i].scriptPubKey, dst)) {
// Limit output groups to no more than 10 entries, to protect
// against inadvertently creating a too-large transaction
// when using -avoidpartialspends
- if (gmap[dst].m_outputs.size() >= 10) {
+ if (gmap[dst].m_outputs.size() >= OUTPUT_GROUP_MAX_ENTRIES) {
groups.push_back(gmap[dst]);
gmap.erase(dst);
}
@@ -4442,3 +4423,32 @@ std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outpu
}
return groups;
}
+
+bool CWallet::GetKeyOrigin(const CKeyID& keyID, KeyOriginInfo& info) const
+{
+ CKeyMetadata meta;
+ {
+ LOCK(cs_wallet);
+ auto it = mapKeyMetadata.find(keyID);
+ if (it != mapKeyMetadata.end()) {
+ meta = it->second;
+ }
+ }
+ if (meta.has_key_origin) {
+ std::copy(meta.key_origin.fingerprint, meta.key_origin.fingerprint + 4, info.fingerprint);
+ info.path = meta.key_origin.path;
+ } else { // Single pubkeys get the master fingerprint of themselves
+ std::copy(keyID.begin(), keyID.begin() + 4, info.fingerprint);
+ }
+ return true;
+}
+
+bool CWallet::AddKeyOrigin(const CPubKey& pubkey, const KeyOriginInfo& info)
+{
+ LOCK(cs_wallet);
+ std::copy(info.fingerprint, info.fingerprint + 4, mapKeyMetadata[pubkey.GetID()].key_origin.fingerprint);
+ mapKeyMetadata[pubkey.GetID()].key_origin.path = info.path;
+ mapKeyMetadata[pubkey.GetID()].has_key_origin = true;
+ mapKeyMetadata[pubkey.GetID()].hdKeypath = WriteHDKeypath(info.path);
+ return WriteKeyMetadata(mapKeyMetadata[pubkey.GetID()], pubkey, true);
+}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 9f9501cf72..5e3bbe2f37 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,20 +7,22 @@
#define BITCOIN_WALLET_WALLET_H
#include <amount.h>
+#include <interfaces/chain.h>
+#include <interfaces/handler.h>
#include <outputtype.h>
#include <policy/feerate.h>
+#include <script/ismine.h>
+#include <script/sign.h>
#include <streams.h>
#include <tinyformat.h>
#include <ui_interface.h>
-#include <utilstrencodings.h>
+#include <util/strencodings.h>
+#include <util/system.h>
#include <validationinterface.h>
-#include <script/ismine.h>
-#include <script/sign.h>
-#include <util.h>
-#include <wallet/crypter.h>
#include <wallet/coinselection.h>
+#include <wallet/crypter.h>
#include <wallet/walletdb.h>
-#include <wallet/rpcwallet.h>
+#include <wallet/walletutil.h>
#include <algorithm>
#include <atomic>
@@ -33,11 +35,19 @@
#include <utility>
#include <vector>
+//! Explicitly unload and delete the wallet.
+//! Blocks the current thread after signaling the unload intent so that all
+//! wallet clients release the wallet.
+//! Note that, when blocking is not required, the wallet is implicitly unloaded
+//! by the shared pointer deleter.
+void UnloadWallet(std::shared_ptr<CWallet>&& wallet);
+
bool AddWallet(const std::shared_ptr<CWallet>& wallet);
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
bool HasWallets();
std::vector<std::shared_ptr<CWallet>> GetWallets();
std::shared_ptr<CWallet> GetWallet(const std::string& name);
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning);
//! Default for -keypool
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
@@ -63,14 +73,20 @@ static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6;
static const bool DEFAULT_WALLET_RBF = false;
static const bool DEFAULT_WALLETBROADCAST = true;
static const bool DEFAULT_DISABLE_WALLET = false;
+//! -maxtxfee default
+constexpr CAmount DEFAULT_TRANSACTION_MAXFEE{COIN / 10};
+//! Discourage users to set fees higher than this amount (in satoshis) per kB
+constexpr CAmount HIGH_TX_FEE_PER_KB{COIN / 100};
+//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
+constexpr CAmount HIGH_MAX_TX_FEE{100 * HIGH_TX_FEE_PER_KB};
+
+//! Pre-calculated constants for input size estimation in *virtual size*
+static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE = 91;
-class CBlockIndex;
class CCoinControl;
class COutput;
class CReserveKey;
class CScript;
-class CTxMemPool;
-class CBlockPolicyEstimator;
class CWalletTx;
struct FeeCalculation;
enum class FeeEstimateMode;
@@ -102,22 +118,84 @@ constexpr OutputType DEFAULT_CHANGE_TYPE{OutputType::CHANGE_AUTO};
enum WalletFlags : uint64_t {
// wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown
- // unkown wallet flags in the lower section <= (1 << 31) will be tolerated
+ // unknown wallet flags in the lower section <= (1 << 31) will be tolerated
+
+ // Indicates that the metadata has already been upgraded to contain key origins
+ WALLET_FLAG_KEY_ORIGIN_METADATA = (1ULL << 1),
// will enforce the rule that the wallet can't contain any private keys (only watch-only/pubkeys)
WALLET_FLAG_DISABLE_PRIVATE_KEYS = (1ULL << 32),
-};
-static constexpr uint64_t g_known_wallet_flags = WALLET_FLAG_DISABLE_PRIVATE_KEYS;
+ //! Flag set when a wallet contains no HD seed and no private keys, scripts,
+ //! addresses, and other watch only things, and is therefore "blank."
+ //!
+ //! The only function this flag serves is to distinguish a blank wallet from
+ //! a newly created wallet when the wallet database is loaded, to avoid
+ //! initialization that should only happen on first run.
+ //!
+ //! This flag is also a mandatory flag to prevent previous versions of
+ //! bitcoin from opening the wallet, thinking it was newly created, and
+ //! then improperly reinitializing it.
+ WALLET_FLAG_BLANK_WALLET = (1ULL << 33),
+};
-/** A key pool entry */
+static constexpr uint64_t g_known_wallet_flags = WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET | WALLET_FLAG_KEY_ORIGIN_METADATA;
+
+/** A key from a CWallet's keypool
+ *
+ * The wallet holds one (for pre HD-split wallets) or several keypools. These
+ * are sets of keys that have not yet been used to provide addresses or receive
+ * change.
+ *
+ * The Bitcoin Core wallet was originally a collection of unrelated private
+ * keys with their associated addresses. If a non-HD wallet generated a
+ * key/address, gave that address out and then restored a backup from before
+ * that key's generation, then any funds sent to that address would be
+ * lost definitively.
+ *
+ * The keypool was implemented to avoid this scenario (commit: 10384941). The
+ * wallet would generate a set of keys (100 by default). When a new public key
+ * was required, either to give out as an address or to use in a change output,
+ * it would be drawn from the keypool. The keypool would then be topped up to
+ * maintain 100 keys. This ensured that as long as the wallet hadn't used more
+ * than 100 keys since the previous backup, all funds would be safe, since a
+ * restored wallet would be able to scan for all owned addresses.
+ *
+ * A keypool also allowed encrypted wallets to give out addresses without
+ * having to be decrypted to generate a new private key.
+ *
+ * With the introduction of HD wallets (commit: f1902510), the keypool
+ * essentially became an address look-ahead pool. Restoring old backups can no
+ * longer definitively lose funds as long as the addresses used were from the
+ * wallet's HD seed (since all private keys can be rederived from the seed).
+ * However, if many addresses were used since the backup, then the wallet may
+ * not know how far ahead in the HD chain to look for its addresses. The
+ * keypool is used to implement a 'gap limit'. The keypool maintains a set of
+ * keys (by default 1000) ahead of the last used key and scans for the
+ * addresses of those keys. This avoids the risk of not seeing transactions
+ * involving the wallet's addresses, or of re-using the same address.
+ *
+ * The HD-split wallet feature added a second keypool (commit: 02592f4c). There
+ * is an external keypool (for addresses to hand out) and an internal keypool
+ * (for change addresses).
+ *
+ * Keypool keys are stored in the wallet/keystore's keymap. The keypool data is
+ * stored as sets of indexes in the wallet (setInternalKeyPool,
+ * setExternalKeyPool and set_pre_split_keypool), and a map from the key to the
+ * index (m_pool_key_to_index). The CKeyPool object is used to
+ * serialize/deserialize the pool data to/from the database.
+ */
class CKeyPool
{
public:
+ //! The time at which the key was generated. Set in AddKeypoolPubKeyWithDB
int64_t nTime;
+ //! The public key
CPubKey vchPubKey;
- bool fInternal; // for change outputs
- bool m_pre_split; // For keys generated before keypool split upgrade
+ //! Whether this keypool entry is in the internal keypool (for change outputs)
+ bool fInternal;
+ //! Whether this key was generated for a keypool before the wallet was upgraded to HD-split
+ bool m_pre_split;
CKeyPool();
CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn);
@@ -156,6 +234,57 @@ public:
}
};
+/** A wrapper to reserve a key from a wallet keypool
+ *
+ * CReserveKey is used to reserve a key from the keypool. It is passed around
+ * during the CreateTransaction/CommitTransaction procedure.
+ *
+ * Instantiating a CReserveKey does not reserve a keypool key. To do so,
+ * GetReservedKey() needs to be called on the object. Once a key has been
+ * reserved, call KeepKey() on the CReserveKey object to make sure it is not
+ * returned to the keypool. Call ReturnKey() to return the key to the keypool
+ * so it can be re-used (for example, if the key was used in a new transaction
+ * and that transaction was not completed and needed to be aborted).
+ *
+ * If a key is reserved and KeepKey() is not called, then the key will be
+ * returned to the keypool when the CReserveObject goes out of scope.
+ */
+class CReserveKey
+{
+protected:
+ //! The wallet to reserve the keypool key from
+ CWallet* pwallet;
+ //! The index of the key in the keypool
+ int64_t nIndex{-1};
+ //! The public key
+ CPubKey vchPubKey;
+ //! Whether this is from the internal (change output) keypool
+ bool fInternal{false};
+
+public:
+ //! Construct a CReserveKey object. This does NOT reserve a key from the keypool yet
+ explicit CReserveKey(CWallet* pwalletIn)
+ {
+ pwallet = pwalletIn;
+ }
+
+ CReserveKey(const CReserveKey&) = delete;
+ CReserveKey& operator=(const CReserveKey&) = delete;
+
+ //! Destructor. If a key has been reserved and not KeepKey'ed, it will be returned to the keypool
+ ~CReserveKey()
+ {
+ ReturnKey();
+ }
+
+ //! Reserve a key from the keypool
+ bool GetReservedKey(CPubKey &pubkey, bool internal = false);
+ //! Return a key to the keypool
+ void ReturnKey();
+ //! Keep the key. Do not return it to the keypool when this object goes out of scope
+ void KeepKey();
+};
+
/** Address book data */
class CAddressBookData
{
@@ -256,7 +385,7 @@ public:
READWRITE(nIndex);
}
- void SetMerkleBranch(const CBlockIndex* pIndex, int posInBlock);
+ void SetMerkleBranch(const uint256& block_hash, int posInBlock);
/**
* Return depth of transaction in blockchain:
@@ -264,19 +393,26 @@ public:
* 0 : in memory pool, waiting to be included in a block
* >=1 : this many blocks deep in the main chain
*/
- int GetDepthInMainChain() const;
- bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
- int GetBlocksToMaturity() const;
+ int GetDepthInMainChain(interfaces::Chain::Lock& locked_chain) const;
+ bool IsInMainChain(interfaces::Chain::Lock& locked_chain) const { return GetDepthInMainChain(locked_chain) > 0; }
+
+ /**
+ * @return number of blocks to maturity for this transaction:
+ * 0 : is not a coinbase transaction, or is a mature coinbase transaction
+ * >0 : is a coinbase transaction which matures in this many blocks
+ */
+ int GetBlocksToMaturity(interfaces::Chain::Lock& locked_chain) const;
bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }
bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }
void setAbandoned() { hashBlock = ABANDON_HASH; }
const uint256& GetHash() const { return tx->GetHash(); }
bool IsCoinBase() const { return tx->IsCoinBase(); }
+ bool IsImmatureCoinBase(interfaces::Chain::Lock& locked_chain) const;
};
//Get the marginal bytes of spending the specified output
-int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet);
+int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, bool use_max_sig = false);
/**
* A transaction with a bunch of additional info that only the owner cares about.
@@ -295,7 +431,7 @@ public:
* serialized in the wallet database:
*
* "comment", "to" - comment strings provided to sendtoaddress,
- * sendfrom, sendmany wallet RPCs
+ * and sendmany wallet RPCs
* "replaces_txid" - txid (as HexStr) of transaction replaced by
* bumpfee on transaction created by bumpfee
* "replaced_by_txid" - txid (as HexStr) of transaction created by
@@ -333,29 +469,15 @@ public:
* externally and came in through the network or sendrawtransaction RPC.
*/
char fFromMe;
- std::string strFromAccount;
int64_t nOrderPos; //!< position in ordered transaction list
- std::multimap<int64_t, std::pair<CWalletTx*, CAccountingEntry*>>::const_iterator m_it_wtxOrdered;
+ std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
// memory only
- mutable bool fDebitCached;
- mutable bool fCreditCached;
- mutable bool fImmatureCreditCached;
- mutable bool fAvailableCreditCached;
- mutable bool fWatchDebitCached;
- mutable bool fWatchCreditCached;
- mutable bool fImmatureWatchCreditCached;
- mutable bool fAvailableWatchCreditCached;
+ enum AmountType { DEBIT, CREDIT, IMMATURE_CREDIT, AVAILABLE_CREDIT, AMOUNTTYPE_ENUM_ELEMENTS };
+ CAmount GetCachableAmount(AmountType type, const isminefilter& filter, bool recalculate = false) const;
+ mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
mutable bool fChangeCached;
mutable bool fInMempool;
- mutable CAmount nDebitCached;
- mutable CAmount nCreditCached;
- mutable CAmount nImmatureCreditCached;
- mutable CAmount nAvailableCreditCached;
- mutable CAmount nWatchDebitCached;
- mutable CAmount nWatchCreditCached;
- mutable CAmount nImmatureWatchCreditCached;
- mutable CAmount nAvailableWatchCreditCached;
mutable CAmount nChangeCached;
CWalletTx(const CWallet* pwalletIn, CTransactionRef arg) : CMerkleTx(std::move(arg))
@@ -372,25 +494,8 @@ public:
nTimeReceived = 0;
nTimeSmart = 0;
fFromMe = false;
- strFromAccount.clear();
- fDebitCached = false;
- fCreditCached = false;
- fImmatureCreditCached = false;
- fAvailableCreditCached = false;
- fWatchDebitCached = false;
- fWatchCreditCached = false;
- fImmatureWatchCreditCached = false;
- fAvailableWatchCreditCached = false;
fChangeCached = false;
fInMempool = false;
- nDebitCached = 0;
- nCreditCached = 0;
- nImmatureCreditCached = 0;
- nAvailableCreditCached = 0;
- nWatchDebitCached = 0;
- nWatchCreditCached = 0;
- nAvailableWatchCreditCached = 0;
- nImmatureWatchCreditCached = 0;
nChangeCached = 0;
nOrderPos = -1;
}
@@ -401,7 +506,7 @@ public:
char fSpent = false;
mapValue_t mapValueCopy = mapValue;
- mapValueCopy["fromaccount"] = strFromAccount;
+ mapValueCopy["fromaccount"] = "";
WriteOrderPos(nOrderPos, mapValueCopy);
if (nTimeSmart) {
mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
@@ -422,7 +527,6 @@ public:
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent;
- strFromAccount = std::move(mapValue["fromaccount"]);
ReadOrderPos(nOrderPos, mapValue);
nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
@@ -435,14 +539,10 @@ public:
//! make sure balances are recalculated
void MarkDirty()
{
- fCreditCached = false;
- fAvailableCreditCached = false;
- fImmatureCreditCached = false;
- fWatchDebitCached = false;
- fWatchCreditCached = false;
- fAvailableWatchCreditCached = false;
- fImmatureWatchCreditCached = false;
- fDebitCached = false;
+ m_amounts[DEBIT].Reset();
+ m_amounts[CREDIT].Reset();
+ m_amounts[IMMATURE_CREDIT].Reset();
+ m_amounts[AVAILABLE_CREDIT].Reset();
fChangeCached = false;
}
@@ -454,20 +554,24 @@ public:
//! filter decides which addresses will count towards the debit
CAmount GetDebit(const isminefilter& filter) const;
- CAmount GetCredit(const isminefilter& filter) const;
- CAmount GetImmatureCredit(bool fUseCache=true) const;
- CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const;
- CAmount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const;
+ CAmount GetCredit(interfaces::Chain::Lock& locked_chain, const isminefilter& filter) const;
+ CAmount GetImmatureCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache=true) const;
+ // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
+ // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The
+ // annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid
+ // having to resolve the issue of member access into incomplete type CWallet.
+ CAmount GetAvailableCredit(interfaces::Chain::Lock& locked_chain, bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS;
+ CAmount GetImmatureWatchOnlyCredit(interfaces::Chain::Lock& locked_chain, const bool fUseCache=true) const;
CAmount GetChange() const;
// Get the marginal bytes if spending the specified output from this transaction
- int GetSpendSize(unsigned int out) const
+ int GetSpendSize(unsigned int out, bool use_max_sig = false) const
{
- return CalculateMaximumSignedInputSize(tx->vout[out], pwallet);
+ return CalculateMaximumSignedInputSize(tx->vout[out], pwallet, use_max_sig);
}
void GetAmounts(std::list<COutputEntry>& listReceived,
- std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;
+ std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter) const;
bool IsFromMe(const isminefilter& filter) const
{
@@ -478,17 +582,23 @@ public:
bool IsEquivalentTo(const CWalletTx& tx) const;
bool InMempool() const;
- bool IsTrusted() const;
+ bool IsTrusted(interfaces::Chain::Lock& locked_chain) const;
int64_t GetTxTime() const;
- // RelayWalletTransaction may only be called if fBroadcastTransactions!
- bool RelayWalletTransaction(CConnman* connman);
+ // Pass this transaction to the node to relay to its peers
+ bool RelayWalletTransaction(interfaces::Chain::Lock& locked_chain);
/** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */
- bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state);
-
- std::set<uint256> GetConflicts() const;
+ bool AcceptToMemoryPool(interfaces::Chain::Lock& locked_chain, CValidationState& state);
+
+ // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
+ // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation
+ // "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid having to
+ // resolve the issue of member access into incomplete type CWallet. Note
+ // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)"
+ // in place.
+ std::set<uint256> GetConflicts() const NO_THREAD_SAFETY_ANALYSIS;
};
class COutput
@@ -507,6 +617,9 @@ public:
/** Whether we know how to spend this output, ignoring the lack of keys */
bool fSolvable;
+ /** Whether to use the maximum sized, 72 byte signature when calculating the size of the input spend. This should only be set when watch-only outputs are allowed */
+ bool use_max_sig;
+
/**
* Whether this output is considered safe to spend. Unconfirmed transactions
* from outside keys and unconfirmed replacement transactions are considered
@@ -514,13 +627,13 @@ public:
*/
bool fSafe;
- COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn)
+ COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn, bool use_max_sig_in = false)
{
- tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputBytes = -1;
+ tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputBytes = -1; use_max_sig = use_max_sig_in;
// If known and signable by the given wallet, compute nInputBytes
// Failure will keep this value -1
if (fSpendable && tx) {
- nInputBytes = tx->GetSpendSize(i);
+ nInputBytes = tx->GetSpendSize(i, use_max_sig);
}
}
@@ -540,8 +653,8 @@ public:
int64_t nTimeCreated;
int64_t nTimeExpires;
std::string strComment;
- //! todo: add something to note what created it (user, getnewaddress, change)
- //! maybe should have a map<string, string> property map
+ // todo: add something to note what created it (user, getnewaddress, change)
+ // maybe should have a map<string, string> property map
explicit CWalletKey(int64_t nExpires=0);
@@ -559,89 +672,6 @@ public:
}
};
-/**
- * DEPRECATED Internal transfers.
- * Database key is acentry<account><counter>.
- */
-class CAccountingEntry
-{
-public:
- std::string strAccount;
- CAmount nCreditDebit;
- int64_t nTime;
- std::string strOtherAccount;
- std::string strComment;
- mapValue_t mapValue;
- int64_t nOrderPos; //!< position in ordered transaction list
- uint64_t nEntryNo;
-
- CAccountingEntry()
- {
- SetNull();
- }
-
- void SetNull()
- {
- nCreditDebit = 0;
- nTime = 0;
- strAccount.clear();
- strOtherAccount.clear();
- strComment.clear();
- nOrderPos = -1;
- nEntryNo = 0;
- }
-
- template <typename Stream>
- void Serialize(Stream& s) const {
- int nVersion = s.GetVersion();
- if (!(s.GetType() & SER_GETHASH)) {
- s << nVersion;
- }
- //! Note: strAccount is serialized as part of the key, not here.
- s << nCreditDebit << nTime << strOtherAccount;
-
- mapValue_t mapValueCopy = mapValue;
- WriteOrderPos(nOrderPos, mapValueCopy);
-
- std::string strCommentCopy = strComment;
- if (!mapValueCopy.empty() || !_ssExtra.empty()) {
- CDataStream ss(s.GetType(), s.GetVersion());
- ss.insert(ss.begin(), '\0');
- ss << mapValueCopy;
- ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
- strCommentCopy.append(ss.str());
- }
- s << strCommentCopy;
- }
-
- template <typename Stream>
- void Unserialize(Stream& s) {
- int nVersion = s.GetVersion();
- if (!(s.GetType() & SER_GETHASH)) {
- s >> nVersion;
- }
- //! Note: strAccount is serialized as part of the key, not here.
- s >> nCreditDebit >> nTime >> LIMITED_STRING(strOtherAccount, 65536) >> LIMITED_STRING(strComment, 65536);
-
- size_t nSepPos = strComment.find("\0", 0, 1);
- mapValue.clear();
- if (std::string::npos != nSepPos) {
- CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());
- ss >> mapValue;
- _ssExtra = std::vector<char>(ss.begin(), ss.end());
- }
- ReadOrderPos(nOrderPos, mapValue);
- if (std::string::npos != nSepPos) {
- strComment.erase(nSepPos);
- }
-
- mapValue.erase("n");
- }
-
-private:
- std::vector<char> _ssExtra;
-};
-
struct CoinSelectionParams
{
bool use_bnb = true;
@@ -659,25 +689,29 @@ class WalletRescanReserver; //forward declarations for ScanForWalletTransactions
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
* and provides the ability to create new transactions.
*/
-class CWallet final : public CCryptoKeyStore, public CValidationInterface
+class CWallet final : public CCryptoKeyStore, private interfaces::Chain::Notifications
{
private:
std::atomic<bool> fAbortRescan{false};
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
+ std::atomic<int64_t> m_scanning_start{0};
+ std::atomic<double> m_scanning_progress{0};
std::mutex mutexScanning;
friend class WalletRescanReserver;
- WalletBatch *encrypted_batch = nullptr;
+ WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr;
//! the current wallet version: clients below this version are not able to load the wallet
- int nWalletVersion = FEATURE_BASE;
+ int nWalletVersion GUARDED_BY(cs_wallet){FEATURE_BASE};
//! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
- int nWalletMaxVersion = FEATURE_BASE;
+ int nWalletMaxVersion GUARDED_BY(cs_wallet) = FEATURE_BASE;
int64_t nNextResend = 0;
int64_t nLastResend = 0;
bool fBroadcastTransactions = false;
+ // Local time that the tip block was received. Used to schedule wallet rebroadcasts.
+ std::atomic<int64_t> m_best_block_time {0};
/**
* Used to keep track of spent outpoints, and
@@ -685,9 +719,9 @@ private:
* mutated transactions where the mutant gets mined).
*/
typedef std::multimap<COutPoint, uint256> TxSpends;
- TxSpends mapTxSpends;
- void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
- void AddToSpends(const uint256& wtxid);
+ TxSpends mapTxSpends GUARDED_BY(cs_wallet);
+ void AddToSpends(const COutPoint& outpoint, const uint256& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void AddToSpends(const uint256& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Add a transaction to the wallet, or update it. pIndex and posInBlock should
@@ -702,34 +736,34 @@ private:
* Abandoned state should probably be more carefully tracked via different
* posInBlock signals or by checking mempool presence when necessary.
*/
- bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const uint256& block_hash, int posInBlock, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/* Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */
void MarkConflicted(const uint256& hashBlock, const uint256& hashTx);
/* Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed */
- void MarkInputsDirty(const CTransactionRef& tx);
+ void MarkInputsDirty(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
+ void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
- * Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */
- void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0, bool update_tx = true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ * Should be called with non-zero block_hash and posInBlock if this is for a transaction that is included in a block. */
+ void SyncTransaction(const CTransactionRef& tx, const uint256& block_hash, int posInBlock = 0, bool update_tx = true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/* the HD chain data model (external chain counters) */
CHDChain hdChain;
/* HD derive new child key (on internal or external chain) */
- void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void DeriveNewChildKey(WalletBatch& batch, CKeyMetadata& metadata, CKey& secret, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- std::set<int64_t> setInternalKeyPool;
- std::set<int64_t> setExternalKeyPool;
- std::set<int64_t> set_pre_split_keypool;
- int64_t m_max_keypool_index = 0;
+ std::set<int64_t> setInternalKeyPool GUARDED_BY(cs_wallet);
+ std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_wallet);
+ std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_wallet);
+ int64_t m_max_keypool_index GUARDED_BY(cs_wallet) = 0;
std::map<CKeyID, int64_t> m_pool_key_to_index;
std::atomic<uint64_t> m_wallet_flags{0};
- int64_t nTimeFirstKey = 0;
+ int64_t nTimeFirstKey GUARDED_BY(cs_wallet) = 0;
/**
* Private version of AddWatchOnly method which does not accept a
@@ -742,12 +776,11 @@ private:
*/
bool AddWatchOnly(const CScript& dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- /**
- * Wallet filename from wallet=<path> command line or config option.
- * Used in debug logs and to send RPCs to the right wallet instance when
- * more than one wallet is loaded.
- */
- std::string m_name;
+ /** Interface for accessing chain state. */
+ interfaces::Chain* m_chain;
+
+ /** Wallet location which includes wallet name (see WalletLocation). */
+ WalletLocation m_location;
/** Internal database handle. */
std::unique_ptr<WalletDatabase> database;
@@ -759,10 +792,8 @@ private:
* Note that this is *not* how far we've processed, we may need some rescan
* to have seen all transactions in the chain, but is only used to track
* live BlockConnected callbacks.
- *
- * Protected by cs_main (see BlockUntilSyncedToCurrentChain)
*/
- const CBlockIndex* m_last_block_processed = nullptr;
+ uint256 m_last_block_processed GUARDED_BY(cs_wallet);
public:
/*
@@ -785,49 +816,65 @@ public:
* if they are not ours
*/
bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet,
- const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const;
+ const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ const WalletLocation& GetLocation() const { return m_location; }
/** Get a name for this wallet for logging/debugging purposes.
*/
- const std::string& GetName() const { return m_name; }
+ const std::string& GetName() const { return m_location.GetName(); }
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void MarkPreSplitKeys();
+ void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
// Map from Key ID to key metadata.
- std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
+ std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_wallet);
// Map from Script ID to key metadata (for watch-only keys).
- std::map<CScriptID, CKeyMetadata> m_script_metadata;
+ std::map<CScriptID, CKeyMetadata> m_script_metadata GUARDED_BY(cs_wallet);
+
+ bool WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, bool overwrite);
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
unsigned int nMasterKeyMaxID = 0;
/** Construct wallet with specified name and database implementation. */
- CWallet(std::string name, std::unique_ptr<WalletDatabase> database) : m_name(std::move(name)), database(std::move(database))
+ CWallet(interfaces::Chain* chain, const WalletLocation& location, std::unique_ptr<WalletDatabase> database)
+ : m_chain(chain),
+ m_location(location),
+ database(std::move(database))
{
}
~CWallet()
{
+ // Should not have slots connected at this point.
+ assert(NotifyUnload.empty());
delete encrypted_batch;
encrypted_batch = nullptr;
}
- std::map<uint256, CWalletTx> mapWallet;
- std::list<CAccountingEntry> laccentries;
+ std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
- typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
- typedef std::multimap<int64_t, TxPair > TxItems;
+ typedef std::multimap<int64_t, CWalletTx*> TxItems;
TxItems wtxOrdered;
- int64_t nOrderPosNext = 0;
+ int64_t nOrderPosNext GUARDED_BY(cs_wallet) = 0;
uint64_t nAccountingEntryNumber = 0;
- std::map<CTxDestination, CAddressBookData> mapAddressBook;
+ std::map<CTxDestination, CAddressBookData> mapAddressBook GUARDED_BY(cs_wallet);
- std::set<COutPoint> setLockedCoins;
+ std::set<COutPoint> setLockedCoins GUARDED_BY(cs_wallet);
+
+ /** Registered interfaces::Chain::Notifications handler. */
+ std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
+
+ /** Register the wallet for chain notifications */
+ void handleNotifications();
+
+ /** Interface for accessing chain state. */
+ interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
const CWalletTx* GetWalletTx(const uint256& hash) const;
@@ -837,17 +884,17 @@ public:
/**
* populate vCoins with vector of available COutputs.
*/
- void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Return list of available coins and locked coins grouped by non-change output address.
*/
- std::map<CTxDestination, std::vector<COutput>> ListCoins() const;
+ std::map<CTxDestination, std::vector<COutput>> ListCoins(interfaces::Chain::Lock& locked_chain) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Find non-change parent output.
*/
- const CTxOut& FindNonChangeParentOutput(const CTransaction& tx, int output) const;
+ const CTxOut& FindNonChangeParentOutput(const CTransaction& tx, int output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Shuffle and select coins until nTargetValue is reached while avoiding
@@ -858,7 +905,7 @@ public:
bool SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<OutputGroup> groups,
std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CoinSelectionParams& coin_selection_params, bool& bnb_used) const;
- bool IsSpent(const uint256& hash, unsigned int n) const;
+ bool IsSpent(interfaces::Chain::Lock& locked_chain, const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -873,6 +920,8 @@ public:
void AbortRescan() { fAbortRescan = true; }
bool IsAbortingRescan() { return fAbortRescan; }
bool IsScanning() { return fScanningWallet; }
+ int64_t ScanningDuration() const { return fScanningWallet ? GetTimeMillis() - m_scanning_start : 0; }
+ double ScanningProgress() const { return fScanningWallet ? (double) m_scanning_progress : 0; }
/**
* keystore implementation
@@ -887,6 +936,8 @@ public:
//! Load metadata (used by LoadWallet)
void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ //! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
+ void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -899,15 +950,15 @@ public:
bool LoadCScript(const CScript& redeemScript);
//! Adds a destination data tuple to the store, and saves it to disk
- bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
+ bool AddDestData(const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Erases a destination data tuple in the store and on disk
- bool EraseDestData(const CTxDestination &dest, const std::string &key);
+ bool EraseDestData(const CTxDestination& dest, const std::string& key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Adds a destination data tuple to the store, without saving it to disk
- void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
+ void LoadDestData(const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Look up a destination data tuple in the store, return true if found false otherwise
- bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const;
+ bool GetDestData(const CTxDestination& dest, const std::string& key, std::string* value) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Get all destination values matching a prefix.
- std::vector<std::string> GetDestValues(const std::string& prefix) const;
+ std::vector<std::string> GetDestValues(const std::string& prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Adds a watch-only address to the store, and saves it to disk.
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -918,11 +969,11 @@ public:
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
int64_t nRelockTime = 0;
- bool Unlock(const SecureString& strWalletPassphrase);
+ bool Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys = false);
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);
- void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
/**
@@ -931,28 +982,44 @@ public:
*/
int64_t IncOrderPosNext(WalletBatch *batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
DBErrors ReorderTransactions();
- bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "") EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool GetLabelDestination(CTxDestination &dest, const std::string& label, bool bForceNew = false);
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
- void LoadToWallet(const CWalletTx& wtxIn);
+ void LoadToWallet(const CWalletTx& wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void TransactionAddedToMempool(const CTransactionRef& tx) override;
- void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
- void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
+ void BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& vtxConflicted) override;
+ void BlockDisconnected(const CBlock& block) override;
+ void UpdatedBlockTip() override;
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
- CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver& reserver, bool fUpdate = false);
+
+ struct ScanResult {
+ enum { SUCCESS, FAILURE, USER_ABORT } status = SUCCESS;
+
+ //! Hash and height of most recent block that was successfully scanned.
+ //! Unset if no blocks were scanned due to read errors or the chain
+ //! being empty.
+ uint256 last_scanned_block;
+ Optional<int> last_scanned_height;
+
+ //! Height of the most recent block that could not be scanned due to
+ //! read errors or pruning. Will be set if status is FAILURE, unset if
+ //! status is SUCCESS, and may or may not be set if status is
+ //! USER_ABORT.
+ uint256 last_failed_block;
+ };
+ ScanResult ScanForWalletTransactions(const uint256& first_block, const uint256& last_block, const WalletRescanReserver& reserver, bool fUpdate);
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
- void ReacceptWalletTransactions();
- void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override;
- // ResendWalletTransactionsBefore may only be called if fBroadcastTransactions!
- std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman);
- CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE, const int min_depth=0) const;
- CAmount GetUnconfirmedBalance() const;
- CAmount GetImmatureBalance() const;
- CAmount GetUnconfirmedWatchOnlyBalance() const;
- CAmount GetImmatureWatchOnlyBalance() const;
- CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const;
+ void ReacceptWalletTransactions(interfaces::Chain::Lock& locked_chain) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void ResendWalletTransactions();
+ struct Balance {
+ CAmount m_mine_trusted{0}; //!< Trusted, at depth=GetBalance.min_depth or more
+ CAmount m_mine_untrusted_pending{0}; //!< Untrusted, but in mempool (pending)
+ CAmount m_mine_immature{0}; //!< Immature coinbases in the main chain
+ CAmount m_watchonly_trusted{0};
+ CAmount m_watchonly_untrusted_pending{0};
+ CAmount m_watchonly_immature{0};
+ };
+ Balance GetBalance(int min_depth = 0) const;
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend);
@@ -969,27 +1036,24 @@ public:
* selected by SelectCoins(); Also create the change output, when needed
* @note passing nChangePosInOut as -1 will result in setting a random position
*/
- bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
+ bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
- bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, std::string fromAccount, CReserveKey& reservekey, CConnman* connman, CValidationState& state);
+ bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CReserveKey& reservekey, CValidationState& state);
- void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries);
- bool AddAccountingEntry(const CAccountingEntry&);
- bool AddAccountingEntry(const CAccountingEntry&, WalletBatch *batch);
- bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts) const
+ bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const
{
std::vector<CTxOut> v_txouts(txouts.size());
std::copy(txouts.begin(), txouts.end(), v_txouts.begin());
- return DummySignTx(txNew, v_txouts);
+ return DummySignTx(txNew, v_txouts, use_max_sig);
}
- bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts) const;
- bool DummySignInput(CTxIn &tx_in, const CTxOut &txout) const;
+ bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig = false) const;
+ bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig = false) const;
CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
bool m_spend_zero_conf_change{DEFAULT_SPEND_ZEROCONF_CHANGE};
bool m_signal_rbf{DEFAULT_WALLET_RBF};
- bool m_allow_fallback_fee{true}; //<! will be defined via chainparams
+ bool m_allow_fallback_fee{true}; //!< will be defined via chainparams
CFeeRate m_min_fee{DEFAULT_TRANSACTION_MINFEE}; //!< Override with -mintxfee
/**
* If fee estimation does not have enough data to provide estimates, use this fee instead.
@@ -1000,10 +1064,14 @@ public:
CFeeRate m_discard_rate{DEFAULT_DISCARD_FEE};
OutputType m_default_address_type{DEFAULT_ADDRESS_TYPE};
OutputType m_default_change_type{DEFAULT_CHANGE_TYPE};
+ /** Absolute maximum transaction fee (in satoshis) used by default for the wallet */
+ CAmount m_default_max_tx_fee{DEFAULT_TRANSACTION_MAXFEE};
bool NewKeyPool();
size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool TopUpKeyPool(unsigned int kpSize = 0);
+ void AddKeypoolPubkey(const CPubKey& pubkey, const bool internal);
+ void AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch);
/**
* Reserves a key from the keypool and sets nIndex to its index
@@ -1031,10 +1099,9 @@ public:
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
std::set<std::set<CTxDestination>> GetAddressGroupings() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- std::map<CTxDestination, CAmount> GetAddressBalances();
+ std::map<CTxDestination, CAmount> GetAddressBalances(interfaces::Chain::Lock& locked_chain);
std::set<CTxDestination> GetLabelAddresses(const std::string& label) const;
- void DeleteLabel(const std::string& label);
isminetype IsMine(const CTxIn& txin) const;
/**
@@ -1045,6 +1112,7 @@ public:
isminetype IsMine(const CTxOut& txout) const;
CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const;
bool IsChange(const CTxOut& txout) const;
+ bool IsChange(const CScript& script) const;
CAmount GetChange(const CTxOut& txout) const;
bool IsMine(const CTransaction& tx) const;
/** should probably be renamed to IsRelevantToMe */
@@ -1064,13 +1132,11 @@ public:
bool DelAddressBook(const CTxDestination& address);
- const std::string& GetLabelName(const CScript& scriptPubKey) const;
-
- void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
+ const std::string& GetLabelName(const CScript& scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
{
- AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool
+ AssertLockHeld(cs_wallet);
return setInternalKeyPool.size() + setExternalKeyPool.size();
}
@@ -1084,7 +1150,7 @@ public:
int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
//! Get wallet transactions that conflict with given transaction (spend same outputs)
- std::set<uint256> GetConflicts(const uint256& txid) const;
+ std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -1117,6 +1183,9 @@ public:
/** Watch-only address added */
boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
+ /** Keypool has new keys */
+ boost::signals2::signal<void ()> NotifyCanGetAddressesChanged;
+
/** Inquire whether this wallet broadcasts transactions. */
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
/** Set whether this wallet broadcasts transactions. */
@@ -1126,16 +1195,16 @@ public:
bool TransactionCanBeAbandoned(const uint256& hashTx) const;
/* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */
- bool AbandonTransaction(const uint256& hashTx);
+ bool AbandonTransaction(interfaces::Chain::Lock& locked_chain, const uint256& hashTx);
/** Mark a transaction as replaced by another transaction (e.g., BIP 125). */
bool MarkReplaced(const uint256& originalHash, const uint256& newHash);
//! Verify wallet naming and perform salvage on the wallet if required
- static bool Verify(std::string wallet_file, bool salvage_wallet, std::string& error_string, std::string& warning_string);
+ static bool Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
- static std::shared_ptr<CWallet> CreateWalletFromFile(const std::string& name, const fs::path& path, uint64_t wallet_creation_flags = 0);
+ static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags = 0);
/**
* Wallet post-init setup
@@ -1152,6 +1221,12 @@ public:
/* Returns true if HD is enabled */
bool IsHDEnabled() const;
+ /* Returns true if the wallet can generate new keys */
+ bool CanGenerateKeys();
+
+ /* Returns true if the wallet can give out new addresses. This means it has keys in the keypool or can generate new keys */
+ bool CanGetAddresses(bool internal = false);
+
/* Generates a new HD seed (will not be activated) */
CPubKey GenerateNewSeed();
@@ -1170,7 +1245,7 @@ public:
* Obviously holding cs_main/cs_wallet when going into this call may cause
* deadlock
*/
- void BlockUntilSyncedToCurrentChain() LOCKS_EXCLUDED(cs_wallet);
+ void BlockUntilSyncedToCurrentChain() LOCKS_EXCLUDED(cs_main, cs_wallet);
/**
* Explicitly make the wallet learn the related scripts for outputs to the
@@ -1189,75 +1264,40 @@ public:
/** set a single wallet flag */
void SetWalletFlag(uint64_t flags);
+ /** Unsets a single wallet flag */
+ void UnsetWalletFlag(uint64_t flag);
+
/** check if a certain wallet flag is set */
bool IsWalletFlagSet(uint64_t flag);
/** overwrite all flags by the given uint64_t
returns false if unknown, non-tolerable flags are present */
bool SetWalletFlags(uint64_t overwriteFlags, bool memOnly);
-};
-/** A key allocated from the key pool. */
-class CReserveKey final : public CReserveScript
-{
-protected:
- CWallet* pwallet;
- int64_t nIndex;
- CPubKey vchPubKey;
- bool fInternal;
-public:
- explicit CReserveKey(CWallet* pwalletIn)
- {
- nIndex = -1;
- pwallet = pwalletIn;
- fInternal = false;
- }
+ /** Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet has no name */
+ const std::string GetDisplayName() const {
+ std::string wallet_name = GetName().length() == 0 ? "default wallet" : GetName();
+ return strprintf("[%s]", wallet_name);
+ };
- CReserveKey() = default;
- CReserveKey(const CReserveKey&) = delete;
- CReserveKey& operator=(const CReserveKey&) = delete;
+ /** Prepends the wallet name in logging output to ease debugging in multi-wallet use cases */
+ template<typename... Params>
+ void WalletLogPrintf(std::string fmt, Params... parameters) const {
+ LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
+ };
- ~CReserveKey()
- {
- ReturnKey();
- }
+ /** Implement lookup of key origin information through wallet key metadata. */
+ bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
- void ReturnKey();
- bool GetReservedKey(CPubKey &pubkey, bool internal = false);
- void KeepKey();
- void KeepScript() override { KeepKey(); }
+ /** Add a KeyOriginInfo to the wallet */
+ bool AddKeyOrigin(const CPubKey& pubkey, const KeyOriginInfo& info);
};
-
/**
- * DEPRECATED Account information.
- * Stored in wallet with key "acc"+string account name.
+ * Called periodically by the schedule thread. Prompts individual wallets to resend
+ * their transactions. Actual rebroadcast schedule is managed by the wallets themselves.
*/
-class CAccount
-{
-public:
- CPubKey vchPubKey;
-
- CAccount()
- {
- SetNull();
- }
-
- void SetNull()
- {
- vchPubKey = CPubKey();
- }
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- int nVersion = s.GetVersion();
- if (!(s.GetType() & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vchPubKey);
- }
-};
+void MaybeResendWalletTxs();
/** RAII object to check and reserve a wallet rescan */
class WalletRescanReserver
@@ -1275,6 +1315,8 @@ public:
if (m_wallet->fScanningWallet) {
return false;
}
+ m_wallet->m_scanning_start = GetTimeMillis();
+ m_wallet->m_scanning_progress = 0;
m_wallet->fScanningWallet = true;
m_could_reserve = true;
return true;
@@ -1295,9 +1337,9 @@ public:
};
// Calculate the size of the transaction assuming all signatures are max size
-// Use DummySignatureCreator, which inserts 72 byte signatures everywhere.
+// Use DummySignatureCreator, which inserts 71 byte signatures everywhere.
// NOTE: this requires that all inputs must be in mapWallet (eg the tx should
// be IsAllFromMe).
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet);
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts);
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig = false);
#endif // BITCOIN_WALLET_WALLET_H
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 43e4747317..ece97e2a75 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -1,22 +1,23 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <wallet/walletdb.h>
-#include <consensus/tx_verify.h>
+#include <consensus/tx_check.h>
#include <consensus/validation.h>
#include <fs.h>
#include <key_io.h>
#include <protocol.h>
#include <serialize.h>
#include <sync.h>
-#include <util.h>
-#include <utiltime.h>
+#include <util/system.h>
+#include <util/time.h>
#include <wallet/wallet.h>
#include <atomic>
+#include <string>
#include <boost/thread.hpp>
@@ -56,9 +57,14 @@ bool WalletBatch::EraseTx(uint256 hash)
return EraseIC(std::make_pair(std::string("tx"), hash));
}
+bool WalletBatch::WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite)
+{
+ return WriteIC(std::make_pair(std::string("keymeta"), pubkey), meta, overwrite);
+}
+
bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
{
- if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) {
+ if (!WriteKeyMetadata(keyMeta, vchPubKey, false)) {
return false;
}
@@ -75,7 +81,7 @@ bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey,
const std::vector<unsigned char>& vchCryptedSecret,
const CKeyMetadata &keyMeta)
{
- if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) {
+ if (!WriteKeyMetadata(keyMeta, vchPubKey, true)) {
return false;
}
@@ -150,99 +156,19 @@ bool WalletBatch::WriteMinVersion(int nVersion)
return WriteIC(std::string("minversion"), nVersion);
}
-bool WalletBatch::ReadAccount(const std::string& strAccount, CAccount& account)
-{
- account.SetNull();
- return m_batch.Read(std::make_pair(std::string("acc"), strAccount), account);
-}
-
-bool WalletBatch::WriteAccount(const std::string& strAccount, const CAccount& account)
-{
- return WriteIC(std::make_pair(std::string("acc"), strAccount), account);
-}
-
-bool WalletBatch::EraseAccount(const std::string& strAccount)
-{
- return EraseIC(std::make_pair(std::string("acc"), strAccount));
-}
-
-bool WalletBatch::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
-{
- return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry);
-}
-
-CAmount WalletBatch::GetAccountCreditDebit(const std::string& strAccount)
-{
- std::list<CAccountingEntry> entries;
- ListAccountCreditDebit(strAccount, entries);
-
- CAmount nCreditDebit = 0;
- for (const CAccountingEntry& entry : entries)
- nCreditDebit += entry.nCreditDebit;
-
- return nCreditDebit;
-}
-
-void WalletBatch::ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries)
-{
- bool fAllAccounts = (strAccount == "*");
-
- Dbc* pcursor = m_batch.GetCursor();
- if (!pcursor)
- throw std::runtime_error(std::string(__func__) + ": cannot create DB cursor");
- bool setRange = true;
- while (true)
- {
- // Read next record
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- if (setRange)
- ssKey << std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts ? std::string("") : strAccount), uint64_t(0)));
- CDataStream ssValue(SER_DISK, CLIENT_VERSION);
- int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue, setRange);
- setRange = false;
- if (ret == DB_NOTFOUND)
- break;
- else if (ret != 0)
- {
- pcursor->close();
- throw std::runtime_error(std::string(__func__) + ": error scanning DB");
- }
-
- // Unserialize
- std::string strType;
- ssKey >> strType;
- if (strType != "acentry")
- break;
- CAccountingEntry acentry;
- ssKey >> acentry.strAccount;
- if (!fAllAccounts && acentry.strAccount != strAccount)
- break;
-
- ssValue >> acentry;
- ssKey >> acentry.nEntryNo;
- entries.push_back(acentry);
- }
-
- pcursor->close();
-}
-
class CWalletScanState {
public:
- unsigned int nKeys;
- unsigned int nCKeys;
- unsigned int nWatchKeys;
- unsigned int nKeyMeta;
- unsigned int m_unknown_records;
- bool fIsEncrypted;
- bool fAnyUnordered;
- int nFileVersion;
+ unsigned int nKeys{0};
+ unsigned int nCKeys{0};
+ unsigned int nWatchKeys{0};
+ unsigned int nKeyMeta{0};
+ unsigned int m_unknown_records{0};
+ bool fIsEncrypted{false};
+ bool fAnyUnordered{false};
+ int nFileVersion{0};
std::vector<uint256> vWalletUpgrade;
CWalletScanState() {
- nKeys = nCKeys = nWatchKeys = nKeyMeta = m_unknown_records = 0;
- fIsEncrypted = false;
- fAnyUnordered = false;
- nFileVersion = 0;
}
};
@@ -284,9 +210,10 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
{
char fTmp;
char fUnused;
- ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
- strErr = strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s",
- wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount, hash.ToString());
+ std::string unused_string;
+ ssValue >> fTmp >> fUnused >> unused_string;
+ strErr = strprintf("LoadWallet() upgrading tx ver=%d %d %s",
+ wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
wtx.fTimeReceivedIsTxTime = fTmp;
}
else
@@ -302,24 +229,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
pwallet->LoadToWallet(wtx);
}
- else if (strType == "acentry")
- {
- std::string strAccount;
- ssKey >> strAccount;
- uint64_t nNumber;
- ssKey >> nNumber;
- if (nNumber > pwallet->nAccountingEntryNumber) {
- pwallet->nAccountingEntryNumber = nNumber;
- }
-
- if (!wss.fAnyUnordered)
- {
- CAccountingEntry acentry;
- ssValue >> acentry;
- if (acentry.nOrderPos == -1)
- wss.fAnyUnordered = true;
- }
- }
else if (strType == "watchs")
{
wss.nWatchKeys++;
@@ -509,11 +418,19 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error reading wallet database: Unknown non-tolerable wallet flags found";
return false;
}
- } else if (strType != "bestblock" && strType != "bestblock_nomerkle") {
+ } else if (strType != "bestblock" && strType != "bestblock_nomerkle" &&
+ strType != "minversion" && strType != "acentry") {
wss.m_unknown_records++;
}
- } catch (...)
- {
+ } catch (const std::exception& e) {
+ if (strErr.empty()) {
+ strErr = e.what();
+ }
+ return false;
+ } catch (...) {
+ if (strErr.empty()) {
+ strErr = "Caught unknown exception in ReadKeyValue";
+ }
return false;
}
return true;
@@ -545,7 +462,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
Dbc* pcursor = m_batch.GetCursor();
if (!pcursor)
{
- LogPrintf("Error getting wallet database cursor\n");
+ pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
return DBErrors::CORRUPT;
}
@@ -559,7 +476,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
break;
else if (ret != 0)
{
- LogPrintf("Error reading next record from wallet database\n");
+ pwallet->WalletLogPrintf("Error reading next record from wallet database\n");
return DBErrors::CORRUPT;
}
@@ -583,7 +500,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
}
}
if (!strErr.empty())
- LogPrintf("%s\n", strErr);
+ pwallet->WalletLogPrintf("%s\n", strErr);
}
pcursor->close();
}
@@ -602,16 +519,16 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
if (result != DBErrors::LOAD_OK)
return result;
- LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
+ pwallet->WalletLogPrintf("nFileVersion = %d\n", wss.nFileVersion);
- LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
+ pwallet->WalletLogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys, wss.m_unknown_records);
// nTimeFirstKey is only reliable if all keys have metadata
if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta)
pwallet->UpdateTimeFirstKey(1);
- for (uint256 hash : wss.vWalletUpgrade)
+ for (const uint256& hash : wss.vWalletUpgrade)
WriteTx(pwallet->mapWallet.at(hash));
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
@@ -624,10 +541,12 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
if (wss.fAnyUnordered)
result = pwallet->ReorderTransactions();
- pwallet->laccentries.clear();
- ListAccountCreditDebit("*", pwallet->laccentries);
- for (CAccountingEntry& entry : pwallet->laccentries) {
- pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair(nullptr, &entry)));
+ // Upgrade all of the wallet keymetadata to have the hd master key id
+ // This operation is not atomic, but if it fails, updated entries are still backwards compatible with older software
+ try {
+ pwallet->UpgradeKeyMetadata();
+ } catch (...) {
+ result = DBErrors::CORRUPT;
}
return result;
@@ -708,7 +627,7 @@ DBErrors WalletBatch::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<u
// erase each matching wallet TX
bool delerror = false;
std::vector<uint256>::iterator it = vTxHashIn.begin();
- for (uint256 hash : vTxHash) {
+ for (const uint256& hash : vTxHash) {
while (it < vTxHashIn.end() && (*it) < hash) {
it++;
}
@@ -739,7 +658,7 @@ DBErrors WalletBatch::ZapWalletTx(std::vector<CWalletTx>& vWtx)
return err;
// erase each wallet TX
- for (uint256& hash : vTxHash) {
+ for (const uint256& hash : vTxHash) {
if (!EraseTx(hash))
return DBErrors::CORRUPT;
}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 674d1c2201..0532a55ff5 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,6 +8,7 @@
#include <amount.h>
#include <primitives/transaction.h>
+#include <script/sign.h>
#include <wallet/db.h>
#include <key.h>
@@ -31,8 +32,6 @@
static const bool DEFAULT_FLUSHWALLET = true;
-class CAccount;
-class CAccountingEntry;
struct CBlockLocator;
class CKeyPool;
class CMasterKey;
@@ -95,11 +94,14 @@ class CKeyMetadata
public:
static const int VERSION_BASIC=1;
static const int VERSION_WITH_HDDATA=10;
- static const int CURRENT_VERSION=VERSION_WITH_HDDATA;
+ static const int VERSION_WITH_KEY_ORIGIN = 12;
+ static const int CURRENT_VERSION=VERSION_WITH_KEY_ORIGIN;
int nVersion;
int64_t nCreateTime; // 0 means unknown
- std::string hdKeypath; //optional HD/bip32 keypath
+ std::string hdKeypath; //optional HD/bip32 keypath. Still used to determine whether a key is a seed. Also kept for backwards compatibility
CKeyID hd_seed_id; //id of the HD seed used to derive this key
+ KeyOriginInfo key_origin; // Key origin info with path and fingerprint
+ bool has_key_origin = false; //< Whether the key_origin is useful
CKeyMetadata()
{
@@ -122,6 +124,11 @@ public:
READWRITE(hdKeypath);
READWRITE(hd_seed_id);
}
+ if (this->nVersion >= VERSION_WITH_KEY_ORIGIN)
+ {
+ READWRITE(key_origin);
+ READWRITE(has_key_origin);
+ }
}
void SetNull()
@@ -130,6 +137,8 @@ public:
nCreateTime = 0;
hdKeypath.clear();
hd_seed_id.SetNull();
+ key_origin.clear();
+ has_key_origin = false;
}
};
@@ -179,6 +188,7 @@ public:
bool WriteTx(const CWalletTx& wtx);
bool EraseTx(uint256 hash);
+ bool WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite);
bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta);
bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta);
bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey);
@@ -199,21 +209,11 @@ public:
bool WriteMinVersion(int nVersion);
- /// This writes directly to the database, and will not update the CWallet's cached accounting entries!
- /// Use wallet.AddAccountingEntry instead, to write *and* update its caches.
- bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry);
- bool ReadAccount(const std::string& strAccount, CAccount& account);
- bool WriteAccount(const std::string& strAccount, const CAccount& account);
- bool EraseAccount(const std::string& strAccount);
-
/// Write destination data key,value tuple to database
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value);
/// Erase destination data tuple from wallet database
bool EraseDestData(const std::string &address, const std::string &key);
- CAmount GetAccountCreditDebit(const std::string& strAccount);
- void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
-
DBErrors LoadWallet(CWallet* pwallet);
DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx);
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
new file mode 100644
index 0000000000..5c1b086703
--- /dev/null
+++ b/src/wallet/wallettool.cpp
@@ -0,0 +1,135 @@
+// Copyright (c) 2016-2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <base58.h>
+#include <fs.h>
+#include <util/system.h>
+#include <wallet/wallet.h>
+#include <wallet/walletutil.h>
+
+namespace WalletTool {
+
+// The standard wallet deleter function blocks on the validation interface
+// queue, which doesn't exist for the bitcoin-wallet. Define our own
+// deleter here.
+static void WalletToolReleaseWallet(CWallet* wallet)
+{
+ wallet->WalletLogPrintf("Releasing wallet\n");
+ wallet->Flush(true);
+ delete wallet;
+}
+
+static std::shared_ptr<CWallet> CreateWallet(const std::string& name, const fs::path& path)
+{
+ if (fs::exists(path)) {
+ fprintf(stderr, "Error: File exists already\n");
+ return nullptr;
+ }
+ // dummy chain interface
+ std::shared_ptr<CWallet> wallet_instance(new CWallet(nullptr /* chain */, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet);
+ bool first_run = true;
+ DBErrors load_wallet_ret = wallet_instance->LoadWallet(first_run);
+ if (load_wallet_ret != DBErrors::LOAD_OK) {
+ fprintf(stderr, "Error creating %s", name.c_str());
+ return nullptr;
+ }
+
+ wallet_instance->SetMinVersion(FEATURE_HD_SPLIT);
+
+ // generate a new HD seed
+ CPubKey seed = wallet_instance->GenerateNewSeed();
+ wallet_instance->SetHDSeed(seed);
+
+ fprintf(stdout, "Topping up keypool...\n");
+ wallet_instance->TopUpKeyPool();
+ return wallet_instance;
+}
+
+static std::shared_ptr<CWallet> LoadWallet(const std::string& name, const fs::path& path)
+{
+ if (!fs::exists(path)) {
+ fprintf(stderr, "Error: Wallet files does not exist\n");
+ return nullptr;
+ }
+
+ // dummy chain interface
+ std::shared_ptr<CWallet> wallet_instance(new CWallet(nullptr /* chain */, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet);
+ DBErrors load_wallet_ret;
+ try {
+ bool first_run;
+ load_wallet_ret = wallet_instance->LoadWallet(first_run);
+ } catch (const std::runtime_error) {
+ fprintf(stderr, "Error loading %s. Is wallet being used by another process?\n", name.c_str());
+ return nullptr;
+ }
+
+ if (load_wallet_ret != DBErrors::LOAD_OK) {
+ wallet_instance = nullptr;
+ if (load_wallet_ret == DBErrors::CORRUPT) {
+ fprintf(stderr, "Error loading %s: Wallet corrupted", name.c_str());
+ return nullptr;
+ } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) {
+ fprintf(stderr, "Error reading %s! All keys read correctly, but transaction data"
+ " or address book entries might be missing or incorrect.",
+ name.c_str());
+ } else if (load_wallet_ret == DBErrors::TOO_NEW) {
+ fprintf(stderr, "Error loading %s: Wallet requires newer version of %s",
+ name.c_str(), PACKAGE_NAME);
+ return nullptr;
+ } else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
+ fprintf(stderr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME);
+ return nullptr;
+ } else {
+ fprintf(stderr, "Error loading %s", name.c_str());
+ return nullptr;
+ }
+ }
+
+ return wallet_instance;
+}
+
+static void WalletShowInfo(CWallet* wallet_instance)
+{
+ LOCK(wallet_instance->cs_wallet);
+
+ fprintf(stdout, "Wallet info\n===========\n");
+ fprintf(stdout, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no");
+ fprintf(stdout, "HD (hd seed available): %s\n", wallet_instance->GetHDChain().seed_id.IsNull() ? "no" : "yes");
+ fprintf(stdout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
+ fprintf(stdout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
+ fprintf(stdout, "Address Book: %zu\n", wallet_instance->mapAddressBook.size());
+}
+
+bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
+{
+ fs::path path = fs::absolute(name, GetWalletDir());
+
+ if (command == "create") {
+ std::shared_ptr<CWallet> wallet_instance = CreateWallet(name, path);
+ if (wallet_instance) {
+ WalletShowInfo(wallet_instance.get());
+ wallet_instance->Flush(true);
+ }
+ } else if (command == "info") {
+ if (!fs::exists(path)) {
+ fprintf(stderr, "Error: no wallet file at %s\n", name.c_str());
+ return false;
+ }
+ std::string error;
+ if (!WalletBatch::VerifyEnvironment(path, error)) {
+ fprintf(stderr, "Error loading %s. Is wallet being used by other process?\n", name.c_str());
+ return false;
+ }
+ std::shared_ptr<CWallet> wallet_instance = LoadWallet(name, path);
+ if (!wallet_instance) return false;
+ WalletShowInfo(wallet_instance.get());
+ wallet_instance->Flush(true);
+ } else {
+ fprintf(stderr, "Invalid command: %s\n", command.c_str());
+ return false;
+ }
+
+ return true;
+}
+} // namespace WalletTool
diff --git a/src/wallet/wallettool.h b/src/wallet/wallettool.h
new file mode 100644
index 0000000000..da848a747b
--- /dev/null
+++ b/src/wallet/wallettool.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_WALLET_WALLETTOOL_H
+#define BITCOIN_WALLET_WALLETTOOL_H
+
+#include <script/ismine.h>
+#include <wallet/wallet.h>
+
+namespace WalletTool {
+
+std::shared_ptr<CWallet> CreateWallet(const std::string& name, const fs::path& path);
+std::shared_ptr<CWallet> LoadWallet(const std::string& name, const fs::path& path);
+void WalletShowInfo(CWallet* wallet_instance);
+bool ExecuteWalletToolFunc(const std::string& command, const std::string& file);
+
+} // namespace WalletTool
+
+#endif // BITCOIN_WALLET_WALLETTOOL_H
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index 7c97b668ae..04c2407a89 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -1,9 +1,12 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <wallet/walletutil.h>
+#include <logging.h>
+#include <util/system.h>
+
fs::path GetWalletDir()
{
fs::path path;
@@ -25,3 +28,77 @@ fs::path GetWalletDir()
return path;
}
+
+static bool IsBerkeleyBtree(const fs::path& path)
+{
+ if (!fs::exists(path)) return false;
+
+ // A Berkeley DB Btree file has at least 4K.
+ // This check also prevents opening lock files.
+ boost::system::error_code ec;
+ auto size = fs::file_size(path, ec);
+ if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
+ if (size < 4096) return false;
+
+ fsbridge::ifstream file(path, std::ios::binary);
+ if (!file.is_open()) return false;
+
+ file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
+ uint32_t data = 0;
+ file.read((char*) &data, sizeof(data)); // Read 4 bytes of file to compare against magic
+
+ // Berkeley DB Btree magic bytes, from:
+ // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
+ // - big endian systems - 00 05 31 62
+ // - little endian systems - 62 31 05 00
+ return data == 0x00053162 || data == 0x62310500;
+}
+
+std::vector<fs::path> ListWalletDir()
+{
+ const fs::path wallet_dir = GetWalletDir();
+ const size_t offset = wallet_dir.string().size() + 1;
+ std::vector<fs::path> paths;
+ boost::system::error_code ec;
+
+ for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
+ if (ec) {
+ LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string());
+ continue;
+ }
+
+ // Get wallet path relative to walletdir by removing walletdir from the wallet path.
+ // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
+ const fs::path path = it->path().string().substr(offset);
+
+ if (it->status().type() == fs::directory_file && IsBerkeleyBtree(it->path() / "wallet.dat")) {
+ // Found a directory which contains wallet.dat btree file, add it as a wallet.
+ paths.emplace_back(path);
+ } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBerkeleyBtree(it->path())) {
+ if (it->path().filename() == "wallet.dat") {
+ // Found top-level wallet.dat btree file, add top level directory ""
+ // as a wallet.
+ paths.emplace_back();
+ } else {
+ // Found top-level btree file not called wallet.dat. Current bitcoin
+ // software will never create these files but will allow them to be
+ // opened in a shared database environment for backwards compatibility.
+ // Add it to the list of available wallets.
+ paths.emplace_back(path);
+ }
+ }
+ }
+
+ return paths;
+}
+
+WalletLocation::WalletLocation(const std::string& name)
+ : m_name(name)
+ , m_path(fs::absolute(name, GetWalletDir()))
+{
+}
+
+bool WalletLocation::Exists() const
+{
+ return fs::symlink_status(m_path).type() != fs::file_not_found;
+}
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index f12acacd00..ba2f913841 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -1,14 +1,38 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_WALLETUTIL_H
#define BITCOIN_WALLET_WALLETUTIL_H
-#include <chainparamsbase.h>
-#include <util.h>
+#include <fs.h>
+
+#include <vector>
//! Get the path of the wallet directory.
fs::path GetWalletDir();
+//! Get wallets in wallet directory.
+std::vector<fs::path> ListWalletDir();
+
+//! The WalletLocation class provides wallet information.
+class WalletLocation final
+{
+ std::string m_name;
+ fs::path m_path;
+
+public:
+ explicit WalletLocation() {}
+ explicit WalletLocation(const std::string& name);
+
+ //! Get wallet name.
+ const std::string& GetName() const { return m_name; }
+
+ //! Get wallet absolute path.
+ const fs::path& GetPath() const { return m_path; }
+
+ //! Return whether the wallet exists.
+ bool Exists() const;
+};
+
#endif // BITCOIN_WALLET_WALLETUTIL_H
diff --git a/src/walletinitinterface.h b/src/walletinitinterface.h
index 020d8971cb..22aca65990 100644
--- a/src/walletinitinterface.h
+++ b/src/walletinitinterface.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,29 +9,22 @@
class CScheduler;
class CRPCTable;
+struct InitInterfaces;
class WalletInitInterface {
public:
+ /** Is the wallet component enabled */
+ virtual bool HasWalletSupport() const = 0;
/** Get wallet help string */
virtual void AddWalletOptions() const = 0;
/** Check wallet parameter interaction */
virtual bool ParameterInteraction() const = 0;
- /** Register wallet RPC*/
- virtual void RegisterRPC(CRPCTable &) const = 0;
- /** Verify wallets */
- virtual bool Verify() const = 0;
- /** Open wallets*/
- virtual bool Open() const = 0;
- /** Start wallets*/
- virtual void Start(CScheduler& scheduler) const = 0;
- /** Flush Wallets*/
- virtual void Flush() const = 0;
- /** Stop Wallets*/
- virtual void Stop() const = 0;
- /** Close wallets */
- virtual void Close() const = 0;
+ /** Add wallets that should be opened to list of init interfaces. */
+ virtual void Construct(InitInterfaces& interfaces) const = 0;
virtual ~WalletInitInterface() {}
};
+extern const WalletInitInterface& g_wallet_init_interface;
+
#endif // BITCOIN_WALLETINITINTERFACE_H
diff --git a/src/warnings.cpp b/src/warnings.cpp
index 534745f998..1c6ba13f60 100644
--- a/src/warnings.cpp
+++ b/src/warnings.cpp
@@ -1,11 +1,11 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <sync.h>
#include <clientversion.h>
-#include <util.h>
+#include <util/system.h>
#include <warnings.h>
CCriticalSection cs_warnings;
diff --git a/src/warnings.h b/src/warnings.h
index 904e8c0440..16c8f7b52e 100644
--- a/src/warnings.h
+++ b/src/warnings.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,10 +14,10 @@ void SetfLargeWorkForkFound(bool flag);
bool GetfLargeWorkForkFound();
void SetfLargeWorkInvalidChainFound(bool flag);
/** Format a string that describes several potential problems detected by the core.
- * strFor can have three values:
- * - "statusbar": get all warnings
- * - "gui": get all warnings, translated (where possible) for GUI
- * This function only returns the highest priority warning of the set selected by strFor.
+ * @param[in] strFor can have the following values:
+ * - "statusbar": get the most important warning
+ * - "gui": get all warnings, translated (where possible) for GUI, separated by <hr />
+ * @returns the warning string selected by strFor
*/
std::string GetWarnings(const std::string& strFor);
diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp
index fc1ff6d031..6a9661e3e8 100644
--- a/src/zmq/zmqabstractnotifier.cpp
+++ b/src/zmq/zmqabstractnotifier.cpp
@@ -1,10 +1,11 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <zmq/zmqabstractnotifier.h>
-#include <util.h>
+#include <util/system.h>
+const int CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM;
CZMQAbstractNotifier::~CZMQAbstractNotifier()
{
diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h
index 7270ae203b..887dde7b27 100644
--- a/src/zmq/zmqabstractnotifier.h
+++ b/src/zmq/zmqabstractnotifier.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,7 +15,9 @@ typedef CZMQAbstractNotifier* (*CZMQNotifierFactory)();
class CZMQAbstractNotifier
{
public:
- CZMQAbstractNotifier() : psocket(nullptr) { }
+ static const int DEFAULT_ZMQ_SNDHWM {1000};
+
+ CZMQAbstractNotifier() : psocket(nullptr), outbound_message_high_water_mark(DEFAULT_ZMQ_SNDHWM) { }
virtual ~CZMQAbstractNotifier();
template <typename T>
@@ -28,6 +30,12 @@ public:
void SetType(const std::string &t) { type = t; }
std::string GetAddress() const { return address; }
void SetAddress(const std::string &a) { address = a; }
+ int GetOutboundMessageHighWaterMark() const { return outbound_message_high_water_mark; }
+ void SetOutboundMessageHighWaterMark(const int sndhwm) {
+ if (sndhwm >= 0) {
+ outbound_message_high_water_mark = sndhwm;
+ }
+ }
virtual bool Initialize(void *pcontext) = 0;
virtual void Shutdown() = 0;
@@ -39,6 +47,7 @@ protected:
void *psocket;
std::string type;
std::string address;
+ int outbound_message_high_water_mark; // aka SNDHWM
};
#endif // BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H
diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h
index 1ba1262a83..5219ffad40 100644
--- a/src/zmq/zmqconfig.h
+++ b/src/zmq/zmqconfig.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 8cbc969972..6826cf62d6 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -8,7 +8,7 @@
#include <version.h>
#include <validation.h>
#include <streams.h>
-#include <util.h>
+#include <util/system.h>
void zmqError(const char *str)
{
@@ -59,6 +59,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create()
CZMQAbstractNotifier *notifier = factory();
notifier->SetType(entry.first);
notifier->SetAddress(address);
+ notifier->SetOutboundMessageHighWaterMark(static_cast<int>(gArgs.GetArg(arg + "hwm", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM)));
notifiers.push_back(notifier);
}
}
@@ -81,10 +82,14 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create()
// Called at startup to conditionally set up ZMQ socket(s)
bool CZMQNotificationInterface::Initialize()
{
+ int major = 0, minor = 0, patch = 0;
+ zmq_version(&major, &minor, &patch);
+ LogPrint(BCLog::ZMQ, "zmq: version %d.%d.%d\n", major, minor, patch);
+
LogPrint(BCLog::ZMQ, "zmq: Initialize notification interface\n");
assert(!pcontext);
- pcontext = zmq_init(1);
+ pcontext = zmq_ctx_new();
if (!pcontext)
{
@@ -98,11 +103,11 @@ bool CZMQNotificationInterface::Initialize()
CZMQAbstractNotifier *notifier = *i;
if (notifier->Initialize(pcontext))
{
- LogPrint(BCLog::ZMQ, " Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());
+ LogPrint(BCLog::ZMQ, "zmq: Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());
}
else
{
- LogPrint(BCLog::ZMQ, " Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());
+ LogPrint(BCLog::ZMQ, "zmq: Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());
break;
}
}
@@ -124,10 +129,10 @@ void CZMQNotificationInterface::Shutdown()
for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
{
CZMQAbstractNotifier *notifier = *i;
- LogPrint(BCLog::ZMQ, " Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());
+ LogPrint(BCLog::ZMQ, "zmq: Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());
notifier->Shutdown();
}
- zmq_ctx_destroy(pcontext);
+ zmq_ctx_term(pcontext);
pcontext = nullptr;
}
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index 8c9acef257..ba89d1401d 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,7 +7,7 @@
#include <streams.h>
#include <zmq/zmqpublishnotifier.h>
#include <validation.h>
-#include <util.h>
+#include <util/system.h>
#include <rpc/server.h>
static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;
@@ -76,8 +76,18 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
return false;
}
- int rc = zmq_bind(psocket, address.c_str());
- if (rc!=0)
+ LogPrint(BCLog::ZMQ, "zmq: Outbound message high water mark for %s at %s is %d\n", type, address, outbound_message_high_water_mark);
+
+ int rc = zmq_setsockopt(psocket, ZMQ_SNDHWM, &outbound_message_high_water_mark, sizeof(outbound_message_high_water_mark));
+ if (rc != 0)
+ {
+ zmqError("Failed to set outbound message high water mark");
+ zmq_close(psocket);
+ return false;
+ }
+
+ rc = zmq_bind(psocket, address.c_str());
+ if (rc != 0)
{
zmqError("Failed to bind address");
zmq_close(psocket);
@@ -91,6 +101,7 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
else
{
LogPrint(BCLog::ZMQ, "zmq: Reusing socket for address %s\n", address);
+ LogPrint(BCLog::ZMQ, "zmq: Outbound message high water mark for %s at %s is %d\n", type, address, outbound_message_high_water_mark);
psocket = i->second->psocket;
mapPublishNotifiers.insert(std::make_pair(address, this));
@@ -120,7 +131,7 @@ void CZMQAbstractPublishNotifier::Shutdown()
if (count == 1)
{
- LogPrint(BCLog::ZMQ, "Close socket at address %s\n", address);
+ LogPrint(BCLog::ZMQ, "zmq: Close socket at address %s\n", address);
int linger = 0;
zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger));
zmq_close(psocket);
diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h
index d53bba9971..278fdb94d2 100644
--- a/src/zmq/zmqpublishnotifier.h
+++ b/src/zmq/zmqpublishnotifier.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,7 +12,7 @@ class CBlockIndex;
class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier
{
private:
- uint32_t nSequence; //!< upcounting per message sequence number
+ uint32_t nSequence {0U}; //!< upcounting per message sequence number
public:
diff --git a/src/zmq/zmqrpc.cpp b/src/zmq/zmqrpc.cpp
index 4f88bf4eb9..a34968ef7d 100644
--- a/src/zmq/zmqrpc.cpp
+++ b/src/zmq/zmqrpc.cpp
@@ -5,6 +5,7 @@
#include <zmq/zmqrpc.h>
#include <rpc/server.h>
+#include <rpc/util.h>
#include <zmq/zmqabstractnotifier.h>
#include <zmq/zmqnotificationinterface.h>
@@ -16,20 +17,24 @@ UniValue getzmqnotifications(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
- "getzmqnotifications\n"
- "\nReturns information about the active ZeroMQ notifications.\n"
- "\nResult:\n"
+ RPCHelpMan{"getzmqnotifications",
+ "\nReturns information about the active ZeroMQ notifications.\n",
+ {},
+ RPCResult{
"[\n"
" { (json object)\n"
" \"type\": \"pubhashtx\", (string) Type of notification\n"
- " \"address\": \"...\" (string) Address of the publisher\n"
+ " \"address\": \"...\", (string) Address of the publisher\n"
+ " \"hwm\": n (numeric) Outbound message high water mark\n"
" },\n"
" ...\n"
"]\n"
- "\nExamples:\n"
- + HelpExampleCli("getzmqnotifications", "")
+ },
+ RPCExamples{
+ HelpExampleCli("getzmqnotifications", "")
+ HelpExampleRpc("getzmqnotifications", "")
- );
+ },
+ }.ToString());
}
UniValue result(UniValue::VARR);
@@ -38,6 +43,7 @@ UniValue getzmqnotifications(const JSONRPCRequest& request)
UniValue obj(UniValue::VOBJ);
obj.pushKV("type", n->GetType());
obj.pushKV("address", n->GetAddress());
+ obj.pushKV("hwm", n->GetOutboundMessageHighWaterMark());
result.push_back(obj);
}
}