Auto merge of #2099 - str4d:2074-misc, r=arcalinea
Bitcoin 0.12 misc PRs 1 Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#6198 - bitcoin/bitcoin#6206 - bitcoin/bitcoin#5927 - bitcoin/bitcoin#6213 - bitcoin/bitcoin#6061 - bitcoin/bitcoin#6283 (partial, remainder was pulled in #929) - bitcoin/bitcoin#6272 - bitcoin/bitcoin#6316 - bitcoin/bitcoin#6133 - bitcoin/bitcoin#6387 - bitcoin/bitcoin#6401 - bitcoin/bitcoin#6434 - bitcoin/bitcoin#6372 - bitcoin/bitcoin#6447 - bitcoin/bitcoin#6149 - bitcoin/bitcoin#6468 Part of #2074.
This commit is contained in:
commit
99c4c6de0c
|
@ -178,12 +178,13 @@ AC_ARG_ENABLE([debug],
|
||||||
[enable_debug=no])
|
[enable_debug=no])
|
||||||
|
|
||||||
if test "x$enable_debug" = xyes; then
|
if test "x$enable_debug" = xyes; then
|
||||||
|
CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER"
|
||||||
if test "x$GCC" = xyes; then
|
if test "x$GCC" = xyes; then
|
||||||
CFLAGS="-g3 -O0 -DDEBUG"
|
CFLAGS="$CFLAGS -g3 -O0"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$GXX" = xyes; then
|
if test "x$GXX" = xyes; then
|
||||||
CXXFLAGS="-g3 -O0 -DDEBUG"
|
CXXFLAGS="$CXXFLAGS -g3 -O0"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -193,7 +194,7 @@ fi
|
||||||
if test "x$CXXFLAGS_overridden" = "xno"; then
|
if test "x$CXXFLAGS_overridden" = "xno"; then
|
||||||
CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wno-self-assign"
|
CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wno-self-assign"
|
||||||
fi
|
fi
|
||||||
CPPFLAGS="$CPPFLAGS -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
|
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
|
||||||
|
|
||||||
AC_ARG_WITH([utils],
|
AC_ARG_WITH([utils],
|
||||||
[AS_HELP_STRING([--with-utils],
|
[AS_HELP_STRING([--with-utils],
|
||||||
|
|
|
@ -32,7 +32,11 @@ required_files="${BITCOIND_CONFIGFILE}"
|
||||||
start_stop_daemon_args="-u ${BITCOIND_USER} \
|
start_stop_daemon_args="-u ${BITCOIND_USER} \
|
||||||
-N ${BITCOIND_NICE} -w 2000"
|
-N ${BITCOIND_NICE} -w 2000"
|
||||||
pidfile="${BITCOIND_PIDFILE}"
|
pidfile="${BITCOIND_PIDFILE}"
|
||||||
retry=60
|
|
||||||
|
# The retry schedule to use when stopping the daemon. Could be either
|
||||||
|
# a timeout in seconds or multiple signal/timeout pairs (like
|
||||||
|
# "SIGKILL/180 SIGTERM/300")
|
||||||
|
retry="${BITCOIND_SIGTERM_TIMEOUT}"
|
||||||
|
|
||||||
depend() {
|
depend() {
|
||||||
need localmount net
|
need localmount net
|
||||||
|
|
|
@ -25,3 +25,9 @@
|
||||||
# Additional options (avoid -conf and -datadir, use flags above)
|
# Additional options (avoid -conf and -datadir, use flags above)
|
||||||
BITCOIND_OPTS="-disablewallet"
|
BITCOIND_OPTS="-disablewallet"
|
||||||
|
|
||||||
|
# The timeout in seconds OpenRC will wait for bitcoind to terminate
|
||||||
|
# after a SIGTERM has been raised.
|
||||||
|
# Note that this will be mapped as argument to start-stop-daemon's
|
||||||
|
# '--retry' option, which means you can specify a retry schedule
|
||||||
|
# here. For more information see man 8 start-stop-daemon.
|
||||||
|
BITCOIND_SIGTERM_TIMEOUT=60
|
||||||
|
|
|
@ -3,7 +3,7 @@ Construct a linear, no-fork, best version of the blockchain.
|
||||||
|
|
||||||
## Step 1: Download hash list
|
## Step 1: Download hash list
|
||||||
|
|
||||||
$ ./linearize-hashes.py linearize.cfg > hashlist.txt
|
$ ./linearize-hashes.py linearize.cfg > hashlist.txt
|
||||||
|
|
||||||
Required configuration file settings for linearize-hashes:
|
Required configuration file settings for linearize-hashes:
|
||||||
* RPC: rpcuser, rpcpassword
|
* RPC: rpcuser, rpcpassword
|
||||||
|
@ -14,7 +14,7 @@ Optional config file setting for linearize-hashes:
|
||||||
|
|
||||||
## Step 2: Copy local block data
|
## Step 2: Copy local block data
|
||||||
|
|
||||||
$ ./linearize-data.py linearize.cfg
|
$ ./linearize-data.py linearize.cfg
|
||||||
|
|
||||||
Required configuration file settings:
|
Required configuration file settings:
|
||||||
* "input": bitcoind blocks/ directory containing blkNNNNN.dat
|
* "input": bitcoind blocks/ directory containing blkNNNNN.dat
|
||||||
|
@ -26,7 +26,7 @@ output.
|
||||||
|
|
||||||
Optional config file setting for linearize-data:
|
Optional config file setting for linearize-data:
|
||||||
* "netmagic": network magic number
|
* "netmagic": network magic number
|
||||||
* "max_out_sz": maximum output file size (default 1000*1000*1000)
|
* "max_out_sz": maximum output file size (default `1000*1000*1000`)
|
||||||
* "split_timestamp": Split files when a new month is first seen, in addition to
|
* "split_timestamp": Split files when a new month is first seen, in addition to
|
||||||
reaching a maximum file size.
|
reaching a maximum file size.
|
||||||
* "file_timestamp": Set each file's last-modified time to that of the
|
* "file_timestamp": Set each file's last-modified time to that of the
|
||||||
|
|
|
@ -12,6 +12,7 @@ import json
|
||||||
import struct
|
import struct
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
import os.path
|
||||||
import base64
|
import base64
|
||||||
import httplib
|
import httplib
|
||||||
import sys
|
import sys
|
||||||
|
@ -115,19 +116,20 @@ class BlockDataCopier:
|
||||||
self.setFileTime = True
|
self.setFileTime = True
|
||||||
if settings['split_timestamp'] != 0:
|
if settings['split_timestamp'] != 0:
|
||||||
self.timestampSplit = True
|
self.timestampSplit = True
|
||||||
# Extents and cache for out-of-order blocks
|
# Extents and cache for out-of-order blocks
|
||||||
self.blockExtents = {}
|
self.blockExtents = {}
|
||||||
self.outOfOrderData = {}
|
self.outOfOrderData = {}
|
||||||
self.outOfOrderSize = 0 # running total size for items in outOfOrderData
|
self.outOfOrderSize = 0 # running total size for items in outOfOrderData
|
||||||
|
|
||||||
def writeBlock(self, inhdr, blk_hdr, rawblock):
|
def writeBlock(self, inhdr, blk_hdr, rawblock):
|
||||||
if not self.fileOutput and ((self.outsz + self.inLen) > self.maxOutSz):
|
blockSizeOnDisk = len(inhdr) + len(blk_hdr) + len(rawblock)
|
||||||
|
if not self.fileOutput and ((self.outsz + blockSizeOnDisk) > self.maxOutSz):
|
||||||
self.outF.close()
|
self.outF.close()
|
||||||
if self.setFileTime:
|
if self.setFileTime:
|
||||||
os.utime(outFname, (int(time.time()), highTS))
|
os.utime(outFname, (int(time.time()), highTS))
|
||||||
self.outF = None
|
self.outF = None
|
||||||
self.outFname = None
|
self.outFname = None
|
||||||
self.outFn = outFn + 1
|
self.outFn = self.outFn + 1
|
||||||
self.outsz = 0
|
self.outsz = 0
|
||||||
|
|
||||||
(blkDate, blkTS) = get_blk_dt(blk_hdr)
|
(blkDate, blkTS) = get_blk_dt(blk_hdr)
|
||||||
|
@ -147,7 +149,7 @@ class BlockDataCopier:
|
||||||
if self.fileOutput:
|
if self.fileOutput:
|
||||||
outFname = self.settings['output_file']
|
outFname = self.settings['output_file']
|
||||||
else:
|
else:
|
||||||
outFname = "%s/blk%05d.dat" % (self.settings['output'], outFn)
|
outFname = os.path.join(self.settings['output'], "blk%05d.dat" % self.outFn)
|
||||||
print("Output file " + outFname)
|
print("Output file " + outFname)
|
||||||
self.outF = open(outFname, "wb")
|
self.outF = open(outFname, "wb")
|
||||||
|
|
||||||
|
@ -165,7 +167,7 @@ class BlockDataCopier:
|
||||||
(self.blkCountIn, self.blkCountOut, len(self.blkindex), 100.0 * self.blkCountOut / len(self.blkindex)))
|
(self.blkCountIn, self.blkCountOut, len(self.blkindex), 100.0 * self.blkCountOut / len(self.blkindex)))
|
||||||
|
|
||||||
def inFileName(self, fn):
|
def inFileName(self, fn):
|
||||||
return "%s/blk%05d.dat" % (self.settings['input'], fn)
|
return os.path.join(self.settings['input'], "blk%05d.dat" % fn)
|
||||||
|
|
||||||
def fetchBlock(self, extent):
|
def fetchBlock(self, extent):
|
||||||
'''Fetch block contents from disk given extents'''
|
'''Fetch block contents from disk given extents'''
|
||||||
|
|
|
@ -68,10 +68,10 @@ class ProxyTest(BitcoinTestFramework):
|
||||||
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
|
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
|
||||||
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
|
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
|
||||||
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
|
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
|
||||||
['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0']
|
['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
|
||||||
])
|
])
|
||||||
|
|
||||||
def node_test(self, node, proxies, auth):
|
def node_test(self, node, proxies, auth, test_onion=True):
|
||||||
rv = []
|
rv = []
|
||||||
# Test: outgoing IPv4 connection through node
|
# Test: outgoing IPv4 connection through node
|
||||||
node.addnode("15.61.23.23:1234", "onetry")
|
node.addnode("15.61.23.23:1234", "onetry")
|
||||||
|
@ -99,17 +99,18 @@ class ProxyTest(BitcoinTestFramework):
|
||||||
assert_equal(cmd.password, None)
|
assert_equal(cmd.password, None)
|
||||||
rv.append(cmd)
|
rv.append(cmd)
|
||||||
|
|
||||||
# Test: outgoing onion connection through node
|
if test_onion:
|
||||||
node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
|
# Test: outgoing onion connection through node
|
||||||
cmd = proxies[2].queue.get()
|
node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
|
||||||
assert(isinstance(cmd, Socks5Command))
|
cmd = proxies[2].queue.get()
|
||||||
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
assert(isinstance(cmd, Socks5Command))
|
||||||
assert_equal(cmd.addr, "bitcoinostk4e4re.onion")
|
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
||||||
assert_equal(cmd.port, 8333)
|
assert_equal(cmd.addr, "bitcoinostk4e4re.onion")
|
||||||
if not auth:
|
assert_equal(cmd.port, 8333)
|
||||||
assert_equal(cmd.username, None)
|
if not auth:
|
||||||
assert_equal(cmd.password, None)
|
assert_equal(cmd.username, None)
|
||||||
rv.append(cmd)
|
assert_equal(cmd.password, None)
|
||||||
|
rv.append(cmd)
|
||||||
|
|
||||||
# Test: outgoing DNS name connection through node
|
# Test: outgoing DNS name connection through node
|
||||||
node.addnode("node.noumenon:8333", "onetry")
|
node.addnode("node.noumenon:8333", "onetry")
|
||||||
|
@ -139,8 +140,41 @@ class ProxyTest(BitcoinTestFramework):
|
||||||
assert_equal(len(credentials), 4)
|
assert_equal(len(credentials), 4)
|
||||||
|
|
||||||
# proxy on IPv6 localhost
|
# proxy on IPv6 localhost
|
||||||
self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False)
|
self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False)
|
||||||
|
|
||||||
|
def networks_dict(d):
|
||||||
|
r = {}
|
||||||
|
for x in d['networks']:
|
||||||
|
r[x['name']] = x
|
||||||
|
return r
|
||||||
|
|
||||||
|
# test RPC getnetworkinfo
|
||||||
|
n0 = networks_dict(self.nodes[0].getnetworkinfo())
|
||||||
|
for net in ['ipv4','ipv6','onion']:
|
||||||
|
assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr))
|
||||||
|
assert_equal(n0[net]['proxy_randomize_credentials'], True)
|
||||||
|
assert_equal(n0['onion']['reachable'], True)
|
||||||
|
|
||||||
|
n1 = networks_dict(self.nodes[1].getnetworkinfo())
|
||||||
|
for net in ['ipv4','ipv6']:
|
||||||
|
assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr))
|
||||||
|
assert_equal(n1[net]['proxy_randomize_credentials'], False)
|
||||||
|
assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr))
|
||||||
|
assert_equal(n1['onion']['proxy_randomize_credentials'], False)
|
||||||
|
assert_equal(n1['onion']['reachable'], True)
|
||||||
|
|
||||||
|
n2 = networks_dict(self.nodes[2].getnetworkinfo())
|
||||||
|
for net in ['ipv4','ipv6','onion']:
|
||||||
|
assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr))
|
||||||
|
assert_equal(n2[net]['proxy_randomize_credentials'], True)
|
||||||
|
assert_equal(n2['onion']['reachable'], True)
|
||||||
|
|
||||||
|
n3 = networks_dict(self.nodes[3].getnetworkinfo())
|
||||||
|
for net in ['ipv4','ipv6']:
|
||||||
|
assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
|
||||||
|
assert_equal(n3[net]['proxy_randomize_credentials'], False)
|
||||||
|
assert_equal(n3['onion']['reachable'], False)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ProxyTest().main()
|
ProxyTest().main()
|
||||||
|
|
||||||
|
|
|
@ -470,7 +470,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Return the number of (unique) addresses in all tables.
|
//! Return the number of (unique) addresses in all tables.
|
||||||
int size()
|
size_t size() const
|
||||||
{
|
{
|
||||||
return vRandom.size();
|
return vRandom.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ std::string CUnsignedAlert::ToString() const
|
||||||
BOOST_FOREACH(int n, setCancel)
|
BOOST_FOREACH(int n, setCancel)
|
||||||
strSetCancel += strprintf("%d ", n);
|
strSetCancel += strprintf("%d ", n);
|
||||||
std::string strSetSubVer;
|
std::string strSetSubVer;
|
||||||
BOOST_FOREACH(std::string str, setSubVer)
|
BOOST_FOREACH(const std::string& str, setSubVer)
|
||||||
strSetSubVer += "\"" + str + "\" ";
|
strSetSubVer += "\"" + str + "\" ";
|
||||||
return strprintf(
|
return strprintf(
|
||||||
"CAlert(\n"
|
"CAlert(\n"
|
||||||
|
@ -112,7 +112,7 @@ bool CAlert::Cancels(const CAlert& alert) const
|
||||||
return (alert.nID <= nCancel || setCancel.count(alert.nID));
|
return (alert.nID <= nCancel || setCancel.count(alert.nID));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
|
bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const
|
||||||
{
|
{
|
||||||
// TODO: rework for client-version-embedded-in-strSubVer ?
|
// TODO: rework for client-version-embedded-in-strSubVer ?
|
||||||
return (IsInEffect() &&
|
return (IsInEffect() &&
|
||||||
|
|
|
@ -97,7 +97,7 @@ public:
|
||||||
uint256 GetHash() const;
|
uint256 GetHash() const;
|
||||||
bool IsInEffect() const;
|
bool IsInEffect() const;
|
||||||
bool Cancels(const CAlert& alert) const;
|
bool Cancels(const CAlert& alert) const;
|
||||||
bool AppliesTo(int nVersion, std::string strSubVerIn) const;
|
bool AppliesTo(int nVersion, const std::string& strSubVerIn) const;
|
||||||
bool AppliesToMe() const;
|
bool AppliesToMe() const;
|
||||||
bool RelayTo(CNode* pnode) const;
|
bool RelayTo(CNode* pnode) const;
|
||||||
bool CheckSignature(const std::vector<unsigned char>& alertKey) const;
|
bool CheckSignature(const std::vector<unsigned char>& alertKey) const;
|
||||||
|
|
10
src/amount.h
10
src/amount.h
|
@ -16,7 +16,15 @@ typedef int64_t CAmount;
|
||||||
static const CAmount COIN = 100000000;
|
static const CAmount COIN = 100000000;
|
||||||
static const CAmount CENT = 1000000;
|
static const CAmount CENT = 1000000;
|
||||||
|
|
||||||
/** No amount larger than this (in satoshi) is valid */
|
/** No amount larger than this (in satoshi) is valid.
|
||||||
|
*
|
||||||
|
* Note that this constant is *not* the total money supply, which in Bitcoin
|
||||||
|
* currently happens to be less than 21,000,000 BTC for various reasons, but
|
||||||
|
* rather a sanity check. As this sanity check is used by consensus-critical
|
||||||
|
* validation code, the exact value of the MAX_MONEY constant is consensus
|
||||||
|
* critical; in unusual circumstances like a(nother) overflow bug that allowed
|
||||||
|
* for the creation of coins out of thin air modification could lead to a fork.
|
||||||
|
* */
|
||||||
static const CAmount MAX_MONEY = 21000000 * COIN;
|
static const CAmount MAX_MONEY = 21000000 * COIN;
|
||||||
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
|
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,10 @@ public:
|
||||||
|
|
||||||
K GetKey() {
|
K GetKey() {
|
||||||
K ret;
|
K ret;
|
||||||
ret.Decode(&vchData[0], &vchData[Size]);
|
if (vchData.size() == Size) {
|
||||||
|
//if base58 encouded data not holds a ext key, return a !IsValid() key
|
||||||
|
ret.Decode(&vchData[0]);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +182,10 @@ public:
|
||||||
SetKey(key);
|
SetKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBitcoinExtKeyBase(const std::string& strBase58c) {
|
||||||
|
SetString(strBase58c.c_str(), Params().Base58Prefix(Type).size());
|
||||||
|
}
|
||||||
|
|
||||||
CBitcoinExtKeyBase() {}
|
CBitcoinExtKeyBase() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,15 @@ int CommandLineRPC(int argc, char *argv[])
|
||||||
throw CConnectionFailed("server in warmup");
|
throw CConnectionFailed("server in warmup");
|
||||||
strPrint = "error: " + error.write();
|
strPrint = "error: " + error.write();
|
||||||
nRet = abs(code);
|
nRet = abs(code);
|
||||||
|
if (error.isObject())
|
||||||
|
{
|
||||||
|
UniValue errCode = find_value(error, "code");
|
||||||
|
UniValue errMsg = find_value(error, "message");
|
||||||
|
strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n";
|
||||||
|
|
||||||
|
if (errMsg.isStr())
|
||||||
|
strPrint += "error message:\n"+errMsg.get_str();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Result
|
// Result
|
||||||
if (result.isNull())
|
if (result.isNull())
|
||||||
|
|
|
@ -82,9 +82,10 @@ CBlockIndex* CBlockIndex::GetAncestor(int height)
|
||||||
while (heightWalk > height) {
|
while (heightWalk > height) {
|
||||||
int heightSkip = GetSkipHeight(heightWalk);
|
int heightSkip = GetSkipHeight(heightWalk);
|
||||||
int heightSkipPrev = GetSkipHeight(heightWalk - 1);
|
int heightSkipPrev = GetSkipHeight(heightWalk - 1);
|
||||||
if (heightSkip == height ||
|
if (pindexWalk->pskip != NULL &&
|
||||||
(heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
|
(heightSkip == height ||
|
||||||
heightSkipPrev >= height))) {
|
(heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
|
||||||
|
heightSkipPrev >= height)))) {
|
||||||
// Only follow pskip if pprev->pskip isn't better than pskip->pprev.
|
// Only follow pskip if pprev->pskip isn't better than pskip->pprev.
|
||||||
pindexWalk = pindexWalk->pskip;
|
pindexWalk = pindexWalk->pskip;
|
||||||
heightWalk = heightSkip;
|
heightWalk = heightSkip;
|
||||||
|
|
|
@ -24,15 +24,6 @@ namespace Checkpoints {
|
||||||
*/
|
*/
|
||||||
static const double SIGCHECK_VERIFICATION_FACTOR = 5.0;
|
static const double SIGCHECK_VERIFICATION_FACTOR = 5.0;
|
||||||
|
|
||||||
bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash)
|
|
||||||
{
|
|
||||||
const MapCheckpoints& checkpoints = data.mapCheckpoints;
|
|
||||||
|
|
||||||
MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
|
|
||||||
if (i == checkpoints.end()) return true;
|
|
||||||
return hash == i->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Guess how far we are in the verification process at the given block index
|
//! Guess how far we are in the verification process at the given block index
|
||||||
double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex *pindex, bool fSigchecks) {
|
double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex *pindex, bool fSigchecks) {
|
||||||
if (pindex==NULL)
|
if (pindex==NULL)
|
||||||
|
|
|
@ -26,9 +26,6 @@ struct CCheckpointData {
|
||||||
double fTransactionsPerDay;
|
double fTransactionsPerDay;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Returns true if block passes checkpoint checks
|
|
||||||
bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash);
|
|
||||||
|
|
||||||
//! Return conservative estimate of total number of blocks, 0 if unknown
|
//! Return conservative estimate of total number of blocks, 0 if unknown
|
||||||
int GetTotalBlocksEstimate(const CCheckpointData& data);
|
int GetTotalBlocksEstimate(const CCheckpointData& data);
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
unsigned char _chRejectCode=0, std::string _strRejectReason="") {
|
unsigned char _chRejectCode=0, std::string _strRejectReason="") {
|
||||||
return DoS(0, ret, _chRejectCode, _strRejectReason);
|
return DoS(0, ret, _chRejectCode, _strRejectReason);
|
||||||
}
|
}
|
||||||
virtual bool Error(std::string strRejectReasonIn="") {
|
virtual bool Error(const std::string& strRejectReasonIn) {
|
||||||
if (mode == MODE_VALID)
|
if (mode == MODE_VALID)
|
||||||
strRejectReason = strRejectReasonIn;
|
strRejectReason = strRejectReasonIn;
|
||||||
mode = MODE_ERROR;
|
mode = MODE_ERROR;
|
||||||
|
|
|
@ -15,7 +15,7 @@ class uint256;
|
||||||
class UniValue;
|
class UniValue;
|
||||||
|
|
||||||
// core_read.cpp
|
// core_read.cpp
|
||||||
extern CScript ParseScript(std::string s);
|
extern CScript ParseScript(const std::string& s);
|
||||||
extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
|
extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
|
||||||
extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
|
extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
|
||||||
extern uint256 ParseHashUV(const UniValue& v, const std::string& strName);
|
extern uint256 ParseHashUV(const UniValue& v, const std::string& strName);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CScript ParseScript(std::string s)
|
CScript ParseScript(const std::string& s)
|
||||||
{
|
{
|
||||||
CScript result;
|
CScript result;
|
||||||
|
|
||||||
|
|
77
src/init.cpp
77
src/init.cpp
|
@ -357,7 +357,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
strUsage += HelpMessageOpt("-timeout=<n>", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT));
|
strUsage += HelpMessageOpt("-timeout=<n>", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT));
|
||||||
#ifdef USE_UPNP
|
#ifdef USE_UPNP
|
||||||
#if USE_UPNP
|
#if USE_UPNP
|
||||||
strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening)"));
|
strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening and no -proxy)"));
|
||||||
#else
|
#else
|
||||||
strUsage += HelpMessageOpt("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), 0));
|
strUsage += HelpMessageOpt("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), 0));
|
||||||
#endif
|
#endif
|
||||||
|
@ -387,7 +387,6 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
|
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
|
||||||
strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
|
strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
|
||||||
" " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
|
" " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_ZMQ
|
#if ENABLE_ZMQ
|
||||||
|
@ -401,7 +400,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
|
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
|
||||||
if (showDebug)
|
if (showDebug)
|
||||||
{
|
{
|
||||||
strUsage += HelpMessageOpt("-checkpoints", strprintf("Only accept block chain matching built-in checkpoints (default: %u)", 1));
|
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", 1));
|
||||||
strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)", 100));
|
strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)", 100));
|
||||||
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", 0));
|
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", 0));
|
||||||
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", 0));
|
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", 0));
|
||||||
|
@ -446,6 +445,8 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), 0));
|
strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), 0));
|
||||||
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
|
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
|
||||||
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
|
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
|
||||||
|
if (GetBoolArg("-help-debug", false))
|
||||||
|
strUsage += HelpMessageOpt("-blockversion=<n>", strprintf("Override block version to test forking scenarios (default: %d)", (int)CBlock::CURRENT_VERSION));
|
||||||
|
|
||||||
#ifdef ENABLE_MINING
|
#ifdef ENABLE_MINING
|
||||||
strUsage += HelpMessageGroup(_("Mining options:"));
|
strUsage += HelpMessageGroup(_("Mining options:"));
|
||||||
|
@ -612,7 +613,7 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -loadblock=
|
// -loadblock=
|
||||||
BOOST_FOREACH(boost::filesystem::path &path, vImportFiles) {
|
BOOST_FOREACH(const boost::filesystem::path& path, vImportFiles) {
|
||||||
FILE *file = fopen(path.string().c_str(), "rb");
|
FILE *file = fopen(path.string().c_str(), "rb");
|
||||||
if (file) {
|
if (file) {
|
||||||
CImportingNow imp;
|
CImportingNow imp;
|
||||||
|
@ -766,6 +767,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
fLogTimestamps = GetBoolArg("-logtimestamps", true);
|
fLogTimestamps = GetBoolArg("-logtimestamps", true);
|
||||||
fLogIPs = GetBoolArg("-logips", false);
|
fLogIPs = GetBoolArg("-logips", false);
|
||||||
|
|
||||||
|
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
||||||
|
LogPrintf("Zcash version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
|
||||||
|
|
||||||
// when specifying an explicit binding address, you want to listen on it
|
// when specifying an explicit binding address, you want to listen on it
|
||||||
// even when -connect or -proxy is specified
|
// even when -connect or -proxy is specified
|
||||||
if (mapArgs.count("-bind")) {
|
if (mapArgs.count("-bind")) {
|
||||||
|
@ -1030,8 +1034,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
#endif
|
#endif
|
||||||
if (GetBoolArg("-shrinkdebugfile", !fDebug))
|
if (GetBoolArg("-shrinkdebugfile", !fDebug))
|
||||||
ShrinkDebugFile();
|
ShrinkDebugFile();
|
||||||
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
|
||||||
LogPrintf("Zcash version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
|
if (fPrintToDebugLog)
|
||||||
|
OpenDebugLog();
|
||||||
|
|
||||||
LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
|
LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
|
LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
|
||||||
|
@ -1096,15 +1102,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
|
|
||||||
std::string warningString;
|
std::string warningString;
|
||||||
std::string errorString;
|
std::string errorString;
|
||||||
|
|
||||||
if (!CWallet::Verify(strWalletFile, warningString, errorString))
|
if (!CWallet::Verify(strWalletFile, warningString, errorString))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!warningString.empty())
|
if (!warningString.empty())
|
||||||
InitWarning(warningString);
|
InitWarning(warningString);
|
||||||
if (!errorString.empty())
|
if (!errorString.empty())
|
||||||
return InitError(warningString);
|
return InitError(warningString);
|
||||||
|
|
||||||
} // (!fDisableWallet)
|
} // (!fDisableWallet)
|
||||||
#endif // ENABLE_WALLET
|
#endif // ENABLE_WALLET
|
||||||
// ********************************************************* Step 6: network initialization
|
// ********************************************************* Step 6: network initialization
|
||||||
|
@ -1113,7 +1119,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
|
|
||||||
if (mapArgs.count("-onlynet")) {
|
if (mapArgs.count("-onlynet")) {
|
||||||
std::set<enum Network> nets;
|
std::set<enum Network> nets;
|
||||||
BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) {
|
BOOST_FOREACH(const std::string& snet, mapMultiArgs["-onlynet"]) {
|
||||||
enum Network net = ParseNetwork(snet);
|
enum Network net = ParseNetwork(snet);
|
||||||
if (net == NET_UNROUTABLE)
|
if (net == NET_UNROUTABLE)
|
||||||
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
|
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
|
||||||
|
@ -1135,31 +1141,36 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyType addrProxy;
|
bool proxyRandomize = GetBoolArg("-proxyrandomize", true);
|
||||||
bool fProxy = false;
|
// -proxy sets a proxy for all outgoing network traffic
|
||||||
if (mapArgs.count("-proxy")) {
|
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
|
||||||
addrProxy = proxyType(CService(mapArgs["-proxy"], 9050), GetBoolArg("-proxyrandomize", true));
|
std::string proxyArg = GetArg("-proxy", "");
|
||||||
|
if (proxyArg != "" && proxyArg != "0") {
|
||||||
|
proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize);
|
||||||
if (!addrProxy.IsValid())
|
if (!addrProxy.IsValid())
|
||||||
return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"]));
|
return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg));
|
||||||
|
|
||||||
SetProxy(NET_IPV4, addrProxy);
|
SetProxy(NET_IPV4, addrProxy);
|
||||||
SetProxy(NET_IPV6, addrProxy);
|
SetProxy(NET_IPV6, addrProxy);
|
||||||
|
SetProxy(NET_TOR, addrProxy);
|
||||||
SetNameProxy(addrProxy);
|
SetNameProxy(addrProxy);
|
||||||
fProxy = true;
|
SetReachable(NET_TOR); // by default, -proxy sets onion as reachable, unless -noonion later
|
||||||
}
|
}
|
||||||
|
|
||||||
// -onion can override normal proxy, -noonion disables connecting to .onion entirely
|
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
|
||||||
if (!(mapArgs.count("-onion") && mapArgs["-onion"] == "0") &&
|
// -noonion (or -onion=0) disables connecting to .onion entirely
|
||||||
(fProxy || mapArgs.count("-onion"))) {
|
// An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none)
|
||||||
proxyType addrOnion;
|
std::string onionArg = GetArg("-onion", "");
|
||||||
if (!mapArgs.count("-onion"))
|
if (onionArg != "") {
|
||||||
addrOnion = addrProxy;
|
if (onionArg == "0") { // Handle -noonion/-onion=0
|
||||||
else
|
SetReachable(NET_TOR, false); // set onions as unreachable
|
||||||
addrOnion = proxyType(CService(mapArgs["-onion"], 9050), GetBoolArg("-proxyrandomize", true));
|
} else {
|
||||||
if (!addrOnion.IsValid())
|
proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize);
|
||||||
return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"]));
|
if (!addrOnion.IsValid())
|
||||||
SetProxy(NET_TOR, addrOnion);
|
return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg));
|
||||||
SetReachable(NET_TOR);
|
SetProxy(NET_TOR, addrOnion);
|
||||||
|
SetReachable(NET_TOR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// see Step 2: parameter interactions for more information about these
|
// see Step 2: parameter interactions for more information about these
|
||||||
|
@ -1170,13 +1181,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
bool fBound = false;
|
bool fBound = false;
|
||||||
if (fListen) {
|
if (fListen) {
|
||||||
if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
|
if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
|
||||||
BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
|
BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-bind"]) {
|
||||||
CService addrBind;
|
CService addrBind;
|
||||||
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
|
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
|
||||||
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind));
|
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind));
|
||||||
fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR));
|
fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR));
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(std::string strBind, mapMultiArgs["-whitebind"]) {
|
BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-whitebind"]) {
|
||||||
CService addrBind;
|
CService addrBind;
|
||||||
if (!Lookup(strBind.c_str(), addrBind, 0, false))
|
if (!Lookup(strBind.c_str(), addrBind, 0, false))
|
||||||
return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind));
|
return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind));
|
||||||
|
@ -1196,7 +1207,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapArgs.count("-externalip")) {
|
if (mapArgs.count("-externalip")) {
|
||||||
BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) {
|
BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) {
|
||||||
CService addrLocal(strAddr, GetListenPort(), fNameLookup);
|
CService addrLocal(strAddr, GetListenPort(), fNameLookup);
|
||||||
if (!addrLocal.IsValid())
|
if (!addrLocal.IsValid())
|
||||||
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr));
|
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr));
|
||||||
|
@ -1204,7 +1215,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"])
|
BOOST_FOREACH(const std::string& strDest, mapMultiArgs["-seednode"])
|
||||||
AddOneShot(strDest);
|
AddOneShot(strDest);
|
||||||
|
|
||||||
#if ENABLE_ZMQ
|
#if ENABLE_ZMQ
|
||||||
|
@ -1572,7 +1583,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
std::vector<boost::filesystem::path> vImportFiles;
|
std::vector<boost::filesystem::path> vImportFiles;
|
||||||
if (mapArgs.count("-loadblock"))
|
if (mapArgs.count("-loadblock"))
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"])
|
BOOST_FOREACH(const std::string& strFile, mapMultiArgs["-loadblock"])
|
||||||
vImportFiles.push_back(strFile);
|
vImportFiles.push_back(strFile);
|
||||||
}
|
}
|
||||||
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
|
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
|
||||||
|
|
93
src/main.cpp
93
src/main.cpp
|
@ -740,7 +740,7 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
|
||||||
/**
|
/**
|
||||||
* Check transaction inputs to mitigate two
|
* Check transaction inputs to mitigate two
|
||||||
* potential denial-of-service attacks:
|
* potential denial-of-service attacks:
|
||||||
*
|
*
|
||||||
* 1. scriptSigs with extra data stuffed into them,
|
* 1. scriptSigs with extra data stuffed into them,
|
||||||
* not consumed by scriptPubKey (or P2SH script)
|
* not consumed by scriptPubKey (or P2SH script)
|
||||||
* 2. P2SH scripts with a crazy number of expensive
|
* 2. P2SH scripts with a crazy number of expensive
|
||||||
|
@ -1607,13 +1607,16 @@ bool CScriptCheck::operator()() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector<CScriptCheck> *pvChecks)
|
int GetSpendHeight(const CCoinsViewCache& inputs)
|
||||||
{
|
{
|
||||||
if (!tx.IsCoinBase())
|
LOCK(cs_main);
|
||||||
{
|
CBlockIndex* pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second;
|
||||||
if (pvChecks)
|
return pindexPrev->nHeight + 1;
|
||||||
pvChecks->reserve(tx.vin.size());
|
}
|
||||||
|
|
||||||
|
namespace Consensus {
|
||||||
|
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams)
|
||||||
|
{
|
||||||
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
|
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
|
||||||
// for an attacker to attempt to split the network.
|
// for an attacker to attempt to split the network.
|
||||||
if (!inputs.HaveInputs(tx))
|
if (!inputs.HaveInputs(tx))
|
||||||
|
@ -1632,6 +1635,13 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c
|
||||||
assert(coins);
|
assert(coins);
|
||||||
|
|
||||||
if (coins->IsCoinBase()) {
|
if (coins->IsCoinBase()) {
|
||||||
|
// Ensure that coinbases are matured
|
||||||
|
if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) {
|
||||||
|
return state.Invalid(
|
||||||
|
error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),
|
||||||
|
REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that coinbases cannot be spent to transparent outputs
|
// Ensure that coinbases cannot be spent to transparent outputs
|
||||||
// Disabled on regtest
|
// Disabled on regtest
|
||||||
if (fCoinbaseEnforcedProtectionEnabled &&
|
if (fCoinbaseEnforcedProtectionEnabled &&
|
||||||
|
@ -1670,6 +1680,19 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c
|
||||||
if (!MoneyRange(nFees))
|
if (!MoneyRange(nFees))
|
||||||
return state.DoS(100, error("CheckInputs(): nFees out of range"),
|
return state.DoS(100, error("CheckInputs(): nFees out of range"),
|
||||||
REJECT_INVALID, "bad-txns-fee-outofrange");
|
REJECT_INVALID, "bad-txns-fee-outofrange");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}// namespace Consensus
|
||||||
|
|
||||||
|
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector<CScriptCheck> *pvChecks)
|
||||||
|
{
|
||||||
|
if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), consensusParams))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!tx.IsCoinBase())
|
||||||
|
{
|
||||||
|
if (pvChecks)
|
||||||
|
pvChecks->reserve(tx.vin.size());
|
||||||
|
|
||||||
// The first loop above does all the inexpensive checks.
|
// The first loop above does all the inexpensive checks.
|
||||||
// Only if ALL inputs pass do we perform expensive ECDSA signature checks.
|
// Only if ALL inputs pass do we perform expensive ECDSA signature checks.
|
||||||
|
@ -1718,40 +1741,6 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector<CScriptCheck> *pvChecks)
|
|
||||||
{
|
|
||||||
if (!NonContextualCheckInputs(tx, state, inputs, fScriptChecks, flags, cacheStore, consensusParams, pvChecks)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tx.IsCoinBase())
|
|
||||||
{
|
|
||||||
// While checking, GetBestBlock() refers to the parent block.
|
|
||||||
// This is also true for mempool checks.
|
|
||||||
CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second;
|
|
||||||
int nSpendHeight = pindexPrev->nHeight + 1;
|
|
||||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
|
||||||
{
|
|
||||||
const COutPoint &prevout = tx.vin[i].prevout;
|
|
||||||
const CCoins *coins = inputs.AccessCoins(prevout.hash);
|
|
||||||
// Assertion is okay because NonContextualCheckInputs ensures the inputs
|
|
||||||
// are available.
|
|
||||||
assert(coins);
|
|
||||||
|
|
||||||
// If prev is coinbase, check that it's matured
|
|
||||||
if (coins->IsCoinBase()) {
|
|
||||||
if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) {
|
|
||||||
return state.Invalid(
|
|
||||||
error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),
|
|
||||||
REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
|
bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
|
||||||
|
@ -2044,7 +2033,15 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
|
|
||||||
bool fExpensiveChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()));
|
bool fExpensiveChecks = true;
|
||||||
|
if (fCheckpointsEnabled) {
|
||||||
|
CBlockIndex *pindexLastCheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints());
|
||||||
|
if (pindexLastCheckpoint && pindexLastCheckpoint->GetAncestor(pindex->nHeight) == pindex) {
|
||||||
|
// This block is an ancestor of a checkpoint: disable script checks
|
||||||
|
fExpensiveChecks = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto verifier = libzcash::ProofVerifier::Strict();
|
auto verifier = libzcash::ProofVerifier::Strict();
|
||||||
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
|
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
|
||||||
|
|
||||||
|
@ -2457,7 +2454,7 @@ static int64_t nTimeFlush = 0;
|
||||||
static int64_t nTimeChainState = 0;
|
static int64_t nTimeChainState = 0;
|
||||||
static int64_t nTimePostConnect = 0;
|
static int64_t nTimePostConnect = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
|
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
|
||||||
* corresponding to pindexNew, to bypass loading it again from disk.
|
* corresponding to pindexNew, to bypass loading it again from disk.
|
||||||
*/
|
*/
|
||||||
|
@ -2481,7 +2478,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
|
||||||
LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
|
LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
|
||||||
{
|
{
|
||||||
CCoinsViewCache view(pcoinsTip);
|
CCoinsViewCache view(pcoinsTip);
|
||||||
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
|
|
||||||
bool rv = ConnectBlock(*pblock, state, pindexNew, view);
|
bool rv = ConnectBlock(*pblock, state, pindexNew, view);
|
||||||
GetMainSignals().BlockChecked(*pblock, state);
|
GetMainSignals().BlockChecked(*pblock, state);
|
||||||
if (!rv) {
|
if (!rv) {
|
||||||
|
@ -2489,7 +2485,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
|
||||||
InvalidBlockFound(pindexNew, state);
|
InvalidBlockFound(pindexNew, state);
|
||||||
return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
|
return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
|
||||||
}
|
}
|
||||||
mapBlockSource.erase(inv.hash);
|
mapBlockSource.erase(pindexNew->GetBlockHash());
|
||||||
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
|
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
|
||||||
LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
|
LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
|
||||||
assert(view.Flush());
|
assert(view.Flush());
|
||||||
|
@ -3066,13 +3062,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
|
||||||
return state.Invalid(error("%s: block's timestamp is too early", __func__),
|
return state.Invalid(error("%s: block's timestamp is too early", __func__),
|
||||||
REJECT_INVALID, "time-too-old");
|
REJECT_INVALID, "time-too-old");
|
||||||
|
|
||||||
if(fCheckpointsEnabled)
|
if (fCheckpointsEnabled)
|
||||||
{
|
{
|
||||||
// Check that the block chain matches the known block chain up to a checkpoint
|
|
||||||
if (!Checkpoints::CheckBlock(chainParams.Checkpoints(), nHeight, hash))
|
|
||||||
return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d", __func__, nHeight),
|
|
||||||
REJECT_CHECKPOINT, "checkpoint mismatch");
|
|
||||||
|
|
||||||
// Don't accept any forks from the main chain prior to last checkpoint
|
// Don't accept any forks from the main chain prior to last checkpoint
|
||||||
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
|
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
|
||||||
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
|
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
|
||||||
|
@ -4072,7 +4063,7 @@ void static CheckBlockIndex()
|
||||||
// CAlert
|
// CAlert
|
||||||
//
|
//
|
||||||
|
|
||||||
string GetWarnings(string strFor)
|
std::string GetWarnings(const std::string& strFor)
|
||||||
{
|
{
|
||||||
int nPriority = 0;
|
int nPriority = 0;
|
||||||
string strStatusBar;
|
string strStatusBar;
|
||||||
|
|
21
src/main.h
21
src/main.h
|
@ -145,7 +145,7 @@ extern bool fPruneMode;
|
||||||
/** Number of MiB of block files that we're trying to stay below. */
|
/** Number of MiB of block files that we're trying to stay below. */
|
||||||
extern uint64_t nPruneTarget;
|
extern uint64_t nPruneTarget;
|
||||||
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */
|
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */
|
||||||
static const signed int MIN_BLOCKS_TO_KEEP = 288;
|
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
|
||||||
|
|
||||||
// Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat)
|
// Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat)
|
||||||
// At 1MB per block, 288 blocks = 288MB.
|
// At 1MB per block, 288 blocks = 288MB.
|
||||||
|
@ -155,7 +155,7 @@ static const signed int MIN_BLOCKS_TO_KEEP = 288;
|
||||||
// full block file chunks, we need the high water mark which triggers the prune to be
|
// full block file chunks, we need the high water mark which triggers the prune to be
|
||||||
// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB
|
// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB
|
||||||
// Setting the target to > than 550MB will make it likely we can respect the target.
|
// Setting the target to > than 550MB will make it likely we can respect the target.
|
||||||
static const signed int MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
|
static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
|
||||||
|
|
||||||
/** Register with a network node to receive its signals */
|
/** Register with a network node to receive its signals */
|
||||||
void RegisterNodeSignals(CNodeSignals& nodeSignals);
|
void RegisterNodeSignals(CNodeSignals& nodeSignals);
|
||||||
|
@ -207,7 +207,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
|
||||||
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
|
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
|
||||||
bool IsInitialBlockDownload();
|
bool IsInitialBlockDownload();
|
||||||
/** Format a string that describes several potential problems detected by the core */
|
/** Format a string that describes several potential problems detected by the core */
|
||||||
std::string GetWarnings(std::string strFor);
|
std::string GetWarnings(const std::string& strFor);
|
||||||
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
|
/** 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, uint256 &hashBlock, bool fAllowSlow = false);
|
||||||
/** Find the best known block, and make it the tip of the block chain */
|
/** Find the best known block, and make it the tip of the block chain */
|
||||||
|
@ -332,10 +332,6 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons
|
||||||
unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams,
|
unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams,
|
||||||
std::vector<CScriptCheck> *pvChecks = NULL);
|
std::vector<CScriptCheck> *pvChecks = NULL);
|
||||||
|
|
||||||
bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks,
|
|
||||||
unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams,
|
|
||||||
std::vector<CScriptCheck> *pvChecks = NULL);
|
|
||||||
|
|
||||||
/** Apply the effects of this transaction on the UTXO set represented by view */
|
/** Apply the effects of this transaction on the UTXO set represented by view */
|
||||||
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight);
|
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight);
|
||||||
|
|
||||||
|
@ -520,4 +516,15 @@ extern CCoinsViewCache *pcoinsTip;
|
||||||
/** Global variable that points to the active block tree (protected by cs_main) */
|
/** Global variable that points to the active block tree (protected by cs_main) */
|
||||||
extern CBlockTreeDB *pblocktree;
|
extern CBlockTreeDB *pblocktree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the spend height, which is one more than the inputs.GetBestBlock().
|
||||||
|
* While checking, GetBestBlock() refers to the parent block. (protected by cs_main)
|
||||||
|
* This is also true for mempool checks.
|
||||||
|
*/
|
||||||
|
int GetSpendHeight(const CCoinsViewCache& inputs);
|
||||||
|
|
||||||
|
namespace Consensus {
|
||||||
|
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // BITCOIN_MAIN_H
|
#endif // BITCOIN_MAIN_H
|
||||||
|
|
21
src/net.cpp
21
src/net.cpp
|
@ -107,7 +107,7 @@ boost::condition_variable messageHandlerCondition;
|
||||||
static CNodeSignals g_signals;
|
static CNodeSignals g_signals;
|
||||||
CNodeSignals& GetNodeSignals() { return g_signals; }
|
CNodeSignals& GetNodeSignals() { return g_signals; }
|
||||||
|
|
||||||
void AddOneShot(string strDest)
|
void AddOneShot(const std::string& strDest)
|
||||||
{
|
{
|
||||||
LOCK(cs_vOneShots);
|
LOCK(cs_vOneShots);
|
||||||
vOneShots.push_back(strDest);
|
vOneShots.push_back(strDest);
|
||||||
|
@ -1316,7 +1316,7 @@ void ThreadDNSAddressSeed()
|
||||||
vector<CAddress> vAdd;
|
vector<CAddress> vAdd;
|
||||||
if (LookupHost(seed.host.c_str(), vIPs))
|
if (LookupHost(seed.host.c_str(), vIPs))
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(CNetAddr& ip, vIPs)
|
BOOST_FOREACH(const CNetAddr& ip, vIPs)
|
||||||
{
|
{
|
||||||
int nOneDay = 24*3600;
|
int nOneDay = 24*3600;
|
||||||
CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
|
CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
|
||||||
|
@ -1380,7 +1380,7 @@ void ThreadOpenConnections()
|
||||||
for (int64_t nLoop = 0;; nLoop++)
|
for (int64_t nLoop = 0;; nLoop++)
|
||||||
{
|
{
|
||||||
ProcessOneShot();
|
ProcessOneShot();
|
||||||
BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
|
BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-connect"])
|
||||||
{
|
{
|
||||||
CAddress addr;
|
CAddress addr;
|
||||||
OpenNetworkConnection(addr, NULL, strAddr.c_str());
|
OpenNetworkConnection(addr, NULL, strAddr.c_str());
|
||||||
|
@ -1483,10 +1483,10 @@ void ThreadOpenAddedConnections()
|
||||||
list<string> lAddresses(0);
|
list<string> lAddresses(0);
|
||||||
{
|
{
|
||||||
LOCK(cs_vAddedNodes);
|
LOCK(cs_vAddedNodes);
|
||||||
BOOST_FOREACH(string& strAddNode, vAddedNodes)
|
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
|
||||||
lAddresses.push_back(strAddNode);
|
lAddresses.push_back(strAddNode);
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(string& strAddNode, lAddresses) {
|
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
|
||||||
CAddress addr;
|
CAddress addr;
|
||||||
CSemaphoreGrant grant(*semOutbound);
|
CSemaphoreGrant grant(*semOutbound);
|
||||||
OpenNetworkConnection(addr, &grant, strAddNode.c_str());
|
OpenNetworkConnection(addr, &grant, strAddNode.c_str());
|
||||||
|
@ -1501,20 +1501,19 @@ void ThreadOpenAddedConnections()
|
||||||
list<string> lAddresses(0);
|
list<string> lAddresses(0);
|
||||||
{
|
{
|
||||||
LOCK(cs_vAddedNodes);
|
LOCK(cs_vAddedNodes);
|
||||||
BOOST_FOREACH(string& strAddNode, vAddedNodes)
|
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
|
||||||
lAddresses.push_back(strAddNode);
|
lAddresses.push_back(strAddNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
list<vector<CService> > lservAddressesToAdd(0);
|
list<vector<CService> > lservAddressesToAdd(0);
|
||||||
BOOST_FOREACH(string& strAddNode, lAddresses)
|
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
|
||||||
{
|
|
||||||
vector<CService> vservNode(0);
|
vector<CService> vservNode(0);
|
||||||
if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
|
if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
|
||||||
{
|
{
|
||||||
lservAddressesToAdd.push_back(vservNode);
|
lservAddressesToAdd.push_back(vservNode);
|
||||||
{
|
{
|
||||||
LOCK(cs_setservAddNodeAddresses);
|
LOCK(cs_setservAddNodeAddresses);
|
||||||
BOOST_FOREACH(CService& serv, vservNode)
|
BOOST_FOREACH(const CService& serv, vservNode)
|
||||||
setservAddNodeAddresses.insert(serv);
|
setservAddNodeAddresses.insert(serv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1525,7 +1524,7 @@ void ThreadOpenAddedConnections()
|
||||||
LOCK(cs_vNodes);
|
LOCK(cs_vNodes);
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||||
for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
|
for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
|
||||||
BOOST_FOREACH(CService& addrNode, *(it))
|
BOOST_FOREACH(const CService& addrNode, *(it))
|
||||||
if (pnode->addr == addrNode)
|
if (pnode->addr == addrNode)
|
||||||
{
|
{
|
||||||
it = lservAddressesToAdd.erase(it);
|
it = lservAddressesToAdd.erase(it);
|
||||||
|
@ -2110,7 +2109,7 @@ bool CAddrDB::Read(CAddrMan& addr)
|
||||||
unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
|
unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
|
||||||
unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
|
unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
|
||||||
|
|
||||||
CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) :
|
CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) :
|
||||||
ssSend(SER_NETWORK, INIT_PROTO_VERSION),
|
ssSend(SER_NETWORK, INIT_PROTO_VERSION),
|
||||||
addrKnown(5000, 0.001),
|
addrKnown(5000, 0.001),
|
||||||
setInventoryKnown(SendBufferSize() / 1000)
|
setInventoryKnown(SendBufferSize() / 1000)
|
||||||
|
|
|
@ -65,7 +65,7 @@ static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ;
|
||||||
unsigned int ReceiveFloodSize();
|
unsigned int ReceiveFloodSize();
|
||||||
unsigned int SendBufferSize();
|
unsigned int SendBufferSize();
|
||||||
|
|
||||||
void AddOneShot(std::string strDest);
|
void AddOneShot(const std::string& strDest);
|
||||||
void AddressCurrentlyConnected(const CService& addr);
|
void AddressCurrentlyConnected(const CService& addr);
|
||||||
CNode* FindNode(const CNetAddr& ip);
|
CNode* FindNode(const CNetAddr& ip);
|
||||||
CNode* FindNode(const std::string& addrName);
|
CNode* FindNode(const std::string& addrName);
|
||||||
|
@ -328,7 +328,7 @@ public:
|
||||||
// Whether a ping is requested.
|
// Whether a ping is requested.
|
||||||
bool fPingQueued;
|
bool fPingQueued;
|
||||||
|
|
||||||
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false);
|
CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false);
|
||||||
~CNode();
|
~CNode();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static const int MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
|
static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
|
||||||
|
|
||||||
enum RetFormat {
|
enum RetFormat {
|
||||||
RF_UNDEF,
|
RF_UNDEF,
|
||||||
|
|
|
@ -651,8 +651,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||||
UniValue transactions(UniValue::VARR);
|
UniValue transactions(UniValue::VARR);
|
||||||
map<uint256, int64_t> setTxIndex;
|
map<uint256, int64_t> setTxIndex;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
BOOST_FOREACH (CTransaction& tx, pblock->vtx)
|
BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
|
||||||
{
|
|
||||||
uint256 txHash = tx.GetHash();
|
uint256 txHash = tx.GetHash();
|
||||||
setTxIndex[txHash] = i++;
|
setTxIndex[txHash] = i++;
|
||||||
|
|
||||||
|
|
|
@ -253,19 +253,20 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
|
||||||
if (params.size() == 1)
|
if (params.size() == 1)
|
||||||
{
|
{
|
||||||
LOCK(cs_vAddedNodes);
|
LOCK(cs_vAddedNodes);
|
||||||
BOOST_FOREACH(string& strAddNode, vAddedNodes)
|
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
|
||||||
laddedNodes.push_back(strAddNode);
|
laddedNodes.push_back(strAddNode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string strNode = params[1].get_str();
|
string strNode = params[1].get_str();
|
||||||
LOCK(cs_vAddedNodes);
|
LOCK(cs_vAddedNodes);
|
||||||
BOOST_FOREACH(string& strAddNode, vAddedNodes)
|
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) {
|
||||||
if (strAddNode == strNode)
|
if (strAddNode == strNode)
|
||||||
{
|
{
|
||||||
laddedNodes.push_back(strAddNode);
|
laddedNodes.push_back(strAddNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (laddedNodes.size() == 0)
|
if (laddedNodes.size() == 0)
|
||||||
throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
|
throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
|
||||||
}
|
}
|
||||||
|
@ -273,8 +274,7 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
|
||||||
UniValue ret(UniValue::VARR);
|
UniValue ret(UniValue::VARR);
|
||||||
if (!fDns)
|
if (!fDns)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(string& strAddNode, laddedNodes)
|
BOOST_FOREACH (const std::string& strAddNode, laddedNodes) {
|
||||||
{
|
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.push_back(Pair("addednode", strAddNode));
|
obj.push_back(Pair("addednode", strAddNode));
|
||||||
ret.push_back(obj);
|
ret.push_back(obj);
|
||||||
|
@ -283,8 +283,7 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
|
||||||
}
|
}
|
||||||
|
|
||||||
list<pair<string, vector<CService> > > laddedAddreses(0);
|
list<pair<string, vector<CService> > > laddedAddreses(0);
|
||||||
BOOST_FOREACH(string& strAddNode, laddedNodes)
|
BOOST_FOREACH(const std::string& strAddNode, laddedNodes) {
|
||||||
{
|
|
||||||
vector<CService> vservNode(0);
|
vector<CService> vservNode(0);
|
||||||
if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
|
if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
|
||||||
laddedAddreses.push_back(make_pair(strAddNode, vservNode));
|
laddedAddreses.push_back(make_pair(strAddNode, vservNode));
|
||||||
|
@ -306,12 +305,11 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
|
||||||
|
|
||||||
UniValue addresses(UniValue::VARR);
|
UniValue addresses(UniValue::VARR);
|
||||||
bool fConnected = false;
|
bool fConnected = false;
|
||||||
BOOST_FOREACH(CService& addrNode, it->second)
|
BOOST_FOREACH(const CService& addrNode, it->second) {
|
||||||
{
|
|
||||||
bool fFound = false;
|
bool fFound = false;
|
||||||
UniValue node(UniValue::VOBJ);
|
UniValue node(UniValue::VOBJ);
|
||||||
node.push_back(Pair("address", addrNode.ToString()));
|
node.push_back(Pair("address", addrNode.ToString()));
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||||
if (pnode->addr == addrNode)
|
if (pnode->addr == addrNode)
|
||||||
{
|
{
|
||||||
fFound = true;
|
fFound = true;
|
||||||
|
@ -319,6 +317,7 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
|
||||||
node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
|
node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!fFound)
|
if (!fFound)
|
||||||
node.push_back(Pair("connected", "false"));
|
node.push_back(Pair("connected", "false"));
|
||||||
addresses.push_back(node);
|
addresses.push_back(node);
|
||||||
|
|
|
@ -253,7 +253,6 @@ int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
|
||||||
*
|
*
|
||||||
* 1.0 spec: http://json-rpc.org/wiki/specification
|
* 1.0 spec: http://json-rpc.org/wiki/specification
|
||||||
* 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html
|
* 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html
|
||||||
* http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
string JSONRPCRequest(const string& strMethod, const UniValue& params, const UniValue& id)
|
string JSONRPCRequest(const string& strMethod, const UniValue& params, const UniValue& id)
|
||||||
|
|
|
@ -177,7 +177,7 @@ vector<unsigned char> ParseHexO(const UniValue& o, string strKey)
|
||||||
* Note: This interface may still be subject to change.
|
* Note: This interface may still be subject to change.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
string CRPCTable::help(string strCommand) const
|
std::string CRPCTable::help(const std::string& strCommand) const
|
||||||
{
|
{
|
||||||
string strRet;
|
string strRet;
|
||||||
string category;
|
string category;
|
||||||
|
@ -419,7 +419,7 @@ CRPCTable::CRPCTable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CRPCCommand *CRPCTable::operator[](string name) const
|
const CRPCCommand *CRPCTable::operator[](const std::string& name) const
|
||||||
{
|
{
|
||||||
map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
|
map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
|
||||||
if (it == mapCommands.end())
|
if (it == mapCommands.end())
|
||||||
|
@ -1071,11 +1071,13 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms
|
||||||
g_rpcSignals.PostCommand(*pcmd);
|
g_rpcSignals.PostCommand(*pcmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HelpExampleCli(string methodname, string args){
|
std::string HelpExampleCli(const std::string& methodname, const std::string& args)
|
||||||
|
{
|
||||||
return "> zcash-cli " + methodname + " " + args + "\n";
|
return "> zcash-cli " + methodname + " " + args + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HelpExampleRpc(string methodname, string args){
|
std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
|
||||||
|
{
|
||||||
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
||||||
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8232/\n";
|
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8232/\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ bool IsRPCRunning();
|
||||||
std::shared_ptr<AsyncRPCQueue> getAsyncRPCQueue();
|
std::shared_ptr<AsyncRPCQueue> getAsyncRPCQueue();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the RPC warmup status. When this is done, all RPC calls will error out
|
* Set the RPC warmup status. When this is done, all RPC calls will error out
|
||||||
* immediately with RPC_IN_WARMUP.
|
* immediately with RPC_IN_WARMUP.
|
||||||
*/
|
*/
|
||||||
|
@ -116,8 +116,8 @@ private:
|
||||||
std::map<std::string, const CRPCCommand*> mapCommands;
|
std::map<std::string, const CRPCCommand*> mapCommands;
|
||||||
public:
|
public:
|
||||||
CRPCTable();
|
CRPCTable();
|
||||||
const CRPCCommand* operator[](std::string name) const;
|
const CRPCCommand* operator[](const std::string& name) const;
|
||||||
std::string help(std::string name) const;
|
std::string help(const std::string& name) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a method.
|
* Execute a method.
|
||||||
|
@ -149,8 +149,8 @@ extern UniValue ValueFromAmount(const CAmount& amount);
|
||||||
extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
|
extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
|
||||||
extern double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL);
|
extern double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL);
|
||||||
extern std::string HelpRequiringPassphrase();
|
extern std::string HelpRequiringPassphrase();
|
||||||
extern std::string HelpExampleCli(std::string methodname, std::string args);
|
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
|
||||||
extern std::string HelpExampleRpc(std::string methodname, std::string args);
|
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
|
||||||
|
|
||||||
extern void EnsureWalletIsUnlocked();
|
extern void EnsureWalletIsUnlocked();
|
||||||
|
|
||||||
|
|
|
@ -23,21 +23,7 @@ BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup)
|
||||||
BOOST_AUTO_TEST_CASE(sanity)
|
BOOST_AUTO_TEST_CASE(sanity)
|
||||||
{
|
{
|
||||||
const Checkpoints::CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
|
const Checkpoints::CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
|
||||||
uint256 p11111 = uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d");
|
|
||||||
uint256 p134444 = uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe");
|
|
||||||
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111, p11111));
|
|
||||||
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444, p134444));
|
|
||||||
|
|
||||||
|
|
||||||
// Wrong hashes at checkpoints should fail:
|
|
||||||
BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 11111, p134444));
|
|
||||||
BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 134444, p11111));
|
|
||||||
|
|
||||||
// ... but any hash not at a checkpoint should succeed:
|
|
||||||
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111+1, p134444));
|
|
||||||
BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444+1, p11111));
|
|
||||||
|
|
||||||
BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444);
|
BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
@ -88,12 +88,23 @@ void RunTest(const TestVector &test) {
|
||||||
unsigned char data[74];
|
unsigned char data[74];
|
||||||
key.Encode(data);
|
key.Encode(data);
|
||||||
pubkey.Encode(data);
|
pubkey.Encode(data);
|
||||||
|
|
||||||
// Test private key
|
// Test private key
|
||||||
CBitcoinExtKey b58key; b58key.SetKey(key);
|
CBitcoinExtKey b58key; b58key.SetKey(key);
|
||||||
BOOST_CHECK(b58key.ToString() == derive.prv);
|
BOOST_CHECK(b58key.ToString() == derive.prv);
|
||||||
|
|
||||||
|
CBitcoinExtKey b58keyDecodeCheck(derive.prv);
|
||||||
|
CExtKey checkKey = b58keyDecodeCheck.GetKey();
|
||||||
|
assert(checkKey == key); //ensure a base58 decoded key also matches
|
||||||
|
|
||||||
// Test public key
|
// Test public key
|
||||||
CBitcoinExtPubKey b58pubkey; b58pubkey.SetKey(pubkey);
|
CBitcoinExtPubKey b58pubkey; b58pubkey.SetKey(pubkey);
|
||||||
BOOST_CHECK(b58pubkey.ToString() == derive.pub);
|
BOOST_CHECK(b58pubkey.ToString() == derive.pub);
|
||||||
|
|
||||||
|
CBitcoinExtPubKey b58PubkeyDecodeCheck(derive.pub);
|
||||||
|
CExtPubKey checkPubKey = b58PubkeyDecodeCheck.GetKey();
|
||||||
|
assert(checkPubKey == pubkey); //ensure a base58 decoded pubkey also matches
|
||||||
|
|
||||||
// Derive new keys
|
// Derive new keys
|
||||||
CExtKey keyNew;
|
CExtKey keyNew;
|
||||||
BOOST_CHECK(key.Derive(keyNew, derive.nChild));
|
BOOST_CHECK(key.Derive(keyNew, derive.nChild));
|
||||||
|
|
|
@ -756,7 +756,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends)
|
||||||
|
|
||||||
{
|
{
|
||||||
CTransaction tx2(mtx2);
|
CTransaction tx2(mtx2);
|
||||||
BOOST_CHECK(NonContextualCheckInputs(tx2, state, cache, false, SCRIPT_VERIFY_NONE, false, Params().GetConsensus()));
|
BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
mtx2.vout.resize(1);
|
mtx2.vout.resize(1);
|
||||||
|
@ -765,7 +765,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends)
|
||||||
|
|
||||||
{
|
{
|
||||||
CTransaction tx2(mtx2);
|
CTransaction tx2(mtx2);
|
||||||
BOOST_CHECK(!NonContextualCheckInputs(tx2, state, cache, false, SCRIPT_VERIFY_NONE, false, Params().GetConsensus()));
|
BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus()));
|
||||||
BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs");
|
BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned in
|
||||||
continue;
|
continue;
|
||||||
const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
|
const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
|
||||||
if (fSanityCheck) assert(coins);
|
if (fSanityCheck) assert(coins);
|
||||||
if (!coins || (coins->IsCoinBase() && nMemPoolHeight - coins->nHeight < COINBASE_MATURITY)) {
|
if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
|
||||||
transactionsToRemove.push_back(tx);
|
transactionsToRemove.push_back(tx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
103
src/util.cpp
103
src/util.cpp
|
@ -165,23 +165,51 @@ instance_of_cinit;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
|
static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We use boost::call_once() to make sure these are initialized
|
* We use boost::call_once() to make sure mutexDebugLog and
|
||||||
* in a thread-safe manner the first time called:
|
* vMsgsBeforeOpenLog are initialized in a thread-safe manner.
|
||||||
|
*
|
||||||
|
* NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
|
||||||
|
* are leaked on exit. This is ugly, but will be cleaned up by
|
||||||
|
* the OS/libc. When the shutdown sequence is fully audited and
|
||||||
|
* tested, explicit destruction of these objects can be implemented.
|
||||||
*/
|
*/
|
||||||
static FILE* fileout = NULL;
|
static FILE* fileout = NULL;
|
||||||
static boost::mutex* mutexDebugLog = NULL;
|
static boost::mutex* mutexDebugLog = NULL;
|
||||||
|
static list<string> *vMsgsBeforeOpenLog;
|
||||||
|
|
||||||
|
static int FileWriteStr(const std::string &str, FILE *fp)
|
||||||
|
{
|
||||||
|
return fwrite(str.data(), 1, str.size(), fp);
|
||||||
|
}
|
||||||
|
|
||||||
static void DebugPrintInit()
|
static void DebugPrintInit()
|
||||||
{
|
{
|
||||||
assert(fileout == NULL);
|
|
||||||
assert(mutexDebugLog == NULL);
|
assert(mutexDebugLog == NULL);
|
||||||
|
mutexDebugLog = new boost::mutex();
|
||||||
|
vMsgsBeforeOpenLog = new list<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenDebugLog()
|
||||||
|
{
|
||||||
|
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
|
||||||
|
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
|
||||||
|
|
||||||
|
assert(fileout == NULL);
|
||||||
|
assert(vMsgsBeforeOpenLog);
|
||||||
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
|
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
|
||||||
fileout = fopen(pathDebug.string().c_str(), "a");
|
fileout = fopen(pathDebug.string().c_str(), "a");
|
||||||
if (fileout) setbuf(fileout, NULL); // unbuffered
|
if (fileout) setbuf(fileout, NULL); // unbuffered
|
||||||
|
|
||||||
mutexDebugLog = new boost::mutex();
|
// dump buffered messages from before we opened the log
|
||||||
|
while (!vMsgsBeforeOpenLog->empty()) {
|
||||||
|
FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
|
||||||
|
vMsgsBeforeOpenLog->pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete vMsgsBeforeOpenLog;
|
||||||
|
vMsgsBeforeOpenLog = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LogAcceptCategory(const char* category)
|
bool LogAcceptCategory(const char* category)
|
||||||
|
@ -213,44 +241,67 @@ bool LogAcceptCategory(const char* category)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fStartedNewLine is a state variable held by the calling context that will
|
||||||
|
* suppress printing of the timestamp when multiple calls are made that don't
|
||||||
|
* end in a newline. Initialize it to true, and hold it, in the calling context.
|
||||||
|
*/
|
||||||
|
static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
|
||||||
|
{
|
||||||
|
string strStamped;
|
||||||
|
|
||||||
|
if (!fLogTimestamps)
|
||||||
|
return str;
|
||||||
|
|
||||||
|
if (*fStartedNewLine)
|
||||||
|
strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
|
||||||
|
else
|
||||||
|
strStamped = str;
|
||||||
|
|
||||||
|
if (!str.empty() && str[str.size()-1] == '\n')
|
||||||
|
*fStartedNewLine = true;
|
||||||
|
else
|
||||||
|
*fStartedNewLine = false;
|
||||||
|
|
||||||
|
return strStamped;
|
||||||
|
}
|
||||||
|
|
||||||
int LogPrintStr(const std::string &str)
|
int LogPrintStr(const std::string &str)
|
||||||
{
|
{
|
||||||
int ret = 0; // Returns total number of characters written
|
int ret = 0; // Returns total number of characters written
|
||||||
|
static bool fStartedNewLine = true;
|
||||||
if (fPrintToConsole)
|
if (fPrintToConsole)
|
||||||
{
|
{
|
||||||
// print to console
|
// print to console
|
||||||
ret = fwrite(str.data(), 1, str.size(), stdout);
|
ret = fwrite(str.data(), 1, str.size(), stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
else if (fPrintToDebugLog && AreBaseParamsConfigured())
|
else if (fPrintToDebugLog)
|
||||||
{
|
{
|
||||||
static bool fStartedNewLine = true;
|
|
||||||
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
|
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
|
||||||
|
|
||||||
if (fileout == NULL)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
|
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
|
||||||
|
|
||||||
// reopen the log file, if requested
|
string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
|
||||||
if (fReopenDebugLog) {
|
|
||||||
fReopenDebugLog = false;
|
// buffer if we haven't opened the log yet
|
||||||
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
|
if (fileout == NULL) {
|
||||||
if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
|
assert(vMsgsBeforeOpenLog);
|
||||||
setbuf(fileout, NULL); // unbuffered
|
ret = strTimestamped.length();
|
||||||
|
vMsgsBeforeOpenLog->push_back(strTimestamped);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug print useful for profiling
|
|
||||||
if (fLogTimestamps && fStartedNewLine)
|
|
||||||
ret += fprintf(fileout, "%s ", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str());
|
|
||||||
if (!str.empty() && str[str.size()-1] == '\n')
|
|
||||||
fStartedNewLine = true;
|
|
||||||
else
|
else
|
||||||
fStartedNewLine = false;
|
{
|
||||||
|
// reopen the log file, if requested
|
||||||
|
if (fReopenDebugLog) {
|
||||||
|
fReopenDebugLog = false;
|
||||||
|
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
|
||||||
|
if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
|
||||||
|
setbuf(fileout, NULL); // unbuffered
|
||||||
|
}
|
||||||
|
|
||||||
ret = fwrite(str.data(), 1, str.size(), fileout);
|
ret = FileWriteStr(strTimestamped, fileout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,7 +821,7 @@ boost::filesystem::path GetTempPath() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void runCommand(std::string strCommand)
|
void runCommand(const std::string& strCommand)
|
||||||
{
|
{
|
||||||
int nErr = ::system(strCommand.c_str());
|
int nErr = ::system(strCommand.c_str());
|
||||||
if (nErr)
|
if (nErr)
|
||||||
|
|
|
@ -136,8 +136,9 @@ void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map
|
||||||
boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
|
boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
|
||||||
#endif
|
#endif
|
||||||
boost::filesystem::path GetTempPath();
|
boost::filesystem::path GetTempPath();
|
||||||
|
void OpenDebugLog();
|
||||||
void ShrinkDebugFile();
|
void ShrinkDebugFile();
|
||||||
void runCommand(std::string strCommand);
|
void runCommand(const std::string& strCommand);
|
||||||
const boost::filesystem::path GetExportDir();
|
const boost::filesystem::path GetExportDir();
|
||||||
|
|
||||||
/** Returns licensing information (for -version) */
|
/** Returns licensing information (for -version) */
|
||||||
|
|
|
@ -488,7 +488,7 @@ bool ParseDouble(const std::string& str, double *out)
|
||||||
return text.eof() && !text.fail();
|
return text.eof() && !text.fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FormatParagraph(const std::string in, size_t width, size_t indent)
|
std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
|
||||||
{
|
{
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
size_t col = 0;
|
size_t col = 0;
|
||||||
|
|
|
@ -89,11 +89,11 @@ inline std::string HexStr(const T& vch, bool fSpaces=false)
|
||||||
return HexStr(vch.begin(), vch.end(), fSpaces);
|
return HexStr(vch.begin(), vch.end(), fSpaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format a paragraph of text to a fixed width, adding spaces for
|
* Format a paragraph of text to a fixed width, adding spaces for
|
||||||
* indentation to any added line.
|
* indentation to any added line.
|
||||||
*/
|
*/
|
||||||
std::string FormatParagraph(const std::string in, size_t width=79, size_t indent=0);
|
std::string FormatParagraph(const std::string& in, size_t width = 79, size_t indent = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timing-attack-resistant comparison.
|
* Timing-attack-resistant comparison.
|
||||||
|
|
|
@ -3148,7 +3148,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
|
std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
set<CTxDestination> result;
|
set<CTxDestination> result;
|
||||||
|
|
|
@ -708,7 +708,7 @@ public:
|
||||||
SetNull();
|
SetNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
CWallet(std::string strWalletFileIn)
|
CWallet(const std::string& strWalletFileIn)
|
||||||
{
|
{
|
||||||
SetNull();
|
SetNull();
|
||||||
|
|
||||||
|
@ -931,7 +931,7 @@ public:
|
||||||
std::set< std::set<CTxDestination> > GetAddressGroupings();
|
std::set< std::set<CTxDestination> > GetAddressGroupings();
|
||||||
std::map<CTxDestination, CAmount> GetAddressBalances();
|
std::map<CTxDestination, CAmount> GetAddressBalances();
|
||||||
|
|
||||||
std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const;
|
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
|
||||||
|
|
||||||
boost::optional<uint256> GetNoteNullifier(
|
boost::optional<uint256> GetNoteNullifier(
|
||||||
const JSDescription& jsdesc,
|
const JSDescription& jsdesc,
|
||||||
|
|
Loading…
Reference in New Issue