aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/devtools/README.md5
-rw-r--r--contrib/verify-commits/trusted-keys2
-rw-r--r--doc/build-osx.md2
-rw-r--r--doc/build-unix.md17
-rwxr-xr-xqa/pull-tester/rpc-tests.py1
-rwxr-xr-xqa/rpc-tests/disablewallet.py32
-rw-r--r--src/.clang-format3
-rw-r--r--src/consensus/consensus.h6
-rw-r--r--src/init.cpp15
-rw-r--r--src/leveldb/util/env_win.cc236
-rw-r--r--src/main.cpp119
-rw-r--r--src/main.h18
-rw-r--r--src/miner.cpp8
-rw-r--r--src/policy/policy.h3
-rw-r--r--src/primitives/transaction.h4
-rw-r--r--src/qt/coincontroldialog.cpp8
-rw-r--r--src/qt/guiutil.cpp19
-rw-r--r--src/qt/optionsdialog.cpp2
-rw-r--r--src/qt/sendcoinsdialog.cpp15
-rw-r--r--src/rest.cpp5
-rw-r--r--src/rpcblockchain.cpp4
-rw-r--r--src/rpcmisc.cpp4
-rw-r--r--src/rpcrawtransaction.cpp6
-rw-r--r--src/test/miner_tests.cpp7
-rw-r--r--src/test/transaction_tests.cpp19
-rw-r--r--src/wallet/rpcwallet.cpp17
-rw-r--r--src/wallet/wallet.cpp11
-rw-r--r--src/wallet/wallet.h9
-rw-r--r--src/zmq/zmqpublishnotifier.cpp4
29 files changed, 293 insertions, 308 deletions
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md
index 278794f14c..2e70c5adcc 100644
--- a/contrib/devtools/README.md
+++ b/contrib/devtools/README.md
@@ -62,6 +62,11 @@ optimize-pngs.py
A script to optimize png files in the bitcoin
repository (requires pngcrush).
+security-check.py and test-security-check.py
+============================================
+
+Perform basic ELF security checks on a series of executables.
+
symbol-check.py
===============
diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys
index a0dce7a8a5..fcf2b98e77 100644
--- a/contrib/verify-commits/trusted-keys
+++ b/contrib/verify-commits/trusted-keys
@@ -3,4 +3,4 @@
01CDF4627A3B88AAE4A571C87588242FBE38D3A8
AF8BE07C7049F3A26B239D5325B3083201782B2F
81291FA67D2C379A006A053FEAB5AF94D9E9ABE7
-133EAC179436F14A5CF1B794860FEB804E669320
+3F1888C6DCA92A6499C4911FDBA1A67379A1A931
diff --git a/doc/build-osx.md b/doc/build-osx.md
index 69c401b751..02498e5c4b 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -32,7 +32,7 @@ Instructions: Homebrew
#### Install dependencies using Homebrew
- brew install autoconf automake berkeley-db4 libtool boost miniupnpc openssl pkg-config protobuf qt5 libevent
+ brew install autoconf automake berkeley-db4 libtool boost miniupnpc openssl pkg-config protobuf qt5 libevent
NOTE: Building with Qt4 is still supported, however, could result in a broken UI. As such, building with Qt5 is recommended.
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 2102bbc830..57853a9c9d 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -61,24 +61,24 @@ Dependency Build Instructions: Ubuntu & Debian
----------------------------------------------
Build requirements:
- sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libevent-dev
+ sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libevent-dev
On Ubuntu 15.10+ there are generic names for the individual boost development
packages, so the following can be used to only install necessary parts of
boost:
- apt-get install libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libboost-base-dev
+ apt-get install libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libboost-base-dev
For Ubuntu before 15.10, or Debian 7 and later libboost-all-dev has to be installed:
- sudo apt-get install libboost-all-dev
+ sudo apt-get install libboost-all-dev
BerkeleyDB is required for the wallet. db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin).
You can add the repository and install using the following commands:
- sudo add-apt-repository ppa:bitcoin/bitcoin
- sudo apt-get update
- sudo apt-get install libdb4.8-dev libdb4.8++-dev
+ sudo add-apt-repository ppa:bitcoin/bitcoin
+ sudo apt-get update
+ sudo apt-get install libdb4.8-dev libdb4.8++-dev
Ubuntu and Debian have their own libdb-dev and libdb++-dev packages, but these will install
BerkeleyDB 5.1 or later, which break binary wallet compatibility with the distributed executables which
@@ -89,11 +89,11 @@ See the section "Disable-wallet mode" to build Bitcoin Core without wallet.
Optional:
- sudo apt-get install libminiupnpc-dev (see --with-miniupnpc and --enable-upnp-default)
+ sudo apt-get install libminiupnpc-dev (see --with-miniupnpc and --enable-upnp-default)
ZMQ dependencies:
- sudo apt-get install libzmq3-dev (provides ZMQ API 4.x)
+ sudo apt-get install libzmq3-dev (provides ZMQ API 4.x)
Dependencies for the GUI: Ubuntu & Debian
-----------------------------------------
@@ -213,6 +213,7 @@ Hardening enables the following features:
scanelf -e ./bitcoin
The output should contain:
+
TYPE
ET_DYN
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index 3059fee426..c23dcbdb7c 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -68,6 +68,7 @@ testScripts = [
'decodescript.py',
'p2p-fullblocktest.py',
'blockchain.py',
+ 'disablewallet.py',
]
testScriptsExt = [
'bip65-cltv.py',
diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py
new file mode 100755
index 0000000000..4cb01575e2
--- /dev/null
+++ b/qa/rpc-tests/disablewallet.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Exercise API with -disablewallet.
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+
+class DisableWalletTest (BitcoinTestFramework):
+
+ def setup_chain(self):
+ print("Initializing test directory "+self.options.tmpdir)
+ initialize_chain_clean(self.options.tmpdir, 1)
+
+ def setup_network(self, split=False):
+ self.nodes = start_nodes(1, self.options.tmpdir, [['-disablewallet']])
+ self.is_network_split = False
+ self.sync_all()
+
+ def run_test (self):
+ # Check regression: https://github.com/bitcoin/bitcoin/issues/6963#issuecomment-154548880
+ x = self.nodes[0].validateaddress('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy')
+ assert(x['isvalid'] == False)
+ x = self.nodes[0].validateaddress('mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ')
+ assert(x['isvalid'] == True)
+
+if __name__ == '__main__':
+ DisableWalletTest ().main ()
diff --git a/src/.clang-format b/src/.clang-format
index 226a15d185..129f062ef8 100644
--- a/src/.clang-format
+++ b/src/.clang-format
@@ -1,4 +1,6 @@
+Language: Cpp
AccessModifierOffset: -4
+AlignAfterOpenBracket: false
AlignEscapedNewlinesLeft: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
@@ -26,7 +28,6 @@ IndentCaseLabels: false
IndentFunctionDeclarationAfterType: false
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: false
-Language: Cpp
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index f937844e9f..6d6ce7e099 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -13,4 +13,10 @@ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static const int COINBASE_MATURITY = 100;
+/** Flags for LockTime() */
+enum {
+ /* Use GetMedianTimePast() instead of nTime for end point timestamp. */
+ LOCKTIME_MEDIAN_TIME_PAST = (1 << 1),
+};
+
#endif // BITCOIN_CONSENSUS_CONSENSUS_H
diff --git a/src/init.cpp b/src/init.cpp
index 4dd8090753..5f2dc8bf2f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -317,7 +317,7 @@ std::string HelpMessage(HelpMessageMode mode)
}
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
- strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file") + " " + _("on startup"));
+ strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"));
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
@@ -379,14 +379,14 @@ std::string HelpMessage(HelpMessageMode mode)
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
- strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup"));
- strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup"));
+ strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
+ strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat on startup"));
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)"), DEFAULT_TX_CONFIRM_TARGET));
strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"),
- CURRENCY_UNIT, FormatMoney(maxTxFee)));
- strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup"));
+ CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)));
+ 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"));
strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), true));
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
@@ -439,8 +439,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", 1));
strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit size of signature cache to <n> entries (default: %u)", 50000));
}
- strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying (default: %s)"),
- CURRENCY_UNIT, FormatMoney(::minRelayTxFee.GetFeePerK())));
+ strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)"),
+ CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)));
strUsage += HelpMessageOpt("-printtoconsole", _("Send trace/debug info to console instead of debug.log file"));
if (showDebug)
{
@@ -499,6 +499,7 @@ std::string HelpMessage(HelpMessageMode mode)
std::string LicenseInfo()
{
+ // todo: remove urls from translations on next change
return FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" +
"\n" +
FormatParagraph(_("This is experimental software.")) + "\n" +
diff --git a/src/leveldb/util/env_win.cc b/src/leveldb/util/env_win.cc
index ef2ecae830..e11a96b791 100644
--- a/src/leveldb/util/env_win.cc
+++ b/src/leveldb/util/env_win.cc
@@ -103,39 +103,20 @@ private:
DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile);
};
-class Win32MapFile : public WritableFile
+class Win32WritableFile : public WritableFile
{
public:
- Win32MapFile(const std::string& fname);
+ Win32WritableFile(const std::string& fname);
+ ~Win32WritableFile();
- ~Win32MapFile();
virtual Status Append(const Slice& data);
virtual Status Close();
virtual Status Flush();
virtual Status Sync();
BOOL isEnable();
private:
- std::string _filename;
- HANDLE _hFile;
- size_t _page_size;
- size_t _map_size; // How much extra memory to map at a time
- char* _base; // The mapped region
- HANDLE _base_handle;
- char* _limit; // Limit of the mapped region
- char* _dst; // Where to write next (in range [base_,limit_])
- char* _last_sync; // Where have we synced up to
- uint64_t _file_offset; // Offset of base_ in file
- //LARGE_INTEGER file_offset_;
- // Have we done an munmap of unsynced data?
- bool _pending_sync;
-
- // Roundup x to a multiple of y
- static size_t _Roundup(size_t x, size_t y);
- size_t _TruncateToPageBoundary(size_t s);
- bool _UnmapCurrentRegion();
- bool _MapNewRegion();
- DISALLOW_COPY_AND_ASSIGN(Win32MapFile);
- BOOL _Init(LPCWSTR Path);
+ std::string filename_;
+ ::HANDLE _hFile;
};
class Win32FileLock : public FileLock
@@ -442,202 +423,63 @@ void Win32RandomAccessFile::_CleanUp()
}
}
-size_t Win32MapFile::_Roundup( size_t x, size_t y )
+Win32WritableFile::Win32WritableFile(const std::string& fname)
+ : filename_(fname)
{
- return ((x + y - 1) / y) * y;
+ std::wstring path;
+ ToWidePath(fname, path);
+ DWORD Flag = PathFileExistsW(path.c_str()) ? OPEN_EXISTING : CREATE_ALWAYS;
+ _hFile = CreateFileW(path.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
+ NULL,
+ Flag,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ // CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use
}
-size_t Win32MapFile::_TruncateToPageBoundary( size_t s )
+Win32WritableFile::~Win32WritableFile()
{
- s -= (s & (_page_size - 1));
- assert((s % _page_size) == 0);
- return s;
+ if (_hFile != INVALID_HANDLE_VALUE)
+ Close();
}
-bool Win32MapFile::_UnmapCurrentRegion()
+Status Win32WritableFile::Append(const Slice& data)
{
- bool result = true;
- if (_base != NULL) {
- if (_last_sync < _limit) {
- // Defer syncing this data until next Sync() call, if any
- _pending_sync = true;
- }
- if (!UnmapViewOfFile(_base) || !CloseHandle(_base_handle))
- result = false;
- _file_offset += _limit - _base;
- _base = NULL;
- _base_handle = NULL;
- _limit = NULL;
- _last_sync = NULL;
- _dst = NULL;
- // Increase the amount we map the next time, but capped at 1MB
- if (_map_size < (1<<20)) {
- _map_size *= 2;
- }
+ DWORD r = 0;
+ if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) {
+ return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz());
}
- return result;
-}
-
-bool Win32MapFile::_MapNewRegion()
-{
- assert(_base == NULL);
- //LONG newSizeHigh = (LONG)((file_offset_ + map_size_) >> 32);
- //LONG newSizeLow = (LONG)((file_offset_ + map_size_) & 0xFFFFFFFF);
- DWORD off_hi = (DWORD)(_file_offset >> 32);
- DWORD off_lo = (DWORD)(_file_offset & 0xFFFFFFFF);
- LARGE_INTEGER newSize;
- newSize.QuadPart = _file_offset + _map_size;
- SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN);
- SetEndOfFile(_hFile);
-
- _base_handle = CreateFileMappingA(
- _hFile,
- NULL,
- PAGE_READWRITE,
- 0,
- 0,
- 0);
- if (_base_handle != NULL) {
- _base = (char*) MapViewOfFile(_base_handle,
- FILE_MAP_ALL_ACCESS,
- off_hi,
- off_lo,
- _map_size);
- if (_base != NULL) {
- _limit = _base + _map_size;
- _dst = _base;
- _last_sync = _base;
- return true;
- }
- }
- return false;
+ return Status::OK();
}
-Win32MapFile::Win32MapFile( const std::string& fname) :
- _filename(fname),
- _hFile(NULL),
- _page_size(Win32::g_PageSize),
- _map_size(_Roundup(65536, Win32::g_PageSize)),
- _base(NULL),
- _base_handle(NULL),
- _limit(NULL),
- _dst(NULL),
- _last_sync(NULL),
- _file_offset(0),
- _pending_sync(false)
+Status Win32WritableFile::Close()
{
- std::wstring path;
- ToWidePath(fname, path);
- _Init(path.c_str());
- assert((Win32::g_PageSize & (Win32::g_PageSize - 1)) == 0);
-}
-
-Status Win32MapFile::Append( const Slice& data )
-{
- const char* src = data.data();
- size_t left = data.size();
- Status s;
- while (left > 0) {
- assert(_base <= _dst);
- assert(_dst <= _limit);
- size_t avail = _limit - _dst;
- if (avail == 0) {
- if (!_UnmapCurrentRegion() ||
- !_MapNewRegion()) {
- return Status::IOError("WinMmapFile.Append::UnmapCurrentRegion or MapNewRegion: ", Win32::GetLastErrSz());
- }
- }
- size_t n = (left <= avail) ? left : avail;
- memcpy(_dst, src, n);
- _dst += n;
- src += n;
- left -= n;
- }
- return s;
-}
-
-Status Win32MapFile::Close()
-{
- Status s;
- size_t unused = _limit - _dst;
- if (!_UnmapCurrentRegion()) {
- s = Status::IOError("WinMmapFile.Close::UnmapCurrentRegion: ",Win32::GetLastErrSz());
- } else if (unused > 0) {
- // Trim the extra space at the end of the file
- LARGE_INTEGER newSize;
- newSize.QuadPart = _file_offset - unused;
- if (!SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN)) {
- s = Status::IOError("WinMmapFile.Close::SetFilePointer: ",Win32::GetLastErrSz());
- } else
- SetEndOfFile(_hFile);
- }
if (!CloseHandle(_hFile)) {
- if (s.ok()) {
- s = Status::IOError("WinMmapFile.Close::CloseHandle: ", Win32::GetLastErrSz());
- }
+ return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz());
}
_hFile = INVALID_HANDLE_VALUE;
- _base = NULL;
- _base_handle = NULL;
- _limit = NULL;
-
- return s;
-}
-
-Status Win32MapFile::Sync()
-{
- Status s;
- if (_pending_sync) {
- // Some unmapped data was not synced
- _pending_sync = false;
- if (!FlushFileBuffers(_hFile)) {
- s = Status::IOError("WinMmapFile.Sync::FlushFileBuffers: ",Win32::GetLastErrSz());
- }
- }
- if (_dst > _last_sync) {
- // Find the beginnings of the pages that contain the first and last
- // bytes to be synced.
- size_t p1 = _TruncateToPageBoundary(_last_sync - _base);
- size_t p2 = _TruncateToPageBoundary(_dst - _base - 1);
- _last_sync = _dst;
- if (!FlushViewOfFile(_base + p1, p2 - p1 + _page_size)) {
- s = Status::IOError("WinMmapFile.Sync::FlushViewOfFile: ",Win32::GetLastErrSz());
- }
- }
- return s;
+ return Status::OK();
}
-Status Win32MapFile::Flush()
+Status Win32WritableFile::Flush()
{
+ // Nothing to do here, there are no application-side buffers
return Status::OK();
}
-Win32MapFile::~Win32MapFile()
+Status Win32WritableFile::Sync()
{
- if (_hFile != INVALID_HANDLE_VALUE) {
- Win32MapFile::Close();
+ if (!FlushFileBuffers(_hFile)) {
+ return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz());
}
+ return Status::OK();
}
-BOOL Win32MapFile::_Init( LPCWSTR Path )
-{
- DWORD Flag = PathFileExistsW(Path) ? OPEN_EXISTING : CREATE_ALWAYS;
- _hFile = CreateFileW(Path,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
- NULL,
- Flag,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if(!_hFile || _hFile == INVALID_HANDLE_VALUE)
- return FALSE;
- else
- return TRUE;
-}
-
-BOOL Win32MapFile::isEnable()
+BOOL Win32WritableFile::isEnable()
{
- return _hFile ? TRUE : FALSE;
+ return _hFile != INVALID_HANDLE_VALUE;
}
Win32FileLock::Win32FileLock( const std::string& fname ) :
@@ -981,7 +823,7 @@ Status Win32Env::NewLogger( const std::string& fname, Logger** result )
{
Status sRet;
std::string path = fname;
- Win32MapFile* pMapFile = new Win32MapFile(ModifyPath(path));
+ Win32WritableFile* pMapFile = new Win32WritableFile(ModifyPath(path));
if(!pMapFile->isEnable()){
delete pMapFile;
*result = NULL;
@@ -995,7 +837,7 @@ Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** resul
{
Status sRet;
std::string path = fname;
- Win32MapFile* pFile = new Win32MapFile(ModifyPath(path));
+ Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path));
if(!pFile->isEnable()){
*result = NULL;
sRet = Status::IOError(fname,Win32::GetLastErrSz());
diff --git a/src/main.cpp b/src/main.cpp
index 26a22ae6fd..cd932b5d3a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -74,8 +74,8 @@ size_t nCoinCacheUsage = 5000 * 300;
uint64_t nPruneTarget = 0;
bool fAlerts = DEFAULT_ALERTS;
-/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
-CFeeRate minRelayTxFee = CFeeRate(1000);
+/** Fees smaller than this (in satoshi) are considered zero fee (for relaying, mining and transaction creation) */
+CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
CTxMemPool mempool(::minRelayTxFee);
@@ -92,7 +92,7 @@ void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
* in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards.
*/
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams);
-static void CheckBlockIndex();
+static void CheckBlockIndex(const Consensus::Params& consensusParams);
/** Constant stuff for coinbase transactions we create: */
CScript COINBASE_FLAGS;
@@ -650,10 +650,35 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true;
}
-bool CheckFinalTx(const CTransaction &tx)
+bool CheckFinalTx(const CTransaction &tx, int flags)
{
AssertLockHeld(cs_main);
- return IsFinalTx(tx, chainActive.Height() + 1, GetAdjustedTime());
+
+ // By convention a negative value for flags indicates that the
+ // current network-enforced consensus rules should be used. In
+ // a future soft-fork scenario that would mean checking which
+ // rules would be enforced for the next block and setting the
+ // appropriate flags. At the present time no soft-forks are
+ // scheduled, so no flags are set.
+ flags = std::max(flags, 0);
+
+ // CheckFinalTx() uses chainActive.Height()+1 to evaluate
+ // nLockTime because when IsFinalTx() is called within
+ // CBlock::AcceptBlock(), the height of the block *being*
+ // evaluated is what is used. Thus if we want to know if a
+ // transaction can be part of the *next* block, we need to call
+ // IsFinalTx() with one more than chainActive.Height().
+ const int nBlockHeight = chainActive.Height() + 1;
+
+ // Timestamps on the other hand don't get any special treatment,
+ // because we can't know what timestamp the next block will have,
+ // and there aren't timestamp applications where it matters.
+ // However this changes once median past time-locks are enforced:
+ const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
+ ? chainActive.Tip()->GetMedianTimePast()
+ : GetAdjustedTime();
+
+ return IsFinalTx(tx, nBlockHeight, nBlockTime);
}
unsigned int GetLegacySigOpCount(const CTransaction& tx)
@@ -797,7 +822,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
- if (!CheckFinalTx(tx))
+ if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
// is it already in the memory pool?
@@ -973,7 +998,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
}
/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
-bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
+bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow)
{
CBlockIndex *pindexSlow = NULL;
@@ -1019,7 +1044,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
if (pindexSlow) {
CBlock block;
- if (ReadBlockFromDisk(block, pindexSlow)) {
+ if (ReadBlockFromDisk(block, pindexSlow, consensusParams)) {
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
if (tx.GetHash() == hash) {
txOut = tx;
@@ -1064,7 +1089,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHea
return true;
}
-bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
+bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
{
block.SetNull();
@@ -1082,15 +1107,15 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
}
// Check the header
- if (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus()))
+ if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
return true;
}
-bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
+bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
{
- if (!ReadBlockFromDisk(block, pindex->GetBlockPos()))
+ if (!ReadBlockFromDisk(block, pindex->GetBlockPos(), consensusParams))
return false;
if (block.GetHash() != pindex->GetBlockHash())
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
@@ -2039,13 +2064,14 @@ void static UpdateTip(CBlockIndex *pindexNew) {
}
/** Disconnect chainActive's tip. You want to manually re-limit mempool size after this */
-bool static DisconnectTip(CValidationState &state) {
+bool static DisconnectTip(CValidationState& state, const Consensus::Params& consensusParams)
+{
CBlockIndex *pindexDelete = chainActive.Tip();
assert(pindexDelete);
mempool.check(pcoinsTip);
// Read block from disk.
CBlock block;
- if (!ReadBlockFromDisk(block, pindexDelete))
+ if (!ReadBlockFromDisk(block, pindexDelete, consensusParams))
return AbortNode(state, "Failed to read block");
// Apply the block atomically to the chain state.
int64_t nStart = GetTimeMicros();
@@ -2100,13 +2126,14 @@ static int64_t nTimePostConnect = 0;
* corresponding to pindexNew, to bypass loading it again from disk.
*/
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, const CBlock *pblock) {
+ const CChainParams& chainparams = Params();
assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip);
// Read block from disk.
int64_t nTime1 = GetTimeMicros();
CBlock block;
if (!pblock) {
- if (!ReadBlockFromDisk(block, pindexNew))
+ if (!ReadBlockFromDisk(block, pindexNew, chainparams.GetConsensus()))
return AbortNode(state, "Failed to read block");
pblock = &block;
}
@@ -2232,6 +2259,7 @@ static void PruneBlockIndexCandidates() {
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, const CBlock *pblock) {
+ const CChainParams& chainparams = Params();
AssertLockHeld(cs_main);
bool fInvalidFound = false;
const CBlockIndex *pindexOldTip = chainActive.Tip();
@@ -2240,7 +2268,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
// Disconnect active blocks which are no longer in the best chain.
bool fBlocksDisconnected = false;
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
- if (!DisconnectTip(state))
+ if (!DisconnectTip(state, chainparams.GetConsensus()))
return false;
fBlocksDisconnected = true;
}
@@ -2308,7 +2336,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
CBlockIndex *pindexNewTip = NULL;
CBlockIndex *pindexMostWork = NULL;
- const CChainParams& chainParams = Params();
+ const CChainParams& chainparams = Params();
do {
boost::this_thread::interruption_point();
@@ -2335,7 +2363,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
// Relay inventory, but don't relay old inventory during initial block download.
int nBlockEstimate = 0;
if (fCheckpointsEnabled)
- nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints());
+ nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints());
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
@@ -2347,7 +2375,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
uiInterface.NotifyBlockTip(hashNewTip);
}
} while(pindexMostWork != chainActive.Tip());
- CheckBlockIndex();
+ CheckBlockIndex(chainparams.GetConsensus());
// Write changes periodically to disk, after relay.
if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) {
@@ -2357,7 +2385,8 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) {
return true;
}
-bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
+bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex)
+{
AssertLockHeld(cs_main);
// Mark the block itself as invalid.
@@ -2372,7 +2401,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
setBlockIndexCandidates.erase(pindexWalk);
// ActivateBestChain considers blocks already in chainActive
// unconditionally valid already, so force disconnect away from it.
- if (!DisconnectTip(state)) {
+ if (!DisconnectTip(state, consensusParams)) {
return false;
}
}
@@ -2517,8 +2546,6 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
if (!fKnown) {
while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
- LogPrintf("Leaving block file %i: %s\n", nFile, vinfoBlockFile[nFile].ToString());
- FlushBlockFile(true);
nFile++;
if (vinfoBlockFile.size() <= nFile) {
vinfoBlockFile.resize(nFile + 1);
@@ -2528,7 +2555,14 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
pos.nPos = vinfoBlockFile[nFile].nSize;
}
- nLastBlockFile = nFile;
+ if (nFile != nLastBlockFile) {
+ if (!fKnown) {
+ LogPrintf("Leaving block file %i: %s\n", nFile, vinfoBlockFile[nFile].ToString());
+ }
+ FlushBlockFile(!fKnown);
+ nLastBlockFile = nFile;
+ }
+
vinfoBlockFile[nFile].AddBlock(nHeight, nTime);
if (fKnown)
vinfoBlockFile[nFile].nSize = std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize);
@@ -2723,10 +2757,15 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
const Consensus::Params& consensusParams = Params().GetConsensus();
// Check that all transactions are finalized
- BOOST_FOREACH(const CTransaction& tx, block.vtx)
- if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) {
+ BOOST_FOREACH(const CTransaction& tx, block.vtx) {
+ int nLockTimeFlags = 0;
+ int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
+ ? pindexPrev->GetMedianTimePast()
+ : block.GetBlockTime();
+ if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
return state.DoS(10, error("%s: contains a non-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal");
}
+ }
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
@@ -2869,6 +2908,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp)
{
+ const CChainParams& chainparams = Params();
// Preliminary checks
bool checked = CheckBlock(*pblock, state);
@@ -2886,7 +2926,7 @@ bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock*
if (pindex && pfrom) {
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
}
- CheckBlockIndex();
+ CheckBlockIndex(chainparams.GetConsensus());
if (!ret)
return error("%s: AcceptBlock FAILED", __func__);
}
@@ -3218,6 +3258,7 @@ CVerifyDB::~CVerifyDB()
bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
{
+ const CChainParams& chainparams = Params();
LOCK(cs_main);
if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL)
return true;
@@ -3242,7 +3283,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
break;
CBlock block;
// check level 0: read from disk
- if (!ReadBlockFromDisk(block, pindex))
+ if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 1: verify block validity
if (nCheckLevel >= 1 && !CheckBlock(block, state))
@@ -3282,7 +3323,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))));
pindex = chainActive.Next(pindex);
CBlock block;
- if (!ReadBlockFromDisk(block, pindex))
+ if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
if (!ConnectBlock(block, state, pindex, coins))
return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
@@ -3455,7 +3496,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
while (range.first != range.second) {
std::multimap<uint256, CDiskBlockPos>::iterator it = range.first;
- if (ReadBlockFromDisk(block, it->second))
+ if (ReadBlockFromDisk(block, it->second, chainparams.GetConsensus()))
{
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
head.ToString());
@@ -3482,9 +3523,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
return nLoaded > 0;
}
-void static CheckBlockIndex()
+void static CheckBlockIndex(const Consensus::Params& consensusParams)
{
- const Consensus::Params& consensusParams = Params().GetConsensus();
if (!fCheckBlockIndex) {
return;
}
@@ -3766,7 +3806,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
return true;
}
-void static ProcessGetData(CNode* pfrom)
+void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams)
{
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
@@ -3821,7 +3861,7 @@ void static ProcessGetData(CNode* pfrom)
{
// Send block from disk
CBlock block;
- if (!ReadBlockFromDisk(block, (*mi).second))
+ if (!ReadBlockFromDisk(block, (*mi).second, consensusParams))
assert(!"cannot load block from disk");
if (inv.type == MSG_BLOCK)
pfrom->PushMessage("block", block);
@@ -4213,7 +4253,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LogPrint("net", "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id);
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
- ProcessGetData(pfrom);
+ ProcessGetData(pfrom, chainparams.GetConsensus());
}
@@ -4479,7 +4519,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexLast), uint256());
}
- CheckBlockIndex();
+ CheckBlockIndex(chainparams.GetConsensus());
}
else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing
@@ -4763,6 +4803,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// requires LOCK(cs_vRecvMsg)
bool ProcessMessages(CNode* pfrom)
{
+ const CChainParams& chainparams = Params();
//if (fDebug)
// LogPrintf("%s(%u messages)\n", __func__, pfrom->vRecvMsg.size());
@@ -4777,7 +4818,7 @@ bool ProcessMessages(CNode* pfrom)
bool fOk = true;
if (!pfrom->vRecvGetData.empty())
- ProcessGetData(pfrom);
+ ProcessGetData(pfrom, chainparams.GetConsensus());
// this maintains the order of responses
if (!pfrom->vRecvGetData.empty()) return fOk;
@@ -4804,7 +4845,7 @@ bool ProcessMessages(CNode* pfrom)
it++;
// Scan for message start
- if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
+ if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), MESSAGE_START_SIZE) != 0) {
LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id);
fOk = false;
break;
@@ -4812,7 +4853,7 @@ bool ProcessMessages(CNode* pfrom)
// Read header
CMessageHeader& hdr = msg.hdr;
- if (!hdr.IsValid(Params().MessageStart()))
+ if (!hdr.IsValid(chainparams.MessageStart()))
{
LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
continue;
diff --git a/src/main.h b/src/main.h
index c3874be663..a82e3faa45 100644
--- a/src/main.h
+++ b/src/main.h
@@ -41,6 +41,8 @@ struct CNodeStateStats;
/** Default for accepting alerts from the P2P network. */
static const bool DEFAULT_ALERTS = true;
+/** Default for -minrelaytxfee, minimum relay fee for transactions */
+static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
/** Default for -limitancestorcount, max number of in-mempool ancestors */
@@ -192,7 +194,7 @@ bool IsInitialBlockDownload();
/** Format a string that describes several potential problems detected by the core */
std::string GetWarnings(const std::string& strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
-bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false);
+bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false);
/** Find the best known block, and make it the tip of the block chain */
bool ActivateBestChain(CValidationState &state, const CBlock *pblock = NULL);
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
@@ -311,8 +313,10 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
* Check if transaction will be final in the next block to be created.
*
* Calls IsFinalTx() with current block height and appropriate block time.
+ *
+ * See consensus/consensus.h for flag definitions.
*/
-bool CheckFinalTx(const CTransaction &tx);
+bool CheckFinalTx(const CTransaction &tx, int flags = -1);
/**
* Closure representing one script verification
@@ -351,9 +355,8 @@ public:
/** Functions for disk access for blocks */
bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart);
-bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
-bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
-
+bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
+bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
/** Functions for validating blocks and updating the block tree */
@@ -379,8 +382,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
/** Store block on disk. If dbp is non-NULL, the file is known to already reside on disk */
bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp);
-bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);
-
+bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex **ppindex= NULL);
class CBlockFileInfo
@@ -449,7 +451,7 @@ public:
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
/** Mark a block as invalid. */
-bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex);
+bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex);
/** Remove invalidity status from a block and its descendants. */
bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex);
diff --git a/src/miner.cpp b/src/miner.cpp
index 42c8bb970b..053d9cdbc4 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -148,6 +148,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1;
pblock->nTime = GetAdjustedTime();
+ const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
CCoinsViewCache view(pcoinsTip);
// Priority order to process transactions
@@ -162,7 +163,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
mi != mempool.mapTx.end(); ++mi)
{
const CTransaction& tx = mi->GetTx();
- if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, pblock->nTime))
+
+ int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
+ ? nMedianTimePast
+ : pblock->GetBlockTime();
+
+ if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff))
continue;
COrphan* porphan = NULL;
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 747c5ce8ce..f269e8d476 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -43,6 +43,9 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
/** For convenience, standard but not mandatory verify flags. */
static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
+/** Used as the flags parameter to CheckFinalTx() in non-consensus code */
+static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_MEDIAN_TIME_PAST;
+
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
/**
* Check for standard transaction types
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 2a457cdae7..98882d315e 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -143,8 +143,8 @@ public:
// to spend something, then we consider it dust.
// A typical spendable txout is 34 bytes big, and will
// need a CTxIn of at least 148 bytes to spend:
- // so dust is a spendable txout less than 546 satoshis
- // with default minRelayTxFee.
+ // so dust is a spendable txout less than
+ // 546*minRelayTxFee/1000 (in satoshis)
if (scriptPubKey.IsUnspendable())
return 0;
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 74bc8dbec9..81b2597c3b 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -636,21 +636,21 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
// tool tips
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("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::GetRequiredFee(1000))) + "<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 means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK()));
+ toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::GetRequiredFee(1000)));
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;
if (payTxFee.GetFeePerK() > 0)
- dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000;
+ dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000;
else
- dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), mempool.estimateFee(nTxConfirmTarget).GetFeePerK()) / 1000;
+ dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), mempool.estimateFee(nTxConfirmTarget).GetFeePerK()) / 1000;
QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
l3->setToolTip(toolTip4);
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 1c0056a7bd..845459b76a 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -581,12 +581,12 @@ TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* t
#ifdef WIN32
boost::filesystem::path static StartupShortcutPath()
{
- if (GetBoolArg("-testnet", false))
+ std::string chain = ChainNameFromCommandLine();
+ if (chain == CBaseChainParams::MAIN)
+ return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
+ if (chain == CBaseChainParams::TESTNET) // Remove this special case when CBaseChainParams::TESTNET = "testnet4"
return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin (testnet).lnk";
- else if (GetBoolArg("-regtest", false))
- return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin (regtest).lnk";
-
- return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
+ return GetSpecialFolderPath(CSIDL_STARTUP) / strprintf("Bitcoin (%s).lnk", chain);
}
bool GetStartOnSystemStartup()
@@ -719,15 +719,14 @@ bool SetStartOnSystemStartup(bool fAutoStart)
boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
if (!optionFile.good())
return false;
+ std::string chain = ChainNameFromCommandLine();
// Write a bitcoin.desktop file to the autostart directory:
optionFile << "[Desktop Entry]\n";
optionFile << "Type=Application\n";
- if (GetBoolArg("-testnet", false))
- optionFile << "Name=Bitcoin (testnet)\n";
- else if (GetBoolArg("-regtest", false))
- optionFile << "Name=Bitcoin (regtest)\n";
- else
+ if (chain == CBaseChainParams::MAIN)
optionFile << "Name=Bitcoin\n";
+ else
+ optionFile << strprintf("Name=Bitcoin (%s)\n", chain);
optionFile << "Exec=" << pszExePath << strprintf(" -min -testnet=%d -regtest=%d\n", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false));
optionFile << "Terminal=false\n";
optionFile << "Hidden=false\n";
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index f57c1203f6..d0191fa6d8 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -18,7 +18,7 @@
#include "txdb.h" // for -dbcache defaults
#ifdef ENABLE_WALLET
-#include "wallet/wallet.h" // for CWallet::minTxFee
+#include "wallet/wallet.h" // for CWallet::GetRequiredFee()
#endif
#include <boost/thread.hpp>
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index a083a6f80e..0ee08a1b0c 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -172,7 +172,7 @@ void SendCoinsDialog::setModel(WalletModel *model)
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
connect(ui->checkBoxFreeTx, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables()));
connect(ui->checkBoxFreeTx, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
- ui->customFee->setSingleStep(CWallet::minTxFee.GetFeePerK());
+ ui->customFee->setSingleStep(CWallet::GetRequiredFee(1000));
updateFeeSectionControls();
updateMinFeeLabel();
updateSmartFeeLabel();
@@ -312,8 +312,9 @@ void SendCoinsDialog::on_sendButton_clicked()
if(u != model->getOptionsModel()->getDisplayUnit())
alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount));
}
- questionString.append(tr("Total Amount %1<span style='font-size:10pt;font-weight:normal;'><br />(=%2)</span>")
- .arg(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), totalAmount))
+ questionString.append(tr("Total Amount %1")
+ .arg(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), totalAmount)));
+ questionString.append(QString("<span style='font-size:10pt;font-weight:normal;'><br />(=%2)</span>")
.arg(alternativeUnits.join(" " + tr("or") + "<br />")));
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
@@ -569,7 +570,7 @@ void SendCoinsDialog::on_buttonMinimizeFee_clicked()
void SendCoinsDialog::setMinimumFee()
{
ui->radioCustomPerKilobyte->setChecked(true);
- ui->customFee->setValue(CWallet::minTxFee.GetFeePerK());
+ ui->customFee->setValue(CWallet::GetRequiredFee(1000));
}
void SendCoinsDialog::updateFeeSectionControls()
@@ -621,8 +622,8 @@ void SendCoinsDialog::updateFeeMinimizedLabel()
void SendCoinsDialog::updateMinFeeLabel()
{
if (model && model->getOptionsModel())
- ui->checkBoxMinimumFee->setText(tr("Pay only the minimum fee of %1").arg(
- BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::minTxFee.GetFeePerK()) + "/kB")
+ ui->checkBoxMinimumFee->setText(tr("Pay only the required fee of %1").arg(
+ BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::GetRequiredFee(1000)) + "/kB")
);
}
@@ -635,7 +636,7 @@ void SendCoinsDialog::updateSmartFeeLabel()
CFeeRate feeRate = mempool.estimateFee(nBlocksToConfirm);
if (feeRate <= CFeeRate(0)) // not enough data => minfee
{
- ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::minTxFee.GetFeePerK()) + "/kB");
+ ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::GetRequiredFee(1000)) + "/kB");
ui->labelSmartFee2->show(); // (Smart fee not initialized yet. This usually takes a few blocks...)
ui->labelFeeEstimation->setText("");
}
diff --git a/src/rest.cpp b/src/rest.cpp
index c46d7a8bd2..5d69542a91 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chain.h"
+#include "chainparams.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "main.h"
@@ -223,7 +224,7 @@ static bool rest_block(HTTPRequest* req,
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)");
- if (!ReadBlockFromDisk(block, pblockindex))
+ if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}
@@ -360,7 +361,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
CTransaction tx;
uint256 hashBlock = uint256();
- if (!GetTransaction(hash, tx, hashBlock, true))
+ if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 146eb3905a..9c0e78f772 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -405,7 +405,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
- if(!ReadBlockFromDisk(block, pblockindex))
+ if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
if (!fVerbose)
@@ -824,7 +824,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
CBlockIndex* pblockindex = mapBlockIndex[hash];
- InvalidateBlock(state, pblockindex);
+ InvalidateBlock(state, Params().GetConsensus(), pblockindex);
}
if (state.IsValid()) {
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index 0f0457c5cf..0c656d5cf1 100644
--- a/src/rpcmisc.cpp
+++ b/src/rpcmisc.cpp
@@ -117,7 +117,7 @@ public:
UniValue obj(UniValue::VOBJ);
CPubKey vchPubKey;
obj.push_back(Pair("isscript", false));
- if (pwalletMain->GetPubKey(keyID, vchPubKey)) {
+ if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
}
@@ -128,7 +128,7 @@ public:
UniValue obj(UniValue::VOBJ);
CScript subscript;
obj.push_back(Pair("isscript", true));
- if (pwalletMain->GetCScript(scriptID, subscript)) {
+ if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
std::vector<CTxDestination> addresses;
txnouttype whichType;
int nRequired;
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 5f3363d097..11d9a6f2bb 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -186,7 +186,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp)
CTransaction tx;
uint256 hashBlock;
- if (!GetTransaction(hash, tx, hashBlock, true))
+ if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
string strHex = EncodeHexTx(tx);
@@ -256,7 +256,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp)
if (pblockindex == NULL)
{
CTransaction tx;
- if (!GetTransaction(oneTxid, tx, hashBlock, false) || hashBlock.IsNull())
+ if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock, false) || hashBlock.IsNull())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
if (!mapBlockIndex.count(hashBlock))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
@@ -264,7 +264,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp)
}
CBlock block;
- if(!ReadBlockFromDisk(block, pblockindex))
+ if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
unsigned int ntxFound = 0;
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 91a3a5738e..827525783a 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -4,6 +4,7 @@
#include "chainparams.h"
#include "coins.h"
+#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "main.h"
#include "miner.h"
@@ -229,7 +230,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = chainActive.Tip()->nHeight+1;
hash = tx.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(!CheckFinalTx(tx));
+ BOOST_CHECK(!CheckFinalTx(tx, LOCKTIME_MEDIAN_TIME_PAST));
// time locked
tx2.vin.resize(1);
@@ -243,7 +244,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx2.nLockTime = chainActive.Tip()->GetMedianTimePast()+1;
hash = tx2.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx2, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(!CheckFinalTx(tx2));
+ BOOST_CHECK(!CheckFinalTx(tx2, LOCKTIME_MEDIAN_TIME_PAST));
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
@@ -261,7 +262,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
//BOOST_CHECK(CheckFinalTx(tx2));
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
- BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3);
+ BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 2);
delete pblocktemplate;
chainActive.Tip()->nHeight--;
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index f9423bc0de..fb0df1aff4 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -342,11 +342,26 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
string reason;
BOOST_CHECK(IsStandardTx(t, reason));
- t.vout[0].nValue = 501; // dust
+ // Check dust with default relay fee:
+ CAmount nDustThreshold = 182 * minRelayTxFee.GetFeePerK()/1000 * 3;
+ BOOST_CHECK_EQUAL(nDustThreshold, 546);
+ // dust:
+ t.vout[0].nValue = nDustThreshold - 1;
BOOST_CHECK(!IsStandardTx(t, reason));
+ // not dust:
+ t.vout[0].nValue = nDustThreshold;
+ BOOST_CHECK(IsStandardTx(t, reason));
- t.vout[0].nValue = 2730; // not dust
+ // Check dust with odd relay fee to verify rounding:
+ // nDustThreshold = 182 * 1234 / 1000 * 3
+ minRelayTxFee = CFeeRate(1234);
+ // dust:
+ t.vout[0].nValue = 672 - 1;
+ BOOST_CHECK(!IsStandardTx(t, reason));
+ // not dust:
+ t.vout[0].nValue = 672;
BOOST_CHECK(IsStandardTx(t, reason));
+ minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
t.vout[0].scriptPubKey = CScript() << OP_1;
BOOST_CHECK(!IsStandardTx(t, reason));
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 30b854477b..d93050d98c 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1182,6 +1182,8 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
+ if (!fByAccounts)
+ obj.push_back(Pair("label", strAccount));
UniValue transactions(UniValue::VARR);
if (it != mapTally.end())
{
@@ -1235,7 +1237,8 @@ UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
" \"address\" : \"receivingaddress\", (string) The receiving address\n"
" \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
" \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
- " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
+ " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
+ " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
" }\n"
" ,...\n"
"]\n"
@@ -1271,7 +1274,8 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
" \"account\" : \"accountname\", (string) The account name of the receiving account\n"
" \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
- " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
+ " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
+ " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
" }\n"
" ,...\n"
"]\n"
@@ -1318,6 +1322,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
MaybePushAddress(entry, s.destination);
entry.push_back(Pair("category", "send"));
entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
+ if (pwalletMain->mapAddressBook.count(s.destination))
+ entry.push_back(Pair("label", pwalletMain->mapAddressBook[s.destination].name));
entry.push_back(Pair("vout", s.vout));
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
if (fLong)
@@ -1355,6 +1361,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
entry.push_back(Pair("category", "receive"));
}
entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
+ if (pwalletMain->mapAddressBook.count(r.destination))
+ entry.push_back(Pair("label", account));
entry.push_back(Pair("vout", r.vout));
if (fLong)
WalletTxToJSON(wtx, entry);
@@ -1423,6 +1431,7 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
" for 'send' and 'receive' category of transactions.\n"
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
+ " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
" \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
" from (for receiving funds, positive amounts), or went to (for sending funds,\n"
" negative amounts).\n"
@@ -1613,6 +1622,7 @@ UniValue listsinceblock(const UniValue& params, bool fHelp)
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
+ " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
" \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
" ],\n"
" \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
@@ -1700,7 +1710,8 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
" \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
" \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
" \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
- " \"amount\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n"
+ " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n"
+ " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
" \"vout\" : n, (numeric) the vout value\n"
" }\n"
" ,...\n"
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 93c7c7f247..d51b8ddaef 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1078,7 +1078,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
CBlock block;
- ReadBlockFromDisk(block, pindex);
+ ReadBlockFromDisk(block, pindex, Params().GetConsensus());
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
@@ -2118,6 +2118,11 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
return true;
}
+CAmount CWallet::GetRequiredFee(unsigned int nTxBytes)
+{
+ return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes));
+}
+
CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
{
// payTxFee is user-set "I want to pay this much"
@@ -2129,9 +2134,9 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge
if (nFeeNeeded == 0)
nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes);
// ... unless we don't have enough mempool data, in which case fall
- // back to a hard-coded fee
+ // back to the required fee
if (nFeeNeeded == 0)
- nFeeNeeded = minTxFee.GetFee(nTxBytes);
+ nFeeNeeded = GetRequiredFee(nTxBytes);
// prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee
if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes))
nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes);
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 7e8dcc2914..719f11f206 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -657,7 +657,16 @@ public:
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
static CFeeRate minTxFee;
+ /**
+ * Estimate the minimum fee considering user set parameters
+ * and the required fee
+ */
static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);
+ /**
+ * Return the minimum required fee taking into account the
+ * floating relay fee and user set minimum transaction fee
+ */
+ static CAmount GetRequiredFee(unsigned int nTxBytes);
bool NewKeyPool();
bool TopUpKeyPool(unsigned int kpSize = 0);
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index 4c3eb8f2d9..ac788843eb 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "chainparams.h"
#include "zmqpublishnotifier.h"
#include "main.h"
#include "util.h"
@@ -142,11 +143,12 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
LogPrint("zmq", "Publish raw block %s\n", pindex->GetBlockHash().GetHex());
+ const Consensus::Params& consensusParams = Params().GetConsensus();
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
{
LOCK(cs_main);
CBlock block;
- if(!ReadBlockFromDisk(block, pindex))
+ if(!ReadBlockFromDisk(block, pindex, consensusParams))
{
zmqError("Can't read block from disk");
return false;