aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac21
-rwxr-xr-xcontrib/devtools/github-merge.py34
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml2
-rw-r--r--contrib/gitian-downloader/jl2012-key.pgp105
-rw-r--r--doc/build-unix.md20
-rw-r--r--doc/developer-notes.md6
-rw-r--r--doc/gitian-building.md34
-rw-r--r--doc/gitian-building/all_files_in_one_partition.pngbin0 -> 3350 bytes
-rw-r--r--doc/gitian-building/create_vm_file_location_size.pngbin71743 -> 111942 bytes
-rw-r--r--doc/gitian-building/select_startup_disk.pngbin130324 -> 72785 bytes
-rw-r--r--doc/tor.md2
-rwxr-xr-xqa/rpc-tests/bip68-112-113-p2p.py19
-rwxr-xr-xqa/rpc-tests/bip68-sequence.py46
-rwxr-xr-xqa/rpc-tests/bip9-softforks.py6
-rwxr-xr-xqa/rpc-tests/blockchain.py1
-rwxr-xr-xqa/rpc-tests/httpbasics.py18
-rwxr-xr-xqa/rpc-tests/importprunedfunds.py10
-rwxr-xr-xqa/rpc-tests/maxblocksinflight.py56
-rwxr-xr-xqa/rpc-tests/rawtransactions.py6
-rwxr-xr-xqa/rpc-tests/test_framework/test_framework.py3
-rw-r--r--qa/rpc-tests/test_framework/util.py4
-rwxr-xr-xqa/rpc-tests/wallet.py19
-rw-r--r--src/Makefile.am2
-rw-r--r--src/amount.cpp20
-rw-r--r--src/amount.h11
-rw-r--r--src/chainparams.cpp4
-rw-r--r--src/main.cpp86
-rw-r--r--src/main.h18
-rw-r--r--src/netbase.cpp10
-rw-r--r--src/netbase.h3
-rw-r--r--src/policy/fees.h4
-rw-r--r--src/policy/policy.cpp4
-rw-r--r--src/rpc/blockchain.cpp30
-rw-r--r--src/rpc/client.cpp4
-rw-r--r--src/script/interpreter.cpp12
-rw-r--r--src/script/standard.h2
-rw-r--r--src/test/amount_tests.cpp29
-rw-r--r--src/txmempool.h40
-rw-r--r--src/utiltime.cpp2
-rw-r--r--src/wallet/wallet.h8
42 files changed, 478 insertions, 227 deletions
diff --git a/configure.ac b/configure.ac
index 1e894f5767..ec5656814f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -98,6 +98,11 @@ AC_ARG_ENABLE(tests,
[use_tests=$enableval],
[use_tests=yes])
+AC_ARG_ENABLE(gui-tests,
+ AS_HELP_STRING([--disable-gui-tests],[do not compile GUI tests (default is to compile if GUI and tests enabled)]),
+ [use_gui_tests=$enableval],
+ [use_gui_tests=$use_tests])
+
AC_ARG_ENABLE(bench,
AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
[use_bench=$enableval],
@@ -919,8 +924,8 @@ else
fi
dnl these are only used when qt is enabled
+BUILD_TEST_QT=""
if test x$bitcoin_enable_qt != xno; then
- BUILD_QT=qt
dnl enable dbus support
AC_MSG_CHECKING([whether to build GUI with support for D-Bus])
if test x$bitcoin_enable_qt_dbus != xno; then
@@ -950,9 +955,9 @@ if test x$bitcoin_enable_qt != xno; then
fi
AC_MSG_CHECKING([whether to build test_bitcoin-qt])
- if test x$use_tests$bitcoin_enable_qt_test = xyesyes; then
+ if test x$use_gui_tests$bitcoin_enable_qt_test = xyesyes; then
AC_MSG_RESULT([yes])
- BUILD_TEST_QT="test"
+ BUILD_TEST_QT="yes"
else
AC_MSG_RESULT([no])
fi
@@ -963,9 +968,10 @@ AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"])
AC_MSG_CHECKING([whether to build test_bitcoin])
if test x$use_tests = xyes; then
AC_MSG_RESULT([yes])
- BUILD_TEST="test"
+ BUILD_TEST="yes"
else
AC_MSG_RESULT([no])
+ BUILD_TEST=""
fi
AC_MSG_CHECKING([whether to reduce exports])
@@ -983,9 +989,9 @@ AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin])
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
-AM_CONDITIONAL([ENABLE_TESTS],[test x$use_tests = xyes])
+AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes])
-AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$use_tests$bitcoin_enable_qt_test = xyesyes])
+AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes])
AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
@@ -1026,9 +1032,6 @@ AC_SUBST(USE_QRCODE)
AC_SUBST(BOOST_LIBS)
AC_SUBST(TESTDEFS)
AC_SUBST(LEVELDB_TARGET_FLAGS)
-AC_SUBST(BUILD_TEST)
-AC_SUBST(BUILD_QT)
-AC_SUBST(BUILD_TEST_QT)
AC_SUBST(MINIUPNPC_CPPFLAGS)
AC_SUBST(MINIUPNPC_LIBS)
AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py])
diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py
index 9a62fccbbb..f82362fe41 100755
--- a/contrib/devtools/github-merge.py
+++ b/contrib/devtools/github-merge.py
@@ -47,9 +47,9 @@ def git_config_get(option, default=None):
except subprocess.CalledProcessError as e:
return default
-def retrieve_pr_title(repo,pull):
+def retrieve_pr_info(repo,pull):
'''
- Retrieve pull request title from github.
+ Retrieve pull request information from github.
Return None if no title can be found, or an error happens.
'''
try:
@@ -57,9 +57,9 @@ def retrieve_pr_title(repo,pull):
result = urlopen(req)
reader = codecs.getreader('utf-8')
obj = json.load(reader(result))
- return obj['title']
+ return obj
except Exception as e:
- print('Warning: unable to retrieve pull title from github: %s' % e)
+ print('Warning: unable to retrieve pull information from github: %s' % e)
return None
def ask_prompt(text):
@@ -69,13 +69,13 @@ def ask_prompt(text):
print("",file=stderr)
return reply
-def parse_arguments(branch):
+def parse_arguments():
epilog = '''
In addition, you can set the following git configuration variables:
githubmerge.repository (mandatory),
user.signingkey (mandatory),
githubmerge.host (default: git@github.com),
- githubmerge.branch (default: master),
+ githubmerge.branch (no default),
githubmerge.testcmd (default: none).
'''
parser = argparse.ArgumentParser(description='Utility to merge, sign and push github pull requests',
@@ -83,14 +83,14 @@ def parse_arguments(branch):
parser.add_argument('pull', metavar='PULL', type=int, nargs=1,
help='Pull request ID to merge')
parser.add_argument('branch', metavar='BRANCH', type=str, nargs='?',
- default=branch, help='Branch to merge against (default: '+branch+')')
+ default=None, help='Branch to merge against (default: githubmerge.branch setting, or base branch for pull, or \'master\')')
return parser.parse_args()
def main():
# Extract settings from git repo
repo = git_config_get('githubmerge.repository')
host = git_config_get('githubmerge.host','git@github.com')
- branch = git_config_get('githubmerge.branch','master')
+ opt_branch = git_config_get('githubmerge.branch',None)
testcmd = git_config_get('githubmerge.testcmd')
signingkey = git_config_get('user.signingkey')
if repo is None:
@@ -105,9 +105,20 @@ def main():
host_repo = host+":"+repo # shortcut for push/pull target
# Extract settings from command line
- args = parse_arguments(branch)
+ args = parse_arguments()
pull = str(args.pull[0])
- branch = args.branch
+
+ # Receive pull information from github
+ info = retrieve_pr_info(repo,pull)
+ if info is None:
+ exit(1)
+ title = info['title']
+ # precedence order for destination branch argument:
+ # - command line argument
+ # - githubmerge.branch setting
+ # - base branch for pull (as retrieved from github)
+ # - 'master'
+ branch = args.branch or opt_branch or info['base']['ref'] or 'master'
# Initialize source branches
head_branch = 'pull/'+pull+'/head'
@@ -147,7 +158,6 @@ def main():
try:
# Create unsigned merge commit.
- title = retrieve_pr_title(repo,pull)
if title:
firstline = 'Merge #%s: %s' % (pull,title)
else:
@@ -165,7 +175,7 @@ def main():
print("ERROR: Creating merge failed (already merged?).",file=stderr)
exit(4)
- print('%s#%s%s %s' % (ATTR_RESET+ATTR_PR,pull,ATTR_RESET,title))
+ print('%s#%s%s %s %sinto %s%s' % (ATTR_RESET+ATTR_PR,pull,ATTR_RESET,title,ATTR_RESET+ATTR_PR,branch,ATTR_RESET))
subprocess.check_call([GIT,'log','--graph','--topo-order','--pretty=format:'+COMMIT_FORMAT,base_branch+'..'+head_branch])
print()
# Run test command if configured.
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index 1f2c4f9999..13941f5d55 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -26,7 +26,7 @@ files: []
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu"
- CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
+ CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests LDFLAGS=-static-libstdc++"
FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="date ar ranlib nm strip"
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index 6f68ae08ce..c430932f9d 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -36,7 +36,7 @@ files:
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-apple-darwin11"
- CONFIGFLAGS="--enable-reduce-exports GENISOIMAGE=$WRAP_DIR/genisoimage"
+ CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage"
FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="ar ranlib date dmg genisoimage"
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index f0fbff3e10..9f7322f0b5 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -29,7 +29,7 @@ files: []
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-w64-mingw32 i686-w64-mingw32"
- CONFIGFLAGS="--enable-reduce-exports"
+ CONFIGFLAGS="--enable-reduce-exports --disable-gui-tests"
FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip"
FAKETIME_PROGS="date makensis zip"
diff --git a/contrib/gitian-downloader/jl2012-key.pgp b/contrib/gitian-downloader/jl2012-key.pgp
new file mode 100644
index 0000000000..b8aad7fd88
--- /dev/null
+++ b/contrib/gitian-downloader/jl2012-key.pgp
@@ -0,0 +1,105 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: GPGTools - https://gpgtools.org
+
+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
+=1irw
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/doc/build-unix.md b/doc/build-unix.md
index c1e92d8d15..dc754fc733 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -250,6 +250,24 @@ A list of additional configure flags can be displayed with:
./configure --help
+Setup and Build Example: Arch Linux
+-----------------------------------
+This example lists the steps necessary to setup and build a command line only, non-wallet distribution of the latest changes on Arch Linux:
+
+ pacman -S git base-devel boost libevent python
+ git clone https://github.com/bitcoin/bitcoin.git
+ cd bitcoin/
+ ./autogen.sh
+ ./configure --disable-wallet --without-gui --without-miniupnpc
+ make check
+
+Note:
+Enabling wallet support requires either compiling against a Berkeley DB newer than 4.8 (package `db`) using `--with-incompatible-bdb`,
+or building and depending on a local version of Berkeley DB 4.8. The readily available Arch Linux packages are currently built using
+`--with-incompatible-bdb` according to the [PKGBUILD](https://projects.archlinux.org/svntogit/community.git/tree/bitcoin/trunk/PKGBUILD).
+As mentioned above, when maintaining portability of the wallet between the standard Bitcoin Core distributions and independently built
+node software is desired, Berkeley DB 4.8 must be used.
+
ARM Cross-compilation
-------------------
@@ -270,4 +288,4 @@ To build executables for ARM:
make
-For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory. \ No newline at end of file
+For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 358792251b..8affb2158a 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -71,6 +71,12 @@ To describe a member or variable use:
int var; //!< Detailed description after the member
```
+or
+```cpp
+//! Description before the member
+int var;
+```
+
Also OK:
```c++
///
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 54993d13a9..3126218518 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -47,7 +47,7 @@ You can also install Gitian on actual hardware instead of using virtualization.
Create a new VirtualBox VM
---------------------------
-In the VirtualBox GUI click "Create" and choose the following parameters in the wizard:
+In the VirtualBox GUI click "New" and choose the following parameters in the wizard:
![](gitian-building/create_new_vm.png)
@@ -74,13 +74,6 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the
- File location and size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side
- Click `Create`
-Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.3.0/amd64/iso-cd/debian-8.3.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
-This DVD image can be validated using a SHA256 hashing tool, for example on
-Unixy OSes by entering the following in a terminal:
-
- echo "dd25bcdde3c6ea5703cc0f313cde621b13d42ff7d252e2538a11663c93bf8654 debian-8.3.0-amd64-netinst.iso" | sha256sum -c
- # (must return OK)
-
After creating the VM, we need to configure it.
- Click the `Settings` button, then go to the `Network` tab. Adapter 1 should be attached to `NAT`.
@@ -102,6 +95,13 @@ After creating the VM, we need to configure it.
- Click `Ok` twice to save.
+Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.4.0/amd64/iso-cd/debian-8.4.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
+This DVD image can be validated using a SHA256 hashing tool, for example on
+Unixy OSes by entering the following in a terminal:
+
+ echo "7a6b418e6a4ee3ca75dda04d79ed96c9e2c33bb0c703ca7e40c6374ab4590748 debian-8.4.0-amd64-netinst.iso" | sha256sum -c
+ # (must return OK)
+
Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso.
![](gitian-building/select_startup_disk.png)
@@ -160,6 +160,10 @@ To select a different button, press `Tab`.
![](gitian-building/debian_install_12_choose_disk.png)
+ - Partition Disks -> *All files in one partition*
+
+![](gitian-building/all_files_in_one_partition.png)
+
- Finish partitioning and write changes to disk -> *Yes* (`Tab`, `Enter` to select the `Yes` button)
![](gitian-building/debian_install_14_finish.png)
@@ -313,7 +317,7 @@ Setting up the Gitian image
-------------------------
Gitian needs a virtual image of the operating system to build in.
-Currently this is Ubuntu Precise x86_64.
+Currently this is Ubuntu Trusty x86_64.
This image will be copied and used every time that a build is started to
make sure that the build is deterministic.
Creating the image will take a while, but only has to be done once.
@@ -363,7 +367,7 @@ Output from `gbuild` will look something like
Resolving deltas: 100% (41590/41590), done.
From https://github.com/bitcoin/bitcoin
... (new tags, new branch etc)
- --- Building for precise amd64 ---
+ --- Building for trusty amd64 ---
Stopping target if it is up
Making a new image copy
stdin: is not a tty
@@ -412,14 +416,14 @@ So, if you use LXC:
export PATH="$PATH":/path/to/gitian-builder/libexec
export USE_LXC=1
cd /path/to/gitian-builder
-./libexec/make-clean-vm --suite precise --arch amd64
+./libexec/make-clean-vm --suite trusty --arch amd64
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root apt-get update
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root \
+LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root apt-get update
+LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root \
-e DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install \
$( sed -ne '/^packages:/,/[^-] .*/ {/^- .*/{s/"//g;s/- //;p}}' ../bitcoin/contrib/gitian-descriptors/*|sort|uniq )
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root apt-get -q -y purge grub
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root -e DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
+LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root apt-get -q -y purge grub
+LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root -e DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
```
And then set offline mode for apt-cacher-ng:
diff --git a/doc/gitian-building/all_files_in_one_partition.png b/doc/gitian-building/all_files_in_one_partition.png
new file mode 100644
index 0000000000..8cbb0d8adc
--- /dev/null
+++ b/doc/gitian-building/all_files_in_one_partition.png
Binary files differ
diff --git a/doc/gitian-building/create_vm_file_location_size.png b/doc/gitian-building/create_vm_file_location_size.png
index 14aef5abae..5f77206b6f 100644
--- a/doc/gitian-building/create_vm_file_location_size.png
+++ b/doc/gitian-building/create_vm_file_location_size.png
Binary files differ
diff --git a/doc/gitian-building/select_startup_disk.png b/doc/gitian-building/select_startup_disk.png
index 5acdc3fe10..59bc093e2c 100644
--- a/doc/gitian-building/select_startup_disk.png
+++ b/doc/gitian-building/select_startup_disk.png
Binary files differ
diff --git a/doc/tor.md b/doc/tor.md
index be41255449..43e922718b 100644
--- a/doc/tor.md
+++ b/doc/tor.md
@@ -3,7 +3,7 @@ TOR SUPPORT IN BITCOIN
It is possible to run Bitcoin as a Tor hidden service, and connect to such services.
-The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on a random port. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly
+The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on port 9150. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly
configure Tor.
diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py
index f391cb0b7a..35c831cb8b 100755
--- a/qa/rpc-tests/bip68-112-113-p2p.py
+++ b/qa/rpc-tests/bip68-112-113-p2p.py
@@ -149,13 +149,6 @@ class BIP68_112_113Test(ComparisonTestFramework):
block.solve()
return block
- def get_bip9_status(self, key):
- info = self.nodes[0].getblockchaininfo()
- for row in info['bip9_softforks']:
- if row['id'] == key:
- return row
- raise IndexError ('key:"%s" not found' % key)
-
def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0):
txs = []
assert(len(bip68inputs) >= 16)
@@ -223,11 +216,11 @@ class BIP68_112_113Test(ComparisonTestFramework):
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
self.nodeaddress = self.nodes[0].getnewaddress()
- assert_equal(self.get_bip9_status('csv')['status'], 'defined')
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
test_blocks = self.generate_blocks(61, 4)
yield TestInstance(test_blocks, sync_every_block=False) # 1
# Advanced from DEFINED to STARTED, height = 143
- assert_equal(self.get_bip9_status('csv')['status'], 'started')
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
# Fail to achieve LOCKED_IN 100 out of 144 signal bit 0
# using a variety of bits to simulate multiple parallel softforks
@@ -237,7 +230,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
yield TestInstance(test_blocks, sync_every_block=False) # 2
# Failed to advance past STARTED, height = 287
- assert_equal(self.get_bip9_status('csv')['status'], 'started')
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
# 108 out of 144 signal bit 0 to achieve lock-in
# using a variety of bits to simulate multiple parallel softforks
@@ -247,7 +240,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
yield TestInstance(test_blocks, sync_every_block=False) # 3
# Advanced from STARTED to LOCKED_IN, height = 431
- assert_equal(self.get_bip9_status('csv')['status'], 'locked_in')
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
# 140 more version 4 blocks
test_blocks = self.generate_blocks(140, 4)
@@ -291,7 +284,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
test_blocks = self.generate_blocks(2, 4)
yield TestInstance(test_blocks, sync_every_block=False) # 5
# Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)
- assert_equal(self.get_bip9_status('csv')['status'], 'locked_in')
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
# Test both version 1 and version 2 transactions for all tests
# BIP113 test transaction will be modified before each use to put in appropriate block time
@@ -368,7 +361,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
# 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
test_blocks = self.generate_blocks(1, 4)
yield TestInstance(test_blocks, sync_every_block=False) # 8
- assert_equal(self.get_bip9_status('csv')['status'], 'active')
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active')
#################################
diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py
index 377a35b687..33e05dfc51 100755
--- a/qa/rpc-tests/bip68-sequence.py
+++ b/qa/rpc-tests/bip68-sequence.py
@@ -4,7 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-# Test BIP68 implementation (mempool only)
+# Test BIP68 implementation
#
from test_framework.test_framework import BitcoinTestFramework
@@ -26,8 +26,10 @@ class BIP68Test(BitcoinTestFramework):
def setup_network(self):
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-blockprioritysize=0"]))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-blockprioritysize=0", "-acceptnonstdtxn=0"]))
self.is_network_split = False
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
+ connect_nodes(self.nodes[0], 1)
def run_test(self):
# Generate some coins
@@ -42,10 +44,18 @@ class BIP68Test(BitcoinTestFramework):
print "Running test sequence-lock-unconfirmed-inputs"
self.test_sequence_lock_unconfirmed_inputs()
- # This test needs to change when BIP68 becomes consensus
- print "Running test BIP68 not consensus"
+ print "Running test BIP68 not consensus before versionbits activation"
self.test_bip68_not_consensus()
+ print "Verifying nVersion=2 transactions aren't standard"
+ self.test_version2_relay(before_activation=True)
+
+ print "Activating BIP68 (and 112/113)"
+ self.activateCSV()
+
+ print "Verifying nVersion=2 transactions are now standard"
+ self.test_version2_relay(before_activation=False)
+
print "Passed\n"
# Test that BIP68 is not in effect if tx version is 1, or if
@@ -333,8 +343,12 @@ class BIP68Test(BitcoinTestFramework):
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
self.nodes[0].generate(10)
- # Make sure that BIP68 isn't being used to validate blocks.
+ # Make sure that BIP68 isn't being used to validate blocks, prior to
+ # versionbits activation. If more blocks are mined prior to this test
+ # being run, then it's possible the test has activated the soft fork, and
+ # this test should be moved to run earlier, or deleted.
def test_bip68_not_consensus(self):
+ assert(get_bip9_status(self.nodes[0], 'csv')['status'] != 'active')
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
@@ -381,6 +395,30 @@ class BIP68Test(BitcoinTestFramework):
self.nodes[0].submitblock(ToHex(block))
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
+ def activateCSV(self):
+ # activation should happen at block height 432 (3 periods)
+ min_activation_height = 432
+ height = self.nodes[0].getblockcount()
+ assert(height < 432)
+ self.nodes[0].generate(432-height)
+ assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active')
+ sync_blocks(self.nodes)
+
+ # Use self.nodes[1] to test standardness relay policy
+ def test_version2_relay(self, before_activation):
+ inputs = [ ]
+ outputs = { self.nodes[1].getnewaddress() : 1.0 }
+ rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
+ rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex']
+ tx = FromHex(CTransaction(), rawtxfund)
+ tx.nVersion = 2
+ tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"]
+ try:
+ tx_id = self.nodes[1].sendrawtransaction(tx_signed)
+ assert(before_activation == False)
+ except:
+ assert(before_activation)
+
if __name__ == '__main__':
BIP68Test().main()
diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py
index 98975e7193..e63343d352 100755
--- a/qa/rpc-tests/bip9-softforks.py
+++ b/qa/rpc-tests/bip9-softforks.py
@@ -79,11 +79,7 @@ class BIP9SoftForksTest(ComparisonTestFramework):
def get_bip9_status(self, key):
info = self.nodes[0].getblockchaininfo()
- for row in info['bip9_softforks']:
- if row['id'] == key:
- return row
- raise IndexError ('key:"%s" not found' % key)
-
+ return info['bip9_softforks'][key]
def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature):
# generate some coins for later
diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py
index 272a5dc154..8f59ee741c 100755
--- a/qa/rpc-tests/blockchain.py
+++ b/qa/rpc-tests/blockchain.py
@@ -82,6 +82,7 @@ class BlockchainTest(BitcoinTestFramework):
assert isinstance(header['mediantime'], int)
assert isinstance(header['nonce'], int)
assert isinstance(header['version'], int)
+ assert isinstance(int(header['versionHex'], 16), int)
assert isinstance(header['difficulty'], Decimal)
if __name__ == '__main__':
diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py
index c231676ec8..eff4c6e808 100755
--- a/qa/rpc-tests/httpbasics.py
+++ b/qa/rpc-tests/httpbasics.py
@@ -37,13 +37,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read()
- assert('"error":null' in out1)
+ assert(b'"error":null' in out1)
assert(conn.sock!=None) #according to http/1.1 connection must still be open!
#send 2nd request without closing connection
conn.request('POST', '/', '{"method": "getchaintips"}', headers)
- out2 = conn.getresponse().read()
- assert('"error":null' in out1) #must also response with a correct json-rpc message
+ out1 = conn.getresponse().read()
+ assert(b'"error":null' in out1) #must also response with a correct json-rpc message
assert(conn.sock!=None) #according to http/1.1 connection must still be open!
conn.close()
@@ -54,13 +54,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read()
- assert('"error":null' in out1)
+ assert(b'"error":null' in out1)
assert(conn.sock!=None) #according to http/1.1 connection must still be open!
#send 2nd request without closing connection
conn.request('POST', '/', '{"method": "getchaintips"}', headers)
- out2 = conn.getresponse().read()
- assert('"error":null' in out1) #must also response with a correct json-rpc message
+ out1 = conn.getresponse().read()
+ assert(b'"error":null' in out1) #must also response with a correct json-rpc message
assert(conn.sock!=None) #according to http/1.1 connection must still be open!
conn.close()
@@ -71,7 +71,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read()
- assert('"error":null' in out1)
+ assert(b'"error":null' in out1)
assert(conn.sock==None) #now the connection must be closed after the response
#node1 (2nd node) is running with disabled keep-alive option
@@ -83,7 +83,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read()
- assert('"error":null' in out1)
+ assert(b'"error":null' in out1)
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is on
urlNode2 = urlparse.urlparse(self.nodes[2].url)
@@ -94,7 +94,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read()
- assert('"error":null' in out1)
+ assert(b'"error":null' in out1)
assert(conn.sock!=None) #connection must be closed because bitcoind should use keep-alive by default
# Check excessive request size
diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py
index db875800d4..a9324196ee 100755
--- a/qa/rpc-tests/importprunedfunds.py
+++ b/qa/rpc-tests/importprunedfunds.py
@@ -83,9 +83,10 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
try:
result1 = self.nodes[1].importprunedfunds(rawtxn1, proof1, "")
except JSONRPCException as e:
- errorString = e.error['message']
+ assert('No addresses' in e.error['message'])
+ else:
+ assert(False)
- assert('No addresses' in errorString)
balance1 = self.nodes[1].getbalance("", 0, True)
assert_equal(balance1, Decimal(0))
@@ -120,9 +121,10 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
try:
self.nodes[1].removeprunedfunds(txnid1)
except JSONRPCException as e:
- errorString = e.error['message']
+ assert('does not exist' in e.error['message'])
+ else:
+ assert(False)
- assert('does not exist' in errorString)
balance1 = Decimal(self.nodes[1].getbalance("", 0, True))
assert_equal(balance1, Decimal('0.075'))
diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py
index 0313bce736..ad633f661d 100755
--- a/qa/rpc-tests/maxblocksinflight.py
+++ b/qa/rpc-tests/maxblocksinflight.py
@@ -41,40 +41,36 @@ class TestManager(NodeConnCB):
self.disconnectOkay = False
def run(self):
- try:
- fail = False
- self.connection.rpc.generate(1) # Leave IBD
-
- numBlocksToGenerate = [ 8, 16, 128, 1024 ]
- for count in range(len(numBlocksToGenerate)):
- current_invs = []
- for i in range(numBlocksToGenerate[count]):
- current_invs.append(CInv(2, random.randrange(0, 1<<256)))
- if len(current_invs) >= 50000:
- self.connection.send_message(msg_inv(current_invs))
- current_invs = []
- if len(current_invs) > 0:
+ self.connection.rpc.generate(1) # Leave IBD
+
+ numBlocksToGenerate = [8, 16, 128, 1024]
+ for count in range(len(numBlocksToGenerate)):
+ current_invs = []
+ for i in range(numBlocksToGenerate[count]):
+ current_invs.append(CInv(2, random.randrange(0, 1 << 256)))
+ if len(current_invs) >= 50000:
self.connection.send_message(msg_inv(current_invs))
-
- # Wait and see how many blocks were requested
- time.sleep(2)
-
- total_requests = 0
- 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)
- except AssertionError as e:
- print "TEST FAILED: ", e.args
+ current_invs = []
+ if len(current_invs) > 0:
+ self.connection.send_message(msg_inv(current_invs))
+
+ # Wait and see how many blocks were requested
+ time.sleep(2)
+
+ total_requests = 0
+ 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)
self.disconnectOkay = True
self.connection.disconnect_node()
-
+
class MaxBlocksInFlightTest(BitcoinTestFramework):
def add_options(self, parser):
parser.add_option("--testbinary", dest="testbinary",
@@ -86,7 +82,7 @@ class MaxBlocksInFlightTest(BitcoinTestFramework):
initialize_chain_clean(self.options.tmpdir, 1)
def setup_network(self):
- self.nodes = start_nodes(1, self.options.tmpdir,
+ self.nodes = start_nodes(1, self.options.tmpdir,
extra_args=[['-debug', '-whitelist=127.0.0.1']],
binary=[self.options.testbinary])
diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py
index 9f660c8bda..762a6d6a30 100755
--- a/qa/rpc-tests/rawtransactions.py
+++ b/qa/rpc-tests/rawtransactions.py
@@ -56,13 +56,13 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
rawtx = self.nodes[2].signrawtransaction(rawtx)
- errorString = ""
try:
rawtx = self.nodes[2].sendrawtransaction(rawtx['hex'])
except JSONRPCException as e:
- errorString = e.error['message']
+ assert("Missing inputs" in e.error['message'])
+ else:
+ assert(False)
- assert("Missing inputs" in errorString)
#########################
# RAW TX MULTISIG TESTS #
diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py
index 19ee472609..3b08cd1384 100755
--- a/qa/rpc-tests/test_framework/test_framework.py
+++ b/qa/rpc-tests/test_framework/test_framework.py
@@ -142,6 +142,9 @@ class BitcoinTestFramework(object):
except AssertionError as e:
print("Assertion failed: "+ str(e))
traceback.print_tb(sys.exc_info()[2])
+ except KeyError as e:
+ print("key not found: "+ str(e))
+ traceback.print_tb(sys.exc_info()[2])
except Exception as e:
print("Unexpected exception caught during testing: "+str(e))
traceback.print_tb(sys.exc_info()[2])
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index f069c32a60..acb7f8a6b4 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -545,3 +545,7 @@ def create_lots_of_big_transactions(node, txouts, utxos, fee):
txid = node.sendrawtransaction(signresult["hex"], True)
txids.append(txid)
return txids
+
+def get_bip9_status(node, key):
+ info = node.getblockchaininfo()
+ return info['bip9_softforks'][key]
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index cb876aae5c..8fdcea50b6 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -245,22 +245,20 @@ class WalletTest (BitcoinTestFramework):
txObj = self.nodes[0].gettransaction(txId)
assert_equal(txObj['amount'], Decimal('-0.0001'))
- #this should fail
- errorString = ""
try:
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1f-4")
except JSONRPCException as e:
- errorString = e.error['message']
+ assert("Invalid amount" in e.error['message'])
+ else:
+ raise AssertionError("Must not parse invalid amounts")
- assert("Invalid amount" in errorString)
- errorString = ""
try:
- self.nodes[0].generate("2") #use a string to as block amount parameter must fail because it's not interpreted as amount
+ self.nodes[0].generate("2")
+ raise AssertionError("Must not accept strings as numeric")
except JSONRPCException as e:
- errorString = e.error['message']
+ assert("not an integer" in e.error['message'])
- assert("not an integer" in errorString)
# Mine a block from node0 to an address from node1
cbAddr = self.nodes[1].getnewaddress()
@@ -269,10 +267,7 @@ class WalletTest (BitcoinTestFramework):
self.sync_all()
# Check that the txid and balance is found by node1
- try:
- self.nodes[1].gettransaction(cbTxId)
- except JSONRPCException as e:
- assert("Invalid or non-wallet transaction id" not in e.error['message'])
+ self.nodes[1].gettransaction(cbTxId)
#check if wallet or blochchain maintenance changes the balance
self.sync_all()
diff --git a/src/Makefile.am b/src/Makefile.am
index 1e54512cbd..d91e959cff 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -479,7 +479,7 @@ endif
%.pb.cc %.pb.h: %.proto
@test -f $(PROTOC)
- $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<)
+ $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $<
if ENABLE_TESTS
include Makefile.test.include
diff --git a/src/amount.cpp b/src/amount.cpp
index 68806ff062..7b8618de33 100644
--- a/src/amount.cpp
+++ b/src/amount.cpp
@@ -9,20 +9,30 @@
const std::string CURRENCY_UNIT = "BTC";
-CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize)
+CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_)
{
+ assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
+ int64_t nSize = int64_t(nBytes_);
+
if (nSize > 0)
- nSatoshisPerK = nFeePaid*1000/nSize;
+ nSatoshisPerK = nFeePaid * 1000 / nSize;
else
nSatoshisPerK = 0;
}
-CAmount CFeeRate::GetFee(size_t nSize) const
+CAmount CFeeRate::GetFee(size_t nBytes_) const
{
+ assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
+ int64_t nSize = int64_t(nBytes_);
+
CAmount nFee = nSatoshisPerK * nSize / 1000;
- if (nFee == 0 && nSize != 0 && nSatoshisPerK > 0)
- nFee = CAmount(1);
+ if (nFee == 0 && nSize != 0) {
+ if (nSatoshisPerK > 0)
+ nFee = CAmount(1);
+ if (nSatoshisPerK < 0)
+ nFee = CAmount(-1);
+ }
return nFee;
}
diff --git a/src/amount.h b/src/amount.h
index 9aba6525c7..5e52f37f23 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string>
+/** Amount in satoshis (Can be negative) */
typedef int64_t CAmount;
static const CAmount COIN = 100000000;
@@ -30,22 +31,24 @@ extern const std::string CURRENCY_UNIT;
static const CAmount MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
-/** Type-safe wrapper class for fee rates
- * (how much to pay based on transaction size)
+/**
+ * Fee rate in satoshis per kilobyte: CAmount / kB
*/
class CFeeRate
{
private:
CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes
public:
+ /** Fee rate of 0 satoshis per kB */
CFeeRate() : nSatoshisPerK(0) { }
explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
- CFeeRate(const CAmount& nFeePaid, size_t nSize);
+ /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/
+ CFeeRate(const CAmount& nFeePaid, size_t nBytes);
CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
/**
* Return the fee in satoshis for the given size in bytes.
*/
- CAmount GetFee(size_t size) const;
+ CAmount GetFee(size_t nBytes) const;
/**
* Return the fee in satoshis for a size of 1000 bytes
*/
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 965d131695..5c7d190125 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -266,8 +266,8 @@ public:
assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
- vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds.
- vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds.
+ vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds.
+ vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds.
fMiningRequiresPeers = false;
fDefaultConsistencyChecks = true;
diff --git a/src/main.cpp b/src/main.cpp
index 2c0b3bfee7..9b164c7999 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -194,16 +194,11 @@ namespace {
/** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
struct QueuedBlock {
uint256 hash;
- CBlockIndex *pindex; //! Optional.
- int64_t nTime; //! Time of "getdata" request in microseconds.
- bool fValidatedHeaders; //! Whether this block has validated headers at the time of request.
- int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer)
+ CBlockIndex* pindex; //!< Optional.
+ bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request.
};
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
- /** Number of blocks in flight with validated headers. */
- int nQueuedValidatedHeaders = 0;
-
/** Number of preferable block download peers. */
int nPreferredDownload = 0;
@@ -212,6 +207,9 @@ namespace {
/** Dirty block file entries. */
set<int> setDirtyFileInfo;
+
+ /** Number of peers from which we're downloading blocks. */
+ int nPeersWithValidatedDownloads = 0;
} // anon namespace
//////////////////////////////////////////////////////////////////////////////
@@ -259,6 +257,8 @@ struct CNodeState {
//! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince;
list<QueuedBlock> vBlocksInFlight;
+ //! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
+ int64_t nDownloadingSince;
int nBlocksInFlight;
int nBlocksInFlightValidHeaders;
//! Whether we consider this a preferred download peer.
@@ -276,6 +276,7 @@ struct CNodeState {
pindexBestHeaderSent = NULL;
fSyncStarted = false;
nStallingSince = 0;
+ nDownloadingSince = 0;
nBlocksInFlight = 0;
nBlocksInFlightValidHeaders = 0;
fPreferredDownload = false;
@@ -310,12 +311,6 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
nPreferredDownload += state->fPreferredDownload;
}
-// Returns time at which to timeout block request (nTime in microseconds)
-int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consensus::Params &consensusParams)
-{
- return nTime + 500000 * consensusParams.nPowTargetSpacing * (4 + nValidatedQueuedBefore);
-}
-
void InitializeNode(NodeId nodeid, const CNode *pnode) {
LOCK(cs_main);
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
@@ -335,13 +330,21 @@ void FinalizeNode(NodeId nodeid) {
}
BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight) {
- nQueuedValidatedHeaders -= entry.fValidatedHeaders;
mapBlocksInFlight.erase(entry.hash);
}
EraseOrphansFor(nodeid);
nPreferredDownload -= state->fPreferredDownload;
+ nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
+ assert(nPeersWithValidatedDownloads >= 0);
mapNodeState.erase(nodeid);
+
+ if (mapNodeState.empty()) {
+ // Do a consistency check after the last peer is removed.
+ assert(mapBlocksInFlight.empty());
+ assert(nPreferredDownload == 0);
+ assert(nPeersWithValidatedDownloads == 0);
+ }
}
// Requires cs_main.
@@ -350,8 +353,15 @@ bool MarkBlockAsReceived(const uint256& hash) {
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first);
- nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders;
state->nBlocksInFlightValidHeaders -= itInFlight->second.second->fValidatedHeaders;
+ if (state->nBlocksInFlightValidHeaders == 0 && itInFlight->second.second->fValidatedHeaders) {
+ // Last validated block on the queue was received.
+ nPeersWithValidatedDownloads--;
+ }
+ if (state->vBlocksInFlight.begin() == itInFlight->second.second) {
+ // First block on the queue was received, update the start download time for the next one
+ state->nDownloadingSince = std::max(state->nDownloadingSince, GetTimeMicros());
+ }
state->vBlocksInFlight.erase(itInFlight->second.second);
state->nBlocksInFlight--;
state->nStallingSince = 0;
@@ -369,12 +379,17 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Pa
// Make sure it's not listed somewhere already.
MarkBlockAsReceived(hash);
- int64_t nNow = GetTimeMicros();
- QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams)};
- nQueuedValidatedHeaders += newentry.fValidatedHeaders;
+ QueuedBlock newentry = {hash, pindex, pindex != NULL};
list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
state->nBlocksInFlight++;
state->nBlocksInFlightValidHeaders += newentry.fValidatedHeaders;
+ if (state->nBlocksInFlight == 1) {
+ // We're starting a block download (batch) from this peer.
+ state->nDownloadingSince = GetTimeMicros();
+ }
+ if (state->nBlocksInFlightValidHeaders == 1 && pindex != NULL) {
+ nPeersWithValidatedDownloads++;
+ }
mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
}
@@ -1010,6 +1025,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
if (fRequireStandard && !IsStandardTx(tx, reason))
return state.DoS(0, false, REJECT_NONSTANDARD, reason);
+ // Don't relay version 2 transactions until CSV is active, and we can be
+ // sure that such transactions will be mined (unless we're on
+ // -testnet/-regtest).
+ const CChainParams& chainparams = Params();
+ if (fRequireStandard && tx.nVersion >= 2 && VersionBitsTipState(chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV) != THRESHOLD_ACTIVE) {
+ return state.DoS(0, false, REJECT_NONSTANDARD, "premature-version2-tx");
+ }
+
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
@@ -2877,6 +2900,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
CBlockIndex *pindexMostWork = NULL;
do {
boost::this_thread::interruption_point();
+ if (ShutdownRequested())
+ break;
CBlockIndex *pindexNewTip = NULL;
const CBlockIndex *pindexFork;
@@ -3894,7 +3919,6 @@ void UnloadBlockIndex()
nBlockSequenceId = 1;
mapBlockSource.clear();
mapBlocksInFlight.clear();
- nQueuedValidatedHeaders = 0;
nPreferredDownload = 0;
setDirtyBlockIndex.clear();
setDirtyFileInfo.clear();
@@ -4475,9 +4499,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
-bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
+bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams)
{
- const CChainParams& chainparams = Params();
RandAddSeedPerfmon();
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
@@ -5487,7 +5510,7 @@ bool ProcessMessages(CNode* pfrom)
bool fRet = false;
try
{
- fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime);
+ fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams);
boost::this_thread::interruption_point();
}
catch (const std::ios_base::failure& e)
@@ -5811,24 +5834,15 @@ bool SendMessages(CNode* pto)
LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
pto->fDisconnect = true;
}
- // 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
+ // 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 peers from which we're downloading validated blocks), disconnect due to timeout.
+ // We compensate for other peers to prevent killing off peers due to our own downstream link
// being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
// to unreasonably increase our timeout.
- // We also compare the block download timeout originally calculated against the time at which we'd disconnect
- // if we assumed the block were being requested now (ignoring blocks we've requested from this peer, since we're
- // only looking at this peer's oldest request). This way a large queue in the past doesn't result in a
- // permanently large window for this block to be delivered (ie if the number of blocks in flight is decreasing
- // more quickly than once every 5 minutes, then we'll shorten the download window for this block).
if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0) {
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
- int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders, consensusParams);
- if (queuedBlock.nTimeDisconnect > nTimeoutIfRequestedNow) {
- LogPrint("net", "Reducing block download timeout for peer=%d block=%s, orig=%d new=%d\n", pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow);
- queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow;
- }
- if (queuedBlock.nTimeDisconnect < nNow) {
+ int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
+ if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id);
pto->fDisconnect = true;
}
diff --git a/src/main.h b/src/main.h
index 0bfcfab213..0962f44e94 100644
--- a/src/main.h
+++ b/src/main.h
@@ -106,6 +106,10 @@ static const unsigned int AVG_INVENTORY_BROADCAST_INTERVAL = 5;
static const unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60;
/** Maximum feefilter broadcast delay after significant change. */
static const unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60;
+/** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */
+static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000;
+/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
+static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
static const unsigned int DEFAULT_LIMITFREERELAY = 15;
static const bool DEFAULT_RELAYPRIORITY = true;
@@ -469,13 +473,13 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
class CBlockFileInfo
{
public:
- unsigned int nBlocks; //! number of blocks stored in file
- unsigned int nSize; //! number of used bytes of block file
- unsigned int nUndoSize; //! number of used bytes in the undo file
- unsigned int nHeightFirst; //! lowest height of block in file
- unsigned int nHeightLast; //! highest height of block in file
- uint64_t nTimeFirst; //! earliest time of block in file
- uint64_t nTimeLast; //! latest time of block in file
+ unsigned int nBlocks; //!< number of blocks stored in file
+ unsigned int nSize; //!< number of used bytes of block file
+ unsigned int nUndoSize; //!< number of used bytes in the undo file
+ unsigned int nHeightFirst; //!< lowest height of block in file
+ unsigned int nHeightLast; //!< highest height of block in file
+ uint64_t nTimeFirst; //!< earliest time of block in file
+ uint64_t nTimeLast; //!< latest time of block in file
ADD_SERIALIZE_METHODS;
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 7f79dd02c6..281c6bcb7f 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -170,7 +170,8 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
if (aiTrav->ai_family == AF_INET6)
{
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
- vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
+ struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
+ vIP.push_back(CNetAddr(s6->sin6_addr, s6->sin6_scope_id));
}
aiTrav = aiTrav->ai_next;
@@ -629,6 +630,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
void CNetAddr::Init()
{
memset(ip, 0, sizeof(ip));
+ scopeId = 0;
}
void CNetAddr::SetIP(const CNetAddr& ipIn)
@@ -678,9 +680,10 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
}
-CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
+CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
{
SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
+ scopeId = scope;
}
CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
@@ -1099,7 +1102,7 @@ CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), po
assert(addr.sin_family == AF_INET);
}
-CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port))
+CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port))
{
assert(addr.sin6_family == AF_INET6);
}
@@ -1192,6 +1195,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
memset(paddrin6, 0, *addrlen);
if (!GetIn6Addr(&paddrin6->sin6_addr))
return false;
+ paddrin6->sin6_scope_id = scopeId;
paddrin6->sin6_family = AF_INET6;
paddrin6->sin6_port = htons(port);
return true;
diff --git a/src/netbase.h b/src/netbase.h
index 1db66ac27f..db736154fa 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -44,6 +44,7 @@ class CNetAddr
{
protected:
unsigned char ip[16]; // in network byte order
+ uint32_t scopeId; // for scoped/link-local ipv6 addresses
public:
CNetAddr();
@@ -89,7 +90,7 @@ class CNetAddr
std::vector<unsigned char> GetGroup() const;
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
- CNetAddr(const struct in6_addr& pipv6Addr);
+ CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0);
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
diff --git a/src/policy/fees.h b/src/policy/fees.h
index cdd984de7d..463f62f710 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -265,8 +265,8 @@ public:
void Read(CAutoFile& filein);
private:
- CFeeRate minTrackedFee; //! Passed to constructor to avoid dependency on main
- double minTrackedPriority; //! Set to AllowFreeThreshold
+ CFeeRate minTrackedFee; //!< Passed to constructor to avoid dependency on main
+ double minTrackedPriority; //!< Set to AllowFreeThreshold
unsigned int nBestSeenHeight;
struct TxStatsInfo
{
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index e3ed7be000..d1a15451dc 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -73,12 +73,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
- // keys. (remember the 520 byte limit on redeemScript size) That works
+ // keys (remember the 520 byte limit on redeemScript size). That works
// out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
// bytes of scriptSig, which we round off to 1650 bytes for some minor
// future-proofing. That's also enough to spend a 20-of-20
// CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
- // considered standard)
+ // considered standard.
if (txin.scriptSig.size() > 1650) {
reason = "scriptsig-size";
return false;
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index f1c9d9f7ab..7a01a10b7d 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -70,6 +70,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
result.push_back(Pair("confirmations", confirmations));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", blockindex->nVersion));
+ result.push_back(Pair("versionHex", strprintf("%08x", blockindex->nVersion)));
result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
result.push_back(Pair("time", (int64_t)blockindex->nTime));
result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
@@ -98,6 +99,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
+ result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
UniValue txs(UniValue::VARR);
BOOST_FOREACH(const CTransaction&tx, block.vtx)
@@ -316,6 +318,7 @@ UniValue getblockheader(const UniValue& params, bool fHelp)
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
+ " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
@@ -375,6 +378,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"size\" : n, (numeric) The block size\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
+ " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"tx\" : [ (array of string) The transaction ids\n"
" \"transactionid\" (string) The transaction id\n"
@@ -604,17 +608,23 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex*
return rv;
}
-static UniValue BIP9SoftForkDesc(const std::string& name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
+static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
UniValue rv(UniValue::VOBJ);
- rv.push_back(Pair("id", name));
- switch (VersionBitsTipState(consensusParams, id)) {
+ const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
+ switch (thresholdState) {
case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break;
case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break;
case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break;
case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break;
case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break;
}
+ if (THRESHOLD_STARTED == thresholdState)
+ {
+ rv.push_back(Pair("bit", consensusParams.vDeployments[id].bit));
+ }
+ rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime));
+ rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout));
return rv;
}
@@ -649,12 +659,14 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
" }, ...\n"
" ],\n"
- " \"bip9_softforks\": [ (array) status of BIP9 softforks in progress\n"
- " {\n"
- " \"id\": \"xxxx\", (string) name of the softfork\n"
+ " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
+ " \"xxxx\" : { (string) name of the softfork\n"
" \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n"
+ " \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n"
+ " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
+ " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
" }\n"
- " ]\n"
+ " }\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getblockchaininfo", "")
@@ -677,11 +689,11 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
const Consensus::Params& consensusParams = Params().GetConsensus();
CBlockIndex* tip = chainActive.Tip();
UniValue softforks(UniValue::VARR);
- UniValue bip9_softforks(UniValue::VARR);
+ UniValue bip9_softforks(UniValue::VOBJ);
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
- bip9_softforks.push_back(BIP9SoftForkDesc("csv", consensusParams, Consensus::DEPLOYMENT_CSV));
+ bip9_softforks.push_back(Pair("csv", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_CSV)));
obj.push_back(Pair("softforks", softforks));
obj.push_back(Pair("bip9_softforks", bip9_softforks));
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index b040d2bc80..c89af6bfa7 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -18,8 +18,8 @@ using namespace std;
class CRPCConvertParam
{
public:
- std::string methodName; //! method whose params want conversion
- int paramIdx; //! 0-based idx of param to convert
+ std::string methodName; //!< method whose params want conversion
+ int paramIdx; //!< 0-based idx of param to convert
};
static const CRPCConvertParam vRPCConvertParams[] =
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 149a4f0156..9c47f7c6c9 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1015,12 +1015,12 @@ namespace {
*/
class CTransactionSignatureSerializer {
private:
- const CTransaction &txTo; //! reference to the spending transaction (the one being serialized)
- const CScript &scriptCode; //! output script being consumed
- const unsigned int nIn; //! input index of txTo being signed
- const bool fAnyoneCanPay; //! whether the hashtype has the SIGHASH_ANYONECANPAY flag set
- const bool fHashSingle; //! whether the hashtype is SIGHASH_SINGLE
- const bool fHashNone; //! whether the hashtype is SIGHASH_NONE
+ const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized)
+ const CScript& scriptCode; //!< output script being consumed
+ const unsigned int nIn; //!< input index of txTo being signed
+ const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE
+ const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
public:
CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
diff --git a/src/script/standard.h b/src/script/standard.h
index 64bf010ec1..f348da8e19 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -27,7 +27,7 @@ public:
CScriptID(const uint160& in) : uint160(in) {}
};
-static const unsigned int MAX_OP_RETURN_RELAY = 83; //! bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
+static const unsigned int MAX_OP_RETURN_RELAY = 83; //!< bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
extern bool fAcceptDatacarrier;
extern unsigned nMaxDatacarrierBytes;
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
index 59dab20633..fd6f88b366 100644
--- a/src/test/amount_tests.cpp
+++ b/src/test/amount_tests.cpp
@@ -27,6 +27,15 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 1e3);
BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 9e3);
+ feeRate = CFeeRate(-1000);
+ // Must always just return -1 * arg
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1), -1);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), -121);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), -999);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), -1e3);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), -9e3);
+
feeRate = CFeeRate(123);
// Truncates the result, if not integer
BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
@@ -37,6 +46,26 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122);
BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 123);
BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 1107);
+
+ feeRate = CFeeRate(-123);
+ // Truncates the result, if not integer
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(8), -1); // Special case: returns -1 instead of 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1);
+
+ // Check full constructor
+ // default value
+ BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1));
+ BOOST_CHECK(CFeeRate(CAmount(0), 1000) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(1), 1000) == CFeeRate(1));
+ // lost precision (can only resolve satoshis per kB)
+ BOOST_CHECK(CFeeRate(CAmount(1), 1001) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(2), 1001) == CFeeRate(1));
+ // some more integer checks
+ BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32));
+ BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34));
+ // Maximum size in bytes, should not crash
+ CFeeRate(MAX_MONEY, std::numeric_limits<size_t>::max() >> 1).GetFeePerK();
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/txmempool.h b/src/txmempool.h
index 9dbb37dad0..de4ba0b371 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -74,28 +74,28 @@ class CTxMemPoolEntry
{
private:
CTransaction tx;
- CAmount nFee; //! Cached to avoid expensive parent-transaction lookups
- size_t nTxSize; //! ... and avoid recomputing tx size
- size_t nModSize; //! ... and modified size for priority
- size_t nUsageSize; //! ... and total memory usage
- int64_t nTime; //! Local time when entering the mempool
- double entryPriority; //! Priority when entering the mempool
- unsigned int entryHeight; //! Chain height when entering the mempool
- bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool
- CAmount inChainInputValue; //! Sum of all txin values that are already in blockchain
- bool spendsCoinbase; //! keep track of transactions that spend a coinbase
- unsigned int sigOpCount; //! Legacy sig ops plus P2SH sig op count
- int64_t feeDelta; //! Used for determining the priority of the transaction for mining in a block
- LockPoints lockPoints; //! Track the height and time at which tx was final
+ CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
+ size_t nTxSize; //!< ... and avoid recomputing tx size
+ size_t nModSize; //!< ... and modified size for priority
+ size_t nUsageSize; //!< ... and total memory usage
+ int64_t nTime; //!< Local time when entering the mempool
+ double entryPriority; //!< Priority when entering the mempool
+ unsigned int entryHeight; //!< Chain height when entering the mempool
+ bool hadNoDependencies; //!< Not dependent on any other txs when it entered the mempool
+ CAmount inChainInputValue; //!< Sum of all txin values that are already in blockchain
+ bool spendsCoinbase; //!< keep track of transactions that spend a coinbase
+ unsigned int sigOpCount; //!< Legacy sig ops plus P2SH sig op count
+ int64_t feeDelta; //!< Used for determining the priority of the transaction for mining in a block
+ LockPoints lockPoints; //!< Track the height and time at which tx was final
// Information about descendants of this transaction that are in the
// mempool; if we remove this transaction we must remove all of these
// descendants as well. if nCountWithDescendants is 0, treat this entry as
// dirty, and nSizeWithDescendants and nModFeesWithDescendants will not be
// correct.
- uint64_t nCountWithDescendants; //! number of descendant transactions
- uint64_t nSizeWithDescendants; //! ... and size
- CAmount nModFeesWithDescendants; //! ... and total fees (all including us)
+ uint64_t nCountWithDescendants; //!< number of descendant transactions
+ uint64_t nSizeWithDescendants; //!< ... and size
+ CAmount nModFeesWithDescendants; //!< ... and total fees (all including us)
// Analogous statistics for ancestor transactions
uint64_t nCountWithAncestors;
@@ -399,18 +399,18 @@ public:
class CTxMemPool
{
private:
- uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check.
+ uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check.
unsigned int nTransactionsUpdated;
CBlockPolicyEstimator* minerPolicyEstimator;
- uint64_t totalTxSize; //! sum of all mempool tx' byte sizes
- uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves)
+ uint64_t totalTxSize; //!< sum of all mempool tx' byte sizes
+ uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves)
CFeeRate minReasonableRelayFee;
mutable int64_t lastRollingFeeUpdate;
mutable bool blockSinceLastRollingFeeBump;
- mutable double rollingMinimumFeeRate; //! minimum fee to get into the pool, decreases exponentially
+ mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially
void trackPackageRemoved(const CFeeRate& rate);
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
index 91b40d9991..da590f8889 100644
--- a/src/utiltime.cpp
+++ b/src/utiltime.cpp
@@ -14,7 +14,7 @@
using namespace std;
-static int64_t nMockTime = 0; //! For unit testing
+static int64_t nMockTime = 0; //!< For unit testing
int64_t GetTime()
{
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 867f33a7b5..96d5d4e1e0 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -228,11 +228,11 @@ public:
mapValue_t mapValue;
std::vector<std::pair<std::string, std::string> > vOrderForm;
unsigned int fTimeReceivedIsTxTime;
- unsigned int nTimeReceived; //! time received by this node
+ unsigned int nTimeReceived; //!< time received by this node
unsigned int nTimeSmart;
char fFromMe;
std::string strFromAccount;
- int64_t nOrderPos; //! position in ordered transaction list
+ int64_t nOrderPos; //!< position in ordered transaction list
// memory only
mutable bool fDebitCached;
@@ -324,7 +324,7 @@ public:
}
READWRITE(*(CMerkleTx*)this);
- std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
+ std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
READWRITE(vUnused);
READWRITE(mapValue);
READWRITE(vOrderForm);
@@ -465,7 +465,7 @@ public:
std::string strOtherAccount;
std::string strComment;
mapValue_t mapValue;
- int64_t nOrderPos; //! position in ordered transaction list
+ int64_t nOrderPos; //!< position in ordered transaction list
uint64_t nEntryNo;
CAccountingEntry()