Merge #10516: Backports for 0.14.3

ff274d3 [doc] Add hint about getmempoolentry to getrawmempool help. (Karl-Johan Alm)
76f9cf9 contrib: Update location of seeds.txt (Wladimir J. van der Laan)
12adedf Trivial: remove extra character from comment (CryptAxe)
d2ec969 Fixed typo in documentation for merkleblock.h (Mikerah)
3612219 contrib/init/bitcoind.openrcconf: Don't disable wallet by default (Luke Dashjr)
692dbb0 [doc] Minor corrections to osx dependencies (fanquake)
87a21d5 Fix: make CCoinsViewDbCursor::Seek work for missing keys (Pieter Wuille)
28b8b8b [wallet] Securely erase potentially sensitive keys/values (Thomas Snider)
ff13f59 [wallet] Make sure pindex is non-null before possibly referencing in LogPrintf call. (Karl-Johan Alm)
e23cef0 Fix some empty vector references (Pieter Wuille)
6ad45b8 Re-enable upnp support in contrib/debian (Matt Corallo)
e9a0d89 Build with QT5 on Debian-based systems using contrib/debian (Matt Corallo)
2ea0358 Bump minimum boost version in contrib/debian (Matt Corallo)
c94e262 Update contrib/debian to latest Ubuntu PPA upload. (Matt Corallo)
96c7f2c Add CheckQueue Tests (Jeremy Rubin)
e207342 Fix CCheckQueue IsIdle (potential) race condition and remove dangerous constructors. (Jeremy Rubin)
ef810c4 [trivial] Fix a typo (introduced two days ago) in the default fee warning (practicalswift)
7abe7bb Qt/Send: Give fallback fee a reasonable indent (Luke Dashjr)
3e4d7bf Qt/Send: Figure a decent warning colour from theme (Luke Dashjr)
c5adf8f [Qt] Show more significant warning if we fall back to the default fee (Jonas Schnelli)
ee1a60d [tests] update disconnect_ban.py test case to work with listbanned (John Newbery)
d289b56 [net] listbanned RPC and QT should show correct banned subnets (John Newbery)
0422693 [tests] disconnect_ban: remove dependency on urllib (John Newbery)
98bd0c3 [tests] disconnect_ban: use wait_until instead of sleep (John Newbery)
bfd1cf6 [tests] disconnectban test - only use two nodes (John Newbery)
5bc75bb [tests] fix nodehandling.py flake8 warnings (John Newbery)
c25d0a8 Update release notes to include RPC error code changes. (John Newbery)
f5efe82 Return correct error codes in fundrawtransaction(). (John Newbery)
4943d7a Return correct error codes in setban(). (John Newbery)
18c109d Return correct error codes in removeprunedfunds(). (John Newbery)
fe51c89 Return correct error codes in blockchain.cpp. (John Newbery)
3ad00b4 Return correct error codes in bumpfee(). (John Newbery)
71463a7 [qa] Test prioritise_transaction / getblocktemplate interaction (Suhas Daftuar)
d28d583 Bugfix: PrioritiseTransaction updates the mempool tx counter (Suhas Daftuar)

Tree-SHA512: fa3628527c8e176e438de992b9c5815cc2f3c296dbe5d81b592d17a907554e9c6af7eb595e96a2c345de399ba5326c07b4791a91b7b07f89dce0787c85891206
This commit is contained in:
Wladimir J. van der Laan 2017-07-06 18:06:38 +02:00
commit 91be5e3c1e
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
34 changed files with 883 additions and 263 deletions

View file

@ -1,3 +1,122 @@
bitcoin (0.14.1-trusty4) trusty; urgency=medium
* Re-enable UPnP support.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 05 May 2017 13:28:00 -0400
bitcoin (0.14.1-trusty3) trusty; urgency=medium
* Build with qt5 if we are on a non-Ubuntu (ie non-Unity) distro.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 04 May 2017 17:13:00 -0400
bitcoin (0.14.1-trusty2) trusty; urgency=medium
* Bump minimum boost version in deps.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 04 May 2017 17:12:00 -0400
bitcoin (0.14.1-trusty1) trusty; urgency=medium
* New upstream release.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Sat, 22 Apr 2017 17:10:00 -0400
bitcoin (0.14.0-trusty1) trusty; urgency=medium
* New upstream release.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 08 Mar 2017 10:30:00 -0500
bitcoin (0.13.2-trusty1) trusty; urgency=medium
* New upstream release.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 05 Jan 2017 09:59:00 -0500
bitcoin (0.13.1-trusty2) trusty; urgency=medium
* Revert to Qt4, due to https://github.com/bitcoin/bitcoin/issues/9038
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Mon, 31 Oct 2016 11:16:00 -0400
bitcoin (0.13.1-trusty1) trusty; urgency=medium
* New upstream release.
* Backport updated bitcoin-qt.desktop from upstream master
* Add zmq dependency
* Switch to Qt5 (breaks precise, but that was already broken by C++11)
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 27 Oct 2016 17:32:00 -0400
bitcoin (0.13.0-trusty1) trusty; urgency=medium
* New upstream release.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Sun, 04 Sep 2016 22:09:00 -0400
bitcoin (0.12.1-trusty1) trusty; urgency=medium
* New upstream release.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Mon, 18 Apr 2016 14:26:00 -0700
bitcoin (0.12.0-trusty6) trusty; urgency=medium
* Fix program-options dep.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 25 Mar 2016 21:41:00 -0700
bitcoin (0.12.0-trusty5) trusty; urgency=medium
* Test explicit --with-gui
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 23:25:00 -0800
bitcoin (0.12.0-trusty4) trusty; urgency=medium
* Fix libevent-dev dep.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 23:25:00 -0800
bitcoin (0.12.0-trusty3) trusty; urgency=medium
* Fix precise boost dep.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:55:00 -0800
bitcoin (0.12.0-trusty2) trusty; urgency=medium
* Fix libevent dep.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:53:00 -0800
bitcoin (0.12.0-trusty1) trusty; urgency=medium
* New upstream release
* Various updates to contrib/debian were merged, a few were not
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:29:00 -0800
bitcoin (0.11.2-trusty1) trusty; urgency=low
* New upstream release.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 13 Nov 2015 18:39:00 -0800
bitcoin (0.11.1-trusty2) trusty; urgency=low
* Remove minupnpc builddep.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 14 Oct 2015 23:06:00 -1000
bitcoin (0.11.1-trusty1) trusty; urgency=high
* New upstream release.
* Disable all UPnP support.
-- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 14 Oct 2015 13:57:00 -1000
bitcoin (0.11.0-precise1) precise; urgency=medium
* New upstream release.
@ -179,7 +298,7 @@ bitcoin (0.5.3-natty0) natty; urgency=low
bitcoin (0.5.2-natty1) natty; urgency=low
* Remove mentions on anonymity in package descriptions and manpage.
These should never have been there, bitcoin isn't anonymous without
These should never have been there, bitcoin isnt anonymous without
a ton of work that virtually no users will ever be willing and
capable of doing
@ -220,7 +339,7 @@ bitcoin (0.5.0~rc1-natty1) natty; urgency=low
* Add test_bitcoin to build test
* Fix clean
* Remove unnecessary build-dependancies
* Remove uneccessary build-dependancies
-- Matt Corallo <matt@bluematt.me> Wed, 26 Oct 2011 14:37:18 -0400
@ -380,7 +499,7 @@ bitcoin (0.3.20.01~dfsg-1) unstable; urgency=low
bitcoin (0.3.19~dfsg-6) unstable; urgency=low
* Fix override aggressive optimizations.
* Fix override agressive optimizations.
* Fix tighten build-dependencies to really fit backporting to Lenny:
+ Add fallback build-dependency on libdb4.6++-dev.
+ Tighten unversioned Boost build-dependencies to recent versions,

View file

@ -1,27 +1,30 @@
Source: bitcoin
Section: utils
Priority: optional
Maintainer: Jonas Smedegaard <dr@jones.dk>
Uploaders: Micah Anderson <micah@debian.org>
Maintainer: Matt Corallo <matt@mattcorallo.com>
Uploaders: Matt Corallo <matt@mattcorallo.com>
Build-Depends: debhelper,
devscripts,
automake,
libtool,
bash-completion,
libboost-system-dev (>> 1.35) | libboost-system1.35-dev,
libdb4.8++-dev,
libssl-dev,
pkg-config,
libminiupnpc8-dev | libminiupnpc-dev (>> 1.6),
libboost-filesystem-dev (>> 1.35) | libboost-filesystem1.35-dev,
libboost-program-options-dev (>> 1.35) | libboost-program-options1.35-dev,
libboost-thread-dev (>> 1.35) | libboost-thread1.35-dev,
libboost-test-dev (>> 1.35) | libboost-test1.35-dev,
qt4-qmake,
libqt4-dev,
libevent-dev,
libboost-system1.48-dev | libboost-system-dev (>> 1.47),
libboost-filesystem1.48-dev | libboost-filesystem-dev (>> 1.47),
libboost-program-options1.48-dev | libboost-program-options-dev (>> 1.47),
libboost-thread1.48-dev | libboost-thread-dev (>> 1.47),
libboost-test1.48-dev | libboost-test-dev (>> 1.47),
libboost-chrono1.48-dev | libboost-chrono-dev (>> 1.47),
libminiupnpc8-dev | libminiupnpc-dev,
qt4-qmake, libqt4-dev,
qttools5-dev-tools, qttools5-dev,
libqrencode-dev,
libprotobuf-dev, protobuf-compiler,
python
python,
libzmq3-dev
Standards-Version: 3.9.2
Homepage: https://bitcoincore.org/
Vcs-Git: git://github.com/bitcoin/bitcoin.git
@ -31,11 +34,11 @@ Package: bitcoind
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer network based digital currency - daemon
Bitcoin is an experimental new digital currency that enables instant
payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
technology to operate with no central authority: managing transactions
and issuing money are carried out collectively by the network. Bitcoin Core
is the name of the open source software which enables the use of this currency.
Bitcoin is a free open source peer-to-peer electronic cash system that
is completely decentralized, without the need for a central server or
trusted parties. Users hold the crypto keys to their own money and
transact directly with each other, with the help of a P2P network to
check for double-spending.
.
This package provides the daemon, bitcoind, and the CLI tool
bitcoin-cli to interact with the daemon.
@ -44,11 +47,11 @@ Package: bitcoin-qt
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer network based digital currency - Qt GUI
Bitcoin is an experimental new digital currency that enables instant
payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
technology to operate with no central authority: managing transactions
and issuing money are carried out collectively by the network. Bitcoin Core
is the name of the open source software which enables the use of this currency.
Bitcoin is a free open source peer-to-peer electronic cash system that
is completely decentralized, without the need for a central server or
trusted parties. Users hold the crypto keys to their own money and
transact directly with each other, with the help of a P2P network to
check for double-spending.
.
This package provides Bitcoin-Qt, a GUI for Bitcoin based on Qt.
@ -56,11 +59,11 @@ Package: bitcoin-tx
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer digital currency - standalone transaction tool
Bitcoin is an experimental new digital currency that enables instant
payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
technology to operate with no central authority: managing transactions
and issuing money are carried out collectively by the network. Bitcoin Core
is the name of the open source software which enables the use of this currency.
Bitcoin is a free open source peer-to-peer electronic cash system that
is completely decentralized, without the need for a central server or
trusted parties. Users hold the crypto keys to their own money and
transact directly with each other, with the help of a P2P network to
check for double-spending.
.
This package provides bitcoin-tx, a command-line transaction creation
tool which can be used without a bitcoin daemon. Some means of

View file

@ -12,10 +12,12 @@ override_dh_auto_clean:
if [ -f Makefile ]; then $(MAKE) distclean; fi
rm -rf Makefile.in aclocal.m4 configure src/Makefile.in src/bitcoin-config.h.in src/build-aux src/qt/Makefile.in src/qt/test/Makefile.in src/test/Makefile.in
QT=$(shell dpkg-vendor --derives-from Ubuntu && echo qt4 || echo qt5)
# Yea, autogen should be run on the source archive, but I like doing git archive
override_dh_auto_configure:
./autogen.sh
./configure
./configure --with-gui=$(QT)
override_dh_auto_test:
make check

View file

@ -23,7 +23,7 @@
#BITCOIND_NICE=0
# Additional options (avoid -conf and -datadir, use flags above)
BITCOIND_OPTS="-disablewallet"
#BITCOIND_OPTS=""
# The timeout in seconds OpenRC will wait for bitcoind to terminate
# after a SIGTERM has been raised.

View file

@ -8,7 +8,7 @@ and remove old versions as necessary.
The seeds compiled into the release are created from sipa's DNS seed data, like this:
curl -s http://bitcoin.sipa.be/seeds.txt > seeds_main.txt
curl -s http://bitcoin.sipa.be/seeds.txt.gz | gzip -dc > seeds_main.txt
python3 makeseeds.py < seeds_main.txt > nodes_main.txt
python3 generate-seeds.py . > ../../src/chainparamsseeds.h

View file

@ -11,14 +11,14 @@ Install the OS X command line tools:
When the popup appears, click `Install`.
Then install [Homebrew](http://brew.sh).
Then install [Homebrew](https://brew.sh).
Dependencies
----------------------
brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf --c++11 qt5 libevent
brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf qt libevent
In case you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG
If you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG
brew install librsvg

View file

@ -30,6 +30,55 @@ frequently tested on them.
Notable changes
===============
Low-level RPC changes
---------------------
- Error codes have been updated to be more accurate for the following error cases:
- `getblock` now returns RPC_MISC_ERROR if the block can't be found on disk (for
example if the block has been pruned). Previously returned RPC_INTERNAL_ERROR.
- `pruneblockchain` now returns RPC_MISC_ERROR if the blocks cannot be pruned
because the node is not in pruned mode. Previously returned RPC_METHOD_NOT_FOUND.
- `pruneblockchain` now returns RPC_INVALID_PARAMETER if the blocks cannot be pruned
because the supplied timestamp is too late. Previously returned RPC_INTERNAL_ERROR.
- `pruneblockchain` now returns RPC_MISC_ERROR if the blocks cannot be pruned
because the blockchain is too short. Previously returned RPC_INTERNAL_ERROR.
- `setban` now returns RPC_CLIENT_INVALID_IP_OR_SUBNET if the supplied IP address
or subnet is invalid. Previously returned RPC_CLIENT_NODE_ALREADY_ADDED.
- `setban` now returns RPC_CLIENT_INVALID_IP_OR_SUBNET if the user tries to unban
a node that has not previously been banned. Previously returned RPC_MISC_ERROR.
- `removeprunedfunds` now returns RPC_WALLET_ERROR if bitcoind is unable to remove
the transaction. Previously returned RPC_INTERNAL_ERROR.
- `removeprunedfunds` now returns RPC_INVALID_PARAMETER if the transaction does not
exist in the wallet. Previously returned RPC_INTERNAL_ERROR.
- `fundrawtransaction` now returns RPC_INVALID_ADDRESS_OR_KEY if an invalid change
address is provided. Previously returned RPC_INVALID_PARAMETER.
- `fundrawtransaction` now returns RPC_WALLET_ERROR if bitcoind is unable to create
the transaction. The error message provides further details. Previously returned
RPC_INTERNAL_ERROR.
- `bumpfee` now returns RPC_INVALID_PARAMETER if the provided transaction has
descendants in the wallet. Previously returned RPC_MISC_ERROR.
- `bumpfee` now returns RPC_INVALID_PARAMETER if the provided transaction has
descendants in the mempool. Previously returned RPC_MISC_ERROR.
- `bumpfee` now returns RPC_WALLET_ERROR if the provided transaction has
has been mined or conflicts with a mined transaction. Previously returned
RPC_INVALID_ADDRESS_OR_KEY.
- `bumpfee` now returns RPC_WALLET_ERROR if the provided transaction is not
BIP 125 replaceable. Previously returned RPC_INVALID_ADDRESS_OR_KEY.
- `bumpfee` now returns RPC_WALLET_ERROR if the provided transaction has already
been bumped by a different transaction. Previously returned RPC_INVALID_REQUEST.
- `bumpfee` now returns RPC_WALLET_ERROR if the provided transaction contains
inputs which don't belong to this wallet. Previously returned RPC_INVALID_ADDRESS_OR_KEY.
- `bumpfee` now returns RPC_WALLET_ERROR if the provided transaction has multiple change
outputs. Previously returned RPC_MISC_ERROR.
- `bumpfee` now returns RPC_WALLET_ERROR if the provided transaction has no change
output. Previously returned RPC_MISC_ERROR.
- `bumpfee` now returns RPC_WALLET_ERROR if the fee is too high. Previously returned
RPC_MISC_ERROR.
- `bumpfee` now returns RPC_WALLET_ERROR if the fee is too low. Previously returned
RPC_MISC_ERROR.
- `bumpfee` now returns RPC_WALLET_ERROR if the change output is too small to bump the
fee. Previously returned RPC_MISC_ERROR.
miniupnp CVE-2017-8798
----------------------------

View file

@ -129,7 +129,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
def test_nonrbf_bumpfee_fails(peer_node, dest_address):
# cannot replace a non RBF transaction (from node which did not enable RBF)
not_rbfid = create_fund_sign_send(peer_node, {dest_address: 0.00090000})
assert_raises_message(JSONRPCException, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid)
assert_raises_jsonrpc(-4, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid)
def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
@ -149,7 +149,7 @@ def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
signedtx = rbf_node.signrawtransaction(rawtx)
signedtx = peer_node.signrawtransaction(signedtx["hex"])
rbfid = rbf_node.sendrawtransaction(signedtx["hex"])
assert_raises_message(JSONRPCException, "Transaction contains inputs that don't belong to this wallet",
assert_raises_jsonrpc(-4, "Transaction contains inputs that don't belong to this wallet",
rbf_node.bumpfee, rbfid)
@ -160,7 +160,7 @@ def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000})
tx = rbf_node.signrawtransaction(tx)
txid = rbf_node.sendrawtransaction(tx["hex"])
assert_raises_message(JSONRPCException, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
assert_raises_jsonrpc(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
def test_small_output_fails(rbf_node, dest_address):
@ -175,7 +175,7 @@ def test_small_output_fails(rbf_node, dest_address):
Decimal("0.00100000"),
{dest_address: 0.00080000,
get_change_address(rbf_node): Decimal("0.00010000")})
assert_raises_message(JSONRPCException, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 20001})
assert_raises_jsonrpc(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 20001})
def test_dust_to_fee(rbf_node, dest_address):
@ -210,7 +210,7 @@ def test_rebumping(rbf_node, dest_address):
rbf_node.settxfee(Decimal("0.00001000"))
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 1000})
assert_raises_message(JSONRPCException, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 2000})
assert_raises_jsonrpc(-4, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 2000})
rbf_node.bumpfee(bumped["txid"], {"totalFee": 2000})
@ -218,7 +218,7 @@ def test_rebumping_not_replaceable(rbf_node, dest_address):
# check that re-bumping a non-replaceable bump tx fails
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 10000, "replaceable": False})
assert_raises_message(JSONRPCException, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
assert_raises_jsonrpc(-4, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
{"totalFee": 20000})
@ -269,7 +269,7 @@ def test_bumpfee_metadata(rbf_node, dest_address):
def test_locked_wallet_fails(rbf_node, dest_address):
rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000})
rbf_node.walletlock()
assert_raises_message(JSONRPCException, "Please enter the wallet passphrase with walletpassphrase first.",
assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first.",
rbf_node.bumpfee, rbfid)
@ -316,9 +316,7 @@ def submit_block_with_tx(node, tx):
block.rehash()
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()
error = node.submitblock(bytes_to_hex_str(block.serialize(True)))
if error is not None:
raise Exception(error)
node.submitblock(bytes_to_hex_str(block.serialize(True)))
return block

View file

@ -186,12 +186,7 @@ class RawTransactionsTest(BitcoinTestFramework):
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
try:
self.nodes[2].fundrawtransaction(rawtx, {'foo': 'bar'})
raise AssertionError("Accepted invalid option foo")
except JSONRPCException as e:
assert("Unexpected key foo" in e.error['message'])
assert_raises_jsonrpc(-3, "Unexpected key foo", self.nodes[2].fundrawtransaction, rawtx, {'foo':'bar'})
############################################################
# test a fundrawtransaction with an invalid change address #
@ -204,12 +199,7 @@ class RawTransactionsTest(BitcoinTestFramework):
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
try:
self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': 'foobar'})
raise AssertionError("Accepted invalid bitcoin address")
except JSONRPCException as e:
assert("changeAddress must be a valid bitcoin address" in e.error['message'])
assert_raises_jsonrpc(-5, "changeAddress must be a valid bitcoin address", self.nodes[2].fundrawtransaction, rawtx, {'changeAddress':'foobar'})
############################################################
# test a fundrawtransaction with a provided change address #
@ -223,12 +213,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
change = self.nodes[2].getnewaddress()
try:
rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 2})
except JSONRPCException as e:
assert('changePosition out of bounds' == e.error['message'])
else:
assert(False)
assert_raises_jsonrpc(-8, "changePosition out of bounds", self.nodes[2].fundrawtransaction, rawtx, {'changeAddress':change, 'changePosition':2})
rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 0})
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
out = dec_tx['vout'][0]
@ -337,12 +322,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
try:
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
raise AssertionError("Spent more than available")
except JSONRPCException as e:
assert("Insufficient" in e.error['message'])
assert_raises_jsonrpc(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx)
############################################################
#compare fee of a standard pubkeyhash transaction
@ -498,21 +478,13 @@ class RawTransactionsTest(BitcoinTestFramework):
rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
# fund a transaction that requires a new key for the change output
# creating the key must be impossible because the wallet is locked
try:
fundedTx = self.nodes[1].fundrawtransaction(rawTx)
raise AssertionError("Wallet unlocked without passphrase")
except JSONRPCException as e:
assert('Keypool ran out' in e.error['message'])
assert_raises_jsonrpc(-4, "Insufficient funds", self.nodes[1].fundrawtransaction, rawtx)
#refill the keypool
self.nodes[1].walletpassphrase("test", 100)
self.nodes[1].walletlock()
try:
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2)
raise AssertionError("Wallet unlocked without passphrase")
except JSONRPCException as e:
assert('walletpassphrase' in e.error['message'])
assert_raises_jsonrpc(-13, "walletpassphrase", self.nodes[1].sendtoaddress, self.nodes[0].getnewaddress(), 1.2)
oldBalance = self.nodes[0].getbalance()

View file

@ -76,12 +76,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
self.sync_all()
#Import with no affiliated address
try:
self.nodes[1].importprunedfunds(rawtxn1, proof1)
except JSONRPCException as e:
assert('No addresses' in e.error['message'])
else:
assert(False)
assert_raises_jsonrpc(-5, "No addresses", self.nodes[1].importprunedfunds, rawtxn1, proof1)
balance1 = self.nodes[1].getbalance("", 0, True)
assert_equal(balance1, Decimal(0))
@ -112,12 +107,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
assert_equal(address_info['ismine'], True)
#Remove transactions
try:
self.nodes[1].removeprunedfunds(txnid1)
except JSONRPCException as e:
assert('does not exist' in e.error['message'])
else:
assert(False)
assert_raises_jsonrpc(-8, "Transaction does not exist in wallet.", self.nodes[1].removeprunedfunds, txnid1)
balance1 = self.nodes[1].getbalance("*", 0, True)
assert_equal(balance1, Decimal('0.075'))

View file

@ -7,79 +7,83 @@
# Test node handling
#
from test_framework.mininode import wait_until
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.util import (assert_equal,
assert_raises_jsonrpc,
connect_nodes_bi,
start_node,
stop_node,
)
import urllib.parse
class NodeHandlingTest (BitcoinTestFramework):
class NodeHandlingTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 4
self.num_nodes = 2
self.setup_clean_chain = False
def setup_network(self):
self.nodes = self.setup_nodes()
connect_nodes_bi(self.nodes, 0, 1)
def run_test(self):
###########################
# setban/listbanned tests #
###########################
assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point
self.nodes[2].setban("127.0.0.1", "add")
time.sleep(3) #wait till the nodes are disconected
assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point
assert_equal(len(self.nodes[2].listbanned()), 1)
self.nodes[2].clearbanned()
assert_equal(len(self.nodes[2].listbanned()), 0)
self.nodes[2].setban("127.0.0.0/24", "add")
assert_equal(len(self.nodes[2].listbanned()), 1)
try:
self.nodes[2].setban("127.0.0.1", "add") #throws exception because 127.0.0.1 is within range 127.0.0.0/24
except:
pass
assert_equal(len(self.nodes[2].listbanned()), 1) #still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24
try:
self.nodes[2].setban("127.0.0.1", "remove")
except:
pass
assert_equal(len(self.nodes[2].listbanned()), 1)
self.nodes[2].setban("127.0.0.0/24", "remove")
assert_equal(len(self.nodes[2].listbanned()), 0)
self.nodes[2].clearbanned()
assert_equal(len(self.nodes[2].listbanned()), 0)
assert_equal(len(self.nodes[1].getpeerinfo()), 2) # node1 should have 2 connections to node0 at this point
self.nodes[1].setban("127.0.0.1", "add")
assert wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0, timeout=10)
assert_equal(len(self.nodes[1].getpeerinfo()), 0) # all nodes must be disconnected at this point
assert_equal(len(self.nodes[1].listbanned()), 1)
self.nodes[1].clearbanned()
assert_equal(len(self.nodes[1].listbanned()), 0)
self.nodes[1].setban("127.0.0.0/24", "add")
assert_equal(len(self.nodes[1].listbanned()), 1)
# This will throw an exception because 127.0.0.1 is within range 127.0.0.0/24
assert_raises_jsonrpc(-23, "IP/Subnet already banned", self.nodes[1].setban, "127.0.0.1", "add")
# This will throw an exception because 127.0.0.1/42 is not a real subnet
assert_raises_jsonrpc(-30, "Error: Invalid IP/Subnet", self.nodes[1].setban, "127.0.0.1/42", "add")
assert_equal(len(self.nodes[1].listbanned()), 1) # still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24
# This will throw an exception because 127.0.0.1 was not added above
assert_raises_jsonrpc(-30, "Error: Unban failed", self.nodes[1].setban, "127.0.0.1", "remove")
assert_equal(len(self.nodes[1].listbanned()), 1)
self.nodes[1].setban("127.0.0.0/24", "remove")
assert_equal(len(self.nodes[1].listbanned()), 0)
self.nodes[1].clearbanned()
assert_equal(len(self.nodes[1].listbanned()), 0)
##test persisted banlist
self.nodes[2].setban("127.0.0.0/32", "add")
self.nodes[2].setban("127.0.0.0/24", "add")
self.nodes[2].setban("192.168.0.1", "add", 1) #ban for 1 seconds
self.nodes[2].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) #ban for 1000 seconds
listBeforeShutdown = self.nodes[2].listbanned()
assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) #must be here
time.sleep(2) #make 100% sure we expired 192.168.0.1 node time
# test persisted banlist
self.nodes[1].setban("127.0.0.0/32", "add")
self.nodes[1].setban("127.0.0.0/24", "add")
self.nodes[1].setban("192.168.0.1", "add", 1) # ban for 1 seconds
self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) # ban for 1000 seconds
listBeforeShutdown = self.nodes[1].listbanned()
assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address'])
assert wait_until(lambda: len(self.nodes[1].listbanned()) == 3, timeout=10)
#stop node
stop_node(self.nodes[2], 2)
stop_node(self.nodes[1], 1)
self.nodes[2] = start_node(2, self.options.tmpdir)
listAfterShutdown = self.nodes[2].listbanned()
self.nodes[1] = start_node(1, self.options.tmpdir)
listAfterShutdown = self.nodes[1].listbanned()
assert_equal("127.0.0.0/24", listAfterShutdown[0]['address'])
assert_equal("127.0.0.0/32", listAfterShutdown[1]['address'])
assert_equal("/19" in listAfterShutdown[2]['address'], True)
# Clear ban lists
self.nodes[1].clearbanned()
connect_nodes_bi(self.nodes, 0, 1)
###########################
# RPC disconnectnode test #
###########################
url = urllib.parse.urlparse(self.nodes[1].url)
self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
time.sleep(2) #disconnecting a node needs a little bit of time
for node in self.nodes[0].getpeerinfo():
assert(node['addr'] != url.hostname+":"+str(p2p_port(1)))
address1 = self.nodes[0].getpeerinfo()[0]['addr']
self.nodes[0].disconnectnode(address=address1)
assert wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10)
assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
connect_nodes_bi(self.nodes,0,1) #reconnect the node
found = False
for node in self.nodes[0].getpeerinfo():
if node['addr'] == url.hostname+":"+str(p2p_port(1)):
found = True
assert(found)
connect_nodes_bi(self.nodes, 0, 1) # reconnect the node
assert [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
if __name__ == '__main__':
NodeHandlingTest ().main ()
NodeHandlingTest().main()

View file

@ -199,11 +199,8 @@ class AcceptBlockTest(BitcoinTestFramework):
assert_equal(x['status'], "headers-only")
# But this block should be accepted by node0 since it has more work.
try:
self.nodes[0].getblock(blocks_h3[0].hash)
print("Unrequested more-work block accepted from non-whitelisted peer")
except:
raise AssertionError("Unrequested more work block was not processed")
self.nodes[0].getblock(blocks_h3[0].hash)
print("Unrequested more-work block accepted from non-whitelisted peer")
# Node1 should have accepted and reorged.
assert_equal(self.nodes[1].getblockcount(), 3)
@ -227,26 +224,17 @@ class AcceptBlockTest(BitcoinTestFramework):
tips[j] = next_block
time.sleep(2)
for x in all_blocks:
try:
self.nodes[0].getblock(x.hash)
if x == all_blocks[287]:
raise AssertionError("Unrequested block too far-ahead should have been ignored")
except:
if x == all_blocks[287]:
print("Unrequested block too far-ahead not processed")
else:
raise AssertionError("Unrequested block with more work should have been accepted")
# Blocks 1-287 should be accepted, block 288 should be ignored because it's too far ahead
for x in all_blocks[:-1]:
self.nodes[0].getblock(x.hash)
assert_raises_jsonrpc(-1, "Block not found on disk", self.nodes[0].getblock, all_blocks[-1].hash)
headers_message.headers.pop() # Ensure the last block is unrequested
white_node.send_message(headers_message) # Send headers leading to tip
white_node.send_message(msg_block(tips[1])) # Now deliver the tip
try:
white_node.sync_with_ping()
self.nodes[1].getblock(tips[1].hash)
print("Unrequested block far ahead of tip accepted from whitelisted peer")
except:
raise AssertionError("Unrequested block from whitelisted peer not accepted")
white_node.sync_with_ping()
self.nodes[1].getblock(tips[1].hash)
print("Unrequested block far ahead of tip accepted from whitelisted peer")
# 5. Test handling of unrequested block on the node that didn't process
# Should still not be processed (even though it has a child that has more

View file

@ -16,7 +16,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 1
self.num_nodes = 2
self.txouts = gen_return_txouts()
@ -25,8 +25,11 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
self.is_network_split = False
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-printpriority=1"]))
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-printpriority=1"]))
connect_nodes(self.nodes[0], 1)
self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
def run_test(self):
utxo_count = 90
utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], utxo_count)
@ -139,5 +142,16 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
assert_equal(self.nodes[0].sendrawtransaction(tx2_hex), tx2_id)
assert(tx2_id in self.nodes[0].getrawmempool())
# Test that calling prioritisetransaction is sufficient to trigger
# getblocktemplate to (eventually) return a new block.
mock_time = int(time.time())
self.nodes[0].setmocktime(mock_time)
template = self.nodes[0].getblocktemplate()
self.nodes[0].prioritisetransaction(txid, 0, -int(self.relayfee*COIN))
self.nodes[0].setmocktime(mock_time+10)
new_template = self.nodes[0].getblocktemplate()
assert(template != new_template)
if __name__ == '__main__':
PrioritiseTransactionTest().main()

View file

@ -186,11 +186,8 @@ class PruneTest(BitcoinTestFramework):
def reorg_back(self):
# Verify that a block on the old main chain fork has been pruned away
try:
self.nodes[2].getblock(self.forkhash)
raise AssertionError("Old block wasn't pruned so can't test redownload")
except JSONRPCException as e:
print("Will need to redownload block",self.forkheight)
assert_raises_jsonrpc(-1, "Block not available (pruned data)", self.nodes[2].getblock, self.forkhash)
print("Will need to redownload block",self.forkheight)
# Verify that we have enough history to reorg back to the fork point
# Although this is more than 288 blocks, because this chain was written more recently
@ -235,7 +232,7 @@ class PruneTest(BitcoinTestFramework):
# at this point, node has 995 blocks and has not yet run in prune mode
node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-debug=0"], timewait=900)
assert_equal(node.getblockcount(), 995)
assert_raises_message(JSONRPCException, "not in prune mode", node.pruneblockchain, 500)
assert_raises_jsonrpc(-1, "not in prune mode", node.pruneblockchain, 500)
self.stop_node(node_number)
# now re-start in manual pruning mode
@ -267,14 +264,14 @@ class PruneTest(BitcoinTestFramework):
return os.path.isfile(self.options.tmpdir + "/node{}/regtest/blocks/blk{:05}.dat".format(node_number, index))
# should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000)
assert_raises_message(JSONRPCException, "Blockchain is too short for pruning", node.pruneblockchain, height(500))
assert_raises_jsonrpc(-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500))
# mine 6 blocks so we are at height 1001 (i.e., above PruneAfterHeight)
node.generate(6)
assert_equal(node.getblockchaininfo()["blocks"], 1001)
# negative heights should raise an exception
assert_raises_message(JSONRPCException, "Negative", node.pruneblockchain, -10)
assert_raises_jsonrpc(-8, "Negative", node.pruneblockchain, -10)
# height=100 too low to prune first block file so this is a no-op
prune(100)
@ -320,12 +317,9 @@ class PruneTest(BitcoinTestFramework):
def wallet_test(self):
# check that the pruning node's wallet is still in good shape
print("Stop and start pruning node to trigger wallet rescan")
try:
self.stop_node(2)
start_node(2, self.options.tmpdir, ["-debug=1","-prune=550"])
print("Success")
except Exception as detail:
raise AssertionError("Wallet test: unable to re-start the pruning node")
self.stop_node(2)
start_node(2, self.options.tmpdir, ["-debug=1","-prune=550"])
print("Success")
# check that wallet loads loads successfully when restarting a pruned node after IBD.
# this was reported to fail in #7494.
@ -333,12 +327,9 @@ class PruneTest(BitcoinTestFramework):
connect_nodes(self.nodes[0], 5)
nds = [self.nodes[0], self.nodes[5]]
sync_blocks(nds, wait=5, timeout=300)
try:
self.stop_node(5) #stop and start to trigger rescan
start_node(5, self.options.tmpdir, ["-debug=1","-prune=550"])
print ("Success")
except Exception as detail:
raise AssertionError("Wallet test: unable to re-start node5")
self.stop_node(5) #stop and start to trigger rescan
start_node(5, self.options.tmpdir, ["-debug=1","-prune=550"])
print ("Success")
def run_test(self):
print("Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours)")

View file

@ -61,13 +61,8 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
rawtx = self.nodes[2].signrawtransaction(rawtx)
try:
rawtx = self.nodes[2].sendrawtransaction(rawtx['hex'])
except JSONRPCException as e:
assert("Missing inputs" in e.error['message'])
else:
assert(False)
# This will raise an exception since there are missing inputs
assert_raises_jsonrpc(-25, "Missing inputs", self.nodes[2].sendrawtransaction, rawtx['hex'])
#########################
# RAW TX MULTISIG TESTS #
@ -161,13 +156,13 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getrawtransaction(txHash, True)["hex"], rawTxSigned['hex'])
# 6. invalid parameters - supply txid and string "Flase"
assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, txHash, "Flase")
assert_raises_jsonrpc(-3,"Invalid type", self.nodes[0].getrawtransaction, txHash, "Flase")
# 7. invalid parameters - supply txid and empty array
assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, txHash, [])
assert_raises_jsonrpc(-3,"Invalid type", self.nodes[0].getrawtransaction, txHash, [])
# 8. invalid parameters - supply txid and empty dict
assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, txHash, {})
assert_raises_jsonrpc(-3,"Invalid type", self.nodes[0].getrawtransaction, txHash, {})
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}]
outputs = { self.nodes[0].getnewaddress() : 1 }
@ -175,13 +170,15 @@ class RawTransactionsTest(BitcoinTestFramework):
decrawtx= self.nodes[0].decoderawtransaction(rawtx)
assert_equal(decrawtx['vin'][0]['sequence'], 1000)
# 9. invalid parameters - sequence number out of range
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}]
outputs = { self.nodes[0].getnewaddress() : 1 }
assert_raises(JSONRPCException, self.nodes[0].createrawtransaction, inputs, outputs)
assert_raises_jsonrpc(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs)
# 10. invalid parameters - sequence number out of range
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}]
outputs = { self.nodes[0].getnewaddress() : 1 }
assert_raises(JSONRPCException, self.nodes[0].createrawtransaction, inputs, outputs)
assert_raises_jsonrpc(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs)
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}]
outputs = { self.nodes[0].getnewaddress() : 1 }

View file

@ -89,6 +89,7 @@ BITCOIN_TESTS =\
test/blockencodings_tests.cpp \
test/bloom_tests.cpp \
test/bswap_tests.cpp \
test/checkqueue_tests.cpp \
test/coins_tests.cpp \
test/compress_tests.cpp \
test/crypto_tests.cpp \

View file

@ -127,6 +127,9 @@ private:
}
public:
//! Mutex to ensure only one concurrent CCheckQueueControl
boost::mutex ControlMutex;
//! Create a new check queue
CCheckQueue(unsigned int nBatchSizeIn) : nIdle(0), nTotal(0), fAllOk(true), nTodo(0), fQuit(false), nBatchSize(nBatchSizeIn) {}
@ -161,12 +164,6 @@ public:
{
}
bool IsIdle()
{
boost::unique_lock<boost::mutex> lock(mutex);
return (nTotal == nIdle && nTodo == 0 && fAllOk == true);
}
};
/**
@ -177,16 +174,18 @@ template <typename T>
class CCheckQueueControl
{
private:
CCheckQueue<T>* pqueue;
CCheckQueue<T> * const pqueue;
bool fDone;
public:
CCheckQueueControl(CCheckQueue<T>* pqueueIn) : pqueue(pqueueIn), fDone(false)
CCheckQueueControl() = delete;
CCheckQueueControl(const CCheckQueueControl&) = delete;
CCheckQueueControl& operator=(const CCheckQueueControl&) = delete;
explicit CCheckQueueControl(CCheckQueue<T> * const pqueueIn) : pqueue(pqueueIn), fDone(false)
{
// passed queue is supposed to be unused, or NULL
if (pqueue != NULL) {
bool isIdle = pqueue->IsIdle();
assert(isIdle);
ENTER_CRITICAL_SECTION(pqueue->ControlMutex);
}
}
@ -209,6 +208,9 @@ public:
{
if (!fDone)
Wait();
if (pqueue != NULL) {
LEAVE_CRITICAL_SECTION(pqueue->ControlMutex);
}
}
};

View file

@ -65,7 +65,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
} else {
// calculate left hash
uint256 left = CalcHash(height-1, pos*2, vTxid), right;
// calculate right hash if not beyond the end of the array - copy left hash otherwise1
// calculate right hash if not beyond the end of the array - copy left hash otherwise
if (pos*2+1 < CalcTreeWidth(height-1))
right = CalcHash(height-1, pos*2+1, vTxid);
else

View file

@ -23,7 +23,7 @@
* storing a bit for each traversed node, signifying whether the node is the
* parent of at least one matched leaf txid (or a matched txid itself). In
* case we are at the leaf level, or this bit is 0, its merkle node hash is
* stored, and its children are not explorer further. Otherwise, no hash is
* stored, and its children are not explored further. Otherwise, no hash is
* stored, but we recurse into both (or the only) child branch. During
* decoding, the same depth-first traversal is performed, consuming bits and
* hashes as they written during encoding.

View file

@ -413,10 +413,10 @@ void CConnman::DumpBanlist()
CBanDB bandb;
banmap_t banmap;
SetBannedSetDirty(false);
GetBanned(banmap);
if (!bandb.Write(banmap))
SetBannedSetDirty(true);
if (bandb.Write(banmap)) {
SetBannedSetDirty(false);
}
LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
banmap.size(), GetTimeMillis() - nStart);
@ -536,6 +536,8 @@ bool CConnman::Unban(const CSubNet &subNet) {
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
}

View file

@ -759,11 +759,33 @@
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="fallbackFeeWarningLabel">
<property name="toolTip">
<string>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 your have validated the complete chain.</string>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Warning: Fee estimation is currently not possible.</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>

View file

@ -23,6 +23,7 @@
#include "txmempool.h"
#include "wallet/wallet.h"
#include <QFontMetrics>
#include <QMessageBox>
#include <QScrollBar>
#include <QSettings>
@ -656,6 +657,11 @@ void SendCoinsDialog::updateSmartFeeLabel()
std::max(CWallet::fallbackFee.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB");
ui->labelSmartFee2->show(); // (Smart fee not initialized yet. This usually takes a few blocks...)
ui->labelFeeEstimation->setText("");
ui->fallbackFeeWarningLabel->setVisible(true);
int lightness = ui->fallbackFeeWarningLabel->palette().color(QPalette::WindowText).lightness();
QColor warning_colour(255 - (lightness / 5), 176 - (lightness / 3), 48 - (lightness / 14));
ui->fallbackFeeWarningLabel->setStyleSheet("QLabel { color: " + warning_colour.name() + "; }");
ui->fallbackFeeWarningLabel->setIndent(QFontMetrics(ui->fallbackFeeWarningLabel->font()).width("x"));
}
else
{
@ -663,6 +669,7 @@ void SendCoinsDialog::updateSmartFeeLabel()
std::max(feeRate.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB");
ui->labelSmartFee2->hide();
ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %n block(s).", "", estimateFoundAtBlocks));
ui->fallbackFeeWarningLabel->setVisible(false);
}
updateFeeMinimizedLabel();

View file

@ -417,6 +417,7 @@ UniValue getrawmempool(const JSONRPCRequest& request)
throw 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"
@ -744,10 +745,15 @@ UniValue getblock(const JSONRPCRequest& request)
CBlockIndex* pblockindex = mapBlockIndex[hash];
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
// Block not found on disk. This could be because we have the block
// header in our index but don't have the block (for example if a
// non-whitelisted node sends us an unrequested long chain of valid
// blocks, we add the headers to our index, but don't accept the
// block).
throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
if (!fVerbose)
{
@ -829,7 +835,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request)
+ HelpExampleRpc("pruneblockchain", "1000"));
if (!fPruneMode)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Cannot prune blocks because node is not in prune mode.");
throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode.");
LOCK(cs_main);
@ -843,7 +849,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request)
// Add a 2 hour buffer to include blocks which might have had old timestamps
CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - 7200);
if (!pindex) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not find block with at least the specified timestamp.");
throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp.");
}
heightParam = pindex->nHeight;
}
@ -851,7 +857,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request)
unsigned int height = (unsigned int) heightParam;
unsigned int chainHeight = (unsigned int) chainActive.Height();
if (chainHeight < Params().PruneAfterHeight())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Blockchain is too short for pruning.");
throw JSONRPCError(RPC_MISC_ERROR, "Blockchain is too short for pruning.");
else if (height > chainHeight)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Blockchain is shorter than the attempted prune height.");
else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) {

View file

@ -506,7 +506,7 @@ UniValue setban(const JSONRPCRequest& request)
LookupSubNet(request.params[0].get_str().c_str(), subNet);
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
if (strCommand == "add")
{
@ -526,7 +526,7 @@ UniValue setban(const JSONRPCRequest& request)
else if(strCommand == "remove")
{
if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) ))
throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously banned.");
}
return NullUniValue;
}

View file

@ -248,7 +248,8 @@ public:
void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
{
assert(last - first >= 0);
if (last == first) return;
assert(last - first > 0);
if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
{
// special case for inserting at the front when there's room
@ -261,7 +262,8 @@ public:
void insert(iterator it, const char* first, const char* last)
{
assert(last - first >= 0);
if (last == first) return;
assert(last - first > 0);
if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
{
// special case for inserting at the front when there's room
@ -339,6 +341,8 @@ public:
void read(char* pch, size_t nSize)
{
if (nSize == 0) return;
// Read from the beginning of the buffer
unsigned int nReadPosNext = nReadPos + nSize;
if (nReadPosNext >= vch.size())

View file

@ -8,6 +8,7 @@
#include <stdlib.h>
// Attempt to overwrite data in the specified memory span.
void memory_cleanse(void *ptr, size_t len);
#endif // BITCOIN_SUPPORT_CLEANSE_H

View file

@ -0,0 +1,442 @@
// 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 "util.h"
#include "utiltime.h"
#include "validation.h"
#include "test/test_bitcoin.h"
#include "checkqueue.h"
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
#include <atomic>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <unordered_set>
#include <memory>
#include "random.h"
// BasicTestingSetup not sufficient because nScriptCheckThreads is not set
// otherwise.
BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, TestingSetup)
static const int QUEUE_BATCH_SIZE = 128;
struct FakeCheck {
bool operator()()
{
return true;
}
void swap(FakeCheck& x){};
};
struct FakeCheckCheckCompletion {
static std::atomic<size_t> n_calls;
bool operator()()
{
++n_calls;
return true;
}
void swap(FakeCheckCheckCompletion& x){};
};
struct FailingCheck {
bool fails;
FailingCheck(bool fails) : fails(fails){};
FailingCheck() : fails(true){};
bool operator()()
{
return !fails;
}
void swap(FailingCheck& x)
{
std::swap(fails, x.fails);
};
};
struct UniqueCheck {
static std::mutex m;
static std::unordered_multiset<size_t> results;
size_t check_id;
UniqueCheck(size_t check_id_in) : check_id(check_id_in){};
UniqueCheck() : check_id(0){};
bool operator()()
{
std::lock_guard<std::mutex> l(m);
results.insert(check_id);
return true;
}
void swap(UniqueCheck& x) { std::swap(x.check_id, check_id); };
};
struct MemoryCheck {
static std::atomic<size_t> fake_allocated_memory;
bool b {false};
bool operator()()
{
return true;
}
MemoryCheck(){};
MemoryCheck(const MemoryCheck& x)
{
// We have to do this to make sure that destructor calls are paired
//
// Really, copy constructor should be deletable, but CCheckQueue breaks
// if it is deleted because of internal push_back.
fake_allocated_memory += b;
};
MemoryCheck(bool b_) : b(b_)
{
fake_allocated_memory += b;
};
~MemoryCheck(){
fake_allocated_memory -= b;
};
void swap(MemoryCheck& x) { std::swap(b, x.b); };
};
struct FrozenCleanupCheck {
static std::atomic<uint64_t> nFrozen;
static std::condition_variable cv;
static std::mutex m;
// Freezing can't be the default initialized behavior given how the queue
// swaps in default initialized Checks.
bool should_freeze {false};
bool operator()()
{
return true;
}
FrozenCleanupCheck() {}
~FrozenCleanupCheck()
{
if (should_freeze) {
std::unique_lock<std::mutex> l(m);
nFrozen = 1;
cv.notify_one();
cv.wait(l, []{ return nFrozen == 0;});
}
}
void swap(FrozenCleanupCheck& x){std::swap(should_freeze, x.should_freeze);};
};
// Static Allocations
std::mutex FrozenCleanupCheck::m{};
std::atomic<uint64_t> FrozenCleanupCheck::nFrozen{0};
std::condition_variable FrozenCleanupCheck::cv{};
std::mutex UniqueCheck::m;
std::unordered_multiset<size_t> UniqueCheck::results;
std::atomic<size_t> FakeCheckCheckCompletion::n_calls{0};
std::atomic<size_t> MemoryCheck::fake_allocated_memory{0};
// Queue Typedefs
typedef CCheckQueue<FakeCheckCheckCompletion> Correct_Queue;
typedef CCheckQueue<FakeCheck> Standard_Queue;
typedef CCheckQueue<FailingCheck> Failing_Queue;
typedef CCheckQueue<UniqueCheck> Unique_Queue;
typedef CCheckQueue<MemoryCheck> Memory_Queue;
typedef CCheckQueue<FrozenCleanupCheck> FrozenCleanup_Queue;
/** This test case checks that the CCheckQueue works properly
* with each specified size_t Checks pushed.
*/
void Correct_Queue_range(std::vector<size_t> range)
{
auto small_queue = std::unique_ptr<Correct_Queue>(new 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) {
size_t total = i;
FakeCheckCheckCompletion::n_calls = 0;
CCheckQueueControl<FakeCheckCheckCompletion> control(small_queue.get());
while (total) {
vChecks.resize(std::min(total, (size_t) GetRand(10)));
total -= vChecks.size();
control.Add(vChecks);
}
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();
tg.join_all();
}
/** Test that 0 checks is correct
*/
BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Zero)
{
std::vector<size_t> range;
range.push_back((size_t)0);
Correct_Queue_range(range);
}
/** Test that 1 check is correct
*/
BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_One)
{
std::vector<size_t> range;
range.push_back((size_t)1);
Correct_Queue_range(range);
}
/** Test that MAX check is correct
*/
BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Max)
{
std::vector<size_t> range;
range.push_back(100000);
Correct_Queue_range(range);
}
/** Test that random numbers of checks are correct
*/
BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random)
{
std::vector<size_t> range;
range.reserve(100000/1000);
for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)GetRand(std::min((size_t)1000, ((size_t)100000) - i))))
range.push_back(i);
Correct_Queue_range(range);
}
/** 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});
boost::thread_group tg;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
tg.create_thread([&]{fail_queue->Thread();});
}
for (size_t i = 0; i < 1001; ++i) {
CCheckQueueControl<FailingCheck> control(fail_queue.get());
size_t remaining = i;
while (remaining) {
size_t r = GetRand(10);
std::vector<FailingCheck> vChecks;
vChecks.reserve(r);
for (size_t k = 0; k < r && remaining; k++, remaining--)
vChecks.emplace_back(remaining == 1);
control.Add(vChecks);
}
bool success = control.Wait();
if (i > 0) {
BOOST_REQUIRE(!success);
} else if (i == 0) {
BOOST_REQUIRE(success);
}
}
tg.interrupt_all();
tg.join_all();
}
// Test that a block validation which fails does not interfere with
// 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});
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}) {
CCheckQueueControl<FailingCheck> control(fail_queue.get());
{
std::vector<FailingCheck> vChecks;
vChecks.resize(100, false);
vChecks[99] = end_fails;
control.Add(vChecks);
}
bool r =control.Wait();
BOOST_REQUIRE(r || end_fails);
}
}
tg.interrupt_all();
tg.join_all();
}
// Test that unique checks are actually all called individually, rather than
// just one check being called repeatedly. Test that checks are not called
// 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});
boost::thread_group tg;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
tg.create_thread([&]{queue->Thread();});
}
size_t COUNT = 100000;
size_t total = COUNT;
{
CCheckQueueControl<UniqueCheck> control(queue.get());
while (total) {
size_t r = GetRand(10);
std::vector<UniqueCheck> vChecks;
for (size_t k = 0; k < r && total; k++)
vChecks.emplace_back(--total);
control.Add(vChecks);
}
}
bool r = true;
BOOST_REQUIRE_EQUAL(UniqueCheck::results.size(), COUNT);
for (size_t i = 0; i < COUNT; ++i)
r = r && UniqueCheck::results.count(i) == 1;
BOOST_REQUIRE(r);
tg.interrupt_all();
tg.join_all();
}
// Test that blocks which might allocate lots of memory free their memory agressively.
//
// This test attempts to catch a pathological case where by lazily freeing
// checks might mean leaving a check un-swapped out, and decreasing by 1 each
// 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});
boost::thread_group tg;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
tg.create_thread([&]{queue->Thread();});
}
for (size_t i = 0; i < 1000; ++i) {
size_t total = i;
{
CCheckQueueControl<MemoryCheck> control(queue.get());
while (total) {
size_t r = GetRand(10);
std::vector<MemoryCheck> vChecks;
for (size_t k = 0; k < r && total; k++) {
total--;
// Each iteration leaves data at the front, back, and middle
// to catch any sort of deallocation failure
vChecks.emplace_back(total == 0 || total == i || total == i/2);
}
control.Add(vChecks);
}
}
BOOST_REQUIRE_EQUAL(MemoryCheck::fake_allocated_memory, 0);
}
tg.interrupt_all();
tg.join_all();
}
// Test that a new verification cannot occur until all checks
// have been destructed
BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup)
{
auto queue = std::unique_ptr<FrozenCleanup_Queue>(new FrozenCleanup_Queue {QUEUE_BATCH_SIZE});
boost::thread_group tg;
bool fails = false;
for (auto x = 0; x < nScriptCheckThreads; ++x) {
tg.create_thread([&]{queue->Thread();});
}
std::thread t0([&]() {
CCheckQueueControl<FrozenCleanupCheck> control(queue.get());
std::vector<FrozenCleanupCheck> vChecks(1);
// Freezing can't be the default initialized behavior given how the queue
// swaps in default initialized Checks (otherwise freezing destructor
// would get called twice).
vChecks[0].should_freeze = true;
control.Add(vChecks);
control.Wait(); // Hangs here
});
{
std::unique_lock<std::mutex> l(FrozenCleanupCheck::m);
// Wait until the queue has finished all jobs and frozen
FrozenCleanupCheck::cv.wait(l, [](){return FrozenCleanupCheck::nFrozen == 1;});
// Try to get control of the queue a bunch of times
for (auto x = 0; x < 100 && !fails; ++x) {
fails = queue->ControlMutex.try_lock();
}
// Unfreeze
FrozenCleanupCheck::nFrozen = 0;
}
// Awaken frozen destructor
FrozenCleanupCheck::cv.notify_one();
// Wait for control to finish
t0.join();
tg.interrupt_all();
tg.join_all();
BOOST_REQUIRE(!fails);
}
/** 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});
{
boost::thread_group tg;
std::atomic<int> nThreads {0};
std::atomic<int> fails {0};
for (size_t i = 0; i < 3; ++i) {
tg.create_thread(
[&]{
CCheckQueueControl<FakeCheck> control(queue.get());
// While sleeping, no other thread should execute to this point
auto observed = ++nThreads;
MilliSleep(10);
fails += observed != nThreads;
});
}
tg.join_all();
BOOST_REQUIRE_EQUAL(fails, 0);
}
{
boost::thread_group tg;
std::mutex m;
bool has_lock {false};
bool has_tried {false};
bool done {false};
bool done_ack {false};
std::condition_variable cv;
{
std::unique_lock<std::mutex> l(m);
tg.create_thread([&]{
CCheckQueueControl<FakeCheck> control(queue.get());
std::unique_lock<std::mutex> l(m);
has_lock = true;
cv.notify_one();
cv.wait(l, [&]{return has_tried;});
done = true;
cv.notify_one();
// Wait until the done is acknowledged
//
cv.wait(l, [&]{return done_ack;});
});
// Wait for thread to get the lock
cv.wait(l, [&](){return has_lock;});
bool fails = false;
for (auto x = 0; x < 100 && !fails; ++x) {
fails = queue->ControlMutex.try_lock();
}
has_tried = true;
cv.notify_one();
cv.wait(l, [&](){return done;});
// Acknowledge the done
done_ack = true;
cv.notify_one();
BOOST_REQUIRE(!fails);
}
tg.join_all();
}
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -98,7 +98,11 @@ CCoinsViewCursor *CCoinsViewDB::Cursor() const
that restriction. */
i->pcursor->Seek(DB_COINS);
// Cache key of first record
i->pcursor->GetKey(i->keyTmp);
if (i->pcursor->Valid()) {
i->pcursor->GetKey(i->keyTmp);
} else {
i->keyTmp.first = 0; // Make sure Valid() and GetKey() return false
}
return i;
}

View file

@ -945,6 +945,7 @@ void CTxMemPool::PrioritiseTransaction(const uint256 hash, const std::string str
BOOST_FOREACH(txiter descendantIt, setDescendants) {
mapTx.modify(descendantIt, update_ancestor_state(0, nFeeDelta, 0, 0));
}
++nTransactionsUpdated;
}
}
LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, FormatMoney(nFeeDelta));

View file

@ -432,7 +432,7 @@ class CTxMemPool
{
private:
uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check.
unsigned int nTransactionsUpdated;
unsigned int nTransactionsUpdated; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
CBlockPolicyEstimator* minerPolicyEstimator;
uint64_t totalTxSize; //!< sum of all mempool tx's virtual sizes. Differs from serialized tx size since witness data is discounted. Defined in BIP 141.

View file

@ -126,22 +126,23 @@ protected:
Dbt datValue;
datValue.set_flags(DB_DBT_MALLOC);
int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
memset(datKey.get_data(), 0, datKey.get_size());
if (datValue.get_data() == NULL)
return false;
memory_cleanse(datKey.get_data(), datKey.get_size());
bool success = false;
if (datValue.get_data() != NULL) {
// Unserialize value
try {
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
success = true;
} catch (const std::exception&) {
// In this case success remains 'false'
}
// Unserialize value
try {
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
} catch (const std::exception&) {
return false;
// Clear and free memory
memory_cleanse(datValue.get_data(), datValue.get_size());
free(datValue.get_data());
}
// Clear and free memory
memset(datValue.get_data(), 0, datValue.get_size());
free(datValue.get_data());
return (ret == 0);
return ret == 0 && success;
}
template <typename K, typename T>
@ -168,8 +169,8 @@ protected:
int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
// Clear memory in case it was a private key
memset(datKey.get_data(), 0, datKey.get_size());
memset(datValue.get_data(), 0, datValue.get_size());
memory_cleanse(datKey.get_data(), datKey.get_size());
memory_cleanse(datValue.get_data(), datValue.get_size());
return (ret == 0);
}
@ -191,7 +192,7 @@ protected:
int ret = pdb->del(activeTxn, &datKey, 0);
// Clear memory
memset(datKey.get_data(), 0, datKey.get_size());
memory_cleanse(datKey.get_data(), datKey.get_size());
return (ret == 0 || ret == DB_NOTFOUND);
}
@ -211,7 +212,7 @@ protected:
int ret = pdb->exists(activeTxn, &datKey, 0);
// Clear memory
memset(datKey.get_data(), 0, datKey.get_size());
memory_cleanse(datKey.get_data(), datKey.get_size());
return (ret == 0);
}
@ -254,8 +255,8 @@ protected:
ssValue.write((char*)datValue.get_data(), datValue.get_size());
// Clear and free memory
memset(datKey.get_data(), 0, datKey.get_size());
memset(datValue.get_data(), 0, datValue.get_size());
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;

View file

@ -340,11 +340,11 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
vector<uint256> vHashOut;
if(pwalletMain->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not properly delete the transaction.");
throw JSONRPCError(RPC_WALLET_ERROR, "Could not properly delete the transaction.");
}
if(vHashOut.empty()) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction does not exist in wallet.");
throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction does not exist in wallet.");
}
return NullUniValue;

View file

@ -2603,7 +2603,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
CBitcoinAddress address(options["changeAddress"].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid bitcoin address");
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address");
changeAddress = address.Get();
}
@ -2657,7 +2657,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
string strFailReason;
if(!pwalletMain->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, setSubtractFeeFromOutputs, reserveChangeKey, changeAddress))
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(tx)));
@ -2756,33 +2756,33 @@ UniValue bumpfee(const JSONRPCRequest& request)
CWalletTx& wtx = pwalletMain->mapWallet[hash];
if (pwalletMain->HasWalletSpend(hash)) {
throw JSONRPCError(RPC_MISC_ERROR, "Transaction has descendants in the wallet");
throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction has descendants in the wallet");
}
{
LOCK(mempool.cs);
auto it = mempool.mapTx.find(hash);
if (it != mempool.mapTx.end() && it->GetCountWithDescendants() > 1) {
throw JSONRPCError(RPC_MISC_ERROR, "Transaction has descendants in the mempool");
throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction has descendants in the mempool");
}
}
if (wtx.GetDepthInMainChain() != 0) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction has been mined, or is conflicted with a mined transaction");
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction has been mined, or is conflicted with a mined transaction");
}
if (!SignalsOptInRBF(wtx)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction is not BIP 125 replaceable");
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction is not BIP 125 replaceable");
}
if (wtx.mapValue.count("replaced_by_txid")) {
throw JSONRPCError(RPC_INVALID_REQUEST, strprintf("Cannot bump transaction %s which was already bumped by transaction %s", hash.ToString(), wtx.mapValue.at("replaced_by_txid")));
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Cannot bump transaction %s which was already bumped by transaction %s", hash.ToString(), wtx.mapValue.at("replaced_by_txid")));
}
// check that original tx consists entirely of our inputs
// if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
if (!pwalletMain->IsAllFromMe(wtx, ISMINE_SPENDABLE)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction contains inputs that don't belong to this wallet");
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction contains inputs that don't belong to this wallet");
}
// figure out which output was change
@ -2791,13 +2791,13 @@ UniValue bumpfee(const JSONRPCRequest& request)
for (size_t i = 0; i < wtx.tx->vout.size(); ++i) {
if (pwalletMain->IsChange(wtx.tx->vout[i])) {
if (nOutput != -1) {
throw JSONRPCError(RPC_MISC_ERROR, "Transaction has multiple change outputs");
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction has multiple change outputs");
}
nOutput = i;
}
}
if (nOutput == -1) {
throw JSONRPCError(RPC_MISC_ERROR, "Transaction does not have a change output");
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction does not have a change output");
}
// Calculate the expected size of the new transaction.
@ -2888,7 +2888,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
// Check that in all cases the new fee doesn't violate maxTxFee
if (nNewFee > maxTxFee) {
throw JSONRPCError(RPC_MISC_ERROR,
throw JSONRPCError(RPC_WALLET_ERROR,
strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)",
FormatMoney(nNewFee), FormatMoney(maxTxFee)));
}
@ -2900,7 +2900,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
// moment earlier. In this case, we report an error to the user, who may use totalFee to make an adjustment.
CFeeRate minMempoolFeeRate = mempool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
throw JSONRPCError(RPC_MISC_ERROR, strprintf("New fee rate (%s) is less than the minimum fee rate (%s) to get into the mempool. totalFee value should to be at least %s or settxfee value should be at least %s to add transaction.", FormatMoney(nNewFeeRate.GetFeePerK()), FormatMoney(minMempoolFeeRate.GetFeePerK()), FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)), FormatMoney(minMempoolFeeRate.GetFeePerK())));
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("New fee rate (%s) is less than the minimum fee rate (%s) to get into the mempool. totalFee value should to be at least %s or settxfee value should be at least %s to add transaction.", FormatMoney(nNewFeeRate.GetFeePerK()), FormatMoney(minMempoolFeeRate.GetFeePerK()), FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)), FormatMoney(minMempoolFeeRate.GetFeePerK())));
}
// Now modify the output to increase the fee.
@ -2910,7 +2910,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
CMutableTransaction tx(*(wtx.tx));
CTxOut* poutput = &(tx.vout[nOutput]);
if (poutput->nValue < nDelta) {
throw JSONRPCError(RPC_MISC_ERROR, "Change output is too small to bump the fee");
throw JSONRPCError(RPC_WALLET_ERROR, "Change output is too small to bump the fee");
}
// If the output would become dust, discard it (converting the dust to fee)

View file

@ -1572,6 +1572,10 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
{
if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0)
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((GuessVerificationProgress(chainParams.TxData(), pindex) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
if (GetTime() >= nNow + 60) {
nNow = GetTime();
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex));
}
CBlock block;
if (ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
@ -1585,10 +1589,6 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
ret = nullptr;
}
pindex = chainActive.Next(pindex);
if (GetTime() >= nNow + 60) {
nNow = GetTime();
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex));
}
}
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
}