diff options
-rw-r--r-- | contrib/gitian-descriptors/protobuf-win.yml | 4 | ||||
-rw-r--r-- | qa/rpc-tests/README.md | 23 | ||||
-rwxr-xr-x | qa/rpc-tests/txnmall.sh | 6 | ||||
-rwxr-xr-x | qa/rpc-tests/walletbackup.sh | 293 | ||||
-rw-r--r-- | src/alert.cpp | 4 | ||||
-rw-r--r-- | src/bitcoin-cli.cpp | 11 | ||||
-rw-r--r-- | src/core.cpp | 2 | ||||
-rw-r--r-- | src/core.h | 4 | ||||
-rw-r--r-- | src/db.cpp | 2 | ||||
-rw-r--r-- | src/init.cpp | 10 | ||||
-rw-r--r-- | src/main.cpp | 16 | ||||
-rw-r--r-- | src/miner.cpp | 2 | ||||
-rw-r--r-- | src/net.cpp | 2 | ||||
-rw-r--r-- | src/net.h | 2 | ||||
-rw-r--r-- | src/rpcclient.cpp | 2 | ||||
-rw-r--r-- | src/rpcnet.cpp | 2 | ||||
-rw-r--r-- | src/sync.cpp | 5 | ||||
-rw-r--r-- | src/test/base58_tests.cpp | 6 | ||||
-rw-r--r-- | src/test/bignum_tests.cpp | 36 | ||||
-rw-r--r-- | src/test/transaction_tests.cpp | 4 | ||||
-rw-r--r-- | src/test/util_tests.cpp | 6 | ||||
-rw-r--r-- | src/util.cpp | 8 | ||||
-rw-r--r-- | src/util.h | 16 | ||||
-rw-r--r-- | src/wallet.cpp | 51 | ||||
-rw-r--r-- | src/wallet.h | 2 | ||||
-rw-r--r-- | src/walletdb.cpp | 6 |
26 files changed, 441 insertions, 84 deletions
diff --git a/contrib/gitian-descriptors/protobuf-win.yml b/contrib/gitian-descriptors/protobuf-win.yml index 543f20b394..d2fdcaa7f2 100644 --- a/contrib/gitian-descriptors/protobuf-win.yml +++ b/contrib/gitian-descriptors/protobuf-win.yml @@ -38,13 +38,13 @@ script: | tar xjf $INDIR/protobuf-2.5.0.tar.bz2 cd protobuf-2.5.0 # First: build a native (linux) protoc - ./configure --enable-shared=no --disable-dependency-tracking + ./configure --enable-shared=no --disable-dependency-tracking --without-zlib CXXFLAGS="-frandom-seed=11 ${OPTFLAGS}" make mkdir -p $INSTALLPREFIX/host/bin cp src/protoc $INSTALLPREFIX/host/bin # Now recompile with the mingw cross-compiler: make distclean - ./configure --prefix=$INSTALLPREFIX --enable-shared=no --disable-dependency-tracking --with-protoc=$INSTALLPREFIX/host/bin/protoc --host=$HOST CXXFLAGS="-frandom-seed=11 ${OPTFLAGS}" + ./configure --prefix=$INSTALLPREFIX --enable-shared=no --disable-dependency-tracking --without-zlib --with-protoc=$INSTALLPREFIX/host/bin/protoc --host=$HOST CXXFLAGS="-frandom-seed=11 ${OPTFLAGS}" export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 export FAKETIME=$REFERENCE_DATETIME make diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md index c8537247d9..ee9e8b35ca 100644 --- a/qa/rpc-tests/README.md +++ b/qa/rpc-tests/README.md @@ -1,6 +1,25 @@ Regression tests of RPC interface ================================= -wallet.sh : Test wallet send/receive code (see comments for details) +wallet.sh : Exercise wallet send/receive code. -util.sh : useful re-usable functions +walletbackup.sh : Exercise wallet backup / dump / import + +txnmall.sh : Test proper accounting of malleable transactions + +conflictedbalance.sh : More testing of malleable transaction handling + +util.sh : useful re-usable bash functions + + +Tips for creating new tests +=========================== + +To cleanup after a failed or interrupted test: + killall bitcoind + rm -rf test.* + +The most difficult part of writing reproducible tests is +keeping multiple nodes in sync. See WaitBlocks, +WaitPeers, and WaitMemPools for how other tests +deal with this. diff --git a/qa/rpc-tests/txnmall.sh b/qa/rpc-tests/txnmall.sh index 6bf92fce40..06e4f7102d 100755 --- a/qa/rpc-tests/txnmall.sh +++ b/qa/rpc-tests/txnmall.sh @@ -8,6 +8,8 @@ if [ $# -lt 1 ]; then exit 1 fi +set -f + BITCOIND=${1}/bitcoind CLI=${1}/bitcoin-cli @@ -23,13 +25,13 @@ D=$(mktemp -d test.XXXXX) D1=${D}/node1 CreateDataDir $D1 port=11000 rpcport=11001 -B1ARGS="-datadir=$D1 -debug" +B1ARGS="-datadir=$D1" $BITCOIND $B1ARGS & B1PID=$! D2=${D}/node2 CreateDataDir $D2 port=11010 rpcport=11011 -B2ARGS="-datadir=$D2 -debug" +B2ARGS="-datadir=$D2" $BITCOIND $B2ARGS & B2PID=$! diff --git a/qa/rpc-tests/walletbackup.sh b/qa/rpc-tests/walletbackup.sh new file mode 100755 index 0000000000..9207243b62 --- /dev/null +++ b/qa/rpc-tests/walletbackup.sh @@ -0,0 +1,293 @@ +#!/usr/bin/env bash + +# Test wallet backup / dump / restore functionality + +# Test case is: +# 4 nodes. 1 2 3 and send transactions between each other, +# fourth node is a miner. +# 1 2 3 and each mine a block to start, then +# miner creates 100 blocks so 1 2 3 each have 50 mature +# coins to spend. +# Then 5 iterations of 1/2/3 sending coins amongst +# themselves to get transactions in the wallets, +# and the miner mining one block. +# +# Wallets are backed up using dumpwallet/backupwallet. +# Then 5 more iterations of transactions, then block. +# +# Miner then generates 101 more blocks, so any +# transaction fees paid mature. +# +# Sanity checks done: +# Miner balance >= 150*50 +# Sum(1,2,3,4 balances) == 153*150 +# +# 1/2/3 are shutdown, and their wallets erased. +# Then restore using wallet.dat backup. And +# confirm 1/2/3/4 balances are same as before. +# +# Shutdown again, restore using importwallet, +# and confirm again balances are correct. +# + +if [ $# -lt 1 ]; then + echo "Usage: $0 path_to_binaries" + echo "e.g. $0 ../../src" + exit 1 +fi + +BITCOIND=${1}/bitcoind +CLI=${1}/bitcoin-cli + +DIR="${BASH_SOURCE%/*}" +SENDANDWAIT="${DIR}/send.sh" +if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi +. "$DIR/util.sh" + +D=$(mktemp -d test.XXXXX) + +echo "Starting nodes..." + +# "Miner": +D4=${D}/node4 +CreateDataDir $D4 port=11030 rpcport=11031 +B4ARGS="-datadir=$D4" +$BITCOIND $BITCOINDARGS $B4ARGS & +B4PID=$! + +# Want default keypool for 1/2/3, and +# don't need send-and-wait functionality, +# so don't use CreateDataDir: +function CreateConfDir { + DIR=$1 + mkdir -p $DIR + CONF=$DIR/bitcoin.conf + echo "regtest=1" >> $CONF + echo "rpcuser=rt" >> $CONF + echo "rpcpassword=rt" >> $CONF + echo "rpcwait=1" >> $CONF + shift + while (( "$#" )); do + echo $1 >> $CONF + shift + done +} + +# "Spenders" 1/2/3 +D1=${D}/node1 +CreateConfDir $D1 port=11000 rpcport=11001 addnode=127.0.0.1:11030 +B1ARGS="-datadir=$D1" +$BITCOIND $B1ARGS & +B1PID=$! +D2=${D}/node2 +CreateConfDir $D2 port=11010 rpcport=11011 addnode=127.0.0.1:11030 +B2ARGS="-datadir=$D2" +$BITCOIND $B2ARGS & +B2PID=$! +D3=${D}/node3 +CreateConfDir $D3 port=11020 rpcport=11021 addnode=127.0.0.1:11030 addnode=127.0.0.1:11000 +B3ARGS="-datadir=$D3" +$BITCOIND $BITCOINDARGS $B3ARGS & +B3PID=$! + +# Wait until all nodes are at the same block number +function WaitBlocks { + while : + do + sleep 1 + BLOCKS1=$( GetBlocks "$B1ARGS" ) + BLOCKS2=$( GetBlocks "$B2ARGS" ) + BLOCKS3=$( GetBlocks "$B3ARGS" ) + BLOCKS4=$( GetBlocks "$B4ARGS" ) + if (( BLOCKS1 == BLOCKS4 && BLOCKS2 == BLOCKS4 && BLOCKS3 == BLOCKS4 )) + then + break + fi + done +} + +# Wait until all nodes have the same txns in +# their memory pools +function WaitMemPools { + while : + do + sleep 1 + MEMPOOL1=$( $CLI "$B1ARGS" getrawmempool | sort | shasum ) + MEMPOOL2=$( $CLI "$B2ARGS" getrawmempool | sort | shasum ) + MEMPOOL3=$( $CLI "$B3ARGS" getrawmempool | sort | shasum ) + MEMPOOL4=$( $CLI "$B4ARGS" getrawmempool | sort | shasum ) + if [[ $MEMPOOL1 = $MEMPOOL4 && $MEMPOOL2 = $MEMPOOL4 && $MEMPOOL3 = $MEMPOOL4 ]] + then + break + fi + done +} + +echo "Generating initial blockchain..." + +# 1 block, 50 XBT each == 50 BTC +$CLI $B1ARGS setgenerate true 1 +WaitBlocks +$CLI $B2ARGS setgenerate true 1 +WaitBlocks +$CLI $B3ARGS setgenerate true 1 +WaitBlocks + +# 100 blocks, 0 mature +$CLI $B4ARGS setgenerate true 100 +WaitBlocks + +CheckBalance "$B1ARGS" 50 +CheckBalance "$B2ARGS" 50 +CheckBalance "$B3ARGS" 50 +CheckBalance "$B4ARGS" 0 + +echo "Creating transactions..." + +function S { + TXID=$( $CLI -datadir=${D}/node${1} sendtoaddress ${2} "${3}" 0 ) + if [[ $TXID == "" ]] ; then + echoerr "node${1}: error sending ${3} btc" + echo -n "node${1} balance: " + $CLI -datadir=${D}/node${1} getbalance "*" 0 + exit 1 + fi +} + +function OneRound { + A1=$( $CLI $B1ARGS getnewaddress ) + A2=$( $CLI $B2ARGS getnewaddress ) + A3=$( $CLI $B3ARGS getnewaddress ) + if [[ $(( $RANDOM%2 )) < 1 ]] ; then + N=$(( $RANDOM % 9 + 1 )) + S 1 $A2 "0.$N" + fi + if [[ $(( $RANDOM%2 )) < 1 ]] ; then + N=$(( $RANDOM % 9 + 1 )) + S 1 $A3 "0.0$N" + fi + if [[ $(( $RANDOM%2 )) < 1 ]] ; then + N=$(( $RANDOM % 9 + 1 )) + S 2 $A1 "0.$N" + fi + if [[ $(( $RANDOM%2 )) < 1 ]] ; then + N=$(( $RANDOM % 9 + 1 )) + S 2 $A3 "0.$N" + fi + if [[ $(( $RANDOM%2 )) < 1 ]] ; then + N=$(( $RANDOM % 9 + 1 )) + S 3 $A1 "0.$N" + fi + if [[ $(( $RANDOM%2 )) < 1 ]] ; then + N=$(( $RANDOM % 9 + 1 )) + S 3 $A2 "0.0$N" + fi + $CLI "$B4ARGS" setgenerate true 1 +} + +for i in {1..5}; do OneRound ; done + +echo "Backing up..." + +$CLI "$B1ARGS" backupwallet "$D1/wallet.bak" +$CLI "$B1ARGS" dumpwallet "$D1/wallet.dump" +$CLI "$B2ARGS" backupwallet "$D2/wallet.bak" +$CLI "$B2ARGS" dumpwallet "$D2/wallet.dump" +$CLI "$B3ARGS" backupwallet "$D3/wallet.bak" +$CLI "$B3ARGS" dumpwallet "$D3/wallet.dump" + +echo "More transactions..." +for i in {1..5}; do OneRound ; done + +WaitMemPools + +# Generate 101 more blocks, so any fees paid +# mature +$CLI "$B4ARGS" setgenerate true 101 + +BALANCE1=$( $CLI "$B1ARGS" getbalance ) +BALANCE2=$( $CLI "$B2ARGS" getbalance ) +BALANCE3=$( $CLI "$B3ARGS" getbalance ) +BALANCE4=$( $CLI "$B4ARGS" getbalance ) + +TOTAL=$( dc -e "$BALANCE1 $BALANCE2 $BALANCE3 $BALANCE4 + + + p" ) + +AssertEqual $TOTAL 5700.00000000 + +function StopThree { + $CLI $B1ARGS stop > /dev/null 2>&1 + $CLI $B2ARGS stop > /dev/null 2>&1 + $CLI $B3ARGS stop > /dev/null 2>&1 + wait $B1PID + wait $B2PID + wait $B3PID +} +function EraseThree { + rm $D1/regtest/wallet.dat + rm $D2/regtest/wallet.dat + rm $D3/regtest/wallet.dat +} +function StartThree { + $BITCOIND $BITCOINDARGS $B1ARGS & + B1PID=$! + $BITCOIND $BITCOINDARGS $B2ARGS & + B2PID=$! + $BITCOIND $BITCOINDARGS $B3ARGS & + B3PID=$! +} + +echo "Restoring using wallet.dat" + +StopThree +EraseThree + +# Start node3 with no chain +rm -rf $D3/regtest/blocks +rm -rf $D3/regtest/chainstate +rm -rf $D3/regtest/database + +cp $D1/wallet.bak $D1/regtest/wallet.dat +cp $D2/wallet.bak $D2/regtest/wallet.dat +cp $D3/wallet.bak $D3/regtest/wallet.dat + +StartThree +WaitBlocks + +AssertEqual $BALANCE1 $( $CLI "$B1ARGS" getbalance ) +AssertEqual $BALANCE2 $( $CLI "$B2ARGS" getbalance ) +AssertEqual $BALANCE3 $( $CLI "$B3ARGS" getbalance ) + +echo "Restoring using dumped wallet" + +StopThree +EraseThree + +# Start node3 with no chain +rm -rf $D3/regtest/blocks +rm -rf $D3/regtest/chainstate +rm -rf $D3/regtest/database + +StartThree + +AssertEqual 0 $( $CLI "$B1ARGS" getbalance ) +AssertEqual 0 $( $CLI "$B2ARGS" getbalance ) +AssertEqual 0 $( $CLI "$B3ARGS" getbalance ) + +$CLI "$B1ARGS" importwallet $D1/wallet.dump +$CLI "$B2ARGS" importwallet $D2/wallet.dump +$CLI "$B3ARGS" importwallet $D3/wallet.dump + +WaitBlocks + +AssertEqual $BALANCE1 $( $CLI "$B1ARGS" getbalance ) +AssertEqual $BALANCE2 $( $CLI "$B2ARGS" getbalance ) +AssertEqual $BALANCE3 $( $CLI "$B3ARGS" getbalance ) + +StopThree +$CLI $B4ARGS stop > /dev/null 2>&1 +wait $B4PID + +echo "Tests successful, cleaning up" +trap "" EXIT +rm -rf $D +exit 0 diff --git a/src/alert.cpp b/src/alert.cpp index 4429ecadce..46e861be9e 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -51,8 +51,8 @@ std::string CUnsignedAlert::ToString() const return strprintf( "CAlert(\n" " nVersion = %d\n" - " nRelayUntil = %"PRId64"\n" - " nExpiration = %"PRId64"\n" + " nRelayUntil = %d\n" + " nExpiration = %d\n" " nID = %d\n" " nCancel = %d\n" " setCancel = %s\n" diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 04b75e7f1c..51a746f84f 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -6,6 +6,7 @@ #include "util.h" #include "init.h" #include "rpcclient.h" +#include "rpcprotocol.h" #include "ui_interface.h" /* for _(...) */ #include "chainparams.h" @@ -55,23 +56,25 @@ int main(int argc, char* argv[]) try { if(!AppInitRPC(argc, argv)) - return 1; + return abs(RPC_MISC_ERROR); } catch (std::exception& e) { PrintExceptionContinue(&e, "AppInitRPC()"); + return abs(RPC_MISC_ERROR); } catch (...) { PrintExceptionContinue(NULL, "AppInitRPC()"); + return abs(RPC_MISC_ERROR); } + int ret = abs(RPC_MISC_ERROR); try { - if(!CommandLineRPC(argc, argv)) - return 1; + ret = CommandLineRPC(argc, argv); } catch (std::exception& e) { PrintExceptionContinue(&e, "CommandLineRPC()"); } catch (...) { PrintExceptionContinue(NULL, "CommandLineRPC()"); } - return 0; + return ret; } diff --git a/src/core.cpp b/src/core.cpp index f5c460761e..cbdd24e806 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -64,7 +64,7 @@ uint256 CTxOut::GetHash() const std::string CTxOut::ToString() const { - return strprintf("CTxOut(nValue=%"PRId64".%08"PRId64", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30)); + return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30)); } void CTxOut::print() const diff --git a/src/core.h b/src/core.h index e61cad90ec..5eb953610d 100644 --- a/src/core.h +++ b/src/core.h @@ -156,8 +156,8 @@ public: // to spend something, then we consider it dust. // A typical txout is 34 bytes big, and will // need a CTxIn of at least 148 bytes to spend, - // so dust is a txout less than 54 uBTC - // (5460 satoshis) with default nMinRelayTxFee + // so dust is a txout less than 546 satoshis + // with default nMinRelayTxFee. return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < nMinRelayTxFee); } diff --git a/src/db.cpp b/src/db.cpp index 591d4ed477..521562fe69 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -463,7 +463,7 @@ void CDBEnv::Flush(bool fShutdown) else mi++; } - LogPrint("db", "DBFlush(%s)%s ended %15"PRId64"ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart); + LogPrint("db", "DBFlush(%s)%s ended %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart); if (fShutdown) { char** listp; diff --git a/src/init.cpp b/src/init.cpp index 4cc04f5205..4cc18800a5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -599,7 +599,7 @@ bool AppInit2(boost::thread_group& threadGroup) { // try moving the database env out of the way boost::filesystem::path pathDatabase = GetDataDir() / "database"; - boost::filesystem::path pathDatabaseBak = GetDataDir() / strprintf("database.%"PRId64".bak", GetTime()); + boost::filesystem::path pathDatabaseBak = GetDataDir() / strprintf("database.%d.bak", GetTime()); try { boost::filesystem::rename(pathDatabase, pathDatabaseBak); LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string()); @@ -874,7 +874,7 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("Shutdown requested. Exiting.\n"); return false; } - LogPrintf(" block index %15"PRId64"ms\n", GetTimeMillis() - nStart); + LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); if (GetBoolArg("-printblockindex", false) || GetBoolArg("-printblocktree", false)) { @@ -985,7 +985,7 @@ bool AppInit2(boost::thread_group& threadGroup) } LogPrintf("%s", strErrors.str()); - LogPrintf(" wallet %15"PRId64"ms\n", GetTimeMillis() - nStart); + LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); RegisterWallet(pwalletMain); @@ -1007,7 +1007,7 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); nStart = GetTimeMillis(); pwalletMain->ScanForWalletTransactions(pindexRescan, true); - LogPrintf(" rescan %15"PRId64"ms\n", GetTimeMillis() - nStart); + LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); pwalletMain->SetBestChain(chainActive.GetLocator()); nWalletDBUpdated++; } @@ -1042,7 +1042,7 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("Invalid or missing peers.dat; recreating\n"); } - LogPrintf("Loaded %i addresses from peers.dat %"PRId64"ms\n", + LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); // ********************************************************* Step 11: start node diff --git a/src/main.cpp b/src/main.cpp index 4c98345d68..8a5b659e7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,7 +52,7 @@ unsigned int nCoinCacheSize = 5000; /** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ int64_t CTransaction::nMinTxFee = 10000; // Override with -mintxfee /** Fees smaller than this (in satoshi) are considered zero fee (for relaying) */ -int64_t CTransaction::nMinRelayTxFee = 10000; +int64_t CTransaction::nMinRelayTxFee = 1000; static CMedianFilter<int> cPeerBlockCounts(8, 0); // Amount of blocks that other nodes claim to have @@ -822,7 +822,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Don't accept it if it can't get into a block int64_t txMinFee = GetMinFee(tx, nSize, true, GMF_RELAY); if (fLimitFree && nFees < txMinFee) - return state.DoS(0, error("AcceptToMemoryPool : not enough fees %s, %"PRId64" < %"PRId64, + return state.DoS(0, error("AcceptToMemoryPool : not enough fees %s, %d < %d", hash.ToString(), nFees, txMinFee), REJECT_INSUFFICIENTFEE, "insufficient fee"); @@ -851,7 +851,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } if (fRejectInsaneFee && nFees > CTransaction::nMinRelayTxFee * 10000) - return error("AcceptToMemoryPool: : insane fees %s, %"PRId64" > %"PRId64, + return error("AcceptToMemoryPool: : insane fees %s, %d > %d", hash.ToString(), nFees, CTransaction::nMinRelayTxFee * 10000); @@ -1168,7 +1168,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead // Limit adjustment step int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); - LogPrintf(" nActualTimespan = %"PRId64" before bounds\n", nActualTimespan); + LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); if (nActualTimespan < nTargetTimespan/4) nActualTimespan = nTargetTimespan/4; if (nActualTimespan > nTargetTimespan*4) @@ -1185,7 +1185,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead /// debug print LogPrintf("GetNextWorkRequired RETARGET\n"); - LogPrintf("nTargetTimespan = %"PRId64" nActualTimespan = %"PRId64"\n", nTargetTimespan, nActualTimespan); + LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan); LogPrintf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString()); LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString()); @@ -1737,7 +1737,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C if (block.vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees)) return state.DoS(100, - error("ConnectBlock() : coinbase pays too much (actual=%"PRId64" vs limit=%"PRId64")", + error("ConnectBlock() : coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees)), REJECT_INVALID, "bad-cb-amount"); @@ -3014,7 +3014,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) AbortNode(_("Error: system error: ") + e.what()); } if (nLoaded > 0) - LogPrintf("Loaded %i blocks from external file in %"PRId64"ms\n", nLoaded, GetTimeMillis() - nStart); + LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart); return nLoaded > 0; } @@ -3804,7 +3804,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } if (!(sProblem.empty())) { - LogPrint("net", "pong %s %s: %s, %"PRIx64" expected, %"PRIx64" received, %"PRIszu" bytes\n", + LogPrint("net", "pong %s %s: %s, %x expected, %x received, %"PRIszu" bytes\n", pfrom->addr.ToString(), pfrom->cleanSubVer, sProblem, diff --git a/src/miner.cpp b/src/miner.cpp index 73dd0a749d..e52f539085 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -319,7 +319,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; - LogPrintf("CreateNewBlock(): total size %"PRIu64"\n", nBlockSize); + LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize); pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees); pblocktemplate->vTxFees[0] = -nFees; diff --git a/src/net.cpp b/src/net.cpp index 359e629295..bb1d1bac45 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1243,7 +1243,7 @@ void DumpAddresses() CAddrDB adb; adb.Write(addrman); - LogPrint("net", "Flushed %d addresses to peers.dat %"PRId64"ms\n", + LogPrint("net", "Flushed %d addresses to peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); } @@ -423,7 +423,7 @@ public: nRequestTime = it->second; else nRequestTime = 0; - LogPrint("net", "askfor %s %"PRId64" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str()); + LogPrint("net", "askfor %s %d (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str()); // Make sure not to reuse time indexes to keep things in the same order int64_t nNow = (GetTime() - 1) * 1000000; diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index c404ac274b..0d1746b8ca 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -233,7 +233,7 @@ int CommandLineRPC(int argc, char *argv[]) } catch (std::exception& e) { strPrint = string("error: ") + e.what(); - nRet = 87; + nRet = abs(RPC_MISC_ERROR); } catch (...) { PrintException(NULL, "CommandLineRPC()"); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 738b966b8a..efe4f54b0e 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -119,7 +119,7 @@ Value getpeerinfo(const Array& params, bool fHelp) obj.push_back(Pair("addr", stats.addrName)); if (!(stats.addrLocal.empty())) obj.push_back(Pair("addrlocal", stats.addrLocal)); - obj.push_back(Pair("services", strprintf("%08"PRIx64, stats.nServices))); + obj.push_back(Pair("services", strprintf("%08x", stats.nServices))); obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend)); obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv)); obj.push_back(Pair("bytessent", (boost::int64_t)stats.nSendBytes)); diff --git a/src/sync.cpp b/src/sync.cpp index 8f713807f7..e624a9ee84 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -140,8 +140,9 @@ void AssertLockHeldInternal(const char *pszName, const char* pszFile, int nLine, { BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)&i, *lockstack) if (i.first == cs) return; - LogPrintf("Lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld()); - assert(0); + fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", + pszName, pszFile, nLine, LocksHeld().c_str()); + abort(); } #endif /* DEBUG_LOCKORDER */ diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 84db99d816..94e84049be 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -63,6 +63,12 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) } BOOST_CHECK(!DecodeBase58("invalid", result)); + + // check that DecodeBase58 skips whitespace, but still fails with unexpected non-whitespace at the end. + BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result)); + BOOST_CHECK( DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t ", result)); + std::vector<unsigned char> expected = ParseHex("971a55"); + BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end()); } // Visitor to check address type diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp index 9d67324c76..205b15adcf 100644 --- a/src/test/bignum_tests.cpp +++ b/src/test/bignum_tests.cpp @@ -135,6 +135,42 @@ BOOST_AUTO_TEST_CASE(bignum_SetCompact) BOOST_CHECK_EQUAL(num.GetHex(), "0"); BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + num.SetCompact(0x01003456); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + + num.SetCompact(0x02000056); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + + num.SetCompact(0x03000000); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + + num.SetCompact(0x04000000); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + + num.SetCompact(0x00923456); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + + num.SetCompact(0x01803456); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + + num.SetCompact(0x02800056); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + + num.SetCompact(0x03800000); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + + num.SetCompact(0x04800000); + BOOST_CHECK_EQUAL(num.GetHex(), "0"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + num.SetCompact(0x01123456); BOOST_CHECK_EQUAL(num.GetHex(), "12"); BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 104b09972f..588c8013c7 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -271,10 +271,10 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) string reason; BOOST_CHECK(IsStandardTx(t, reason)); - t.vout[0].nValue = 5011; // dust + t.vout[0].nValue = 501; // dust BOOST_CHECK(!IsStandardTx(t, reason)); - t.vout[0].nValue = 6011; // not dust + t.vout[0].nValue = 601; // not dust BOOST_CHECK(IsStandardTx(t, reason)); t.vout[0].scriptPubKey = CScript() << OP_1; diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 691f02a9d7..706737b115 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -311,9 +311,9 @@ BOOST_AUTO_TEST_CASE(strprintf_numbers) { int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */ uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */ - BOOST_CHECK(strprintf("%s %"PRId64" %s", B, s64t, E) == B" -9223372036854775807 "E); - BOOST_CHECK(strprintf("%s %"PRIu64" %s", B, u64t, E) == B" 18446744073709551615 "E); - BOOST_CHECK(strprintf("%s %"PRIx64" %s", B, u64t, E) == B" ffffffffffffffff "E); + BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 "E); + BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 "E); + BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff "E); size_t st = 12345678; /* unsigned size_t test value */ ssize_t sst = -12345678; /* signed size_t test value */ diff --git a/src/util.cpp b/src/util.cpp index 8cfd1c2e03..4e326ffcf4 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -330,7 +330,7 @@ string FormatMoney(int64_t n, bool fPlus) int64_t n_abs = (n > 0 ? n : -n); int64_t quotient = n_abs/COIN; int64_t remainder = n_abs%COIN; - string str = strprintf("%"PRId64".%08"PRId64, quotient, remainder); + string str = strprintf("%d.%08d", quotient, remainder); // Right-trim excess zeros before the decimal point: int nTrim = 0; @@ -1278,7 +1278,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime) // Add data static CMedianFilter<int64_t> vTimeOffsets(200,0); vTimeOffsets.input(nOffsetSample); - LogPrintf("Added time data, samples %d, offset %+"PRId64" (%+"PRId64" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); + LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) { int64_t nMedian = vTimeOffsets.median(); @@ -1313,10 +1313,10 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime) } if (fDebug) { BOOST_FOREACH(int64_t n, vSorted) - LogPrintf("%+"PRId64" ", n); + LogPrintf("%+d ", n); LogPrintf("| "); } - LogPrintf("nTimeOffset = %+"PRId64" (%+"PRId64" minutes)\n", nTimeOffset, nTimeOffset/60); + LogPrintf("nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60); } } diff --git a/src/util.h b/src/util.h index 6ef93021fd..c28380a59b 100644 --- a/src/util.h +++ b/src/util.h @@ -44,15 +44,10 @@ static const int64_t CENT = 1000000; #define UEND(a) ((unsigned char*)&((&(a))[1])) #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) -/* Format characters for (s)size_t, ptrdiff_t, uint64_t. +/* Format characters for (s)size_t, ptrdiff_t. * - * As the tinyformat-based formatting system is type-safe, no special format - * characters are really needed to specify sizes. Tinyformat can support - * (ignores) the C99 prefixes such as "ll" but chokes on MSVC's inttypes - * defines prefixes such as "I64X". So don't include inttypes.h and define our - * own for compatibility. - * If you get a warning here about a redefine of PRI?64, make sure that - * inttypes.h is not included. + * Define these as empty as the tinyformat-based formatting system is + * type-safe, no special format characters are needed to specify sizes. */ #define PRIszx "x" #define PRIszu "u" @@ -60,9 +55,6 @@ static const int64_t CENT = 1000000; #define PRIpdx "x" #define PRIpdu "u" #define PRIpdd "d" -#define PRIx64 "x" -#define PRIu64 "u" -#define PRId64 "d" // This is needed because the foreach macro can't get over the comma in pair<t1, t2> #define PAIRTYPE(t1, t2) std::pair<t1, t2> @@ -234,7 +226,7 @@ void runCommand(std::string strCommand); inline std::string i64tostr(int64_t n) { - return strprintf("%"PRId64, n); + return strprintf("%d", n); } inline std::string itostr(int n) diff --git a/src/wallet.cpp b/src/wallet.cpp index 2119098595..eaf0b98467 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -192,7 +192,7 @@ void CWallet::SetBestChain(const CBlockLocator& loc) bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit) { - AssertLockHeld(cs_wallet); // nWalletVersion + LOCK(cs_wallet); // nWalletVersion if (nWalletVersion >= nVersion) return true; @@ -219,7 +219,7 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool CWallet::SetMaxVersion(int nVersion) { - AssertLockHeld(cs_wallet); // nWalletVersion, nWalletMaxVersion + LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion // cannot downgrade below current version if (nWalletVersion > nVersion) return false; @@ -1621,14 +1621,17 @@ DBErrors CWallet::ZapWalletTx() bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose) { - AssertLockHeld(cs_wallet); // mapAddressBook - std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address); - mapAddressBook[address].name = strName; - if (!strPurpose.empty()) /* update purpose only if requested */ - mapAddressBook[address].purpose = strPurpose; + bool fUpdated = false; + { + LOCK(cs_wallet); // mapAddressBook + std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address); + fUpdated = mi != mapAddressBook.end(); + mapAddressBook[address].name = strName; + if (!strPurpose.empty()) /* update purpose only if requested */ + mapAddressBook[address].purpose = strPurpose; + } NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), - mapAddressBook[address].purpose, - (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED); + strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) ); if (!fFileBacked) return false; if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose)) @@ -1638,21 +1641,23 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam bool CWallet::DelAddressBook(const CTxDestination& address) { - - AssertLockHeld(cs_wallet); // mapAddressBook - - if(fFileBacked) { - // Delete destdata tuples associated with address - std::string strAddress = CBitcoinAddress(address).ToString(); - BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata) + LOCK(cs_wallet); // mapAddressBook + + if(fFileBacked) { - CWalletDB(strWalletFile).EraseDestData(strAddress, item.first); + // Delete destdata tuples associated with address + std::string strAddress = CBitcoinAddress(address).ToString(); + BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata) + { + CWalletDB(strWalletFile).EraseDestData(strAddress, item.first); + } } + mapAddressBook.erase(address); } - mapAddressBook.erase(address); NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED); + if (!fFileBacked) return false; CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString()); @@ -1693,7 +1698,7 @@ bool CWallet::NewKeyPool() walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey())); setKeyPool.insert(nIndex); } - LogPrintf("CWallet::NewKeyPool wrote %"PRId64" new keys\n", nKeys); + LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys); } return true; } @@ -1723,7 +1728,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey()))) throw runtime_error("TopUpKeyPool() : writing generated key failed"); setKeyPool.insert(nEnd); - LogPrintf("keypool added key %"PRId64", size=%"PRIszu"\n", nEnd, setKeyPool.size()); + LogPrintf("keypool added key %d, size=%"PRIszu"\n", nEnd, setKeyPool.size()); } } return true; @@ -1752,7 +1757,7 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool) if (!HaveKey(keypool.vchPubKey.GetID())) throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool"); assert(keypool.vchPubKey.IsValid()); - LogPrintf("keypool reserve %"PRId64"\n", nIndex); + LogPrintf("keypool reserve %d\n", nIndex); } } @@ -1779,7 +1784,7 @@ void CWallet::KeepKey(int64_t nIndex) CWalletDB walletdb(strWalletFile); walletdb.ErasePool(nIndex); } - LogPrintf("keypool keep %"PRId64"\n", nIndex); + LogPrintf("keypool keep %d\n", nIndex); } void CWallet::ReturnKey(int64_t nIndex) @@ -1789,7 +1794,7 @@ void CWallet::ReturnKey(int64_t nIndex) LOCK(cs_wallet); setKeyPool.insert(nIndex); } - LogPrintf("keypool return %"PRId64"\n", nIndex); + LogPrintf("keypool return %d\n", nIndex); } bool CWallet::GetKeyFromPool(CPubKey& result) diff --git a/src/wallet.h b/src/wallet.h index 95fb0ee9de..eb192f1ca6 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -363,7 +363,7 @@ public: bool SetMaxVersion(int nVersion); // get the current wallet format (the oldest client version guaranteed to understand this wallet) - int GetVersion() { AssertLockHeld(cs_wallet); return nWalletVersion; } + int GetVersion() { LOCK(cs_wallet); return nWalletVersion; } // Get wallet transactions that conflict with given transaction (spend same outputs) std::set<uint256> GetConflicts(const uint256& txid) const; diff --git a/src/walletdb.cpp b/src/walletdb.cpp index b5b523740b..b57ea0b518 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -383,7 +383,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, pwallet->AddToWallet(wtx, true); //// debug print //LogPrintf("LoadWallet %s\n", wtx.GetHash().ToString()); - //LogPrintf(" %12"PRId64" %s %s %s\n", + //LogPrintf(" %12d %s %s %s\n", // wtx.vout[0].nValue, // DateTimeStrFormat("%Y-%m-%d %H:%M:%S", wtx.GetBlockTime()), // wtx.hashBlock.ToString(), @@ -816,7 +816,7 @@ void ThreadFlushWalletDB(const string& strFile) bitdb.CheckpointLSN(strFile); bitdb.mapFileUseCount.erase(mi++); - LogPrint("db", "Flushed wallet.dat %"PRId64"ms\n", GetTimeMillis() - nStart); + LogPrint("db", "Flushed wallet.dat %dms\n", GetTimeMillis() - nStart); } } } @@ -877,7 +877,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) // Set -rescan so any missing transactions will be // found. int64_t now = GetTime(); - std::string newFilename = strprintf("wallet.%"PRId64".bak", now); + std::string newFilename = strprintf("wallet.%d.bak", now); int result = dbenv.dbenv.dbrename(NULL, filename.c_str(), NULL, newFilename.c_str(), DB_AUTO_COMMIT); |