Merge pull request #3029 from PastaPastaPasta/backports-0.15-pr21
Backports 0.15 pr21
This commit is contained in:
commit
8231255dd3
34
configure.ac
34
configure.ac
@ -19,6 +19,12 @@ BITCOIN_GUI_NAME=dash-qt
|
|||||||
BITCOIN_CLI_NAME=dash-cli
|
BITCOIN_CLI_NAME=dash-cli
|
||||||
BITCOIN_TX_NAME=dash-tx
|
BITCOIN_TX_NAME=dash-tx
|
||||||
|
|
||||||
|
dnl Unless the user specified ARFLAGS, force it to be cr
|
||||||
|
AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to <cr> if not set])
|
||||||
|
if test "x${ARFLAGS+set}" != "xset"; then
|
||||||
|
ARFLAGS="cr"
|
||||||
|
fi
|
||||||
|
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
AH_TOP([#ifndef DASH_CONFIG_H])
|
AH_TOP([#ifndef DASH_CONFIG_H])
|
||||||
@ -290,9 +296,32 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
|
|||||||
# Check for optional instruction set support. Enabling these does _not_ imply that all code will
|
# Check for optional instruction set support. Enabling these does _not_ imply that all code will
|
||||||
# be compiled with them, rather that specific objects/libs may use them after checking for runtime
|
# be compiled with them, rather that specific objects/libs may use them after checking for runtime
|
||||||
# compatibility.
|
# compatibility.
|
||||||
AX_CHECK_COMPILE_FLAG([-msse4.2],[[enable_sse42=yes; SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]])
|
AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]])
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
TEMP_CXXFLAGS="$CXXFLAGS"
|
||||||
|
CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS"
|
||||||
|
AC_MSG_CHECKING(for assembler crc32 support)
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
#include <stdint.h>
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#include <intrin.h>
|
||||||
|
#elif defined(__GNUC__) && defined(__SSE4_2__)
|
||||||
|
#include <nmmintrin.h>
|
||||||
|
#endif
|
||||||
|
]],[[
|
||||||
|
uint64_t l = 0;
|
||||||
|
l = _mm_crc32_u8(l, 0);
|
||||||
|
l = _mm_crc32_u32(l, 0);
|
||||||
|
l = _mm_crc32_u64(l, 0);
|
||||||
|
return l;
|
||||||
|
]])],
|
||||||
|
[ AC_MSG_RESULT(yes); enable_hwcrc32=yes],
|
||||||
|
[ AC_MSG_RESULT(no)]
|
||||||
|
)
|
||||||
|
CXXFLAGS="$TEMP_CXXFLAGS"
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
|
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
|
||||||
|
|
||||||
AC_ARG_WITH([utils],
|
AC_ARG_WITH([utils],
|
||||||
@ -1188,7 +1217,7 @@ AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
|
|||||||
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
|
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
|
||||||
AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
|
AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
|
||||||
AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
|
AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
|
||||||
AM_CONDITIONAL([ENABLE_SSE42],[test x$enable_sse42 = xyes])
|
AM_CONDITIONAL([ENABLE_HWCRC32],[test x$enable_hwcrc32 = xyes])
|
||||||
|
|
||||||
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
|
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
|
||||||
AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
|
AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
|
||||||
@ -1321,4 +1350,5 @@ echo " CPPFLAGS = $CPPFLAGS"
|
|||||||
echo " CXX = $CXX"
|
echo " CXX = $CXX"
|
||||||
echo " CXXFLAGS = $CXXFLAGS"
|
echo " CXXFLAGS = $CXXFLAGS"
|
||||||
echo " LDFLAGS = $LDFLAGS"
|
echo " LDFLAGS = $LDFLAGS"
|
||||||
|
echo " ARFLAGS = $ARFLAGS"
|
||||||
echo
|
echo
|
||||||
|
@ -175,6 +175,7 @@ def main():
|
|||||||
if info is None:
|
if info is None:
|
||||||
exit(1)
|
exit(1)
|
||||||
title = info['title'].strip()
|
title = info['title'].strip()
|
||||||
|
body = info['body'].strip()
|
||||||
# precedence order for destination branch argument:
|
# precedence order for destination branch argument:
|
||||||
# - command line argument
|
# - command line argument
|
||||||
# - githubmerge.branch setting
|
# - githubmerge.branch setting
|
||||||
@ -229,6 +230,7 @@ def main():
|
|||||||
firstline = 'Merge #%s' % (pull,)
|
firstline = 'Merge #%s' % (pull,)
|
||||||
message = firstline + '\n\n'
|
message = firstline + '\n\n'
|
||||||
message += subprocess.check_output([GIT,'log','--no-merges','--topo-order','--pretty=format:%h %s (%an)',base_branch+'..'+head_branch]).decode('utf-8')
|
message += subprocess.check_output([GIT,'log','--no-merges','--topo-order','--pretty=format:%h %s (%an)',base_branch+'..'+head_branch]).decode('utf-8')
|
||||||
|
message += '\n\nPull request description:\n\n ' + body.replace('\n', '\n ') + '\n'
|
||||||
try:
|
try:
|
||||||
subprocess.check_call([GIT,'merge','-q','--commit','--no-edit','--no-ff','-m',message.encode('utf-8'),head_branch])
|
subprocess.check_call([GIT,'merge','-q','--commit','--no-edit','--no-ff','-m',message.encode('utf-8'),head_branch])
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
### This script attempts to download the signature file SHA256SUMS.asc from bitcoin.org
|
### This script attempts to download the signature file SHA256SUMS.asc from
|
||||||
|
### bitcoincore.org and bitcoin.org and compares them.
|
||||||
### It first checks if the signature passes, and then downloads the files specified in
|
### It first checks if the signature passes, and then downloads the files specified in
|
||||||
### the file, and checks if the hashes of these files match those that are specified
|
### the file, and checks if the hashes of these files match those that are specified
|
||||||
### in the signature file.
|
### in the signature file.
|
||||||
@ -22,7 +23,9 @@ TMPFILE="hashes.tmp"
|
|||||||
|
|
||||||
SIGNATUREFILENAME="SHA256SUMS.asc"
|
SIGNATUREFILENAME="SHA256SUMS.asc"
|
||||||
RCSUBDIR="test"
|
RCSUBDIR="test"
|
||||||
BASEDIR="https://bitcoin.org/bin/"
|
HOST1="https://bitcoincore.org"
|
||||||
|
HOST2="https://bitcoin.org"
|
||||||
|
BASEDIR="/bin/"
|
||||||
VERSIONPREFIX="bitcoin-core-"
|
VERSIONPREFIX="bitcoin-core-"
|
||||||
RCVERSIONSTRING="rc"
|
RCVERSIONSTRING="rc"
|
||||||
|
|
||||||
@ -81,7 +84,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
#first we fetch the file containing the signature
|
#first we fetch the file containing the signature
|
||||||
WGETOUT=$(wget -N "$BASEDIR$SIGNATUREFILENAME" 2>&1)
|
WGETOUT=$(wget -N "$HOST1$BASEDIR$SIGNATUREFILENAME" 2>&1)
|
||||||
|
|
||||||
#and then see if wget completed successfully
|
#and then see if wget completed successfully
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
@ -92,6 +95,22 @@ if [ $? -ne 0 ]; then
|
|||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
WGETOUT=$(wget -N -O "$SIGNATUREFILENAME.2" "$HOST2$BASEDIR$SIGNATUREFILENAME" 2>&1)
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "bitcoin.org failed to provide signature file, but bitcoincore.org did?"
|
||||||
|
echo "wget output:"
|
||||||
|
echo "$WGETOUT"|sed 's/^/\t/g'
|
||||||
|
clean_up $SIGNATUREFILENAME
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
SIGFILEDIFFS="$(diff $SIGNATUREFILENAME $SIGNATUREFILENAME.2)"
|
||||||
|
if [ "$SIGFILEDIFFS" != "" ]; then
|
||||||
|
echo "bitcoin.org and bitcoincore.org signature files were not equal?"
|
||||||
|
clean_up $SIGNATUREFILENAME $SIGNATUREFILENAME.2
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
|
||||||
#then we check it
|
#then we check it
|
||||||
GPGOUT=$(gpg --yes --decrypt --output "$TMPFILE" "$SIGNATUREFILENAME" 2>&1)
|
GPGOUT=$(gpg --yes --decrypt --output "$TMPFILE" "$SIGNATUREFILENAME" 2>&1)
|
||||||
|
|
||||||
@ -111,7 +130,7 @@ if [ $RET -ne 0 ]; then
|
|||||||
|
|
||||||
echo "gpg output:"
|
echo "gpg output:"
|
||||||
echo "$GPGOUT"|sed 's/^/\t/g'
|
echo "$GPGOUT"|sed 's/^/\t/g'
|
||||||
clean_up $SIGNATUREFILENAME $TMPFILE
|
clean_up $SIGNATUREFILENAME $SIGNATUREFILENAME.2 $TMPFILE
|
||||||
exit "$RET"
|
exit "$RET"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -131,7 +150,7 @@ FILES=$(awk '{print $2}' "$TMPFILE")
|
|||||||
for file in $FILES
|
for file in $FILES
|
||||||
do
|
do
|
||||||
echo "Downloading $file"
|
echo "Downloading $file"
|
||||||
wget --quiet -N "$BASEDIR$file"
|
wget --quiet -N "$HOST1$BASEDIR$file"
|
||||||
done
|
done
|
||||||
|
|
||||||
#check hashes
|
#check hashes
|
||||||
@ -149,7 +168,7 @@ fi
|
|||||||
|
|
||||||
if [ -n "$2" ]; then
|
if [ -n "$2" ]; then
|
||||||
echo "Clean up the binaries"
|
echo "Clean up the binaries"
|
||||||
clean_up $FILES $SIGNATUREFILENAME $TMPFILE
|
clean_up $FILES $SIGNATUREFILENAME $SIGNATUREFILENAME.2 $TMPFILE
|
||||||
else
|
else
|
||||||
echo "Keep the binaries in $WORKINGDIR"
|
echo "Keep the binaries in $WORKINGDIR"
|
||||||
clean_up $TMPFILE
|
clean_up $TMPFILE
|
||||||
|
@ -40,11 +40,13 @@ Only supports JSON as output format.
|
|||||||
* headers : (numeric) the current number of headers we have validated
|
* headers : (numeric) the current number of headers we have validated
|
||||||
* bestblockhash : (string) the hash of the currently best block
|
* bestblockhash : (string) the hash of the currently best block
|
||||||
* difficulty : (numeric) the current difficulty
|
* difficulty : (numeric) the current difficulty
|
||||||
|
* mediantime : (numeric) the median time of the 11 blocks before the most recent block on the blockchain
|
||||||
* verificationprogress : (numeric) estimate of verification progress [0..1]
|
* verificationprogress : (numeric) estimate of verification progress [0..1]
|
||||||
* chainwork : (string) total amount of work in active chain, in hexadecimal
|
* chainwork : (string) total amount of work in active chain, in hexadecimal
|
||||||
* pruned : (boolean) if the blocks are subject to pruning
|
* pruned : (boolean) if the blocks are subject to pruning
|
||||||
* pruneheight : (numeric) heighest block available
|
* pruneheight : (numeric) heighest block available
|
||||||
* softforks : (array) status of softforks in progress
|
* softforks : (array) status of softforks in progress
|
||||||
|
* bip9_softforks : (object) status of BIP9 softforks in progress
|
||||||
|
|
||||||
#### Query UTXO set
|
#### Query UTXO set
|
||||||
`GET /rest/getutxos/<checkmempool>/<txid>-<n>/<txid>-<n>/.../<txid>-<n>.<bin|hex|json>`
|
`GET /rest/getutxos/<checkmempool>/<txid>-<n>/<txid>-<n>/.../<txid>-<n>.<bin|hex|json>`
|
||||||
@ -57,25 +59,25 @@ Example:
|
|||||||
```
|
```
|
||||||
$ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff7627ff72e5e8b0f71210f92ea7a4000c5d75-0.json 2>/dev/null | json_pp
|
$ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff7627ff72e5e8b0f71210f92ea7a4000c5d75-0.json 2>/dev/null | json_pp
|
||||||
{
|
{
|
||||||
"chaintipHash" : "00000000fb01a7f3745a717f8caebee056c484e6e0bfe4a9591c235bb70506fb",
|
|
||||||
"chainHeight" : 325347,
|
"chainHeight" : 325347,
|
||||||
|
"chaintipHash" : "00000000fb01a7f3745a717f8caebee056c484e6e0bfe4a9591c235bb70506fb",
|
||||||
|
"bitmap": "1",
|
||||||
"utxos" : [
|
"utxos" : [
|
||||||
{
|
{
|
||||||
|
"txvers" : 1
|
||||||
|
"height" : 2147483647,
|
||||||
|
"value" : 8.8687,
|
||||||
"scriptPubKey" : {
|
"scriptPubKey" : {
|
||||||
"addresses" : [
|
"asm" : "OP_DUP OP_HASH160 1c7cebb529b86a04c683dfa87be49de35bcf589e OP_EQUALVERIFY OP_CHECKSIG",
|
||||||
"mi7as51dvLJsizWnTMurtRmrP8hG2m1XvD"
|
|
||||||
],
|
|
||||||
"type" : "pubkeyhash",
|
|
||||||
"hex" : "76a9141c7cebb529b86a04c683dfa87be49de35bcf589e88ac",
|
"hex" : "76a9141c7cebb529b86a04c683dfa87be49de35bcf589e88ac",
|
||||||
"reqSigs" : 1,
|
"reqSigs" : 1,
|
||||||
"asm" : "OP_DUP OP_HASH160 1c7cebb529b86a04c683dfa87be49de35bcf589e OP_EQUALVERIFY OP_CHECKSIG"
|
"type" : "pubkeyhash",
|
||||||
},
|
"addresses" : [
|
||||||
"value" : 8.8687,
|
"mi7as51dvLJsizWnTMurtRmrP8hG2m1XvD"
|
||||||
"height" : 2147483647,
|
]
|
||||||
"txvers" : 1
|
}
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"bitmap" : "1"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -87,6 +89,8 @@ Only supports JSON as output format.
|
|||||||
* size : (numeric) the number of transactions in the TX mempool
|
* size : (numeric) the number of transactions in the TX mempool
|
||||||
* bytes : (numeric) size of the TX mempool in bytes
|
* bytes : (numeric) size of the TX mempool in bytes
|
||||||
* usage : (numeric) total TX mempool memory usage
|
* usage : (numeric) total TX mempool memory usage
|
||||||
|
* maxmempool : (numeric) maximum memory usage for the mempool in bytes
|
||||||
|
* mempoolminfee : (numeric) minimum feerate (DASH per KB) for tx to be accepted
|
||||||
|
|
||||||
`GET /rest/mempool/contents.json`
|
`GET /rest/mempool/contents.json`
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ leveldb_libmemenv_a_SOURCES += leveldb/helpers/memenv/memenv.h
|
|||||||
|
|
||||||
leveldb_libleveldb_sse42_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS)
|
leveldb_libleveldb_sse42_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS)
|
||||||
leveldb_libleveldb_sse42_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS)
|
leveldb_libleveldb_sse42_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS)
|
||||||
if ENABLE_SSE42
|
if ENABLE_HWCRC32
|
||||||
leveldb_libleveldb_sse42_a_CPPFLAGS += -DLEVELDB_PLATFORM_POSIX_SSE
|
leveldb_libleveldb_sse42_a_CPPFLAGS += -DLEVELDB_PLATFORM_POSIX_SSE
|
||||||
leveldb_libleveldb_sse42_a_CXXFLAGS += $(SSE42_CXXFLAGS)
|
leveldb_libleveldb_sse42_a_CXXFLAGS += $(SSE42_CXXFLAGS)
|
||||||
endif
|
endif
|
||||||
|
@ -110,7 +110,7 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
|
|||||||
|
|
||||||
std::string EncodeBase58(const std::vector<unsigned char>& vch)
|
std::string EncodeBase58(const std::vector<unsigned char>& vch)
|
||||||
{
|
{
|
||||||
return EncodeBase58(&vch[0], &vch[0] + vch.size());
|
return EncodeBase58(vch.data(), vch.data() + vch.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
|
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
|
||||||
@ -160,7 +160,7 @@ void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const
|
|||||||
vchVersion = vchVersionIn;
|
vchVersion = vchVersionIn;
|
||||||
vchData.resize(nSize);
|
vchData.resize(nSize);
|
||||||
if (!vchData.empty())
|
if (!vchData.empty())
|
||||||
memcpy(&vchData[0], pdata, nSize);
|
memcpy(vchData.data(), pdata, nSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
|
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
|
||||||
@ -180,8 +180,8 @@ bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
|
|||||||
vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
|
vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
|
||||||
vchData.resize(vchTemp.size() - nVersionBytes);
|
vchData.resize(vchTemp.size() - nVersionBytes);
|
||||||
if (!vchData.empty())
|
if (!vchData.empty())
|
||||||
memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
|
memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size());
|
||||||
memory_cleanse(&vchTemp[0], vchTemp.size());
|
memory_cleanse(vchTemp.data(), vchTemp.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +262,7 @@ CTxDestination CBitcoinAddress::Get() const
|
|||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
return CNoDestination();
|
return CNoDestination();
|
||||||
uint160 id;
|
uint160 id;
|
||||||
memcpy(&id, &vchData[0], 20);
|
memcpy(&id, vchData.data(), 20);
|
||||||
if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
|
if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
|
||||||
return CKeyID(id);
|
return CKeyID(id);
|
||||||
else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
|
else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
|
||||||
@ -293,7 +293,7 @@ bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
|
|||||||
if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
|
if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
|
||||||
return false;
|
return false;
|
||||||
uint160 id;
|
uint160 id;
|
||||||
memcpy(&id, &vchData[0], 20);
|
memcpy(&id, vchData.data(), 20);
|
||||||
keyID = CKeyID(id);
|
keyID = CKeyID(id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ public:
|
|||||||
K ret;
|
K ret;
|
||||||
if (vchData.size() == Size) {
|
if (vchData.size() == Size) {
|
||||||
// If base58 encoded data does not hold an ext key, return a !IsValid() key
|
// If base58 encoded data does not hold an ext key, return a !IsValid() key
|
||||||
ret.Decode(&vchData[0]);
|
ret.Decode(vchData.data());
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -7,34 +7,37 @@
|
|||||||
#include "validation.h"
|
#include "validation.h"
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
static void Base58Encode(benchmark::State& state)
|
static void Base58Encode(benchmark::State& state)
|
||||||
{
|
{
|
||||||
unsigned char buff[32] = {
|
static const std::array<unsigned char, 32> buff = {
|
||||||
17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147,
|
{
|
||||||
227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90,
|
17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147,
|
||||||
200, 24
|
227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90,
|
||||||
|
200, 24
|
||||||
|
}
|
||||||
};
|
};
|
||||||
unsigned char* b = buff;
|
|
||||||
while (state.KeepRunning()) {
|
while (state.KeepRunning()) {
|
||||||
EncodeBase58(b, b + 32);
|
EncodeBase58(buff.begin(), buff.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void Base58CheckEncode(benchmark::State& state)
|
static void Base58CheckEncode(benchmark::State& state)
|
||||||
{
|
{
|
||||||
unsigned char buff[32] = {
|
static const std::array<unsigned char, 32> buff = {
|
||||||
17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147,
|
{
|
||||||
227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90,
|
17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147,
|
||||||
200, 24
|
227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90,
|
||||||
|
200, 24
|
||||||
|
}
|
||||||
};
|
};
|
||||||
unsigned char* b = buff;
|
|
||||||
std::vector<unsigned char> vch;
|
std::vector<unsigned char> vch;
|
||||||
vch.assign(b, b + 32);
|
vch.assign(buff.begin(), buff.end());
|
||||||
while (state.KeepRunning()) {
|
while (state.KeepRunning()) {
|
||||||
EncodeBase58Check(vch);
|
EncodeBase58Check(vch);
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne
|
|||||||
script[0] = OP_DUP;
|
script[0] = OP_DUP;
|
||||||
script[1] = OP_HASH160;
|
script[1] = OP_HASH160;
|
||||||
script[2] = 20;
|
script[2] = 20;
|
||||||
memcpy(&script[3], &in[0], 20);
|
memcpy(&script[3], in.data(), 20);
|
||||||
script[23] = OP_EQUALVERIFY;
|
script[23] = OP_EQUALVERIFY;
|
||||||
script[24] = OP_CHECKSIG;
|
script[24] = OP_CHECKSIG;
|
||||||
return true;
|
return true;
|
||||||
@ -101,7 +101,7 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne
|
|||||||
script.resize(23);
|
script.resize(23);
|
||||||
script[0] = OP_HASH160;
|
script[0] = OP_HASH160;
|
||||||
script[1] = 20;
|
script[1] = 20;
|
||||||
memcpy(&script[2], &in[0], 20);
|
memcpy(&script[2], in.data(), 20);
|
||||||
script[22] = OP_EQUAL;
|
script[22] = OP_EQUAL;
|
||||||
return true;
|
return true;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
@ -109,14 +109,14 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne
|
|||||||
script.resize(35);
|
script.resize(35);
|
||||||
script[0] = 33;
|
script[0] = 33;
|
||||||
script[1] = nSize;
|
script[1] = nSize;
|
||||||
memcpy(&script[2], &in[0], 32);
|
memcpy(&script[2], in.data(), 32);
|
||||||
script[34] = OP_CHECKSIG;
|
script[34] = OP_CHECKSIG;
|
||||||
return true;
|
return true;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
case 0x05:
|
case 0x05:
|
||||||
unsigned char vch[33] = {};
|
unsigned char vch[33] = {};
|
||||||
vch[0] = nSize - 2;
|
vch[0] = nSize - 2;
|
||||||
memcpy(&vch[1], &in[0], 32);
|
memcpy(&vch[1], in.data(), 32);
|
||||||
CPubKey pubkey(&vch[0], &vch[33]);
|
CPubKey pubkey(&vch[0], &vch[33]);
|
||||||
if (!pubkey.Decompress())
|
if (!pubkey.Decompress())
|
||||||
return false;
|
return false;
|
||||||
|
@ -27,7 +27,7 @@ CScript ParseScript(const std::string& s)
|
|||||||
|
|
||||||
if (mapOpNames.empty())
|
if (mapOpNames.empty())
|
||||||
{
|
{
|
||||||
for (int op = 0; op <= OP_NOP10; op++)
|
for (unsigned int op = 0; op <= OP_NOP10; op++)
|
||||||
{
|
{
|
||||||
// Allow OP_RESERVED to get into mapOpNames
|
// Allow OP_RESERVED to get into mapOpNames
|
||||||
if (op < OP_NOP && op != OP_RESERVED)
|
if (op < OP_NOP && op != OP_RESERVED)
|
||||||
|
@ -204,8 +204,14 @@ static void http_error_cb(enum evhttp_request_error err, void *ctx)
|
|||||||
|
|
||||||
UniValue CallRPC(const std::string& strMethod, const UniValue& params)
|
UniValue CallRPC(const std::string& strMethod, const UniValue& params)
|
||||||
{
|
{
|
||||||
std::string host = gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT);
|
std::string host;
|
||||||
int port = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
|
// In preference order, we choose the following for the port:
|
||||||
|
// 1. -rpcport
|
||||||
|
// 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
|
||||||
|
// 3. default port for chain
|
||||||
|
int port = BaseParams().RPCPort();
|
||||||
|
SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host);
|
||||||
|
port = gArgs.GetArg("-rpcport", port);
|
||||||
|
|
||||||
// Obtain event base
|
// Obtain event base
|
||||||
raii_event_base base = obtain_event_base();
|
raii_event_base base = obtain_event_base();
|
||||||
|
43
src/hash.cpp
43
src/hash.cpp
@ -17,36 +17,34 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
|
|||||||
{
|
{
|
||||||
// The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
|
// The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
|
||||||
uint32_t h1 = nHashSeed;
|
uint32_t h1 = nHashSeed;
|
||||||
if (vDataToHash.size() > 0)
|
const uint32_t c1 = 0xcc9e2d51;
|
||||||
{
|
const uint32_t c2 = 0x1b873593;
|
||||||
const uint32_t c1 = 0xcc9e2d51;
|
|
||||||
const uint32_t c2 = 0x1b873593;
|
|
||||||
|
|
||||||
const int nblocks = vDataToHash.size() / 4;
|
const int nblocks = vDataToHash.size() / 4;
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// body
|
// body
|
||||||
const uint8_t* blocks = &vDataToHash[0] + nblocks * 4;
|
const uint8_t* blocks = vDataToHash.data();
|
||||||
|
|
||||||
for (int i = -nblocks; i; i++) {
|
for (int i = 0; i < nblocks; ++i) {
|
||||||
uint32_t k1 = ReadLE32(blocks + i*4);
|
uint32_t k1 = ReadLE32(blocks + i*4);
|
||||||
|
|
||||||
k1 *= c1;
|
k1 *= c1;
|
||||||
k1 = ROTL32(k1, 15);
|
k1 = ROTL32(k1, 15);
|
||||||
k1 *= c2;
|
k1 *= c2;
|
||||||
|
|
||||||
h1 ^= k1;
|
h1 ^= k1;
|
||||||
h1 = ROTL32(h1, 13);
|
h1 = ROTL32(h1, 13);
|
||||||
h1 = h1 * 5 + 0xe6546b64;
|
h1 = h1 * 5 + 0xe6546b64;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
// tail
|
// tail
|
||||||
const uint8_t* tail = (const uint8_t*)(&vDataToHash[0] + nblocks * 4);
|
const uint8_t* tail = vDataToHash.data() + nblocks * 4;
|
||||||
|
|
||||||
uint32_t k1 = 0;
|
uint32_t k1 = 0;
|
||||||
|
|
||||||
switch (vDataToHash.size() & 3) {
|
switch (vDataToHash.size() & 3) {
|
||||||
case 3:
|
case 3:
|
||||||
k1 ^= tail[2] << 16;
|
k1 ^= tail[2] << 16;
|
||||||
case 2:
|
case 2:
|
||||||
@ -57,7 +55,6 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
|
|||||||
k1 = ROTL32(k1, 15);
|
k1 = ROTL32(k1, 15);
|
||||||
k1 *= c2;
|
k1 *= c2;
|
||||||
h1 ^= k1;
|
h1 ^= k1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "chainparamsbase.h"
|
#include "chainparamsbase.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "utilstrencodings.h"
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "rpc/protocol.h" // For HTTP status codes
|
#include "rpc/protocol.h" // For HTTP status codes
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
|
@ -1850,7 +1850,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
LogPrintf("Shutdown requested. Exiting.\n");
|
LogPrintf("Shutdown requested. Exiting.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart);
|
if (fLoaded) {
|
||||||
|
LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart);
|
||||||
|
}
|
||||||
|
|
||||||
fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
|
fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
|
||||||
CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
|
CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
|
||||||
|
10
src/key.cpp
10
src/key.cpp
@ -138,7 +138,7 @@ CPrivKey CKey::GetPrivKey() const {
|
|||||||
size_t privkeylen;
|
size_t privkeylen;
|
||||||
privkey.resize(279);
|
privkey.resize(279);
|
||||||
privkeylen = 279;
|
privkeylen = 279;
|
||||||
ret = ec_privkey_export_der(secp256k1_context_sign, (unsigned char*)&privkey[0], &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
|
ret = ec_privkey_export_der(secp256k1_context_sign, (unsigned char*) privkey.data(), &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
privkey.resize(privkeylen);
|
privkey.resize(privkeylen);
|
||||||
return privkey;
|
return privkey;
|
||||||
@ -167,7 +167,7 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_
|
|||||||
secp256k1_ecdsa_signature sig;
|
secp256k1_ecdsa_signature sig;
|
||||||
int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, test_case ? extra_entropy : NULL);
|
int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, test_case ? extra_entropy : NULL);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, (unsigned char*)&vchSig[0], &nSigLen, &sig);
|
secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, (unsigned char*)vchSig.data(), &nSigLen, &sig);
|
||||||
vchSig.resize(nSigLen);
|
vchSig.resize(nSigLen);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
|
bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
|
||||||
if (!ec_privkey_import_der(secp256k1_context_sign, (unsigned char*)begin(), &privkey[0], privkey.size()))
|
if (!ec_privkey_import_der(secp256k1_context_sign, (unsigned char*)begin(), privkey.data(), privkey.size()))
|
||||||
return false;
|
return false;
|
||||||
fCompressed = vchPubKey.IsCompressed();
|
fCompressed = vchPubKey.IsCompressed();
|
||||||
fValid = true;
|
fValid = true;
|
||||||
@ -245,8 +245,8 @@ void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
|
|||||||
static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
|
static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
|
||||||
std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
|
std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
|
||||||
CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(vout.data());
|
CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(vout.data());
|
||||||
key.Set(&vout[0], &vout[32], true);
|
key.Set(vout.data(), vout.data() + 32, true);
|
||||||
memcpy(chaincode.begin(), &vout[32], 32);
|
memcpy(chaincode.begin(), vout.data() + 32, 32);
|
||||||
nDepth = 0;
|
nDepth = 0;
|
||||||
nChild = 0;
|
nChild = 0;
|
||||||
memset(vchFingerprint, 0, sizeof(vchFingerprint));
|
memset(vchFingerprint, 0, sizeof(vchFingerprint));
|
||||||
|
@ -3365,5 +3365,5 @@ uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad) const
|
|||||||
{
|
{
|
||||||
std::vector<unsigned char> vchNetGroup(ad.GetGroup());
|
std::vector<unsigned char> vchNetGroup(ad.GetGroup());
|
||||||
|
|
||||||
return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize();
|
return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup.data(), vchNetGroup.size()).Finalize();
|
||||||
}
|
}
|
||||||
|
@ -583,7 +583,7 @@ std::vector<unsigned char> CService::GetKey() const
|
|||||||
{
|
{
|
||||||
std::vector<unsigned char> vKey;
|
std::vector<unsigned char> vKey;
|
||||||
vKey.resize(18);
|
vKey.resize(18);
|
||||||
memcpy(&vKey[0], ip, 16);
|
memcpy(vKey.data(), ip, 16);
|
||||||
vKey[16] = port / 0x100;
|
vKey[16] = port / 0x100;
|
||||||
vKey[17] = port & 0x0FF;
|
vKey[17] = port & 0x0FF;
|
||||||
return vKey;
|
return vKey;
|
||||||
|
@ -58,25 +58,6 @@ std::string GetNetworkName(enum Network net) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
|
|
||||||
size_t colon = in.find_last_of(':');
|
|
||||||
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
|
|
||||||
bool fHaveColon = colon != in.npos;
|
|
||||||
bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
|
|
||||||
bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
|
|
||||||
if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
|
|
||||||
int32_t n;
|
|
||||||
if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
|
|
||||||
in = in.substr(0, colon);
|
|
||||||
portOut = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
|
|
||||||
hostOut = in.substr(1, in.size()-2);
|
|
||||||
else
|
|
||||||
hostOut = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
|
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
|
||||||
{
|
{
|
||||||
vIP.clear();
|
vIP.clear();
|
||||||
@ -563,7 +544,7 @@ static bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDe
|
|||||||
// do socks negotiation
|
// do socks negotiation
|
||||||
if (proxy.randomize_credentials) {
|
if (proxy.randomize_credentials) {
|
||||||
ProxyCredentials random_auth;
|
ProxyCredentials random_auth;
|
||||||
static std::atomic_int counter;
|
static std::atomic_int counter(0);
|
||||||
random_auth.username = random_auth.password = strprintf("%i", counter++);
|
random_auth.username = random_auth.password = strprintf("%i", counter++);
|
||||||
if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket))
|
if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket))
|
||||||
return false;
|
return false;
|
||||||
|
@ -40,7 +40,6 @@ public:
|
|||||||
|
|
||||||
enum Network ParseNetwork(std::string net);
|
enum Network ParseNetwork(std::string net);
|
||||||
std::string GetNetworkName(enum Network net);
|
std::string GetNetworkName(enum Network net);
|
||||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
|
||||||
bool SetProxy(enum Network net, const proxyType &addrProxy);
|
bool SetProxy(enum Network net, const proxyType &addrProxy);
|
||||||
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
|
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
|
||||||
bool IsProxy(const CNetAddr &addr);
|
bool IsProxy(const CNetAddr &addr);
|
||||||
|
@ -220,7 +220,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prevector() : _size(0) {}
|
prevector() : _size(0), _union{{}} {}
|
||||||
|
|
||||||
explicit prevector(size_type n) : _size(0) {
|
explicit prevector(size_type n) : _size(0) {
|
||||||
resize(n);
|
resize(n);
|
||||||
|
@ -172,10 +172,7 @@ bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchS
|
|||||||
if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
|
if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (vchSig.size() == 0) {
|
if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* libsecp256k1's ECDSA verification requires lower-S signatures, which have
|
/* libsecp256k1's ECDSA verification requires lower-S signatures, which have
|
||||||
@ -274,7 +271,7 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
|
|||||||
|
|
||||||
/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
|
/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
|
||||||
secp256k1_ecdsa_signature sig;
|
secp256k1_ecdsa_signature sig;
|
||||||
if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
|
if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig));
|
return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig));
|
||||||
|
@ -389,6 +389,10 @@ void TransactionView::changedAmount(const QString &amount)
|
|||||||
|
|
||||||
void TransactionView::exportClicked()
|
void TransactionView::exportClicked()
|
||||||
{
|
{
|
||||||
|
if (!model || !model->getOptionsModel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// CSV is currently the only supported format
|
// CSV is currently the only supported format
|
||||||
QString filename = GUIUtil::getSaveFileName(this,
|
QString filename = GUIUtil::getSaveFileName(this,
|
||||||
tr("Export Transaction History"), QString(),
|
tr("Export Transaction History"), QString(),
|
||||||
|
@ -36,6 +36,10 @@
|
|||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
|
||||||
|
#include <cpuid.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
@ -72,18 +76,9 @@ static bool rdrand_supported = false;
|
|||||||
static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
|
static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
|
||||||
static void RDRandInit()
|
static void RDRandInit()
|
||||||
{
|
{
|
||||||
uint32_t eax, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
#if defined(__i386__) && ( defined(__PIC__) || defined(__PIE__))
|
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & CPUID_F1_ECX_RDRAND)) {
|
||||||
// Avoid clobbering ebx, as that is used for PIC on x86.
|
LogPrintf("Using RdRand as an additional entropy source\n");
|
||||||
uint32_t tmp;
|
|
||||||
__asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1));
|
|
||||||
#else
|
|
||||||
uint32_t ebx;
|
|
||||||
__asm__ ("cpuid": "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1));
|
|
||||||
#endif
|
|
||||||
//! When calling cpuid function #1, ecx register will have this set if RDRAND is available.
|
|
||||||
if (ecx & CPUID_F1_ECX_RDRAND) {
|
|
||||||
LogPrintf("Using RdRand as entropy source\n");
|
|
||||||
rdrand_supported = true;
|
rdrand_supported = true;
|
||||||
}
|
}
|
||||||
hwrand_initialized.store(true);
|
hwrand_initialized.store(true);
|
||||||
|
@ -1229,7 +1229,7 @@ UniValue gettxout(const JSONRPCRequest& request)
|
|||||||
if (fMempool) {
|
if (fMempool) {
|
||||||
LOCK(mempool.cs);
|
LOCK(mempool.cs);
|
||||||
CCoinsViewMemPool view(pcoinsTip, mempool);
|
CCoinsViewMemPool view(pcoinsTip, mempool);
|
||||||
if (!view.GetCoin(out, coin) || mempool.isSpent(out)) { // TODO: filtering spent coins should be done by the CCoinsViewMemPool
|
if (!view.GetCoin(out, coin) || mempool.isSpent(out)) {
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -101,6 +101,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "listunspent", 3, "include_unsafe" },
|
{ "listunspent", 3, "include_unsafe" },
|
||||||
{ "listunspent", 4, "query_options" },
|
{ "listunspent", 4, "query_options" },
|
||||||
{ "getblock", 1, "verbosity" },
|
{ "getblock", 1, "verbosity" },
|
||||||
|
{ "getblock", 1, "verbose" },
|
||||||
{ "getblockheader", 1, "verbose" },
|
{ "getblockheader", 1, "verbose" },
|
||||||
{ "getblockheaders", 1, "count" },
|
{ "getblockheaders", 1, "count" },
|
||||||
{ "getblockheaders", 2, "verbose" },
|
{ "getblockheaders", 2, "verbose" },
|
||||||
|
@ -335,6 +335,14 @@ UniValue validateaddress(const JSONRPCRequest& request)
|
|||||||
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
|
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
|
||||||
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
|
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
|
||||||
" \"isscript\" : true|false, (boolean) If the key is a script\n"
|
" \"isscript\" : true|false, (boolean) If the key is a script\n"
|
||||||
|
" \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata\n"
|
||||||
|
" \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n"
|
||||||
|
" \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n"
|
||||||
|
" [\n"
|
||||||
|
" \"address\"\n"
|
||||||
|
" ,...\n"
|
||||||
|
" ]\n"
|
||||||
|
" \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n"
|
||||||
" \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
|
" \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
|
||||||
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
|
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
|
||||||
" \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
|
" \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
|
||||||
|
@ -630,7 +630,7 @@ public:
|
|||||||
}
|
}
|
||||||
string.resize(size);
|
string.resize(size);
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
s.read((char*)&string[0], size);
|
s.read((char*)string.data(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
@ -638,7 +638,7 @@ public:
|
|||||||
{
|
{
|
||||||
WriteCompactSize(s, string.size());
|
WriteCompactSize(s, string.size());
|
||||||
if (!string.empty())
|
if (!string.empty())
|
||||||
s.write((char*)&string[0], string.size());
|
s.write((char*)string.data(), string.size());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -778,7 +778,7 @@ void Serialize(Stream& os, const std::basic_string<C>& str)
|
|||||||
{
|
{
|
||||||
WriteCompactSize(os, str.size());
|
WriteCompactSize(os, str.size());
|
||||||
if (!str.empty())
|
if (!str.empty())
|
||||||
os.write((char*)&str[0], str.size() * sizeof(str[0]));
|
os.write((char*)str.data(), str.size() * sizeof(C));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream, typename C>
|
template<typename Stream, typename C>
|
||||||
@ -787,7 +787,7 @@ void Unserialize(Stream& is, std::basic_string<C>& str)
|
|||||||
unsigned int nSize = ReadCompactSize(is);
|
unsigned int nSize = ReadCompactSize(is);
|
||||||
str.resize(nSize);
|
str.resize(nSize);
|
||||||
if (nSize != 0)
|
if (nSize != 0)
|
||||||
is.read((char*)&str[0], nSize * sizeof(str[0]));
|
is.read((char*)str.data(), nSize * sizeof(C));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -800,7 +800,7 @@ void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
|
|||||||
{
|
{
|
||||||
WriteCompactSize(os, v.size());
|
WriteCompactSize(os, v.size());
|
||||||
if (!v.empty())
|
if (!v.empty())
|
||||||
os.write((char*)&v[0], v.size() * sizeof(T));
|
os.write((char*)v.data(), v.size() * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream, unsigned int N, typename T, typename V>
|
template<typename Stream, unsigned int N, typename T, typename V>
|
||||||
@ -868,7 +868,7 @@ void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&
|
|||||||
{
|
{
|
||||||
WriteCompactSize(os, v.size());
|
WriteCompactSize(os, v.size());
|
||||||
if (!v.empty())
|
if (!v.empty())
|
||||||
os.write((char*)&v[0], v.size() * sizeof(T));
|
os.write((char*)v.data(), v.size() * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream, typename T, typename A, typename V>
|
template<typename Stream, typename T, typename A, typename V>
|
||||||
|
@ -346,7 +346,7 @@ public:
|
|||||||
{
|
{
|
||||||
// Special case: stream << stream concatenates like stream += stream
|
// Special case: stream << stream concatenates like stream += stream
|
||||||
if (!vch.empty())
|
if (!vch.empty())
|
||||||
s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
|
s.write((char*)vch.data(), vch.size() * sizeof(value_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -148,9 +148,9 @@ class Win32LockedPageAllocator: public LockedPageAllocator
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Win32LockedPageAllocator();
|
Win32LockedPageAllocator();
|
||||||
void* AllocateLocked(size_t len, bool *lockingSuccess);
|
void* AllocateLocked(size_t len, bool *lockingSuccess) override;
|
||||||
void FreeLocked(void* addr, size_t len);
|
void FreeLocked(void* addr, size_t len) override;
|
||||||
size_t GetLimit();
|
size_t GetLimit() override;
|
||||||
private:
|
private:
|
||||||
size_t page_size;
|
size_t page_size;
|
||||||
};
|
};
|
||||||
@ -200,9 +200,9 @@ class PosixLockedPageAllocator: public LockedPageAllocator
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PosixLockedPageAllocator();
|
PosixLockedPageAllocator();
|
||||||
void* AllocateLocked(size_t len, bool *lockingSuccess);
|
void* AllocateLocked(size_t len, bool *lockingSuccess) override;
|
||||||
void FreeLocked(void* addr, size_t len);
|
void FreeLocked(void* addr, size_t len) override;
|
||||||
size_t GetLimit();
|
size_t GetLimit() override;
|
||||||
private:
|
private:
|
||||||
size_t page_size;
|
size_t page_size;
|
||||||
};
|
};
|
||||||
|
@ -131,7 +131,7 @@ class TestLockedPageAllocator: public LockedPageAllocator
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestLockedPageAllocator(int count_in, int lockedcount_in): count(count_in), lockedcount(lockedcount_in) {}
|
TestLockedPageAllocator(int count_in, int lockedcount_in): count(count_in), lockedcount(lockedcount_in) {}
|
||||||
void* AllocateLocked(size_t len, bool *lockingSuccess)
|
void* AllocateLocked(size_t len, bool *lockingSuccess) override
|
||||||
{
|
{
|
||||||
*lockingSuccess = false;
|
*lockingSuccess = false;
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
@ -146,10 +146,10 @@ public:
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void FreeLocked(void* addr, size_t len)
|
void FreeLocked(void* addr, size_t len) override
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
size_t GetLimit()
|
size_t GetLimit() override
|
||||||
{
|
{
|
||||||
return std::numeric_limits<size_t>::max();
|
return std::numeric_limits<size_t>::max();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "test/test_dash.h"
|
#include "test/test_dash.h"
|
||||||
|
#include "utilstrencodings.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -663,7 +663,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro
|
|||||||
// _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2));
|
// _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2));
|
||||||
cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end());
|
cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end());
|
||||||
clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0);
|
clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0);
|
||||||
GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE);
|
GetRandBytes(clientNonce.data(), TOR_NONCE_SIZE);
|
||||||
_conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2));
|
_conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2));
|
||||||
} else {
|
} else {
|
||||||
if (status_cookie.first) {
|
if (status_cookie.first) {
|
||||||
|
@ -657,13 +657,6 @@ public:
|
|||||||
return (mapTx.count(hash) != 0);
|
return (mapTx.count(hash) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exists(const COutPoint& outpoint) const
|
|
||||||
{
|
|
||||||
LOCK(cs);
|
|
||||||
auto it = mapTx.find(outpoint.hash);
|
|
||||||
return (it != mapTx.end() && outpoint.n < it->GetTx().vout.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
CTransactionRef get(const uint256& hash) const;
|
CTransactionRef get(const uint256& hash) const;
|
||||||
TxMempoolInfo info(const uint256& hash) const;
|
TxMempoolInfo info(const uint256& hash) const;
|
||||||
std::vector<TxMempoolInfo> infoAll() const;
|
std::vector<TxMempoolInfo> infoAll() const;
|
||||||
@ -717,6 +710,13 @@ private:
|
|||||||
/**
|
/**
|
||||||
* CCoinsView that brings transactions from a memorypool into view.
|
* CCoinsView that brings transactions from a memorypool into view.
|
||||||
* It does not check for spendings by memory pool transactions.
|
* It does not check for spendings by memory pool transactions.
|
||||||
|
* Instead, it provides access to all Coins which are either unspent in the
|
||||||
|
* base CCoinsView, or are outputs from any mempool transaction!
|
||||||
|
* This allows transaction replacement to work as expected, as you want to
|
||||||
|
* have all inputs "available" to check signatures, and any cycles in the
|
||||||
|
* dependency graph are checked directly in AcceptToMemoryPool.
|
||||||
|
* It also allows you to sign a double-spend directly in signrawtransaction,
|
||||||
|
* as long as the conflicting transaction is not yet confirmed.
|
||||||
*/
|
*/
|
||||||
class CCoinsViewMemPool : public CCoinsViewBacked
|
class CCoinsViewMemPool : public CCoinsViewBacked
|
||||||
{
|
{
|
||||||
|
@ -91,6 +91,25 @@ std::vector<unsigned char> ParseHex(const std::string& str)
|
|||||||
return ParseHex(str.c_str());
|
return ParseHex(str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
|
||||||
|
size_t colon = in.find_last_of(':');
|
||||||
|
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
|
||||||
|
bool fHaveColon = colon != in.npos;
|
||||||
|
bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
|
||||||
|
bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
|
||||||
|
if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
|
||||||
|
int32_t n;
|
||||||
|
if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
|
||||||
|
in = in.substr(0, colon);
|
||||||
|
portOut = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
|
||||||
|
hostOut = in.substr(1, in.size()-2);
|
||||||
|
else
|
||||||
|
hostOut = in;
|
||||||
|
}
|
||||||
|
|
||||||
std::string EncodeBase64(const unsigned char* pch, size_t len)
|
std::string EncodeBase64(const unsigned char* pch, size_t len)
|
||||||
{
|
{
|
||||||
static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
@ -228,7 +247,7 @@ std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
|
|||||||
std::string DecodeBase64(const std::string& str)
|
std::string DecodeBase64(const std::string& str)
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> vchRet = DecodeBase64(str.c_str());
|
std::vector<unsigned char> vchRet = DecodeBase64(str.c_str());
|
||||||
return (vchRet.size() == 0) ? std::string() : std::string((const char*)&vchRet[0], vchRet.size());
|
return std::string((const char*)vchRet.data(), vchRet.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EncodeBase32(const unsigned char* pch, size_t len)
|
std::string EncodeBase32(const unsigned char* pch, size_t len)
|
||||||
@ -415,7 +434,7 @@ std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
|
|||||||
std::string DecodeBase32(const std::string& str)
|
std::string DecodeBase32(const std::string& str)
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> vchRet = DecodeBase32(str.c_str());
|
std::vector<unsigned char> vchRet = DecodeBase32(str.c_str());
|
||||||
return (vchRet.size() == 0) ? std::string() : std::string((const char*)&vchRet[0], vchRet.size());
|
return std::string((const char*)vchRet.data(), vchRet.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParsePrechecks(const std::string& str)
|
static bool ParsePrechecks(const std::string& str)
|
||||||
|
@ -48,6 +48,7 @@ std::string DecodeBase32(const std::string& str);
|
|||||||
std::string EncodeBase32(const unsigned char* pch, size_t len);
|
std::string EncodeBase32(const unsigned char* pch, size_t len);
|
||||||
std::string EncodeBase32(const std::string& str);
|
std::string EncodeBase32(const std::string& str);
|
||||||
|
|
||||||
|
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
||||||
std::string i64tostr(int64_t n);
|
std::string i64tostr(int64_t n);
|
||||||
std::string itostr(int n);
|
std::string itostr(int n);
|
||||||
int64_t atoi64(const char* psz);
|
int64_t atoi64(const char* psz);
|
||||||
|
@ -734,24 +734,20 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
|
|||||||
CCoinsViewMemPool viewMemPool(pcoinsTip, pool);
|
CCoinsViewMemPool viewMemPool(pcoinsTip, pool);
|
||||||
view.SetBackend(viewMemPool);
|
view.SetBackend(viewMemPool);
|
||||||
|
|
||||||
// do we already have it?
|
|
||||||
for (size_t out = 0; out < tx.vout.size(); out++) {
|
|
||||||
COutPoint outpoint(hash, out);
|
|
||||||
bool had_coin_in_cache = pcoinsTip->HaveCoinInCache(outpoint);
|
|
||||||
if (view.HaveCoin(outpoint)) {
|
|
||||||
if (!had_coin_in_cache) {
|
|
||||||
coins_to_uncache.push_back(outpoint);
|
|
||||||
}
|
|
||||||
return state.Invalid(false, REJECT_DUPLICATE, "txn-already-known");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do all inputs exist?
|
// do all inputs exist?
|
||||||
for (const CTxIn txin : tx.vin) {
|
for (const CTxIn txin : tx.vin) {
|
||||||
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
|
if (!pcoinsTip->HaveCoinInCache(txin.prevout)) {
|
||||||
coins_to_uncache.push_back(txin.prevout);
|
coins_to_uncache.push_back(txin.prevout);
|
||||||
}
|
}
|
||||||
if (!view.HaveCoin(txin.prevout)) {
|
if (!view.HaveCoin(txin.prevout)) {
|
||||||
|
// Are inputs missing because we already have the tx?
|
||||||
|
for (size_t out = 0; out < tx.vout.size(); out++) {
|
||||||
|
// Optimistically just do efficient check of cache for outputs
|
||||||
|
if (pcoinsTip->HaveCoinInCache(COutPoint(hash, out))) {
|
||||||
|
return state.Invalid(false, REJECT_DUPLICATE, "txn-already-known");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise assume this might be an orphan tx for which we just haven't seen parents yet
|
||||||
if (pfMissingInputs) {
|
if (pfMissingInputs) {
|
||||||
*pfMissingInputs = true;
|
*pfMissingInputs = true;
|
||||||
}
|
}
|
||||||
@ -1314,7 +1310,7 @@ static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
|
|||||||
// hash rate operating on the fork.
|
// hash rate operating on the fork.
|
||||||
// We define it this way because it allows us to only store the highest fork tip (+ base) which meets
|
// We define it this way because it allows us to only store the highest fork tip (+ base) which meets
|
||||||
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
|
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
|
||||||
if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) &&
|
if (pfork && (!pindexBestForkTip || pindexNewForkTip->nHeight > pindexBestForkTip->nHeight) &&
|
||||||
pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) &&
|
pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) &&
|
||||||
chainActive.Height() - pindexNewForkTip->nHeight < 72)
|
chainActive.Height() - pindexNewForkTip->nHeight < 72)
|
||||||
{
|
{
|
||||||
|
@ -95,13 +95,13 @@ class CWalletDBWrapper
|
|||||||
friend class CDB;
|
friend class CDB;
|
||||||
public:
|
public:
|
||||||
/** Create dummy DB handle */
|
/** Create dummy DB handle */
|
||||||
CWalletDBWrapper() : nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr)
|
CWalletDBWrapper() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create DB handle to real database */
|
/** Create DB handle to real database */
|
||||||
CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) :
|
CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) :
|
||||||
nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in)
|
nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
|
|||||||
"\nExamples:\n"
|
"\nExamples:\n"
|
||||||
+ HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
|
+ HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
|
||||||
"\nAs a JSON-RPC call\n"
|
"\nAs a JSON-RPC call\n"
|
||||||
+ HelpExampleRpc("removprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
|
+ HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
|
||||||
);
|
);
|
||||||
|
|
||||||
LOCK2(cs_main, pwallet->cs_wallet);
|
LOCK2(cs_main, pwallet->cs_wallet);
|
||||||
|
@ -767,9 +767,9 @@ UniValue getbalance(const JSONRPCRequest& request)
|
|||||||
"\nResult:\n"
|
"\nResult:\n"
|
||||||
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
|
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
|
||||||
"\nExamples:\n"
|
"\nExamples:\n"
|
||||||
"\nThe total amount in the wallet\n"
|
"\nThe total amount in the wallet with 1 or more confirmations\n"
|
||||||
+ HelpExampleCli("getbalance", "") +
|
+ HelpExampleCli("getbalance", "") +
|
||||||
"\nThe total amount in the wallet at least 5 blocks confirmed\n"
|
"\nThe total amount in the wallet at least 6 blocks confirmed\n"
|
||||||
+ HelpExampleCli("getbalance", "\"*\" 6") +
|
+ HelpExampleCli("getbalance", "\"*\" 6") +
|
||||||
"\nAs a json rpc call\n"
|
"\nAs a json rpc call\n"
|
||||||
+ HelpExampleRpc("getbalance", "\"*\", 6")
|
+ HelpExampleRpc("getbalance", "\"*\", 6")
|
||||||
|
@ -5131,20 +5131,24 @@ bool CWallet::ParameterInteraction()
|
|||||||
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
|
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gArgs.GetBoolArg("-salvagewallet", false) && gArgs.SoftSetBoolArg("-rescan", true)) {
|
if (gArgs.GetBoolArg("-salvagewallet", false)) {
|
||||||
if (is_multiwallet) {
|
if (is_multiwallet) {
|
||||||
return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
|
return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet"));
|
||||||
}
|
}
|
||||||
// Rewrite just private keys: rescan to find transactions
|
// Rewrite just private keys: rescan to find transactions
|
||||||
LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
|
if (gArgs.SoftSetBoolArg("-rescan", true)) {
|
||||||
|
LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -zapwallettx implies a rescan
|
// -zapwallettx implies a rescan
|
||||||
if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.SoftSetBoolArg("-rescan", true)) {
|
if (gArgs.GetBoolArg("-zapwallettxes", false)) {
|
||||||
if (is_multiwallet) {
|
if (is_multiwallet) {
|
||||||
return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
|
return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes"));
|
||||||
}
|
}
|
||||||
LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__);
|
if (gArgs.SoftSetBoolArg("-rescan", true)) {
|
||||||
|
LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_multiwallet) {
|
if (is_multiwallet) {
|
||||||
|
@ -782,7 +782,7 @@ DBErrors CWalletDB::ZapWalletTx(std::vector<CWalletTx>& vWtx)
|
|||||||
|
|
||||||
void MaybeCompactWalletDB()
|
void MaybeCompactWalletDB()
|
||||||
{
|
{
|
||||||
static std::atomic<bool> fOneThread;
|
static std::atomic<bool> fOneThread(false);
|
||||||
if (fOneThread.exchange(true)) {
|
if (fOneThread.exchange(true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,157 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
|
||||||
# Distributed under the MIT software license, see the accompanying
|
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
"""Test block proposals with getblocktemplate."""
|
|
||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
|
||||||
from test_framework.util import *
|
|
||||||
|
|
||||||
from binascii import a2b_hex, b2a_hex
|
|
||||||
from hashlib import sha256
|
|
||||||
from struct import pack
|
|
||||||
|
|
||||||
def b2x(b):
|
|
||||||
return b2a_hex(b).decode('ascii')
|
|
||||||
|
|
||||||
# NOTE: This does not work for signed numbers (set the high bit) or zero (use b'\0')
|
|
||||||
def encodeUNum(n):
|
|
||||||
s = bytearray(b'\1')
|
|
||||||
while n > 127:
|
|
||||||
s[0] += 1
|
|
||||||
s.append(n % 256)
|
|
||||||
n //= 256
|
|
||||||
s.append(n)
|
|
||||||
return bytes(s)
|
|
||||||
|
|
||||||
def varlenEncode(n):
|
|
||||||
if n < 0xfd:
|
|
||||||
return pack('<B', n)
|
|
||||||
if n <= 0xffff:
|
|
||||||
return b'\xfd' + pack('<H', n)
|
|
||||||
if n <= 0xffffffff:
|
|
||||||
return b'\xfe' + pack('<L', n)
|
|
||||||
return b'\xff' + pack('<Q', n)
|
|
||||||
|
|
||||||
def dblsha(b):
|
|
||||||
return sha256(sha256(b).digest()).digest()
|
|
||||||
|
|
||||||
def genmrklroot(leaflist):
|
|
||||||
cur = leaflist
|
|
||||||
while len(cur) > 1:
|
|
||||||
n = []
|
|
||||||
if len(cur) & 1:
|
|
||||||
cur.append(cur[-1])
|
|
||||||
for i in range(0, len(cur), 2):
|
|
||||||
n.append(dblsha(cur[i] + cur[i+1]))
|
|
||||||
cur = n
|
|
||||||
return cur[0]
|
|
||||||
|
|
||||||
def template_to_bytearray(tmpl, txlist):
|
|
||||||
blkver = pack('<L', tmpl['version'])
|
|
||||||
mrklroot = genmrklroot(list(dblsha(a) for a in txlist))
|
|
||||||
timestamp = pack('<L', tmpl['curtime'])
|
|
||||||
nonce = b'\0\0\0\0'
|
|
||||||
blk = blkver + a2b_hex(tmpl['previousblockhash'])[::-1] + mrklroot + timestamp + a2b_hex(tmpl['bits'])[::-1] + nonce
|
|
||||||
blk += varlenEncode(len(txlist))
|
|
||||||
for tx in txlist:
|
|
||||||
blk += tx
|
|
||||||
return bytearray(blk)
|
|
||||||
|
|
||||||
def template_to_hex(tmpl, txlist):
|
|
||||||
return b2x(template_to_bytearray(tmpl, txlist))
|
|
||||||
|
|
||||||
def assert_template(node, tmpl, txlist, expect):
|
|
||||||
rsp = node.getblocktemplate({'data':template_to_hex(tmpl, txlist),'mode':'proposal'})
|
|
||||||
if rsp != expect:
|
|
||||||
raise AssertionError('unexpected: %s' % (rsp,))
|
|
||||||
|
|
||||||
class GetBlockTemplateProposalTest(BitcoinTestFramework):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.num_nodes = 2
|
|
||||||
self.setup_clean_chain = False
|
|
||||||
|
|
||||||
def run_test(self):
|
|
||||||
node = self.nodes[0]
|
|
||||||
node.generate(1) # Mine a block to leave initial block download
|
|
||||||
tmpl = node.getblocktemplate()
|
|
||||||
if 'coinbasetxn' not in tmpl:
|
|
||||||
rawcoinbase = encodeUNum(tmpl['height'])
|
|
||||||
rawcoinbase += b'\x01-'
|
|
||||||
hexcoinbase = b2x(rawcoinbase)
|
|
||||||
hexoutval = b2x(pack('<Q', tmpl['coinbasevalue']))
|
|
||||||
tmpl['coinbasetxn'] = {'data': '01000000' + '01' + '0000000000000000000000000000000000000000000000000000000000000000ffffffff' + ('%02x' % (len(rawcoinbase),)) + hexcoinbase + 'fffffffe' + '01' + hexoutval + '00' + '00000000'}
|
|
||||||
txlist = list(bytearray(a2b_hex(a['data'])) for a in (tmpl['coinbasetxn'],) + tuple(tmpl['transactions']))
|
|
||||||
|
|
||||||
# Test 0: Capability advertised
|
|
||||||
assert('proposal' in tmpl['capabilities'])
|
|
||||||
|
|
||||||
# NOTE: This test currently FAILS (regtest mode doesn't enforce block height in coinbase)
|
|
||||||
## Test 1: Bad height in coinbase
|
|
||||||
#txlist[0][4+1+36+1+1] += 1
|
|
||||||
#assert_template(node, tmpl, txlist, 'FIXME')
|
|
||||||
#txlist[0][4+1+36+1+1] -= 1
|
|
||||||
|
|
||||||
# Test 2: Bad input hash for gen tx
|
|
||||||
txlist[0][4+1] += 1
|
|
||||||
assert_template(node, tmpl, txlist, 'bad-cb-missing')
|
|
||||||
txlist[0][4+1] -= 1
|
|
||||||
|
|
||||||
# Test 3: Truncated final tx
|
|
||||||
lastbyte = txlist[-1].pop()
|
|
||||||
assert_raises_jsonrpc(-22, "Block decode failed", assert_template, node, tmpl, txlist, 'n/a')
|
|
||||||
txlist[-1].append(lastbyte)
|
|
||||||
|
|
||||||
# Test 4: Add an invalid tx to the end (duplicate of gen tx)
|
|
||||||
txlist.append(txlist[0])
|
|
||||||
assert_template(node, tmpl, txlist, 'bad-txns-duplicate')
|
|
||||||
txlist.pop()
|
|
||||||
|
|
||||||
# Test 5: Add an invalid tx to the end (non-duplicate)
|
|
||||||
txlist.append(bytearray(txlist[0]))
|
|
||||||
txlist[-1][4+1] = 0xff
|
|
||||||
assert_template(node, tmpl, txlist, 'bad-txns-inputs-missingorspent')
|
|
||||||
txlist.pop()
|
|
||||||
|
|
||||||
# Test 6: Future tx lock time
|
|
||||||
txlist[0][-4:] = b'\xff\xff\xff\xff'
|
|
||||||
assert_template(node, tmpl, txlist, 'bad-txns-nonfinal')
|
|
||||||
txlist[0][-4:] = b'\0\0\0\0'
|
|
||||||
|
|
||||||
# Test 7: Bad tx count
|
|
||||||
txlist.append(b'')
|
|
||||||
assert_raises_jsonrpc(-22, 'Block decode failed', assert_template, node, tmpl, txlist, 'n/a')
|
|
||||||
txlist.pop()
|
|
||||||
|
|
||||||
# Test 8: Bad bits
|
|
||||||
realbits = tmpl['bits']
|
|
||||||
tmpl['bits'] = '1c0000ff' # impossible in the real world
|
|
||||||
assert_template(node, tmpl, txlist, 'bad-diffbits')
|
|
||||||
tmpl['bits'] = realbits
|
|
||||||
|
|
||||||
# Test 9: Bad merkle root
|
|
||||||
rawtmpl = template_to_bytearray(tmpl, txlist)
|
|
||||||
rawtmpl[4+32] = (rawtmpl[4+32] + 1) % 0x100
|
|
||||||
rsp = node.getblocktemplate({'data':b2x(rawtmpl),'mode':'proposal'})
|
|
||||||
if rsp != 'bad-txnmrklroot':
|
|
||||||
raise AssertionError('unexpected: %s' % (rsp,))
|
|
||||||
|
|
||||||
# Test 10: Bad timestamps
|
|
||||||
realtime = tmpl['curtime']
|
|
||||||
tmpl['curtime'] = 0x7fffffff
|
|
||||||
assert_template(node, tmpl, txlist, 'time-too-new')
|
|
||||||
tmpl['curtime'] = 0
|
|
||||||
assert_template(node, tmpl, txlist, 'time-too-old')
|
|
||||||
tmpl['curtime'] = realtime
|
|
||||||
|
|
||||||
# Test 11: Valid block
|
|
||||||
assert_template(node, tmpl, txlist, None)
|
|
||||||
|
|
||||||
# Test 12: Orphan block
|
|
||||||
tmpl['previousblockhash'] = 'ff00' * 16
|
|
||||||
assert_template(node, tmpl, txlist, 'inconclusive-not-best-prevblk')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
GetBlockTemplateProposalTest().main()
|
|
124
test/functional/mining.py
Executable file
124
test/functional/mining.py
Executable file
@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
"""Test mining RPCs
|
||||||
|
|
||||||
|
- getblocktemplate proposal mode
|
||||||
|
- submitblock"""
|
||||||
|
|
||||||
|
from binascii import b2a_hex
|
||||||
|
import copy
|
||||||
|
|
||||||
|
from test_framework.blocktools import create_coinbase
|
||||||
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
|
from test_framework.mininode import CBlock
|
||||||
|
from test_framework.util import *
|
||||||
|
|
||||||
|
def b2x(b):
|
||||||
|
return b2a_hex(b).decode('ascii')
|
||||||
|
|
||||||
|
def assert_template(node, block, expect, rehash=True):
|
||||||
|
if rehash:
|
||||||
|
block.hashMerkleRoot = block.calc_merkle_root()
|
||||||
|
rsp = node.getblocktemplate({'data': b2x(block.serialize()), 'mode': 'proposal'})
|
||||||
|
assert_equal(rsp, expect)
|
||||||
|
|
||||||
|
class MiningTest(BitcoinTestFramework):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.num_nodes = 2
|
||||||
|
self.setup_clean_chain = False
|
||||||
|
|
||||||
|
def run_test(self):
|
||||||
|
node = self.nodes[0]
|
||||||
|
# Mine a block to leave initial block download
|
||||||
|
node.generate(1)
|
||||||
|
tmpl = node.getblocktemplate()
|
||||||
|
self.log.info("getblocktemplate: Test capability advertised")
|
||||||
|
assert 'proposal' in tmpl['capabilities']
|
||||||
|
assert 'coinbasetxn' not in tmpl
|
||||||
|
|
||||||
|
coinbase_tx = create_coinbase(height=int(tmpl["height"]) + 1)
|
||||||
|
# sequence numbers must not be max for nLockTime to have effect
|
||||||
|
coinbase_tx.vin[0].nSequence = 2 ** 32 - 2
|
||||||
|
coinbase_tx.rehash()
|
||||||
|
|
||||||
|
block = CBlock()
|
||||||
|
block.nVersion = tmpl["version"]
|
||||||
|
block.hashPrevBlock = int(tmpl["previousblockhash"], 16)
|
||||||
|
block.nTime = tmpl["curtime"]
|
||||||
|
block.nBits = int(tmpl["bits"], 16)
|
||||||
|
block.nNonce = 0
|
||||||
|
block.vtx = [coinbase_tx]
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test valid block")
|
||||||
|
assert_template(node, block, None)
|
||||||
|
|
||||||
|
self.log.info("submitblock: Test block decode failure")
|
||||||
|
assert_raises_jsonrpc(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15]))
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test bad input hash for coinbase transaction")
|
||||||
|
bad_block = copy.deepcopy(block)
|
||||||
|
bad_block.vtx[0].vin[0].prevout.hash += 1
|
||||||
|
bad_block.vtx[0].rehash()
|
||||||
|
assert_template(node, bad_block, 'bad-cb-missing')
|
||||||
|
|
||||||
|
self.log.info("submitblock: Test invalid coinbase transaction")
|
||||||
|
assert_raises_jsonrpc(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize()))
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test truncated final transaction")
|
||||||
|
assert_raises_jsonrpc(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(block.serialize()[:-1]), 'mode': 'proposal'})
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test duplicate transaction")
|
||||||
|
bad_block = copy.deepcopy(block)
|
||||||
|
bad_block.vtx.append(bad_block.vtx[0])
|
||||||
|
assert_template(node, bad_block, 'bad-txns-duplicate')
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test invalid transaction")
|
||||||
|
bad_block = copy.deepcopy(block)
|
||||||
|
bad_tx = copy.deepcopy(bad_block.vtx[0])
|
||||||
|
bad_tx.vin[0].prevout.hash = 255
|
||||||
|
bad_tx.rehash()
|
||||||
|
bad_block.vtx.append(bad_tx)
|
||||||
|
assert_template(node, bad_block, 'bad-txns-inputs-missingorspent')
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test nonfinal transaction")
|
||||||
|
bad_block = copy.deepcopy(block)
|
||||||
|
bad_block.vtx[0].nLockTime = 2 ** 32 - 1
|
||||||
|
bad_block.vtx[0].rehash()
|
||||||
|
assert_template(node, bad_block, 'bad-txns-nonfinal')
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test bad tx count")
|
||||||
|
# The tx count is immediately after the block header
|
||||||
|
TX_COUNT_OFFSET = 80
|
||||||
|
bad_block_sn = bytearray(block.serialize())
|
||||||
|
assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1)
|
||||||
|
bad_block_sn[TX_COUNT_OFFSET] += 1
|
||||||
|
assert_raises_jsonrpc(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(bad_block_sn), 'mode': 'proposal'})
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test bad bits")
|
||||||
|
bad_block = copy.deepcopy(block)
|
||||||
|
bad_block.nBits = 469762303 # impossible in the real world
|
||||||
|
assert_template(node, bad_block, 'bad-diffbits')
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test bad merkle root")
|
||||||
|
bad_block = copy.deepcopy(block)
|
||||||
|
bad_block.hashMerkleRoot += 1
|
||||||
|
assert_template(node, bad_block, 'bad-txnmrklroot', False)
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test bad timestamps")
|
||||||
|
bad_block = copy.deepcopy(block)
|
||||||
|
bad_block.nTime = 2 ** 31 - 1
|
||||||
|
assert_template(node, bad_block, 'time-too-new')
|
||||||
|
bad_block.nTime = 0
|
||||||
|
assert_template(node, bad_block, 'time-too-old')
|
||||||
|
|
||||||
|
self.log.info("getblocktemplate: Test not best block")
|
||||||
|
bad_block = copy.deepcopy(block)
|
||||||
|
bad_block.hashPrevBlock = 123
|
||||||
|
assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
MiningTest().main()
|
@ -119,6 +119,7 @@ BASE_SCRIPTS= [
|
|||||||
'signmessages.py',
|
'signmessages.py',
|
||||||
'nulldummy.py',
|
'nulldummy.py',
|
||||||
'import-rescan.py',
|
'import-rescan.py',
|
||||||
|
'mining.py',
|
||||||
'rpcnamedargs.py',
|
'rpcnamedargs.py',
|
||||||
'listsinceblock.py',
|
'listsinceblock.py',
|
||||||
'p2p-leaktests.py',
|
'p2p-leaktests.py',
|
||||||
@ -152,7 +153,6 @@ EXTENDED_SCRIPTS = [
|
|||||||
'bipdersig-p2p.py', # NOTE: needs dash_hash to pass
|
'bipdersig-p2p.py', # NOTE: needs dash_hash to pass
|
||||||
'bipdersig.py',
|
'bipdersig.py',
|
||||||
'example_test.py',
|
'example_test.py',
|
||||||
'getblocktemplate_proposals.py',
|
|
||||||
'txn_doublespend.py',
|
'txn_doublespend.py',
|
||||||
'txn_clone.py --mineblock',
|
'txn_clone.py --mineblock',
|
||||||
'txindex.py',
|
'txindex.py',
|
||||||
|
Loading…
Reference in New Issue
Block a user