aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.tx/config2
-rw-r--r--configure.ac2
-rw-r--r--doc/README_osx.txt4
-rw-r--r--doc/bips.md2
-rw-r--r--doc/build-osx.md2
-rw-r--r--doc/build-unix.md6
-rw-r--r--doc/developer-notes.md6
-rw-r--r--doc/dnsseed-policy.md13
-rw-r--r--doc/gitian-building.md10
-rw-r--r--doc/init.md2
-rw-r--r--doc/release-process.md2
-rw-r--r--doc/translation_process.md4
-rw-r--r--qa/rpc-tests/README.md2
-rwxr-xr-xqa/rpc-tests/comptool.py85
-rwxr-xr-xqa/rpc-tests/maxblocksinflight.py9
-rwxr-xr-xqa/rpc-tests/mininode.py67
-rw-r--r--qa/rpc-tests/util.py2
-rwxr-xr-xqa/rpc-tests/wallet.py2
-rw-r--r--src/addrman.h8
-rw-r--r--src/base58.h6
-rw-r--r--src/bloom.cpp83
-rw-r--r--src/bloom.h36
-rw-r--r--src/chain.h2
-rw-r--r--src/chainparams.cpp9
-rw-r--r--src/chainparams.h6
-rw-r--r--src/chainparamsbase.h4
-rw-r--r--src/checkpoints.cpp7
-rw-r--r--src/checkpoints.h2
-rw-r--r--src/checkqueue.h6
-rw-r--r--src/init.cpp4
-rw-r--r--src/main.cpp55
-rw-r--r--src/main.h2
-rw-r--r--src/merkleblock.cpp4
-rw-r--r--src/merkleblock.h2
-rw-r--r--src/mruset.h36
-rw-r--r--src/net.cpp6
-rw-r--r--src/net.h10
-rw-r--r--src/qt/askpassphrasedialog.cpp2
-rw-r--r--src/qt/bitcoinstrings.cpp6
-rw-r--r--src/qt/coincontroldialog.cpp20
-rw-r--r--src/qt/locale/bitcoin_en.ts108
-rw-r--r--src/qt/optionsdialog.cpp2
-rw-r--r--src/qt/sendcoinsdialog.cpp4
-rw-r--r--src/qt/sendcoinsentry.cpp2
-rw-r--r--src/rpcserver.cpp4
-rw-r--r--src/test/bloom_tests.cpp78
-rw-r--r--src/test/mruset_tests.cpp126
-rw-r--r--src/wallet/wallet.cpp10
48 files changed, 516 insertions, 356 deletions
diff --git a/.tx/config b/.tx/config
index 472d27b46f..6c534f06e4 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,7 +1,7 @@
[main]
host = https://www.transifex.com
-[bitcoin.qt-translation-010x]
+[bitcoin.qt-translation-011x]
file_filter = src/qt/locale/bitcoin_<lang>.ts
source_file = src/qt/locale/bitcoin_en.ts
source_lang = en
diff --git a/configure.ac b/configure.ac
index 2c918218bb..7c0a9f4a94 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ define(_CLIENT_VERSION_REVISION, 99)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_IS_RELEASE, false)
define(_COPYRIGHT_YEAR, 2015)
-AC_INIT([Bitcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@bitcoin.org],[bitcoin])
+AC_INIT([Bitcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/bitcoin/bitcoin/issues],[bitcoin])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/doc/README_osx.txt b/doc/README_osx.txt
index 6c0c21c190..e8af46e0e4 100644
--- a/doc/README_osx.txt
+++ b/doc/README_osx.txt
@@ -1,6 +1,6 @@
Deterministic OSX Dmg Notes.
-Working OSX DMG's are created in Linux by combining a recent clang,
+Working OSX DMGs are created in Linux by combining a recent clang,
the Apple's binutils (ld, ar, etc), and DMG authoring tools.
Apple uses clang extensively for development and has upstreamed the necessary
@@ -58,7 +58,7 @@ libdmg-hfsplus project is used to compress it. There are several bugs in this
tool and its maintainer has seemingly abandoned the project. It has been forked
and is available (with fixes) here: https://github.com/theuni/libdmg-hfsplus .
-The 'dmg' tool has the ability to create DMG's from scratch as well, but this
+The 'dmg' tool has the ability to create DMGs from scratch as well, but this
functionality is broken. Only the compression feature is currently used.
Ideally, the creation could be fixed and genisoimage would no longer be necessary.
diff --git a/doc/bips.md b/doc/bips.md
index 579eadfff3..90e98ed419 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -11,7 +11,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.10.0**):
* [`BIP 31`](https://github.com/bitcoin/bips/blob/master/bip-0031.mediawiki): The 'pong' protocol message (and the protocol version bump to 60001) has been implemented since **v0.6.1** ([PR #1081](https://github.com/bitcoin/bitcoin/pull/1081)).
* [`BIP 34`](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki): The rule that requires blocks to contain their height (number) in the coinbase input, and the introduction of version 2 blocks has been implemented since **v0.7.0**. The rule took effect for version 2 blocks as of *block 224413* (March 5th 2013), and version 1 blocks are no longer allowed since *block 227931* (March 25th 2013) ([PR #1526](https://github.com/bitcoin/bitcoin/pull/1526)).
* [`BIP 35`](https://github.com/bitcoin/bips/blob/master/bip-0035.mediawiki): The 'mempool' protocol message (and the protocol version bump to 60002) has been implemented since **v0.7.0** ([PR #1641](https://github.com/bitcoin/bitcoin/pull/1641)).
-* [`BIP 37`](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki): The bloom filtering for transaction relaying, partial merkle trees for blocks , and the protocol version bump to 70001 (enabling low-bandwidth SPV clients) has been implemented since **v0.8.0** ([PR #1795](https://github.com/bitcoin/bitcoin/pull/1795)).
+* [`BIP 37`](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki): The bloom filtering for transaction relaying, partial merkle trees for blocks, and the protocol version bump to 70001 (enabling low-bandwidth SPV clients) has been implemented since **v0.8.0** ([PR #1795](https://github.com/bitcoin/bitcoin/pull/1795)).
* [`BIP 42`](https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki): The bug that would have caused the subsidy schedule to resume after block 13440000 was fixed in **v0.9.2** ([PR #3842](https://github.com/bitcoin/bitcoin/pull/3842)).
* [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)).
* [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)).
diff --git a/doc/build-osx.md b/doc/build-osx.md
index d6e93cb23d..913e72519f 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -1,6 +1,6 @@
Mac OS X Build Instructions and Notes
====================================
-This guide will show you how to build bitcoind(headless client) for OSX.
+This guide will show you how to build bitcoind (headless client) for OSX.
Notes
-----
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 0984f689a8..f70bf7f1fe 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -195,12 +195,12 @@ Hardening enables the following features:
* Position Independent Executable
Build position independent code to take advantage of Address Space Layout Randomization
- offered by some kernels. An attacker who is able to cause execution of code at an arbitrary
- memory location is thwarted if he or she doesn't know where anything useful is located.
+ offered by some kernels. Attackers who can cause execution of code at an arbitrary memory
+ location are thwarted if they don't know where anything useful is located.
The stack and heap are randomly located by default but this allows the code section to be
randomly located as well.
- On an Amd64 processor where a library was not compiled with -fPIC, this will cause an error
+ On an AMD64 processor where a library was not compiled with -fPIC, this will cause an error
such as: "relocation R_X86_64_32 against `......' can not be used when making a shared object;"
To test that you have built PIE executable, install scanelf, part of paxutils, and use:
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index eaeb90da1d..8f7db31d59 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -53,7 +53,7 @@ bool function(int arg1, const char *arg2)
```
A complete list of `@xxx` commands can be found at http://www.stack.nl/~dimitri/doxygen/manual/commands.html.
As Doxygen recognizes the comments by the delimiters (`/**` and `*/` in this case), you don't
-*need* to provide any commands for a comment to be valid, just a description text is fine.
+*need* to provide any commands for a comment to be valid; just a description text is fine.
To describe a class use the same construct above the class definition:
```c++
@@ -175,7 +175,7 @@ Threads
Pull Request Terminology
------------------------
-Concept ACK - Agree with the idea and overall direction, but haven't reviewed the code changes or tested them.
+Concept ACK - Agree with the idea and overall direction, but have neither reviewed nor tested the code changes.
utACK (untested ACK) - Reviewed and agree with the code changes but haven't actually tested them.
@@ -183,4 +183,4 @@ Tested ACK - Reviewed the code changes and have verified the functionality or bu
ACK - A loose ACK can be confusing. It's best to avoid them unless it's a documentation/comment only change in which case there is nothing to test/verify; therefore the tested/untested distinction is not there.
-NACK - Disagree with the code changes/concept. Should be accompanied by an explanation.
+NACK - Disagree with the code changes/concept. Should be accompanied by an explanation.
diff --git a/doc/dnsseed-policy.md b/doc/dnsseed-policy.md
index f15ff44e5d..506e171153 100644
--- a/doc/dnsseed-policy.md
+++ b/doc/dnsseed-policy.md
@@ -10,15 +10,14 @@ Other implementations of Bitcoin software may also use the same
seeds and may be more exposed. In light of this exposure, this
document establishes some basic expectations for operating dnsseeds.
-0. A DNS seed operating organization or person is expected
-to follow good host security practices and maintain control of
-their serving infrastructure and not sell or transfer control of their
-DNS seed. Any hosting services contracted by the operator are
-equally expected to uphold these expectations.
+0. A DNS seed operating organization or person is expected to follow good
+host security practices, maintain control of applicable infrastructure,
+and not sell or transfer control of the DNS seed. Any hosting services
+contracted by the operator are equally expected to uphold these expectations.
1. The DNS seed results must consist exclusively of fairly selected and
functioning Bitcoin nodes from the public network to the best of the
-operators understanding and capability.
+operator's understanding and capability.
2. For the avoidance of doubt, the results may be randomized but must not
single-out any group of hosts to receive different results unless due to an
@@ -28,7 +27,7 @@ urgent technical necessity and disclosed.
4. Any logging of DNS queries should be only that which is necessary
for the operation of the service or urgent health of the Bitcoin
-network and must not be retained longer than necessary or disclosed
+network and must not be retained longer than necessary nor disclosed
to any third party.
5. Information gathered as a result of the operators node-spidering
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index d285fffdbb..1fa5b5f989 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -87,7 +87,7 @@ After creating the VM, we need to configure it.
![](gitian-building/network_settings.png)
-- Click `Advanced`, then `Port Forwarding`. We want to set up a port through where we can reach the VM to get files in and out.
+- Click `Advanced`, then `Port Forwarding`. We want to set up a port through which we can reach the VM to get files in and out.
- Create a new rule by clicking the plus icon.
![](gitian-building/port_forwarding_rules.png)
@@ -111,7 +111,7 @@ Installing Debian
This section will explain how to install Debian on the newly created VM.
-- Choose the non-graphical installer. We do not need the graphical environment, it will only increase installation time and disk usage.
+- Choose the non-graphical installer. We do not need the graphical environment; it will only increase installation time and disk usage.
![](gitian-building/debian_install_1_boot_menu.png)
@@ -144,7 +144,7 @@ and proceed, just press `Enter`. To select a different button, press `Tab`.
![](gitian-building/debian_install_9_user_password.png)
-- The installer will set up the clock using a time server, this process should be automatic
+- The installer will set up the clock using a time server; this process should be automatic
- Set up the clock: choose a time zone (depends on the locale settings that you picked earlier; specifics don't matter)
![](gitian-building/debian_install_10_configure_clock.png)
@@ -371,7 +371,7 @@ COMMIT=2014_03_windows_unicode_path
Signing externally
-------------------
-If you want to do the PGP signing on another device that's also possible; just define `SIGNER` as mentioned
+If you want to do the PGP signing on another device, that's also possible; just define `SIGNER` as mentioned
and follow the steps in the build process as normal.
gpg: skipped "laanwj": secret key not available
@@ -393,4 +393,4 @@ Uploading signatures
After building and signing you can push your signatures (both the `.assert` and `.assert.sig` files) to the
[bitcoin/gitian.sigs](https://github.com/bitcoin/gitian.sigs/) repository, or if that's not possible create a pull
-request. You can also mail the files to me (laanwj@gmail.com) and I'll commit them.
+request. You can also mail the files to Wladimir (laanwj@gmail.com) and he will commit them.
diff --git a/doc/init.md b/doc/init.md
index 871bdc8123..1f206a6c02 100644
--- a/doc/init.md
+++ b/doc/init.md
@@ -63,7 +63,7 @@ can then be controlled by group membership.
4a) systemd
-Installing this .service file consists on just copying it to
+Installing this .service file consists of just copying it to
/usr/lib/systemd/system directory, followed by the command
"systemctl daemon-reload" in order to update running systemd configuration.
diff --git a/doc/release-process.md b/doc/release-process.md
index 5dad9bf5de..cdcee0ec36 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -164,4 +164,4 @@ Note: check that SHA256SUMS itself doesn't end up in SHA256SUMS, which is a spur
- Add release notes for the new version to the directory `doc/release-notes` in git master
-- Celebrate
+- Celebrate
diff --git a/doc/translation_process.md b/doc/translation_process.md
index eed467706e..3653e53021 100644
--- a/doc/translation_process.md
+++ b/doc/translation_process.md
@@ -32,7 +32,7 @@ QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
### Creating a pull-request
For general PRs, you shouldn’t include any updates to the translation source files. They will be updated periodically, primarily around pre-releases, allowing time for any new phrases to be translated before public releases. This is also important in avoiding translation related merge conflicts.
-When an updated source file is merged into the Github repo, Transifex will automatically detect it (although it can take several hours). Once processed, the new strings will show up as "Remaining" in the Transifex web interface and are ready for translators.
+When an updated source file is merged into the Github repo, Transifex will automatically detect it (although it can take several hours). Once processed, the new strings will show up as "Remaining" in the Transifex web interface and are ready for translators.
To create the pull-request, use the following commands:
```
@@ -108,4 +108,4 @@ To create a new language template, you will need to edit the languages manifest
### Questions and general assistance
The Bitcoin-Core translation maintainers include *tcatm, seone, Diapolo, wumpus and luke-jr*.You can find them, and others, in the Freenode IRC chatroom - `irc.freenode.net #bitcoin-dev`.
-If you are a translator, you should also subscribe to the mailing list, https://groups.google.com/forum/#!forum/bitcoin-translators. Announcements will be posted during application pre-releases to notify translators to check for updates. \ No newline at end of file
+If you are a translator, you should also subscribe to the mailing list, https://groups.google.com/forum/#!forum/bitcoin-translators. Announcements will be posted during application pre-releases to notify translators to check for updates.
diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md
index 02170d13ec..d9fbb109e8 100644
--- a/qa/rpc-tests/README.md
+++ b/qa/rpc-tests/README.md
@@ -28,7 +28,7 @@ Notes
A 200-block -regtest blockchain and wallets for four nodes
is created the first time a regression test is run and
is stored in the cache/ directory. Each node has 25 mature
-blocks (25*50=1250 BTC) in their wallet.
+blocks (25*50=1250 BTC) in its wallet.
After the first run, the cache/ blockchain and wallets are
copied into a temporary directory and used as the initial
diff --git a/qa/rpc-tests/comptool.py b/qa/rpc-tests/comptool.py
index 6125bae51e..23a979250c 100755
--- a/qa/rpc-tests/comptool.py
+++ b/qa/rpc-tests/comptool.py
@@ -25,6 +25,8 @@ generator that returns TestInstance objects. See below for definition.
# on_getheaders: provide headers via BlockStore
# on_getdata: provide blocks via BlockStore
+global mininode_lock
+
class TestNode(NodeConnCB):
def __init__(self, block_store, tx_store):
@@ -148,10 +150,11 @@ class TestManager(object):
max_tries = 10 / sleep_time # Wait at most 10 seconds
while max_tries > 0:
done = True
- for c in self.connections:
- if c.cb.verack_received is False:
- done = False
- break
+ with mininode_lock:
+ for c in self.connections:
+ if c.cb.verack_received is False:
+ done = False
+ break
if done:
break
time.sleep(sleep_time)
@@ -161,10 +164,11 @@ class TestManager(object):
while received_pongs is not True:
time.sleep(0.05)
received_pongs = True
- for c in self.connections:
- if c.cb.received_ping_response(counter) is not True:
- received_pongs = False
- break
+ with mininode_lock:
+ for c in self.connections:
+ if c.cb.received_ping_response(counter) is not True:
+ received_pongs = False
+ break
# sync_blocks: Wait for all connections to request the blockhash given
# then send get_headers to find out the tip of each node, and synchronize
@@ -173,8 +177,9 @@ class TestManager(object):
# Wait for nodes to request block (50ms sleep * 20 tries * num_blocks)
max_tries = 20*num_blocks
while max_tries > 0:
- results = [ blockhash in c.cb.block_request_map and
- c.cb.block_request_map[blockhash] for c in self.connections ]
+ with mininode_lock:
+ results = [ blockhash in c.cb.block_request_map and
+ c.cb.block_request_map[blockhash] for c in self.connections ]
if False not in results:
break
time.sleep(0.05)
@@ -199,8 +204,9 @@ class TestManager(object):
# Wait for nodes to request transaction (50ms sleep * 20 tries * num_events)
max_tries = 20*num_events
while max_tries > 0:
- results = [ txhash in c.cb.tx_request_map and
- c.cb.tx_request_map[txhash] for c in self.connections ]
+ with mininode_lock:
+ results = [ txhash in c.cb.tx_request_map and
+ c.cb.tx_request_map[txhash] for c in self.connections ]
if False not in results:
break
time.sleep(0.05)
@@ -221,19 +227,21 @@ class TestManager(object):
self.ping_counter += 1
# Sort inv responses from each node
- [ c.cb.lastInv.sort() for c in self.connections ]
+ with mininode_lock:
+ [ c.cb.lastInv.sort() for c in self.connections ]
# Verify that the tip of each connection all agree with each other, and
# with the expected outcome (if given)
def check_results(self, blockhash, outcome):
- for c in self.connections:
- if outcome is None:
- if c.cb.bestblockhash != self.connections[0].cb.bestblockhash:
+ with mininode_lock:
+ for c in self.connections:
+ if outcome is None:
+ if c.cb.bestblockhash != self.connections[0].cb.bestblockhash:
+ return False
+ elif ((c.cb.bestblockhash == blockhash) != outcome):
+ # print c.cb.bestblockhash, blockhash, outcome
return False
- elif ((c.cb.bestblockhash == blockhash) != outcome):
- # print c.cb.bestblockhash, blockhash, outcome
- return False
- return True
+ return True
# Either check that the mempools all agree with each other, or that
# txhash's presence in the mempool matches the outcome specified.
@@ -242,16 +250,17 @@ class TestManager(object):
# perhaps it would be useful to add the ability to check explicitly that
# a particular tx's existence in the mempool is the same across all nodes.
def check_mempool(self, txhash, outcome):
- for c in self.connections:
- if outcome is None:
- # Make sure the mempools agree with each other
- if c.cb.lastInv != self.connections[0].cb.lastInv:
- # print c.rpc.getrawmempool()
+ with mininode_lock:
+ for c in self.connections:
+ if outcome is None:
+ # Make sure the mempools agree with each other
+ if c.cb.lastInv != self.connections[0].cb.lastInv:
+ # print c.rpc.getrawmempool()
+ return False
+ elif ((txhash in c.cb.lastInv) != outcome):
+ # print c.rpc.getrawmempool(), c.cb.lastInv
return False
- elif ((txhash in c.cb.lastInv) != outcome):
- # print c.rpc.getrawmempool(), c.cb.lastInv
- return False
- return True
+ return True
def run(self):
# Wait until verack is received
@@ -272,9 +281,10 @@ class TestManager(object):
block = b_or_t
block_outcome = outcome
# Add to shared block_store, set as current block
- self.block_store.add_block(block)
- for c in self.connections:
- c.cb.block_request_map[block.sha256] = False
+ with mininode_lock:
+ self.block_store.add_block(block)
+ for c in self.connections:
+ c.cb.block_request_map[block.sha256] = False
# Either send inv's to each node and sync, or add
# to invqueue for later inv'ing.
if (test_instance.sync_every_block):
@@ -288,10 +298,11 @@ class TestManager(object):
assert(isinstance(b_or_t, CTransaction))
tx = b_or_t
tx_outcome = outcome
- # Add to shared tx store
- self.tx_store.add_transaction(tx)
- for c in self.connections:
- c.cb.tx_request_map[tx.sha256] = False
+ # Add to shared tx store and clear map entry
+ with mininode_lock:
+ self.tx_store.add_transaction(tx)
+ for c in self.connections:
+ c.cb.tx_request_map[tx.sha256] = False
# Again, either inv to all nodes or save for later
if (test_instance.sync_every_tx):
[ c.cb.send_inv(tx) for c in self.connections ]
@@ -302,7 +313,7 @@ class TestManager(object):
invqueue.append(CInv(1, tx.sha256))
# Ensure we're not overflowing the inv queue
if len(invqueue) == MAX_INV_SZ:
- [ c.sb.send_message(msg_inv(invqueue)) for c in self.connections ]
+ [ c.send_message(msg_inv(invqueue)) for c in self.connections ]
invqueue = []
# Do final sync if we weren't syncing on every block or every tx.
diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py
index 94535822d8..87c80cd97e 100755
--- a/qa/rpc-tests/maxblocksinflight.py
+++ b/qa/rpc-tests/maxblocksinflight.py
@@ -61,10 +61,11 @@ class TestManager(NodeConnCB):
time.sleep(2)
total_requests = 0
- for key in self.blockReqCounts:
- total_requests += self.blockReqCounts[key]
- if self.blockReqCounts[key] > 1:
- raise AssertionError("Error, test failed: block %064x requested more than once" % key)
+ with mininode_lock:
+ for key in self.blockReqCounts:
+ total_requests += self.blockReqCounts[key]
+ if self.blockReqCounts[key] > 1:
+ raise AssertionError("Error, test failed: block %064x requested more than once" % key)
if total_requests > MAX_REQUESTS:
raise AssertionError("Error, too many blocks (%d) requested" % total_requests)
print "Round %d: success (total requests: %d)" % (count, total_requests)
diff --git a/qa/rpc-tests/mininode.py b/qa/rpc-tests/mininode.py
index c5c1bcfbbe..b7d78e74fa 100755
--- a/qa/rpc-tests/mininode.py
+++ b/qa/rpc-tests/mininode.py
@@ -26,7 +26,7 @@ import sys
import random
import cStringIO
import hashlib
-from threading import Lock
+from threading import RLock
from threading import Thread
import logging
import copy
@@ -37,6 +37,19 @@ MY_SUBVERSION = "/python-mininode-tester:0.0.1/"
MAX_INV_SZ = 50000
+# Keep our own socket map for asyncore, so that we can track disconnects
+# ourselves (to workaround an issue with closing an asyncore socket when
+# using select)
+mininode_socket_map = dict()
+
+# One lock for synchronizing all data access between the networking thread (see
+# NetworkThread below) and the thread running the test logic. For simplicity,
+# NodeConn acquires this lock whenever delivering a message to to a NodeConnCB,
+# and whenever adding anything to the send buffer (in send_message()). This
+# lock should be acquired in the thread running the test logic to synchronize
+# access to any data shared with the NodeConnCB or NodeConn.
+mininode_lock = RLock()
+
# Serialization/deserialization tools
def sha256(s):
return hashlib.new('sha256', s).digest()
@@ -975,10 +988,6 @@ class msg_reject(object):
# Reimplement the on_* functions to provide handling for events
class NodeConnCB(object):
def __init__(self):
- # Acquire on all callbacks -- overkill for now since asyncore is
- # single-threaded, but may be useful for synchronizing access to
- # member variables in derived classes.
- self.cbLock = Lock()
self.verack_received = False
# Derived classes should call this function once to set the message map
@@ -1004,7 +1013,7 @@ class NodeConnCB(object):
}
def deliver(self, conn, message):
- with self.cbLock:
+ with mininode_lock:
try:
self.cbmap[message.command](conn, message)
except:
@@ -1076,7 +1085,7 @@ class NodeConn(asyncore.dispatcher):
}
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest"):
- asyncore.dispatcher.__init__(self)
+ asyncore.dispatcher.__init__(self, map=mininode_socket_map)
self.log = logging.getLogger("NodeConn(%s:%d)" % (dstaddr, dstport))
self.dstaddr = dstaddr
self.dstport = dstport
@@ -1089,7 +1098,6 @@ class NodeConn(asyncore.dispatcher):
self.state = "connecting"
self.network = net
self.cb = callback
- self.sendbufLock = Lock() # for protecting the sendbuffer
self.disconnect = False
# stuff version msg into sendbuf
@@ -1140,24 +1148,18 @@ class NodeConn(asyncore.dispatcher):
return True
def writable(self):
- if self.disconnect:
- self.handle_close()
- return False
- else:
- self.sendbufLock.acquire()
+ with mininode_lock:
length = len(self.sendbuf)
- self.sendbufLock.release()
- return (length > 0)
+ return (length > 0)
def handle_write(self):
- self.sendbufLock.acquire()
- try:
- sent = self.send(self.sendbuf)
- except:
- self.handle_close()
- return
- self.sendbuf = self.sendbuf[sent:]
- self.sendbufLock.release()
+ with mininode_lock:
+ try:
+ sent = self.send(self.sendbuf)
+ except:
+ self.handle_close()
+ return
+ self.sendbuf = self.sendbuf[sent:]
def got_data(self):
while True:
@@ -1201,7 +1203,6 @@ class NodeConn(asyncore.dispatcher):
def send_message(self, message, pushbuf=False):
if self.state != "connected" and not pushbuf:
return
- self.sendbufLock.acquire()
self.show_debug_msg("Send %s" % repr(message))
command = message.command
data = message.serialize()
@@ -1214,9 +1215,9 @@ class NodeConn(asyncore.dispatcher):
h = sha256(th)
tmsg += h[:4]
tmsg += data
- self.sendbuf += tmsg
- self.last_sent = time.time()
- self.sendbufLock.release()
+ with mininode_lock:
+ self.sendbuf += tmsg
+ self.last_sent = time.time()
def got_message(self, message):
if message.command == "version":
@@ -1229,12 +1230,20 @@ class NodeConn(asyncore.dispatcher):
def disconnect_node(self):
self.disconnect = True
- self.send_message(self.messagemap['ping']())
class NetworkThread(Thread):
def run(self):
- asyncore.loop(0.1, True)
+ while mininode_socket_map:
+ # We check for whether to disconnect outside of the asyncore
+ # loop to workaround the behavior of asyncore when using
+ # select
+ disconnected = []
+ for fd, obj in mininode_socket_map.items():
+ if obj.disconnect:
+ disconnected.append(obj)
+ [ obj.handle_close() for obj in disconnected ]
+ asyncore.loop(0.1, use_poll=True, map=mininode_socket_map, count=1)
# An exception we can raise if we detect a potential disconnect
diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py
index 1cf96b314a..3b4a10e46b 100644
--- a/qa/rpc-tests/util.py
+++ b/qa/rpc-tests/util.py
@@ -283,7 +283,7 @@ def send_zeropri_transaction(from_node, to_node, amount, fee):
Create&broadcast a zero-priority transaction.
Returns (txid, hex-encoded-txdata)
Ensures transaction is zero-priority by first creating a send-to-self,
- then using it's output
+ then using its output
"""
# Create a send-to-self with confirmed inputs:
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index 08032fc538..b8965b3662 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -62,7 +62,7 @@ class WalletTest (BitcoinTestFramework):
walletinfo = self.nodes[0].getwalletinfo()
assert_equal(walletinfo['immature_balance'], 0)
- # Have node0 mine a block, thus they will collect their own fee.
+ # Have node0 mine a block, thus it will collect its own fee.
self.nodes[0].generate(1)
self.sync_all()
diff --git a/src/addrman.h b/src/addrman.h
index 5badd4ef95..b72dda49d1 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -17,8 +17,8 @@
#include <stdint.h>
#include <vector>
-/**
- * Extended statistics about a CAddress
+/**
+ * Extended statistics about a CAddress
*/
class CAddrInfo : public CAddress
{
@@ -105,14 +105,14 @@ public:
/** Stochastic address manager
*
* Design goals:
- * * Keep the address tables in-memory, and asynchronously dump the entire to able in peers.dat.
+ * * Keep the address tables in-memory, and asynchronously dump the entire table to peers.dat.
* * Make sure no (localized) attacker can fill the entire table with his nodes/addresses.
*
* To that end:
* * Addresses are organized into buckets.
* * Address that have not yet been tried go into 1024 "new" buckets.
* * Based on the address range (/16 for IPv4) of source of the information, 64 buckets are selected at random
- * * The actual bucket is chosen from one of these, based on the range the address itself is located.
+ * * The actual bucket is chosen from one of these, based on the range in which the address itself is located.
* * One single address can occur in up to 8 different buckets, to increase selection chances for addresses that
* are seen frequently. The chance for increasing this multiplicity decreases exponentially.
* * When adding a new address to a full bucket, a randomly chosen entry (with a bias favoring less recently seen
diff --git a/src/base58.h b/src/base58.h
index 8de90046a9..787979c827 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -6,10 +6,10 @@
/**
* Why base-58 instead of standard base-64 encoding?
* - Don't want 0OIl characters that look the same in some fonts and
- * could be used to create visually identical looking account numbers.
- * - A string with non-alphanumeric characters is not as easily accepted as an account number.
+ * could be used to create visually identical looking data.
+ * - A string with non-alphanumeric characters is not as easily accepted as input.
* - E-mail usually won't line-break if there's no punctuation to break at.
- * - Double-clicking selects the whole number as one word if it's all alphanumeric.
+ * - Double-clicking selects the whole string as one word if it's all alphanumeric.
*/
#ifndef BITCOIN_BASE58_H
#define BITCOIN_BASE58_H
diff --git a/src/bloom.cpp b/src/bloom.cpp
index e60576f4b4..36cba491c4 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -21,22 +21,33 @@
using namespace std;
CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweakIn, unsigned char nFlagsIn) :
-/**
- * The ideal size for a bloom filter with a given number of elements and false positive rate is:
- * - nElements * log(fp rate) / ln(2)^2
- * We ignore filter parameters which will create a bloom filter larger than the protocol limits
- */
-vData(min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8),
-/**
- * The ideal number of hash functions is filter size * ln(2) / number of elements
- * Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
- * See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
- */
-isFull(false),
-isEmpty(false),
-nHashFuncs(min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)),
-nTweak(nTweakIn),
-nFlags(nFlagsIn)
+ /**
+ * The ideal size for a bloom filter with a given number of elements and false positive rate is:
+ * - nElements * log(fp rate) / ln(2)^2
+ * We ignore filter parameters which will create a bloom filter larger than the protocol limits
+ */
+ vData(min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8),
+ /**
+ * The ideal number of hash functions is filter size * ln(2) / number of elements
+ * Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
+ * See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
+ */
+ isFull(false),
+ isEmpty(false),
+ nHashFuncs(min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)),
+ nTweak(nTweakIn),
+ nFlags(nFlagsIn)
+{
+}
+
+// Private constructor used by CRollingBloomFilter
+CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, 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)
{
}
@@ -197,3 +208,43 @@ void CBloomFilter::UpdateEmptyFull()
isFull = full;
isEmpty = empty;
}
+
+CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements, double fpRate, unsigned int nTweak) :
+ b1(nElements * 2, fpRate, nTweak), b2(nElements * 2, fpRate, nTweak)
+{
+ // Implemented using two bloom filters of 2 * nElements each.
+ // We fill them up, and clear them, staggered, every nElements
+ // inserted, so at least one always contains the last nElements
+ // inserted.
+ nBloomSize = nElements * 2;
+ nInsertions = 0;
+}
+
+void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
+{
+ if (nInsertions == 0) {
+ b1.clear();
+ } else if (nInsertions == nBloomSize / 2) {
+ b2.clear();
+ }
+ b1.insert(vKey);
+ b2.insert(vKey);
+ if (++nInsertions == nBloomSize) {
+ nInsertions = 0;
+ }
+}
+
+bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
+{
+ if (nInsertions < nBloomSize / 2) {
+ return b2.contains(vKey);
+ }
+ return b1.contains(vKey);
+}
+
+void CRollingBloomFilter::clear()
+{
+ b1.clear();
+ b2.clear();
+ nInsertions = 0;
+}
diff --git a/src/bloom.h b/src/bloom.h
index 191ffa19b3..bb17f59c86 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -32,14 +32,14 @@ enum bloomflags
/**
* BloomFilter is a probabilistic filter which SPV clients provide
- * so that we can filter the transactions we sends them.
+ * so that we can filter the transactions we send them.
*
* This allows for significantly more efficient transaction and block downloads.
*
- * Because bloom filters are probabilistic, an SPV node can increase the false-
- * positive rate, making us send them transactions which aren't actually theirs,
+ * Because bloom filters are probabilistic, a SPV node can increase the false-
+ * positive rate, making us send it transactions which aren't actually its,
* allowing clients to trade more bandwidth for more privacy by obfuscating which
- * keys are owned by them.
+ * keys are controlled by them.
*/
class CBloomFilter
{
@@ -53,6 +53,10 @@ private:
unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const;
+ // Private constructor for CRollingBloomFilter, no restrictions on size
+ CBloomFilter(unsigned int nElements, double nFPRate, 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
@@ -97,4 +101,28 @@ public:
void UpdateEmptyFull();
};
+/**
+ * RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
+ * Construct it with the number of items to keep track of, and a false-positive rate.
+ *
+ * contains(item) will always return true if item was one of the last N things
+ * insert()'ed ... but may also return true for items that were not inserted.
+ */
+class CRollingBloomFilter
+{
+public:
+ CRollingBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak);
+
+ void insert(const std::vector<unsigned char>& vKey);
+ bool contains(const std::vector<unsigned char>& vKey) const;
+
+ void clear();
+
+private:
+ unsigned int nBloomSize;
+ unsigned int nInsertions;
+ CBloomFilter b1, b2;
+};
+
+
#endif // BITCOIN_BLOOM_H
diff --git a/src/chain.h b/src/chain.h
index 02f53cd2f2..01be2d6e5c 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -74,7 +74,7 @@ enum BlockStatus {
*/
BLOCK_VALID_TRANSACTIONS = 3,
- //! Outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends, BIP30.
+ //! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30.
//! Implies all parents are also at least CHAIN.
BLOCK_VALID_CHAIN = 4,
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index a3434bd6e8..1e044ad491 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -87,7 +87,7 @@ public:
/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
- * a large 4-byte int at any alignment.
+ * a large 32-bit integer with any alignment.
*/
pchMessageStart[0] = 0xf9;
pchMessageStart[1] = 0xbe;
@@ -99,9 +99,10 @@ public:
nPruneAfterHeight = 100000;
/**
- * Build the genesis block. Note that the output of the genesis coinbase cannot
- * be spent as it did not originally exist in the database.
- *
+ * Build the genesis block. Note that the output of its generation
+ * transaction cannot be spent since it did not originally exist in the
+ * database.
+ *
* CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
* CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
* CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
diff --git a/src/chainparams.h b/src/chainparams.h
index bf76eb110a..bfefe242b7 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -62,7 +62,7 @@ public:
bool MiningRequiresPeers() const { return fMiningRequiresPeers; }
/** Default value for -checkmempool and -checkblockindex argument */
bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; }
- /** Make standard checks */
+ /** Policy: Filter transactions that do not match well-defined patterns */
bool RequireStandard() const { return fRequireStandard; }
int64_t PruneAfterHeight() const { return nPruneAfterHeight; }
/** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */
@@ -99,8 +99,8 @@ protected:
};
/**
- * Return the currently selected parameters. This won't change after app startup
- * outside of the unit tests.
+ * Return the currently selected parameters. This won't change after app
+ * startup, except for unit tests.
*/
const CChainParams &Params();
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 421a3a06ff..4369d0aef7 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -34,8 +34,8 @@ protected:
};
/**
- * Return the currently selected parameters. This won't change after app startup
- * outside of the unit tests.
+ * Return the currently selected parameters. This won't change after app
+ * startup, except for unit tests.
*/
const CBaseChainParams& BaseParams();
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 71579bb309..e3d42c2957 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -15,9 +15,10 @@
namespace Checkpoints {
/**
- * How many times we expect transactions after the last checkpoint to
- * be slower. This number is a compromise, as it can't be accurate for
- * every system. When reindexing from a fast disk with a slow CPU, it
+ * How many times slower we expect checking transactions after the last
+ * checkpoint to be (from checking signatures, which is skipped up to the
+ * last checkpoint). This number is a compromise, as it can't be accurate
+ * for every system. When reindexing from a fast disk with a slow CPU, it
* can be up to 20, while when downloading from a slow network with a
* fast multicore CPU, it won't be much higher than 1.
*/
diff --git a/src/checkpoints.h b/src/checkpoints.h
index 29dc5f83a9..b0e5076788 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -11,7 +11,7 @@
class CBlockIndex;
-/**
+/**
* Block-chain checkpoints are compiled-in sanity checks.
* They are updated every release or three.
*/
diff --git a/src/checkqueue.h b/src/checkqueue.h
index 6f6b97e3a7..20ba25bb41 100644
--- a/src/checkqueue.h
+++ b/src/checkqueue.h
@@ -54,7 +54,7 @@ private:
/**
* Number of verifications that haven't completed yet.
- * This includes elements that are not anymore in queue, but still in
+ * This includes elements that are no longer queued, but still in the
* worker's own batches.
*/
unsigned int nTodo;
@@ -81,7 +81,7 @@ private:
fAllOk &= fOk;
nTodo -= nNow;
if (nTodo == 0 && !fMaster)
- // We processed the last element; inform the master he or she can exit and return the result
+ // We processed the last element; inform the master it can exit and return the result
condMaster.notify_one();
} else {
// first iteration
@@ -136,7 +136,7 @@ public:
Loop();
}
- //! Wait until execution finishes, and return whether all evaluations where successful.
+ //! Wait until execution finishes, and return whether all evaluations were successful.
bool Wait()
{
return Loop(true);
diff --git a/src/init.cpp b/src/init.cpp
index 5272541722..f4caa4717f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -52,7 +52,7 @@ bool fFeeEstimatesInitialized = false;
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
-// accessing block files, don't count towards to fd_set size limit
+// accessing block files don't count towards the fd_set size limit
// anyway.
#define MIN_CORE_FILEDESCRIPTORS 0
#else
@@ -334,7 +334,7 @@ strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current
strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0));
strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1));
strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), 1));
- strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)"),
+ strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"),
FormatMoney(maxTxFee)));
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup"));
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat"));
diff --git a/src/main.cpp b/src/main.cpp
index e6248c6617..7d7e670119 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -142,8 +142,9 @@ namespace {
uint32_t nBlockSequenceId = 1;
/**
- * Sources of received blocks, to be able to send them reject messages or ban
- * them, if processing happens afterwards. Protected by cs_main.
+ * Sources of received blocks, saved to be able to send them reject
+ * messages or ban them when processing happens afterwards. Protected by
+ * cs_main.
*/
map<uint256, NodeId> mapBlockSource;
@@ -389,7 +390,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBl
}
// If the peer reorganized, our previous pindexLastCommonBlock may not be an ancestor
- // of their current tip anymore. Go back enough to fix that.
+ // of its current tip anymore. Go back enough to fix that.
state->pindexLastCommonBlock = LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
return;
@@ -941,7 +942,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
- // only helps filling in pfMissingInputs (to determine missing vs spent).
+ // and only helps with filling in pfMissingInputs (to determine missing vs spent).
BOOST_FOREACH(const CTxIn txin, tx.vin) {
if (!view.HaveCoins(txin.prevout.hash)) {
if (pfMissingInputs)
@@ -1277,8 +1278,8 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
pfork = pfork->pprev;
}
- // We define a condition which we should warn the user about as a fork of at least 7 blocks
- // who's tip is within 72 blocks (+/- 12 hours if no one mines it) of ours
+ // We define a condition where we should warn the user about as a fork of at least 7 blocks
+ // with a tip within 72 blocks (+/- 12 hours if no one mines it) of ours
// We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network
// hash rate operating on the fork.
// or a chain that is entirely longer than ours and invalid (note that this should be detected by both)
@@ -1719,9 +1720,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information.
// This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
// already refuses previously-known transaction ids entirely.
- // This rule was originally applied all blocks whose timestamp was after March 15, 2012, 0:00 UTC.
+ // This rule was originally applied to all blocks with a timestamp after March 15, 2012, 0:00 UTC.
// Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the
- // two in the chain that violate it. This prevents exploiting the issue against nodes in their
+ // two in the chain that violate it. This prevents exploiting the issue against nodes during their
// initial block download.
bool fEnforceBIP30 = (!pindex->phashBlock) || // Enforce on CreateNewBlock invocations which don't have a hash.
!((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256S("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
@@ -1984,7 +1985,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
if (nUpgraded > 100/2)
{
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
- strMiscWarning = _("Warning: This version is obsolete, upgrade required!");
+ strMiscWarning = _("Warning: This version is obsolete; upgrade required!");
CAlert::Notify(strMiscWarning, true);
fWarned = true;
}
@@ -2315,7 +2316,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
}
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
- // add them again.
+ // 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())) {
@@ -3733,7 +3734,7 @@ void static ProcessGetData(CNode* pfrom)
pfrom->PushMessage("merkleblock", merkleBlock);
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
// This avoids hurting performance by pointlessly requiring a round-trip
- // Note that there is currently no way for a node to request any single transactions we didnt send here -
+ // Note that there is currently no way for a node to request any single transactions we didn't send here -
// they must either disconnect and retry or request the full block.
// Thus, the protocol spec specified allows for us to provide duplicate txn here,
// however we MUST always provide at least what the remote peer needs
@@ -3746,7 +3747,7 @@ void static ProcessGetData(CNode* pfrom)
// no response
}
- // Trigger them to send a getblocks request for the next batch of inventory
+ // Trigger the peer node to send a getblocks request for the next batch of inventory
if (inv.hash == pfrom->hashContinue)
{
// Bypass PushInventory, this must send even if redundant,
@@ -3995,7 +3996,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{
LOCK(cs_vNodes);
// Use deterministic randomness to send to the same nodes for 24 hours
- // at a time so the setAddrKnowns of the chosen nodes prevent repeats
+ // at a time so the addrKnowns of the chosen nodes prevent repeats
static uint256 hashSalt;
if (hashSalt.IsNull())
hashSalt = GetRandHash();
@@ -4060,7 +4061,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (inv.type == MSG_BLOCK) {
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
- // First request the headers preceeding the announced block. In the normal fully-synced
+ // First request the headers preceding the announced block. In the normal fully-synced
// case where a new block is announced that succeeds the current tip (no reorganization),
// there are no such headers.
// Secondly, and only when we are close to being synced, we request the announced block directly,
@@ -4142,8 +4143,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
if (--nLimit <= 0)
{
- // When this block is requested, we'll send an inv that'll make them
- // getblocks the next batch of inventory.
+ // When this block is requested, we'll send an inv that'll
+ // trigger the peer to getblocks the next batch of inventory.
LogPrint("net", " getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
pfrom->hashContinue = pindex->GetBlockHash();
break;
@@ -4380,9 +4381,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// 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.
- // Making users (which are behind NAT and can only make outgoing connections) ignore
- // getaddr message mitigates the attack.
+ // to users' AddrMan and later request them by sending getaddr messages.
+ // Making nodes which are behind NAT and can only make outgoing connections ignore
+ // the getaddr message mitigates the attack.
else if ((strCommand == "getaddr") && (pfrom->fInbound))
{
pfrom->vAddrToSend.clear();
@@ -4467,7 +4468,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Nonce mismatches are normal when pings are overlapping
sProblem = "Nonce mismatch";
if (nonce == 0) {
- // This is most likely a bug in another implementation somewhere, cancel this ping
+ // This is most likely a bug in another implementation somewhere; cancel this ping
bPingFinished = true;
sProblem = "Nonce zero";
}
@@ -4476,7 +4477,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
sProblem = "Unsolicited pong without ping";
}
} else {
- // This is most likely a bug in another implementation somewhere, cancel this ping
+ // This is most likely a bug in another implementation somewhere; cancel this ping
bPingFinished = true;
sProblem = "Short payload";
}
@@ -4735,7 +4736,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
{
const Consensus::Params& consensusParams = Params().GetConsensus();
{
- // Don't send anything until we get their version message
+ // Don't send anything until we get its version message
if (pto->nVersion == 0)
return true;
@@ -4779,9 +4780,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
- // Periodically clear setAddrKnown to allow refresh broadcasts
+ // Periodically clear addrKnown to allow refresh broadcasts
if (nLastRebroadcast)
- pnode->setAddrKnown.clear();
+ pnode->addrKnown.clear();
// Rebroadcast our address
AdvertizeLocal(pnode);
@@ -4799,9 +4800,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
vAddr.reserve(pto->vAddrToSend.size());
BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend)
{
- // returns true if wasn't already contained in the set
- if (pto->setAddrKnown.insert(addr).second)
+ if (!pto->addrKnown.contains(addr.GetKey()))
{
+ pto->addrKnown.insert(addr.GetKey());
vAddr.push_back(addr);
// receiver rejects addr messages larger than 1000
if (vAddr.size() >= 1000)
@@ -4919,7 +4920,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval
// (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
// timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
- // being saturated. We only count validated in-flight blocks so peers can't advertize nonexisting block hashes
+ // being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
// to unreasonably increase our timeout.
if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * consensusParams.nPowTargetSpacing * (4 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) {
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", state.vBlocksInFlight.front().hash.ToString(), pto->id);
diff --git a/src/main.h b/src/main.h
index b0aec6662d..38d867675e 100644
--- a/src/main.h
+++ b/src/main.h
@@ -75,7 +75,7 @@ static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
/** Timeout in seconds during which a peer must stall block download progress before being disconnected. */
static const unsigned int BLOCK_STALLING_TIMEOUT = 2;
/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
- * less than this number, we reached their tip. Changing this value is a protocol upgrade. */
+ * less than this number, we reached its tip. Changing this value is a protocol upgrade. */
static const unsigned int MAX_HEADERS_RESULTS = 2000;
/** Size of the "block download window": how far ahead of our current height do we fetch?
* Larger windows tolerate larger download speed differences between peer, but increase the potential
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index dc87d0377a..4d90fd8cd7 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -119,8 +119,8 @@ uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, uns
if (pos*2+1 < CalcTreeWidth(height-1)) {
right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch);
if (right == left) {
- // If the left and right branch should never be identical as the transaction
- // hashes covered by them must be unique.
+ // The left and right branches should never be identical, as the transaction
+ // hashes covered by them must each be unique.
fBad = true;
}
} else {
diff --git a/src/merkleblock.h b/src/merkleblock.h
index d90face17c..904c22abc2 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -104,7 +104,7 @@ public:
}
}
- /** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */
+ /** Construct a partial merkle tree from a list of transaction ids, and a mask that selects a subset of them */
CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
CPartialMerkleTree();
diff --git a/src/mruset.h b/src/mruset.h
index 1969f419cb..398aa173bf 100644
--- a/src/mruset.h
+++ b/src/mruset.h
@@ -1,12 +1,12 @@
-// Copyright (c) 2012 The Bitcoin Core developers
+// Copyright (c) 2012-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.
#ifndef BITCOIN_MRUSET_H
#define BITCOIN_MRUSET_H
-#include <deque>
#include <set>
+#include <vector>
#include <utility>
/** STL-like set container that only keeps the most recent N elements. */
@@ -22,11 +22,13 @@ public:
protected:
std::set<T> set;
- std::deque<T> queue;
- size_type nMaxSize;
+ std::vector<iterator> order;
+ size_type first_used;
+ size_type first_unused;
+ const size_type nMaxSize;
public:
- mruset(size_type nMaxSizeIn = 0) { nMaxSize = nMaxSizeIn; }
+ mruset(size_type nMaxSizeIn = 1) : nMaxSize(nMaxSizeIn) { clear(); }
iterator begin() const { return set.begin(); }
iterator end() const { return set.end(); }
size_type size() const { return set.size(); }
@@ -36,7 +38,9 @@ public:
void clear()
{
set.clear();
- queue.clear();
+ order.assign(nMaxSize, set.end());
+ first_used = 0;
+ first_unused = 0;
}
bool inline friend operator==(const mruset<T>& a, const mruset<T>& b) { return a.set == b.set; }
bool inline friend operator==(const mruset<T>& a, const std::set<T>& b) { return a.set == b; }
@@ -45,25 +49,17 @@ public:
{
std::pair<iterator, bool> ret = set.insert(x);
if (ret.second) {
- if (nMaxSize && queue.size() == nMaxSize) {
- set.erase(queue.front());
- queue.pop_front();
+ if (set.size() == nMaxSize + 1) {
+ set.erase(order[first_used]);
+ order[first_used] = set.end();
+ if (++first_used == nMaxSize) first_used = 0;
}
- queue.push_back(x);
+ order[first_unused] = ret.first;
+ if (++first_unused == nMaxSize) first_unused = 0;
}
return ret;
}
size_type max_size() const { return nMaxSize; }
- size_type max_size(size_type s)
- {
- if (s)
- while (queue.size() > s) {
- set.erase(queue.front());
- queue.pop_front();
- }
- nMaxSize = s;
- return nMaxSize;
- }
};
#endif // BITCOIN_MRUSET_H
diff --git a/src/net.cpp b/src/net.cpp
index 731c810935..2de04fc574 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1905,7 +1905,10 @@ bool CAddrDB::Read(CAddrMan& addr)
unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
-CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000)
+CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) :
+ ssSend(SER_NETWORK, INIT_PROTO_VERSION),
+ addrKnown(5000, 0.001, insecure_rand()),
+ setInventoryKnown(SendBufferSize() / 1000)
{
nServices = 0;
hSocket = hSocketIn;
@@ -1934,7 +1937,6 @@ CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fIn
nStartingHeight = -1;
fGetAddr = false;
fRelayTxes = false;
- setInventoryKnown.max_size(SendBufferSize() / 1000);
pfilter = new CBloomFilter();
nPingNonceSent = 0;
nPingUsecStart = 0;
diff --git a/src/net.h b/src/net.h
index 9fc6ce68d0..7c61a2be6c 100644
--- a/src/net.h
+++ b/src/net.h
@@ -271,8 +271,8 @@ public:
bool fDisconnect;
// 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 their version message that we should not relay tx invs
- // until they have initialized their bloom filter.
+ // b) the peer may tell us in its version message that we should not relay tx invs
+ // until it has initialized its bloom filter.
bool fRelayTxes;
CSemaphoreGrant grantOutbound;
CCriticalSection cs_filter;
@@ -300,7 +300,7 @@ public:
// flood relay
std::vector<CAddress> vAddrToSend;
- mruset<CAddress> setAddrKnown;
+ CRollingBloomFilter addrKnown;
bool fGetAddr;
std::set<uint256> setKnown;
@@ -380,7 +380,7 @@ public:
void AddAddressKnown(const CAddress& addr)
{
- setAddrKnown.insert(addr);
+ addrKnown.insert(addr.GetKey());
}
void PushAddress(const CAddress& addr)
@@ -388,7 +388,7 @@ public:
// Known checking here is only to save space from duplicates.
// SendMessages will filter it again for knowns that were added
// after addresses were pushed.
- if (addr.IsValid() && !setAddrKnown.count(addr)) {
+ if (addr.IsValid() && !addrKnown.contains(addr.GetKey())) {
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr;
} else {
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index 229139e65c..441814ff07 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -62,7 +62,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
break;
case ChangePass: // Ask old passphrase + new passphrase x2
setWindowTitle(tr("Change passphrase"));
- ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet."));
+ ui->warningLabel->setText(tr("Enter the old passphrase and new passphrase to the wallet."));
break;
}
textChanged();
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 7f372debad..aeabfc424d 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -93,8 +93,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Maximum size of data in data carrier transactions we relay and mine "
"(default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Maximum total fees to use in a single wallet transaction, setting too low "
-"may abort large transactions (default: %s)"),
+"Maximum total fees to use in a single wallet transaction; setting this too "
+"low may abort large transactions (default: %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Number of seconds to keep misbehaving peers from reconnecting (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -332,7 +332,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s")
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin Core to complete"),
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete, upgrade required!"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete; upgrade required!"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Unsupported argument -benchmark ignored, use -debug=bench."),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Unsupported argument -debugnet ignored, use -debug=net."),
QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"),
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 0a60632bfa..7531fbddcb 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -129,11 +129,11 @@ CoinControlDialog::CoinControlDialog(QWidget *parent) :
ui->treeWidget->setColumnWidth(COLUMN_DATE, 110);
ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 100);
ui->treeWidget->setColumnWidth(COLUMN_PRIORITY, 100);
- ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transacton hash in this column, but dont show it
- ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true); // store vout index in this column, but dont show it
- ui->treeWidget->setColumnHidden(COLUMN_AMOUNT_INT64, true); // store amount int64 in this column, but dont show it
- ui->treeWidget->setColumnHidden(COLUMN_PRIORITY_INT64, true); // store priority int64 in this column, but dont show it
- ui->treeWidget->setColumnHidden(COLUMN_DATE_INT64, true); // store date int64 in this column, but dont show it
+ ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transacton 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
+ ui->treeWidget->setColumnHidden(COLUMN_AMOUNT_INT64, true); // store amount int64 in this column, but don't show it
+ ui->treeWidget->setColumnHidden(COLUMN_PRIORITY_INT64, true); // store priority int64 in this column, but don't show it
+ ui->treeWidget->setColumnHidden(COLUMN_DATE_INT64, true); // store date int64 in this column, but don't show it
// default view is sorted by amount desc
sortView(COLUMN_AMOUNT_INT64, Qt::DescendingOrder);
@@ -408,8 +408,8 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
}
// todo: this is a temporary qt5 fix: when clicking a parent node in tree mode, the parent node
- // including all childs are partially selected. But the parent node should be fully selected
- // as well as the childs. Childs should never be partially selected in the first place.
+ // including all children are partially selected. But the parent node should be fully selected
+ // as well as the children. Children should never be partially selected in the first place.
// Please remove this ugly fix, once the bug is solved upstream.
#if QT_VERSION >= 0x050000
else if (column == COLUMN_CHECKBOX && item->childCount() > 0)
@@ -635,15 +635,15 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
l7->setStyleSheet((fDust) ? "color:red;" : ""); // Dust = "yes"
// tool tips
- QString toolTip1 = tr("This label turns red, if the transaction size is greater than 1000 bytes.") + "<br /><br />";
+ QString toolTip1 = tr("This label turns red if the transaction size is greater than 1000 bytes.") + "<br /><br />";
toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK())) + "<br /><br />";
toolTip1 += tr("Can vary +/- 1 byte per input.");
QString toolTip2 = tr("Transactions with higher priority are more likely to get included into a block.") + "<br /><br />";
- toolTip2 += tr("This label turns red, if the priority is smaller than \"medium\".") + "<br /><br />";
+ toolTip2 += tr("This label turns red if the priority is smaller than \"medium\".") + "<br /><br />";
toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK()));
- QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, ::minRelayTxFee.GetFee(546)));
+ QString toolTip3 = tr("This label turns red if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, ::minRelayTxFee.GetFee(546)));
// how many satoshis the estimated fee can vary per byte we guess wrong
double dFeeVary;
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 2555cdbb62..ae6f60f6ec 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -195,12 +195,7 @@
<translation>Change passphrase</translation>
</message>
<message>
- <location line="+1"/>
- <source>Enter the old and new passphrase to the wallet.</source>
- <translation>Enter the old and new passphrase to the wallet.</translation>
- </message>
- <message>
- <location line="+45"/>
+ <location line="+46"/>
<source>Confirm wallet encryption</source>
<translation>Confirm wallet encryption</translation>
</message>
@@ -242,7 +237,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+93"/>
+ <location line="+23"/>
+ <source>Enter the old passphrase and new passphrase to the wallet.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+70"/>
<location line="+7"/>
<location line="+42"/>
<location line="+6"/>
@@ -912,7 +912,22 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+177"/>
+ <location line="+161"/>
+ <source>This label turns red if the transaction size is greater than 1000 bytes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>This label turns red if the priority is smaller than &quot;medium&quot;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>This label turns red if any recipient receives an amount smaller than %1.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+8"/>
<source>Can vary +/- %1 satoshi(s) per input.</source>
<translation type="unfinished"></translation>
</message>
@@ -927,12 +942,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+16"/>
- <source>This label turns red, if the transaction size is greater than 1000 bytes.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+17"/>
<location line="+5"/>
<source>This means a fee of at least %1 per kB is required.</source>
<translation type="unfinished"></translation>
@@ -948,17 +958,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
- <source>This label turns red, if the priority is smaller than &quot;medium&quot;.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
- <source>This label turns red, if any recipient receives an amount smaller than %1.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+55"/>
+ <location line="+59"/>
<location line="+61"/>
<source>(no label)</source>
<translation type="unfinished">(no label)</translation>
@@ -1437,7 +1437,7 @@
</message>
<message>
<location line="-29"/>
- <source>Client will be shutdown, do you want to proceed?</source>
+ <source>Client will be shut down. Do you want to proceed?</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -2557,12 +2557,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+193"/>
- <source>The recipient address is not valid, please recheck.</source>
- <translation>The recipient address is not valid, please recheck.</translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+196"/>
<source>The amount to pay must be larger than 0.</source>
<translation>The amount to pay must be larger than 0.</translation>
</message>
@@ -2577,12 +2572,7 @@
<translation>The total exceeds your balance when the %1 transaction fee is included.</translation>
</message>
<message>
- <location line="+3"/>
- <source>Duplicate address found, can only send to each address once per send operation.</source>
- <translation>Duplicate address found, can only send to each address once per send operation.</translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+6"/>
<source>Transaction creation failed!</source>
<translation type="unfinished"></translation>
</message>
@@ -2615,7 +2605,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+129"/>
+ <location line="-114"/>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+231"/>
<source>Warning: Invalid Bitcoin address</source>
<translation type="unfinished"></translation>
</message>
@@ -2978,7 +2978,7 @@
<context>
<name>TransactionDesc</name>
<message>
- <location filename="../transactiondesc.cpp" line="+35"/>
+ <location filename="../transactiondesc.cpp" line="+34"/>
<source>Open until %1</source>
<translation>Open until %1</translation>
</message>
@@ -3659,7 +3659,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+36"/>
+ <location line="+14"/>
+ <source>Maximum total fees to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+22"/>
<source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
<translation type="unfinished"></translation>
</message>
@@ -3879,7 +3884,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+2"/>
+ <source>Warning: This version is obsolete; upgrade required!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<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>
@@ -3964,12 +3974,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+7"/>
+ <location line="+10"/>
<source>Prune configured below the minimum of %d MB. Please use a higher number.</source>
<translation type="unfinished"></translation>
</message>
@@ -4309,12 +4314,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Warning</translation>
</message>
<message>
- <location line="+1"/>
- <source>Warning: This version is obsolete, upgrade required!</source>
- <translation>Warning: This version is obsolete, upgrade required!</translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Warning: Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index a9e4b339e4..efb2bf4158 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -208,7 +208,7 @@ void OptionsDialog::on_resetButton_clicked()
{
// confirmation dialog
QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm options reset"),
- tr("Client restart required to activate changes.") + "<br><br>" + tr("Client will be shutdown, do you want to proceed?"),
+ tr("Client restart required to activate changes.") + "<br><br>" + tr("Client will be shut down. Do you want to proceed?"),
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
if(btnRetVal == QMessageBox::Cancel)
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 0360f160d8..7a33e3567b 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -505,7 +505,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
switch(sendCoinsReturn.status)
{
case WalletModel::InvalidAddress:
- msgParams.first = tr("The recipient address is not valid, please recheck.");
+ msgParams.first = tr("The recipient address is not valid. Please recheck.");
break;
case WalletModel::InvalidAmount:
msgParams.first = tr("The amount to pay must be larger than 0.");
@@ -517,7 +517,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
msgParams.first = tr("The total exceeds your balance when the %1 transaction fee is included.").arg(msgArg);
break;
case WalletModel::DuplicateAddress:
- msgParams.first = tr("Duplicate address found, can only send to each address once per send operation.");
+ msgParams.first = tr("Duplicate address found: addresses should only be used once each.");
break;
case WalletModel::TransactionCreationFailed:
msgParams.first = tr("Transaction creation failed!");
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index ea35ed1d53..6eec33ffd4 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -216,7 +216,7 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
ui->addAsLabel->clear();
ui->payTo->setText(recipient.address); // this may set a label from addressbook
- if (!recipient.label.isEmpty()) // if a label had been set from the addressbook, dont overwrite with an empty label
+ if (!recipient.label.isEmpty()) // if a label had been set from the addressbook, don't overwrite with an empty label
ui->addAsLabel->setText(recipient.label);
ui->payAmount->setValue(recipient.amount);
}
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 61dda9125b..12a5c4aef9 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -912,8 +912,8 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
{
LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", conn->peer_address_to_string());
/* Deter brute-forcing
- If this results in a DoS the user really
- shouldn't have their RPC port exposed. */
+ We don't support exposing the RPC port, so this shouldn't result
+ in a DoS. */
MilliSleep(250);
conn->stream() << HTTPError(HTTP_UNAUTHORIZED, false) << std::flush;
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 73a146f05c..1bda8a7ea1 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -8,6 +8,7 @@
#include "clientversion.h"
#include "key.h"
#include "merkleblock.h"
+#include "random.h"
#include "serialize.h"
#include "streams.h"
#include "uint256.h"
@@ -459,4 +460,81 @@ BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none)
BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"), 0)));
}
+static std::vector<unsigned char> RandomData()
+{
+ uint256 r = GetRandHash();
+ return std::vector<unsigned char>(r.begin(), r.end());
+}
+
+BOOST_AUTO_TEST_CASE(rolling_bloom)
+{
+ // last-100-entry, 1% false positive:
+ CRollingBloomFilter rb1(100, 0.01, 0);
+
+ // Overfill:
+ static const int DATASIZE=399;
+ std::vector<unsigned char> data[DATASIZE];
+ for (int i = 0; i < DATASIZE; i++) {
+ data[i] = RandomData();
+ rb1.insert(data[i]);
+ }
+ // Last 100 guaranteed to be remembered:
+ for (int i = 299; i < DATASIZE; i++) {
+ BOOST_CHECK(rb1.contains(data[i]));
+ }
+
+ // false positive rate is 1%, so we should get about 100 hits if
+ // testing 10,000 random keys. We get worst-case false positive
+ // behavior when the filter is as full as possible, which is
+ // when we've inserted one minus an integer multiple of nElement*2.
+ unsigned int nHits = 0;
+ for (int i = 0; i < 10000; i++) {
+ 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);
+
+ BOOST_CHECK(rb1.contains(data[DATASIZE-1]));
+ rb1.clear();
+ BOOST_CHECK(!rb1.contains(data[DATASIZE-1]));
+
+ // Now roll through data, make sure last 100 entries
+ // are always remembered:
+ for (int i = 0; i < DATASIZE; i++) {
+ if (i >= 100)
+ BOOST_CHECK(rb1.contains(data[i-100]));
+ rb1.insert(data[i]);
+ }
+
+ // Insert 999 more random entries:
+ for (int i = 0; i < 999; i++) {
+ rb1.insert(RandomData());
+ }
+ // Sanity check to make sure the filter isn't just filling up:
+ nHits = 0;
+ for (int i = 0; i < DATASIZE; i++) {
+ 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);
+
+ // last-1000-entry, 0.01% false positive:
+ CRollingBloomFilter rb2(1000, 0.001, 0);
+ for (int i = 0; i < DATASIZE; i++) {
+ rb2.insert(data[i]);
+ }
+ // ... room for all of them:
+ for (int i = 0; i < DATASIZE; i++) {
+ BOOST_CHECK(rb2.contains(data[i]));
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp
index bd4e9c1d38..2b68f8899e 100644
--- a/src/test/mruset_tests.cpp
+++ b/src/test/mruset_tests.cpp
@@ -17,83 +17,65 @@
using namespace std;
-class mrutester
-{
-private:
- mruset<int> mru;
- std::set<int> set;
-
-public:
- mrutester() { mru.max_size(MAX_SIZE); }
- int size() const { return set.size(); }
-
- void insert(int n)
- {
- mru.insert(n);
- set.insert(n);
- BOOST_CHECK(mru == set);
- }
-};
-
BOOST_FIXTURE_TEST_SUITE(mruset_tests, BasicTestingSetup)
-// Test that an mruset behaves like a set, as long as no more than MAX_SIZE elements are in it
-BOOST_AUTO_TEST_CASE(mruset_like_set)
-{
-
- for (int nTest=0; nTest<NUM_TESTS; nTest++)
- {
- mrutester tester;
- while (tester.size() < MAX_SIZE)
- tester.insert(GetRandInt(2 * MAX_SIZE));
- }
-
-}
-
-// Test that an mruset's size never exceeds its max_size
-BOOST_AUTO_TEST_CASE(mruset_limited_size)
+BOOST_AUTO_TEST_CASE(mruset_test)
{
- for (int nTest=0; nTest<NUM_TESTS; nTest++)
- {
- mruset<int> mru(MAX_SIZE);
- for (int nAction=0; nAction<3*MAX_SIZE; nAction++)
- {
- int n = GetRandInt(2 * MAX_SIZE);
- mru.insert(n);
- BOOST_CHECK(mru.size() <= MAX_SIZE);
+ // The mruset being tested.
+ mruset<int> mru(5000);
+
+ // Run the test 10 times.
+ for (int test = 0; test < 10; test++) {
+ // Reset mru.
+ mru.clear();
+
+ // A deque + set to simulate the mruset.
+ std::deque<int> rep;
+ std::set<int> all;
+
+ // Insert 10000 random integers below 15000.
+ for (int j=0; j<10000; j++) {
+ int add = GetRandInt(15000);
+ mru.insert(add);
+
+ // Add the number to rep/all as well.
+ if (all.count(add) == 0) {
+ all.insert(add);
+ rep.push_back(add);
+ if (all.size() == 5001) {
+ all.erase(rep.front());
+ rep.pop_front();
+ }
+ }
+
+ // Do a full comparison between mru and the simulated mru every 1000 and every 5001 elements.
+ if (j % 1000 == 0 || j % 5001 == 0) {
+ mruset<int> mru2 = mru; // Also try making a copy
+
+ // Check that all elements that should be in there, are in there.
+ BOOST_FOREACH(int x, rep) {
+ BOOST_CHECK(mru.count(x));
+ BOOST_CHECK(mru2.count(x));
+ }
+
+ // Check that all elements that are in there, should be in there.
+ BOOST_FOREACH(int x, mru) {
+ BOOST_CHECK(all.count(x));
+ }
+
+ // Check that all elements that are in there, should be in there.
+ BOOST_FOREACH(int x, mru2) {
+ BOOST_CHECK(all.count(x));
+ }
+
+ for (int t = 0; t < 10; t++) {
+ int r = GetRandInt(15000);
+ BOOST_CHECK(all.count(r) == mru.count(r));
+ BOOST_CHECK(all.count(r) == mru2.count(r));
+ }
+ }
}
}
}
-// 16-bit permutation function
-int static permute(int n)
-{
- // hexadecimals of pi; verified to be linearly independent
- static const int table[16] = {0x243F, 0x6A88, 0x85A3, 0x08D3, 0x1319, 0x8A2E, 0x0370, 0x7344,
- 0xA409, 0x3822, 0x299F, 0x31D0, 0x082E, 0xFA98, 0xEC4E, 0x6C89};
-
- int ret = 0;
- for (int bit=0; bit<16; bit++)
- if (n & (1<<bit))
- ret ^= table[bit];
-
- return ret;
-}
-
-// Test that an mruset acts like a moving window, if no duplicate elements are added
-BOOST_AUTO_TEST_CASE(mruset_window)
-{
- mruset<int> mru(MAX_SIZE);
- for (int n=0; n<10*MAX_SIZE; n++)
- {
- mru.insert(permute(n));
-
- set<int> tester;
- for (int m=max(0,n-MAX_SIZE+1); m<=n; m++)
- tester.insert(permute(m));
-
- BOOST_CHECK(mru == tester);
- }
-}
-
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index bb73038b97..cb20998d26 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -35,8 +35,8 @@ bool bSpendZeroConfChange = true;
bool fSendFreeTransactions = false;
bool fPayAtLeastCustomFee = true;
-/**
- * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
+/**
+ * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
* Override with -mintxfee
*/
CFeeRate CWallet::minTxFee = CFeeRate(1000);
@@ -529,7 +529,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
delete pwalletdbEncryption;
}
// We now probably have half of our keys encrypted in memory, and half not...
- // die and let the user reload their unencrypted wallet.
+ // die and let the user reload the unencrypted wallet.
assert(false);
}
@@ -541,7 +541,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (!pwalletdbEncryption->TxnCommit()) {
delete pwalletdbEncryption;
// We now have keys encrypted in memory, but not on disk...
- // die to avoid confusion and let the user reload their unencrypted wallet.
+ // die to avoid confusion and let the user reload the unencrypted wallet.
assert(false);
}
@@ -1097,7 +1097,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
void CWallet::ReacceptWalletTransactions()
{
- // If transcations aren't broadcasted, don't let them into local mempool either
+ // If transactions aren't being broadcasted, don't let them into local mempool either
if (!fBroadcastTransactions)
return;
LOCK2(cs_main, cs_wallet);