diff options
67 files changed, 1189 insertions, 556 deletions
diff --git a/.gitignore b/.gitignore index 85ddf3871f..564fe68fd9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,10 +13,10 @@ autom4te.cache/ config.log config.status configure -src/bitcoin-config.h -src/bitcoin-config.h.in +src/config/bitcoin-config.h +src/config/bitcoin-config.h.in +src/config/stamp-h1 src/build-aux/ -src/stamp-h1 share/setup.nsi share/qt/Info.plist diff --git a/doc/release-process.md b/doc/release-process.md index 9cdc43b9be..d12b41772e 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -52,6 +52,7 @@ Release Process wget 'https://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2' wget 'https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch' -O boost-mingw-gas-cross-compile-2013-03-03.patch wget 'https://download.qt-project.org/official_releases/qt/5.2/5.2.0/single/qt-everywhere-opensource-src-5.2.0.tar.gz' + wget 'https://download.qt-project.org/official_releases/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.tar.gz' wget 'https://download.qt-project.org/archive/qt/4.6/qt-everywhere-opensource-src-4.6.4.tar.gz' wget 'https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.bz2' wget 'https://github.com/mingwandroid/toolchain4/archive/10cc648683617cca8bcbeae507888099b41b530c.tar.gz' @@ -100,6 +101,10 @@ Release Process 751c579830d173ef3e6f194e83d18b92ebef6df03289db13ab77a52b6bc86ef0 qt-win64-5.2.0-gitian-r3.zip e2e403e1a08869c7eed4d4293bce13d51ec6a63592918b90ae215a0eceb44cb4 protobuf-win32-2.5.0-gitian-r4.zip a0999037e8b0ef9ade13efd88fee261ba401f5ca910068b7e0cd3262ba667db0 protobuf-win64-2.5.0-gitian-r4.zip + 512bc0622c883e2e0f4cbc3fedfd8c2402d06c004ce6fb32303cc2a6f405b6df osx-native-depends-r3.tar.gz + 927e4b222be6d590b4bc2fc185872a5d0ca5c322adb983764d3ed84be6bdbc81 osx-depends-r4.tar.gz + ec95abef1df2b096a970359787c01d8c45e2a4475b7ae34e12c022634fbdba8a osx-depends-qt-5.2.1-r4.tar.gz + Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32: @@ -177,34 +182,6 @@ Commit your signature to gitian.sigs: ### After 3 or more people have gitian-built, repackage gitian-signed zips: -From a directory containing bitcoin source, gitian.sigs and gitian zips - - export VERSION=(new version, e.g. 0.8.0) - mkdir bitcoin-${VERSION}-linux-gitian - pushd bitcoin-${VERSION}-linux-gitian - unzip ../bitcoin-${VERSION}-linux-gitian.zip - mkdir gitian - cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/ - for signer in $(ls ../gitian.sigs/${VERSION}/); do - cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert - cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig - done - zip -r bitcoin-${VERSION}-linux-gitian.zip * - cp bitcoin-${VERSION}-linux-gitian.zip ../ - popd - mkdir bitcoin-${VERSION}-win-gitian - pushd bitcoin-${VERSION}-win-gitian - unzip ../bitcoin-${VERSION}-win-gitian.zip - mkdir gitian - cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/ - for signer in $(ls ../gitian.sigs/${VERSION}-win/); do - cp ../gitian.sigs/${VERSION}-win/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert - cp ../gitian.sigs/${VERSION}-win/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig - done - zip -r bitcoin-${VERSION}-win-gitian.zip * - cp bitcoin-${VERSION}-win-gitian.zip ../ - popd - - Upload gitian zips to SourceForge - Announce the release: diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py new file mode 100755 index 0000000000..7f2d79b3c1 --- /dev/null +++ b/qa/rpc-tests/receivedby.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Exercise the listtransactions API + +# Add python-bitcoinrpc to module search path: + +import os +import sys +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc")) + +import json +import shutil +import subprocess +import tempfile +import traceback + +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from util import * + +def get_sub_array_from_array(object_array, to_match): + ''' + Finds and returns a sub array from an array of arrays. + to_match should be a unique idetifier of a sub array + ''' + num_matched = 0 + for item in object_array: + all_match = True + for key,value in to_match.items(): + if item[key] != value: + all_match = False + if not all_match: + continue + return item + return [] + +def check_array_result(object_array, to_match, expected, should_not_find = False): + """ + Pass in array of JSON objects, a dictionary with key/value pairs + to match against, and another dictionary with expected key/value + pairs. + If the should_not_find flag is true, to_match should not be found in object_array + """ + if should_not_find == True: + expected = { } + num_matched = 0 + for item in object_array: + all_match = True + for key,value in to_match.items(): + if item[key] != value: + all_match = False + if not all_match: + continue + for key,value in expected.items(): + if item[key] != value: + raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) + num_matched = num_matched+1 + if num_matched == 0 and should_not_find != True: + raise AssertionError("No objects matched %s"%(str(to_match))) + if num_matched > 0 and should_not_find == True: + raise AssertionError("Objects was matched %s"%(str(to_match))) + +def run_test(nodes): + ''' + listreceivedbyaddress Test + ''' + # Send from node 0 to 1 + addr = nodes[1].getnewaddress() + txid = nodes[0].sendtoaddress(addr, 0.1) + sync_mempools(nodes) + + #Check not listed in listreceivedbyaddress because has 0 confirmations + check_array_result(nodes[1].listreceivedbyaddress(), + {"address":addr}, + { }, + True) + #Bury Tx under 10 block so it will be returned by listreceivedbyaddress + nodes[1].setgenerate(True, 10) + sync_blocks(nodes) + check_array_result(nodes[1].listreceivedbyaddress(), + {"address":addr}, + {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}) + #With min confidence < 10 + check_array_result(nodes[1].listreceivedbyaddress(5), + {"address":addr}, + {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}) + #With min confidence > 10, should not find Tx + check_array_result(nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True) + + #Empty Tx + addr = nodes[1].getnewaddress() + check_array_result(nodes[1].listreceivedbyaddress(0,True), + {"address":addr}, + {"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]}) + + ''' + getreceivedbyaddress Test + ''' + # Send from node 0 to 1 + addr = nodes[1].getnewaddress() + txid = nodes[0].sendtoaddress(addr, 0.1) + sync_mempools(nodes) + + #Check balance is 0 because of 0 confirmations + balance = nodes[1].getreceivedbyaddress(addr) + if balance != Decimal("0.0"): + raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) + + #Check balance is 0.1 + balance = nodes[1].getreceivedbyaddress(addr,0) + if balance != Decimal("0.1"): + raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) + + #Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress + nodes[1].setgenerate(True, 10) + sync_blocks(nodes) + balance = nodes[1].getreceivedbyaddress(addr) + if balance != Decimal("0.1"): + raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) + + ''' + listreceivedbyaccount + getreceivedbyaccount Test + ''' + #set pre-state + addrArr = nodes[1].getnewaddress() + account = nodes[1].getaccount(addrArr) + received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(),{"account":account}) + if len(received_by_account_json) == 0: + raise AssertionError("No accounts found in node") + balance_by_account = rec_by_accountArr = nodes[1].getreceivedbyaccount(account) + + txid = nodes[0].sendtoaddress(addr, 0.1) + + # listreceivedbyaccount should return received_by_account_json because of 0 confirmations + check_array_result(nodes[1].listreceivedbyaccount(), + {"account":account}, + received_by_account_json) + + # getreceivedbyaddress should return same balance because of 0 confirmations + balance = nodes[1].getreceivedbyaccount(account) + if balance != balance_by_account: + raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance)) + + nodes[1].setgenerate(True, 10) + sync_blocks(nodes) + # listreceivedbyaccount should return updated account balance + check_array_result(nodes[1].listreceivedbyaccount(), + {"account":account}, + {"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))}) + + # getreceivedbyaddress should return updates balance + balance = nodes[1].getreceivedbyaccount(account) + if balance != balance_by_account + Decimal("0.1"): + raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance)) + + #Create a new account named "mynewaccount" that has a 0 balance + nodes[1].getaccountaddress("mynewaccount") + received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"}) + if len(received_by_account_json) == 0: + raise AssertionError("No accounts found in node") + + # Test includeempty of listreceivedbyaccount + if received_by_account_json["amount"] != Decimal("0.0"): + raise AssertionError("Wrong balance returned by listreceivedbyaccount, %0.2f"%(received_by_account_json["amount"])) + + # Test getreceivedbyaccount for 0 amount accounts + balance = nodes[1].getreceivedbyaccount("mynewaccount") + if balance != Decimal("0.0"): + raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance)) + +def main(): + import optparse + + parser = optparse.OptionParser(usage="%prog [options]") + parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", + help="Leave bitcoinds and test.* datadir on exit or error") + parser.add_option("--srcdir", dest="srcdir", default="../../src", + help="Source directory containing bitcoind/bitcoin-cli (default: %default%)") + parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), + help="Root directory for datadirs") + (options, args) = parser.parse_args() + + os.environ['PATH'] = options.srcdir+":"+os.environ['PATH'] + + check_json_precision() + + success = False + nodes = [] + try: + print("Initializing test directory "+options.tmpdir) + if not os.path.isdir(options.tmpdir): + os.makedirs(options.tmpdir) + initialize_chain(options.tmpdir) + + nodes = start_nodes(2, options.tmpdir) + connect_nodes(nodes[1], 0) + sync_blocks(nodes) + + run_test(nodes) + + success = True + + except AssertionError as e: + print("Assertion failed: "+e.message) + except Exception as e: + print("Unexpected exception caught during testing: "+str(e)) + traceback.print_tb(sys.exc_info()[2]) + + if not options.nocleanup: + print("Cleaning up") + stop_nodes(nodes) + wait_bitcoinds() + shutil.rmtree(options.tmpdir) + + if success: + print("Tests successful") + sys.exit(0) + else: + print("Failed") + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py index eded098c7c..27c9f778f6 100644 --- a/qa/rpc-tests/util.py +++ b/qa/rpc-tests/util.py @@ -182,6 +182,10 @@ def wait_bitcoinds(): def connect_nodes(from_connection, node_num): ip_port = "127.0.0.1:"+str(p2p_port(node_num)) from_connection.addnode(ip_port, "onetry") + # poll until version handshake complete to avoid race conditions + # with transaction relaying + while any(peer['version'] == 0 for peer in from_connection.getpeerinfo()): + time.sleep(0.1) def find_output(node, txid, amount): """ diff --git a/qa/rpc-tests/util.sh b/qa/rpc-tests/util.sh index 1e7bd6a7ee..b726ef627f 100644 --- a/qa/rpc-tests/util.sh +++ b/qa/rpc-tests/util.sh @@ -38,6 +38,10 @@ function AssertEqual { if (( $( echo "$1 == $2" | bc ) == 0 )) then echoerr "AssertEqual: $1 != $2" + declare -f CleanUp > /dev/null 2>&1 + if [[ $? -eq 0 ]] ; then + CleanUp + fi exit 1 fi } @@ -49,6 +53,10 @@ function CheckBalance { if (( $( echo "$B == $EXPECT" | bc ) == 0 )) then echoerr "bad balance: $B (expected $2)" + declare -f CleanUp > /dev/null 2>&1 + if [[ $? -eq 0 ]] ; then + CleanUp + fi exit 1 fi } diff --git a/qa/rpc-tests/zapwallettxes.sh b/qa/rpc-tests/zapwallettxes.sh new file mode 100755 index 0000000000..bc52a7dacd --- /dev/null +++ b/qa/rpc-tests/zapwallettxes.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +# Test -zapwallettxes=<mode> + +if [ $# -lt 1 ]; then + echo "Usage: $0 path_to_binaries" + echo "e.g. $0 ../../src" + exit 1 +fi + +set -f + +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) + +D1=${D}/node1 +CreateDataDir "$D1" port=11000 rpcport=11001 +B1ARGS="-datadir=$D1" +$BITCOIND $B1ARGS & +B1PID=$! + +D2=${D}/node2 +CreateDataDir "$D2" port=11010 rpcport=11011 +B2ARGS="-datadir=$D2" +$BITCOIND $B2ARGS & +B2PID=$! + +function CleanUp { +$CLI $B2ARGS stop > /dev/null 2>&1 +wait $B2PID +$CLI $B1ARGS stop > /dev/null 2>&1 +wait $B1PID + +rm -rf $D +} + +# 110 blocks, 10 mature == 500 XBT +$CLI $B1ARGS setgenerate true 110 +$CLI $B2ARGS setgenerate true 110 + +CheckBalance "$B1ARGS" 500 +CheckBalance "$B2ARGS" 500 + +# Send 10 XBT +TXID1_DEFAULT=$($CLI $B1ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 10) +TXID2_DEFAULT=$($CLI $B2ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 10) + +CheckBalance $B1ARGS 490 +CheckBalance $B2ARGS 490 + +# Move 10 XBT to testaccount +TMP=$($CLI $B1ARGS move "" "testaccount" 10) +TMP=$($CLI $B2ARGS move "" "testaccount" 10) + +CheckBalance $B1ARGS 10 "testaccount" +CheckBalance $B2ARGS 10 "testaccount" + +# Send 1 XBT from testaccount +TXID1_TESTACCOUNT=$($CLI $B1ARGS sendfrom "testaccount" "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1) +TXID2_TESTACCOUNT=$($CLI $B2ARGS sendfrom "testaccount" "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1) + +CheckBalance $B1ARGS 9 "testaccount" +CheckBalance $B2ARGS 9 "testaccount" + +CheckBalance $B1ARGS 489 +CheckBalance $B2ARGS 489 + +# Confirm transactions +$CLI $B1ARGS setgenerate true 1 +$CLI $B2ARGS setgenerate true 1 + +# Create unconfirmed transaction +TXID1_UNCONFIRMED=$($CLI $B1ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1) +TXID2_UNCONFIRMED=$($CLI $B2ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1) + +# check balance (we created another 50 and spent 1 in the meantime) +CheckBalance $B1ARGS 538 +CheckBalance $B2ARGS 538 + +# Safety check, if unconfirmed transactions are there +$CLI $B1ARGS gettransaction $TXID1_UNCONFIRMED > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "gettransaction1_1: $TXID1_UNCONFIRMED failed" + CleanUp + exit 1 +fi +$CLI $B2ARGS gettransaction $TXID2_UNCONFIRMED > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "gettransaction2_1: $TXID2_UNCONFIRMED failed" + CleanUp + exit 1 +fi + +# stop nodes +$CLI $B2ARGS stop > /dev/null 2>&1 +wait $B2PID +$CLI $B1ARGS stop > /dev/null 2>&1 +wait $B1PID + +# restart nodes with -zapwallettxes +$BITCOIND -zapwallettxes=1 $B1ARGS & +B1PID=$! +$BITCOIND -zapwallettxes=2 $B2ARGS & +B2PID=$! + +# check if confirmed transactions are there +$CLI $B1ARGS gettransaction $TXID1_DEFAULT > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "check confirmed transaction 1: $TXID1_DEFAULT failed" + CleanUp + exit 1 +fi +$CLI $B2ARGS gettransaction $TXID2_DEFAULT > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "check confirmed transaction 2: $TXID2_DEFAULT failed" + CleanUp + exit 1 +fi +$CLI $B1ARGS gettransaction $TXID1_TESTACCOUNT > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "check confirmed transaction 3: $TXID1_TESTACCOUNT failed" + CleanUp + exit 1 +fi +$CLI $B2ARGS gettransaction $TXID2_TESTACCOUNT > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "check confirmed transaction 4: $TXID2_TESTACCOUNT failed" + CleanUp + exit 1 +fi + +# check if unconfirmed transaction is gone +$CLI $B1ARGS gettransaction $TXID1_UNCONFIRMED > /dev/null 2>&1 +if [[ $? -eq 0 ]] ; then + echoerr "check unconfirmed transaction 1: $TXID1_UNCONFIRMED failed" + CleanUp + exit 1 +fi +$CLI $B2ARGS gettransaction $TXID2_UNCONFIRMED > /dev/null 2>&1 +if [[ $? -eq 0 ]] ; then + echoerr "check unconfirmed transaction 2: $TXID2_UNCONFIRMED failed" + CleanUp + exit 1 +fi + +# check zapwallet mode 1, testaccount balance must be 9 (keeping transaction metadata) +CheckBalance $B1ARGS 9 "testaccount" + +# check zapwallet mode 2, testaccount balance must be 10 (dropping transaction metadata) +CheckBalance $B2ARGS 10 "testaccount" + +echo "Tests successful, cleaning up" +CleanUp +exit 0 diff --git a/src/Makefile.am b/src/Makefile.am index 3948ca0780..3643e60201 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,12 +18,21 @@ $(LIBLEVELDB) $(LIBMEMENV): endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config -BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BITCOIN_CONFIG_INCLUDES) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) +BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) + +LIBBITCOIN_SERVER=libbitcoin_server.a +LIBBITCOIN_WALLET=libbitcoin_wallet.a +LIBBITCOIN_COMMON=libbitcoin_common.a +LIBBITCOIN_CLI=libbitcoin_cli.a +LIBBITCOIN_UTIL=libbitcoin_util.a +LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a +LIBBITCOINQT=qt/libbitcoinqt.a noinst_LIBRARIES = \ libbitcoin_server.a \ libbitcoin_common.a \ libbitcoin_cli.a \ + libbitcoin_util.a \ crypto/libbitcoin_crypto.a if ENABLE_WALLET BITCOIN_INCLUDES += $(BDB_CPPFLAGS) @@ -50,6 +59,7 @@ BITCOIN_CORE_H = \ base58.h \ bloom.h \ chainparams.h \ + chainparamsbase.h \ checkpoints.h \ checkqueue.h \ clientversion.h \ @@ -71,6 +81,7 @@ BITCOIN_CORE_H = \ netbase.h \ net.h \ noui.h \ + pow.h \ protocol.h \ rpcclient.h \ rpcprotocol.h \ @@ -79,6 +90,7 @@ BITCOIN_CORE_H = \ serialize.h \ sync.h \ threadsafety.h \ + timedata.h \ tinyformat.h \ txdb.h \ txmempool.h \ @@ -105,33 +117,36 @@ obj/build.h: FORCE @$(MKDIR_P) $(builddir)/obj @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \ $(abs_top_srcdir) -libbitcoin_common_a-version.$(OBJEXT): obj/build.h +libbitcoin_util_a-version.$(OBJEXT): obj/build.h +# server: shared between bitcoind and bitcoin-qt libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_server_a_SOURCES = \ addrman.cpp \ alert.cpp \ bloom.cpp \ checkpoints.cpp \ - coins.cpp \ init.cpp \ - keystore.cpp \ leveldbwrapper.cpp \ main.cpp \ miner.cpp \ net.cpp \ noui.cpp \ + pow.cpp \ rpcblockchain.cpp \ rpcmining.cpp \ rpcmisc.cpp \ rpcnet.cpp \ rpcrawtransaction.cpp \ rpcserver.cpp \ + timedata.cpp \ txdb.cpp \ txmempool.cpp \ $(JSON_H) \ $(BITCOIN_CORE_H) +# wallet: shared between bitcoind and bitcoin-qt, but only linked +# when wallet enabled libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_wallet_a_SOURCES = \ db.cpp \ @@ -142,6 +157,7 @@ libbitcoin_wallet_a_SOURCES = \ walletdb.cpp \ $(BITCOIN_CORE_H) +# crypto primitives library crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES) crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha1.cpp \ @@ -152,18 +168,29 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha1.h \ crypto/ripemd160.h +# common: shared between bitcoind, and bitcoin-qt and non-server tools libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_SOURCES = \ - base58.cpp \ allocators.cpp \ + base58.cpp \ chainparams.cpp \ + coins.cpp \ core.cpp \ hash.cpp \ key.cpp \ + keystore.cpp \ netbase.cpp \ protocol.cpp \ - rpcprotocol.cpp \ script.cpp \ + $(BITCOIN_CORE_H) + +# util: shared between all executables. +# This library *must* be included to make sure that the glibc +# backward-compatibility objects and their sanity checks are linked. +libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES) +libbitcoin_util_a_SOURCES = \ + chainparamsbase.cpp \ + rpcprotocol.cpp \ sync.cpp \ util.cpp \ version.cpp \ @@ -172,22 +199,24 @@ libbitcoin_common_a_SOURCES = \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT -libbitcoin_common_a_SOURCES += compat/glibc_compat.cpp -libbitcoin_common_a_SOURCES += compat/glibcxx_compat.cpp +libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp +libbitcoin_util_a_SOURCES += compat/glibcxx_compat.cpp endif +# cli: shared between bitcoin-cli and bitcoin-qt libbitcoin_cli_a_SOURCES = \ rpcclient.cpp \ $(BITCOIN_CORE_H) -nodist_libbitcoin_common_a_SOURCES = $(srcdir)/obj/build.h +nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h # # bitcoind binary # bitcoind_LDADD = \ - libbitcoin_server.a \ - libbitcoin_common.a \ - crypto/libbitcoin_crypto.a \ + $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ $(LIBMEMENV) if ENABLE_WALLET @@ -205,11 +234,13 @@ bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES) # bitcoin-cli binary # bitcoin_cli_LDADD = \ - libbitcoin_cli.a \ - libbitcoin_common.a \ - crypto/libbitcoin_crypto.a \ + $(LIBBITCOIN_CLI) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_CRYPTO) \ $(BOOST_LIBS) -bitcoin_cli_SOURCES = bitcoin-cli.cpp +bitcoin_cli_SOURCES = \ + bitcoin-cli.cpp bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES) # @@ -240,13 +271,6 @@ clean-local: @test -f $(PROTOC) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<) -LIBBITCOIN_SERVER=libbitcoin_server.a -LIBBITCOIN_WALLET=libbitcoin_wallet.a -LIBBITCOIN_COMMON=libbitcoin_common.a -LIBBITCOIN_CLI=libbitcoin_cli.a -LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a -LIBBITCOINQT=qt/libbitcoinqt.a - if ENABLE_TESTS include Makefile.test.include endif diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 091138dc38..9df0779ba3 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -355,7 +355,7 @@ qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER) if ENABLE_WALLET qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif -qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \ +qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) qt_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) @@ -364,7 +364,7 @@ QT_QM=$(QT_TS:.ts=.qm) .SECONDARY: $(QT_QM) -qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_cli_a_SOURCES) +qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_cli_a_SOURCES) $(libbitcoin_util_a_SOURCES) @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" $(AM_V_GEN) cd $(top_srcdir); XGETTEXT=$(XGETTEXT) share/qt/extract_strings_qt.py diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 0aa31a406d..a509f23755 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -30,7 +30,7 @@ qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) if ENABLE_WALLET qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif -qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) \ +qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) \ $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) qt_test_test_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 64f997f4b5..4dab1773f4 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -63,7 +63,7 @@ endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) -test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \ +test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) diff --git a/src/addrman.h b/src/addrman.h index 5328a93b45..c4c296560e 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -8,6 +8,7 @@ #include "netbase.h" #include "protocol.h" #include "sync.h" +#include "timedata.h" #include "util.h" #include <map> diff --git a/src/alert.cpp b/src/alert.cpp index 638f0d7a1c..258a2b52c4 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -8,6 +8,7 @@ #include "chainparams.h" #include "key.h" #include "net.h" +#include "timedata.h" #include "ui_interface.h" #include "util.h" diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 40b45415c4..db39df4b17 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -8,7 +8,7 @@ #include "rpcclient.h" #include "rpcprotocol.h" #include "ui_interface.h" /* for _(...) */ -#include "chainparams.h" +#include "chainparamsbase.h" #include <boost/filesystem/operations.hpp> @@ -60,12 +60,11 @@ static bool AppInitRPC(int argc, char* argv[]) fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; } - // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) - if (!SelectParamsFromCommandLine()) { + // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause) + if (!SelectBaseParamsFromCommandLine()) { fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); return false; } - if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) { std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n"; @@ -104,7 +103,7 @@ Object CallRPC(const string& strMethod, const Array& params) bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started do { - bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))); + bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort()))); if (fConnected) break; if (fWait) MilliSleep(1000); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index afbae6fc57..63067a153d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -99,7 +99,7 @@ unsigned int pnSeed[] = class CMainParams : public CChainParams { public: CMainParams() { - networkID = CChainParams::MAIN; + networkID = CBaseChainParams::MAIN; strNetworkID = "main"; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -110,13 +110,14 @@ public: pchMessageStart[3] = 0xd9; vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"); nDefaultPort = 8333; - nRPCPort = 8332; bnProofOfWorkLimit = ~uint256(0) >> 32; nSubsidyHalvingInterval = 210000; nEnforceBlockUpgradeMajority = 750; nRejectBlockOutdatedMajority = 950; nToCheckBlockUpgradeMajority = 1000; nMinerThreads = 0; + nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + nTargetSpacing = 10 * 60; // Build the genesis block. Note that the output of the genesis coinbase cannot // be spent as it did not originally exist in the database. @@ -189,7 +190,7 @@ static CMainParams mainParams; class CTestNetParams : public CMainParams { public: CTestNetParams() { - networkID = CChainParams::TESTNET; + networkID = CBaseChainParams::TESTNET; strNetworkID = "test"; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -200,11 +201,12 @@ public: pchMessageStart[3] = 0x07; vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"); nDefaultPort = 18333; - nRPCPort = 18332; nEnforceBlockUpgradeMajority = 51; nRejectBlockOutdatedMajority = 75; nToCheckBlockUpgradeMajority = 100; - strDataDir = "testnet3"; + nMinerThreads = 0; + nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + nTargetSpacing = 10 * 60; // Modify the testnet genesis block so the timestamp is valid for a later start. genesis.nTime = 1296688602; @@ -240,7 +242,7 @@ static CTestNetParams testNetParams; class CRegTestParams : public CTestNetParams { public: CRegTestParams() { - networkID = CChainParams::REGTEST; + networkID = CBaseChainParams::REGTEST; strNetworkID = "regtest"; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; @@ -251,13 +253,14 @@ public: nRejectBlockOutdatedMajority = 950; nToCheckBlockUpgradeMajority = 1000; nMinerThreads = 1; + nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + nTargetSpacing = 10 * 60; bnProofOfWorkLimit = ~uint256(0) >> 1; genesis.nTime = 1296688602; genesis.nBits = 0x207fffff; genesis.nNonce = 2; hashGenesisBlock = genesis.GetHash(); nDefaultPort = 18444; - strDataDir = "regtest"; assert(hashGenesisBlock == uint256("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); vSeeds.clear(); // Regtest mode doesn't have any DNS seeds. @@ -272,21 +275,23 @@ public: }; static CRegTestParams regTestParams; -static CChainParams *pCurrentParams = &mainParams; +static CChainParams *pCurrentParams = 0; const CChainParams &Params() { + assert(pCurrentParams); return *pCurrentParams; } -void SelectParams(CChainParams::Network network) { +void SelectParams(CBaseChainParams::Network network) { + SelectBaseParams(network); switch (network) { - case CChainParams::MAIN: + case CBaseChainParams::MAIN: pCurrentParams = &mainParams; break; - case CChainParams::TESTNET: + case CBaseChainParams::TESTNET: pCurrentParams = &testNetParams; break; - case CChainParams::REGTEST: + case CBaseChainParams::REGTEST: pCurrentParams = ®TestParams; break; default: @@ -296,19 +301,9 @@ void SelectParams(CChainParams::Network network) { } bool SelectParamsFromCommandLine() { - bool fRegTest = GetBoolArg("-regtest", false); - bool fTestNet = GetBoolArg("-testnet", false); - - if (fTestNet && fRegTest) { + if (!SelectBaseParamsFromCommandLine()) return false; - } - if (fRegTest) { - SelectParams(CChainParams::REGTEST); - } else if (fTestNet) { - SelectParams(CChainParams::TESTNET); - } else { - SelectParams(CChainParams::MAIN); - } + SelectParams(BaseParams().NetworkID()); return true; } diff --git a/src/chainparams.h b/src/chainparams.h index c0a6ebda6b..446256ba82 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -7,6 +7,7 @@ #define BITCOIN_CHAIN_PARAMS_H #include "core.h" +#include "chainparamsbase.h" #include "protocol.h" #include "uint256.h" @@ -29,14 +30,6 @@ struct CDNSSeedData { class CChainParams { public: - enum Network { - MAIN, - TESTNET, - REGTEST, - - MAX_NETWORK_TYPES - }; - enum Base58Type { PUBKEY_ADDRESS, SCRIPT_ADDRESS, @@ -70,17 +63,18 @@ public: bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; } /* Make standard checks */ bool RequireStandard() const { return fRequireStandard; } - const std::string& DataDir() const { return strDataDir; } + int64_t TargetTimespan() const { return nTargetTimespan; } + int64_t TargetSpacing() const { return nTargetSpacing; } + int64_t Interval() const { return nTargetTimespan / nTargetSpacing; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } - Network NetworkID() const { return networkID; } + CBaseChainParams::Network NetworkID() const { return networkID; } /* Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; } const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } const std::vector<CAddress>& FixedSeeds() const { return vFixedSeeds; } - int RPCPort() const { return nRPCPort; } protected: CChainParams() {} @@ -89,17 +83,17 @@ protected: // Raw pub key bytes for the broadcast alert signing key. std::vector<unsigned char> vAlertPubKey; int nDefaultPort; - int nRPCPort; uint256 bnProofOfWorkLimit; int nSubsidyHalvingInterval; int nEnforceBlockUpgradeMajority; int nRejectBlockOutdatedMajority; int nToCheckBlockUpgradeMajority; - std::string strDataDir; + int64_t nTargetTimespan; + int64_t nTargetSpacing; int nMinerThreads; std::vector<CDNSSeedData> vSeeds; std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES]; - Network networkID; + CBaseChainParams::Network networkID; std::string strNetworkID; CBlock genesis; std::vector<CAddress> vFixedSeeds; @@ -118,7 +112,7 @@ protected: const CChainParams &Params(); /** Sets the params returned by Params() to those for the given network. */ -void SelectParams(CChainParams::Network network); +void SelectParams(CBaseChainParams::Network network); /** * Looks for -regtest or -testnet and then calls SelectParams as appropriate. diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp new file mode 100644 index 0000000000..19a9e72cc9 --- /dev/null +++ b/src/chainparamsbase.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "chainparamsbase.h" + +#include "assert.h" +#include "util.h" + +#include <boost/assign/list_of.hpp> + +using namespace boost::assign; + +// +// Main network +// + +class CBaseMainParams : public CBaseChainParams { +public: + CBaseMainParams() { + networkID = CBaseChainParams::MAIN; + nRPCPort = 8332; + } +}; +static CBaseMainParams mainParams; + +// +// Testnet (v3) +// +class CBaseTestNetParams : public CBaseMainParams { +public: + CBaseTestNetParams() { + networkID = CBaseChainParams::TESTNET; + nRPCPort = 18332; + strDataDir = "testnet3"; + } +}; +static CBaseTestNetParams testNetParams; + +// +// Regression test +// +class CBaseRegTestParams : public CBaseTestNetParams { +public: + CBaseRegTestParams() { + networkID = CBaseChainParams::REGTEST; + strDataDir = "regtest"; + } +}; +static CBaseRegTestParams regTestParams; + +static CBaseChainParams *pCurrentBaseParams = 0; + +const CBaseChainParams &BaseParams() { + assert(pCurrentBaseParams); + return *pCurrentBaseParams; +} + +void SelectBaseParams(CBaseChainParams::Network network) { + switch (network) { + case CBaseChainParams::MAIN: + pCurrentBaseParams = &mainParams; + break; + case CBaseChainParams::TESTNET: + pCurrentBaseParams = &testNetParams; + break; + case CBaseChainParams::REGTEST: + pCurrentBaseParams = ®TestParams; + break; + default: + assert(false && "Unimplemented network"); + return; + } +} + +bool SelectBaseParamsFromCommandLine() { + bool fRegTest = GetBoolArg("-regtest", false); + bool fTestNet = GetBoolArg("-testnet", false); + + if (fTestNet && fRegTest) { + return false; + } + + if (fRegTest) { + SelectBaseParams(CBaseChainParams::REGTEST); + } else if (fTestNet) { + SelectBaseParams(CBaseChainParams::TESTNET); + } else { + SelectBaseParams(CBaseChainParams::MAIN); + } + return true; +} diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h new file mode 100644 index 0000000000..4a3b268909 --- /dev/null +++ b/src/chainparamsbase.h @@ -0,0 +1,52 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CHAIN_PARAMS_BASE_H +#define BITCOIN_CHAIN_PARAMS_BASE_H + +#include <vector> +#include <string> + +/** + * CBaseChainParams defines the base parameters (shared between bitcoin-cli and bitcoind) + * of a given instance of the Bitcoin system. + */ +class CBaseChainParams +{ +public: + enum Network { + MAIN, + TESTNET, + REGTEST, + + MAX_NETWORK_TYPES + }; + + const std::string& DataDir() const { return strDataDir; } + int RPCPort() const { return nRPCPort; } + Network NetworkID() const { return networkID; } +protected: + CBaseChainParams() {} + + int nRPCPort; + std::string strDataDir; + Network networkID; +}; + +/** + * Return the currently selected parameters. This won't change after app startup + * outside of the unit tests. + */ +const CBaseChainParams &BaseParams(); + +/** Sets the params returned by Params() to those for the given network. */ +void SelectBaseParams(CBaseChainParams::Network network); + +/** + * Looks for -regtest or -testnet and then calls SelectParams as appropriate. + * Returns false if an invalid combination is given. + */ +bool SelectBaseParamsFromCommandLine(); + +#endif diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 926949e06a..75ac418916 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -83,9 +83,9 @@ namespace Checkpoints }; const CCheckpointData &Checkpoints() { - if (Params().NetworkID() == CChainParams::TESTNET) + if (Params().NetworkID() == CBaseChainParams::TESTNET) return dataTestnet; - else if (Params().NetworkID() == CChainParams::MAIN) + else if (Params().NetworkID() == CBaseChainParams::MAIN) return data; else return dataRegtest; diff --git a/src/clientversion.h b/src/clientversion.h index 29b4aa3764..a30bbff06b 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -2,7 +2,7 @@ #define CLIENTVERSION_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #else // // client versioning and copyright year diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp index bb870c01f8..22f82e4259 100644 --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include <cstddef> diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp index 6e5bae8a48..d93602e0fe 100644 --- a/src/compat/glibc_sanity.cpp +++ b/src/compat/glibc_sanity.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include <cstddef> diff --git a/src/init.cpp b/src/init.cpp index 12d2d1bb44..a03629d07a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "init.h" @@ -260,7 +260,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n"; strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; - strUsage += " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n"; + strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n"; + strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n"; #endif strUsage += "\n" + _("Debugging/Testing options:") + "\n"; @@ -536,7 +537,7 @@ bool AppInit2(boost::thread_group& threadGroup) // -zapwallettx implies a rescan if (GetBoolArg("-zapwallettxes", false)) { if (SoftSetBoolArg("-rescan", true)) - LogPrintf("AppInit2 : parameter interaction: -zapwallettxes=1 -> setting -rescan=1\n"); + LogPrintf("AppInit2 : parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n"); } // Make sure enough file descriptors are available @@ -560,6 +561,9 @@ bool AppInit2(boost::thread_group& threadGroup) // Check for -debugnet (deprecated) if (GetBoolArg("-debugnet", false)) InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net")); + // Check for -tor - as this is a privacy risk to continue, exit here + if (GetBoolArg("-tor", false)) + return InitError(_("Error: Unsupported argument -tor found, use -onion.")); fBenchmark = GetBoolArg("-benchmark", false); // Checkmempool defaults to true in regtest mode @@ -766,19 +770,15 @@ bool AppInit2(boost::thread_group& threadGroup) } // -onion can override normal proxy, -noonion disables tor entirely - // -tor here is a temporary backwards compatibility measure - if (mapArgs.count("-tor")) - printf("Notice: option -tor has been replaced with -onion and will be removed in a later version.\n"); if (!(mapArgs.count("-onion") && mapArgs["-onion"] == "0") && - !(mapArgs.count("-tor") && mapArgs["-tor"] == "0") && - (fProxy || mapArgs.count("-onion") || mapArgs.count("-tor"))) { + (fProxy || mapArgs.count("-onion"))) { CService addrOnion; - if (!mapArgs.count("-onion") && !mapArgs.count("-tor")) + if (!mapArgs.count("-onion")) addrOnion = addrProxy; else - addrOnion = mapArgs.count("-onion")?CService(mapArgs["-onion"], 9050):CService(mapArgs["-tor"], 9050); + addrOnion = CService(mapArgs["-onion"], 9050); if (!addrOnion.IsValid()) - return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs.count("-onion")?mapArgs["-onion"]:mapArgs["-tor"])); + return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"])); SetProxy(NET_TOR, addrOnion, 5); SetReachable(NET_TOR); } @@ -993,11 +993,15 @@ bool AppInit2(boost::thread_group& threadGroup) pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); } else { + + // needed to restore wallet transaction meta data after -zapwallettxes + std::vector<CWalletTx> vWtx; + if (GetBoolArg("-zapwallettxes", false)) { uiInterface.InitMessage(_("Zapping all transactions from wallet...")); pwalletMain = new CWallet(strWalletFile); - DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(); + DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(vWtx); if (nZapWalletRet != DB_LOAD_OK) { uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted")); return false; @@ -1092,6 +1096,29 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); pwalletMain->SetBestChain(chainActive.GetLocator()); nWalletDBUpdated++; + + // Restore wallet transaction metadata after -zapwallettxes=1 + if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") + { + BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) + { + uint256 hash = wtxOld.GetHash(); + std::map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash); + if (mi != pwalletMain->mapWallet.end()) + { + const CWalletTx* copyFrom = &wtxOld; + CWalletTx* copyTo = &mi->second; + copyTo->mapValue = copyFrom->mapValue; + copyTo->vOrderForm = copyFrom->vOrderForm; + copyTo->nTimeReceived = copyFrom->nTimeReceived; + copyTo->nTimeSmart = copyFrom->nTimeSmart; + copyTo->fFromMe = copyFrom->fFromMe; + copyTo->strFromAccount = copyFrom->strFromAccount; + copyTo->nOrderPos = copyFrom->nOrderPos; + copyTo->WriteToDisk(); + } + } + } } } // (!fDisableWallet) #else // ENABLE_WALLET diff --git a/src/main.cpp b/src/main.cpp index d3f04b95fa..e06c519ee2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,7 @@ #include "checkqueue.h" #include "init.h" #include "net.h" +#include "pow.h" #include "txdb.h" #include "txmempool.h" #include "ui_interface.h" @@ -788,6 +789,16 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode) { + { + LOCK(mempool.cs); + uint256 hash = tx.GetHash(); + double dPriorityDelta = 0; + int64_t nFeeDelta = 0; + mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); + if (dPriorityDelta > 0 || nFeeDelta > 0) + return 0; + } + // Base fee is either minTxFee or minRelayTxFee CFeeRate baseFeeRate = (mode == GMF_RELAY) ? tx.minRelayTxFee : tx.minTxFee; @@ -1194,118 +1205,6 @@ int64_t GetBlockValue(int nHeight, int64_t nFees) return nSubsidy + nFees; } -static const int64_t nTargetTimespan = 14 * 24 * 60 * 60; // two weeks -static const int64_t nTargetSpacing = 10 * 60; -static const int64_t nInterval = nTargetTimespan / nTargetSpacing; - -// -// minimum amount of work that could possibly be required nTime after -// minimum work required was nBase -// -unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) -{ - const uint256 &bnLimit = Params().ProofOfWorkLimit(); - // Testnet has min-difficulty blocks - // after nTargetSpacing*2 time between blocks: - if (Params().AllowMinDifficultyBlocks() && nTime > nTargetSpacing*2) - return bnLimit.GetCompact(); - - uint256 bnResult; - bnResult.SetCompact(nBase); - while (nTime > 0 && bnResult < bnLimit) - { - // Maximum 400% adjustment... - bnResult *= 4; - // ... in best-case exactly 4-times-normal target time - nTime -= nTargetTimespan*4; - } - if (bnResult > bnLimit) - bnResult = bnLimit; - return bnResult.GetCompact(); -} - -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock) -{ - unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact(); - - // Genesis block - if (pindexLast == NULL) - return nProofOfWorkLimit; - - // Only change once per interval - if ((pindexLast->nHeight+1) % nInterval != 0) - { - if (Params().AllowMinDifficultyBlocks()) - { - // Special difficulty rule for testnet: - // If the new block's timestamp is more than 2* 10 minutes - // then allow mining of a min-difficulty block. - if (pblock->nTime > pindexLast->nTime + nTargetSpacing*2) - return nProofOfWorkLimit; - else - { - // Return the last non-special-min-difficulty-rules-block - const CBlockIndex* pindex = pindexLast; - while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit) - pindex = pindex->pprev; - return pindex->nBits; - } - } - return pindexLast->nBits; - } - - // Go back by what we want to be 14 days worth of blocks - const CBlockIndex* pindexFirst = pindexLast; - for (int i = 0; pindexFirst && i < nInterval-1; i++) - pindexFirst = pindexFirst->pprev; - assert(pindexFirst); - - // Limit adjustment step - int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); - LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); - if (nActualTimespan < nTargetTimespan/4) - nActualTimespan = nTargetTimespan/4; - if (nActualTimespan > nTargetTimespan*4) - nActualTimespan = nTargetTimespan*4; - - // Retarget - uint256 bnNew; - uint256 bnOld; - bnNew.SetCompact(pindexLast->nBits); - bnOld = bnNew; - bnNew *= nActualTimespan; - bnNew /= nTargetTimespan; - - if (bnNew > Params().ProofOfWorkLimit()) - bnNew = Params().ProofOfWorkLimit(); - - /// debug print - LogPrintf("GetNextWorkRequired RETARGET\n"); - LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan); - LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); - LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); - - return bnNew.GetCompact(); -} - -bool CheckProofOfWork(uint256 hash, unsigned int nBits) -{ - bool fNegative; - bool fOverflow; - uint256 bnTarget; - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); - - // Check range - if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit()) - return error("CheckProofOfWork() : nBits below minimum work"); - - // Check proof of work matches claimed amount - if (hash > bnTarget) - return error("CheckProofOfWork() : hash doesn't match nBits"); - - return true; -} - bool IsInitialBlockDownload() { LOCK(cs_main); diff --git a/src/main.h b/src/main.h index 7071f0094f..9858bcfd69 100644 --- a/src/main.h +++ b/src/main.h @@ -7,7 +7,7 @@ #define BITCOIN_MAIN_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "chainparams.h" @@ -146,10 +146,6 @@ bool ProcessMessages(CNode* pfrom); bool SendMessages(CNode* pto, bool fSendTrickle); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); -/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ -bool CheckProofOfWork(uint256 hash, unsigned int nBits); -/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */ -unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(); /** Format a string that describes several potential problems detected by the core */ @@ -159,7 +155,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, b /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(CValidationState &state); int64_t GetBlockValue(int nHeight, int64_t nFees); -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock); void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev); @@ -812,11 +807,6 @@ public: return (~bnTarget / (bnTarget + 1)) + 1; } - bool CheckIndex() const - { - return CheckProofOfWork(GetBlockHash(), nBits); - } - enum { nMedianTimeSpan=11 }; int64_t GetMedianTimePast() const diff --git a/src/miner.cpp b/src/miner.cpp index 63ce125067..69e53756e0 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -3,12 +3,15 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <inttypes.h> + #include "miner.h" #include "core.h" #include "hash.h" #include "main.h" #include "net.h" +#include "pow.h" #ifdef ENABLE_WALLET #include "wallet.h" #endif @@ -49,7 +52,6 @@ public: } }; - uint64_t nLastBlockTx = 0; uint64_t nLastBlockSize = 0; @@ -58,8 +60,10 @@ typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority; class TxPriorityCompare { bool byFee; + public: TxPriorityCompare(bool _byFee) : byFee(_byFee) { } + bool operator()(const TxPriority& a, const TxPriority& b) { if (byFee) @@ -114,6 +118,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // Collect memory pool transactions into the block int64_t nFees = 0; + { LOCK2(cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip(); @@ -183,6 +188,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); dPriority = tx.ComputePriority(dPriority, nTxSize); + uint256 hash = tx.GetHash(); + mempool.ApplyDeltas(hash, dPriority, nTotalIn); + CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize); if (porphan) @@ -224,10 +232,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) continue; // Skip free transactions if we're past the minimum block size: - if (fSortedByFee && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) + const uint256& hash = tx.GetHash(); + double dPriorityDelta = 0; + int64_t nFeeDelta = 0; + mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); + if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) continue; - // Prioritize by fee once past the priority size or we run out of high-priority + // Prioritise by fee once past the priority size or we run out of high-priority // transactions: if (!fSortedByFee && ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority))) @@ -254,7 +266,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) continue; CTxUndo txundo; - const uint256& hash = tx.GetHash(); UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1); // Added @@ -269,7 +280,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (fPrintPriority) { LogPrintf("priority %.1f fee %s txid %s\n", - dPriority, feeRate.ToString(), tx.GetHash().ToString()); + dPriority, feeRate.ToString(), tx.GetHash().ToString()); } // Add transactions that depend on this one to the priority queue @@ -338,7 +349,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } - #ifdef ENABLE_WALLET ////////////////////////////////////////////////////////////////////////////// // @@ -353,7 +363,8 @@ int64_t nHPSTimerStart = 0; // nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at // zero. // -bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash) { +bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash) +{ // Write the first 76 bytes of the block header to a double-SHA256 state. CHash256 hasher; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -361,7 +372,7 @@ bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phas assert(ss.size() == 80); hasher.Write((unsigned char*)&ss[0], 76); - for (;;) { + while (true) { nNonce++; // Write the last 4 bytes of the block header (the nonce) to a copy of @@ -439,114 +450,115 @@ void static BitcoinMiner(CWallet *pwallet) CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; - try { while (true) { - if (Params().MiningRequiresPeers()) { - // Busy-wait for the network to come online so we don't waste time mining - // on an obsolete chain. In regtest mode we expect to fly solo. - while (vNodes.empty()) - MilliSleep(1000); - } - - // - // Create new block - // - unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrev = chainActive.Tip(); - - auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey)); - if (!pblocktemplate.get()) - return; - CBlock *pblock = &pblocktemplate->block; - IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - - LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(), - ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); - - // - // Search - // - int64_t nStart = GetTime(); - uint256 hashTarget = uint256().SetCompact(pblock->nBits); - uint256 hash; - uint32_t nNonce = 0; - uint32_t nOldNonce = 0; - while (true) - { - bool fFound = ScanHash(pblock, nNonce, &hash); - uint32_t nHashesDone = nNonce - nOldNonce; - nOldNonce = nNonce; + try { + while (true) { + if (Params().MiningRequiresPeers()) { + // Busy-wait for the network to come online so we don't waste time mining + // on an obsolete chain. In regtest mode we expect to fly solo. + while (vNodes.empty()) + MilliSleep(1000); + } - // Check if something found - if (fFound) - { - if (hash <= hashTarget) + // + // Create new block + // + unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); + CBlockIndex* pindexPrev = chainActive.Tip(); + + auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey)); + if (!pblocktemplate.get()) + return; + CBlock *pblock = &pblocktemplate->block; + IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); + + LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(), + ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); + + // + // Search + // + int64_t nStart = GetTime(); + uint256 hashTarget = uint256().SetCompact(pblock->nBits); + uint256 hash; + uint32_t nNonce = 0; + uint32_t nOldNonce = 0; + while (true) { + bool fFound = ScanHash(pblock, nNonce, &hash); + uint32_t nHashesDone = nNonce - nOldNonce; + nOldNonce = nNonce; + + // Check if something found + if (fFound) { - // Found a solution - pblock->nNonce = nNonce; - assert(hash == pblock->GetHash()); + if (hash <= hashTarget) + { + // Found a solution + pblock->nNonce = nNonce; + assert(hash == pblock->GetHash()); - SetThreadPriority(THREAD_PRIORITY_NORMAL); - CheckWork(pblock, *pwallet, reservekey); - SetThreadPriority(THREAD_PRIORITY_LOWEST); + SetThreadPriority(THREAD_PRIORITY_NORMAL); + CheckWork(pblock, *pwallet, reservekey); + SetThreadPriority(THREAD_PRIORITY_LOWEST); - // In regression test mode, stop mining after a block is found. - if (Params().MineBlocksOnDemand()) - throw boost::thread_interrupted(); + // In regression test mode, stop mining after a block is found. + if (Params().MineBlocksOnDemand()) + throw boost::thread_interrupted(); - break; + break; + } } - } - // Meter hashes/sec - static int64_t nHashCounter; - if (nHPSTimerStart == 0) - { - nHPSTimerStart = GetTimeMillis(); - nHashCounter = 0; - } - else - nHashCounter += nHashesDone; - if (GetTimeMillis() - nHPSTimerStart > 4000) - { - static CCriticalSection cs; + // Meter hashes/sec + static int64_t nHashCounter; + if (nHPSTimerStart == 0) + { + nHPSTimerStart = GetTimeMillis(); + nHashCounter = 0; + } + else + nHashCounter += nHashesDone; + if (GetTimeMillis() - nHPSTimerStart > 4000) { - LOCK(cs); - if (GetTimeMillis() - nHPSTimerStart > 4000) + static CCriticalSection cs; { - dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart); - nHPSTimerStart = GetTimeMillis(); - nHashCounter = 0; - static int64_t nLogTime; - if (GetTime() - nLogTime > 30 * 60) + LOCK(cs); + if (GetTimeMillis() - nHPSTimerStart > 4000) { - nLogTime = GetTime(); - LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0); + dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart); + nHPSTimerStart = GetTimeMillis(); + nHashCounter = 0; + static int64_t nLogTime; + if (GetTime() - nLogTime > 30 * 60) + { + nLogTime = GetTime(); + LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0); + } } } } - } - // Check for stop or if block needs to be rebuilt - boost::this_thread::interruption_point(); - // Regtest mode doesn't require peers - if (vNodes.empty() && Params().MiningRequiresPeers()) - break; - if (nNonce >= 0xffff0000) - break; - if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) - break; - if (pindexPrev != chainActive.Tip()) - break; - - // Update nTime every few seconds - UpdateTime(*pblock, pindexPrev); - if (Params().AllowMinDifficultyBlocks()) - { - // Changing pblock->nTime can change work required on testnet: - hashTarget.SetCompact(pblock->nBits); + // Check for stop or if block needs to be rebuilt + boost::this_thread::interruption_point(); + // Regtest mode doesn't require peers + if (vNodes.empty() && Params().MiningRequiresPeers()) + break; + if (nNonce >= 0xffff0000) + break; + if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) + break; + if (pindexPrev != chainActive.Tip()) + break; + + // Update nTime every few seconds + UpdateTime(*pblock, pindexPrev); + if (Params().AllowMinDifficultyBlocks()) + { + // Changing pblock->nTime can change work required on testnet: + hashTarget.SetCompact(pblock->nBits); + } } } - } } + } catch (boost::thread_interrupted) { LogPrintf("BitcoinMiner terminated\n"); @@ -581,4 +593,4 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); } -#endif +#endif // ENABLE_WALLET diff --git a/src/net.cpp b/src/net.cpp index 71e3e57fa7..811df43334 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "net.h" diff --git a/src/netbase.cpp b/src/netbase.cpp index 4aa7367f39..3c50174e75 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -337,8 +337,9 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { + int nErr = WSAGetLastError(); // WSAEINVAL is here because some legacy version of winsock uses it - if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL) + if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { struct timeval timeout; timeout.tv_sec = nTimeout / 1000; diff --git a/src/netbase.h b/src/netbase.h index 23cfb1f158..40a3d25676 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -6,7 +6,7 @@ #define BITCOIN_NETBASE_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "compat.h" diff --git a/src/pow.cpp b/src/pow.cpp new file mode 100644 index 0000000000..952250decd --- /dev/null +++ b/src/pow.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "pow.h" + +#include "chainparams.h" +#include "core.h" +#include "main.h" +#include "uint256.h" + +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock) +{ + unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact(); + + // Genesis block + if (pindexLast == NULL) + return nProofOfWorkLimit; + + // Only change once per interval + if ((pindexLast->nHeight+1) % Params().Interval() != 0) + { + if (Params().AllowMinDifficultyBlocks()) + { + // Special difficulty rule for testnet: + // If the new block's timestamp is more than 2* 10 minutes + // then allow mining of a min-difficulty block. + if (pblock->nTime > pindexLast->nTime + Params().TargetSpacing()*2) + return nProofOfWorkLimit; + else + { + // Return the last non-special-min-difficulty-rules-block + const CBlockIndex* pindex = pindexLast; + while (pindex->pprev && pindex->nHeight % Params().Interval() != 0 && pindex->nBits == nProofOfWorkLimit) + pindex = pindex->pprev; + return pindex->nBits; + } + } + return pindexLast->nBits; + } + + // Go back by what we want to be 14 days worth of blocks + const CBlockIndex* pindexFirst = pindexLast; + for (int i = 0; pindexFirst && i < Params().Interval()-1; i++) + pindexFirst = pindexFirst->pprev; + assert(pindexFirst); + + // Limit adjustment step + int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); + LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); + if (nActualTimespan < Params().TargetTimespan()/4) + nActualTimespan = Params().TargetTimespan()/4; + if (nActualTimespan > Params().TargetTimespan()*4) + nActualTimespan = Params().TargetTimespan()*4; + + // Retarget + uint256 bnNew; + uint256 bnOld; + bnNew.SetCompact(pindexLast->nBits); + bnOld = bnNew; + bnNew *= nActualTimespan; + bnNew /= Params().TargetTimespan(); + + if (bnNew > Params().ProofOfWorkLimit()) + bnNew = Params().ProofOfWorkLimit(); + + /// debug print + LogPrintf("GetNextWorkRequired RETARGET\n"); + LogPrintf("Params().TargetTimespan() = %d nActualTimespan = %d\n", Params().TargetTimespan(), nActualTimespan); + LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); + LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); + + return bnNew.GetCompact(); +} + +bool CheckProofOfWork(uint256 hash, unsigned int nBits) +{ + bool fNegative; + bool fOverflow; + uint256 bnTarget; + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + + // Check range + if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit()) + return error("CheckProofOfWork() : nBits below minimum work"); + + // Check proof of work matches claimed amount + if (hash > bnTarget) + return error("CheckProofOfWork() : hash doesn't match nBits"); + + return true; +} + +// +// minimum amount of work that could possibly be required nTime after +// minimum work required was nBase +// +unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) +{ + const uint256 &bnLimit = Params().ProofOfWorkLimit(); + // Testnet has min-difficulty blocks + // after Params().TargetSpacing()*2 time between blocks: + if (Params().AllowMinDifficultyBlocks() && nTime > Params().TargetSpacing()*2) + return bnLimit.GetCompact(); + + uint256 bnResult; + bnResult.SetCompact(nBase); + while (nTime > 0 && bnResult < bnLimit) + { + // Maximum 400% adjustment... + bnResult *= 4; + // ... in best-case exactly 4-times-normal target time + nTime -= Params().TargetTimespan()*4; + } + if (bnResult > bnLimit) + bnResult = bnLimit; + return bnResult.GetCompact(); +} diff --git a/src/pow.h b/src/pow.h new file mode 100644 index 0000000000..0ce5b48766 --- /dev/null +++ b/src/pow.h @@ -0,0 +1,23 @@ + +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_POW_H +#define BITCOIN_POW_H + +#include <stdint.h> + +class CBlockIndex; +class CBlockHeader; +class uint256; + +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock); + +/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ +bool CheckProofOfWork(uint256 hash, unsigned int nBits); +/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */ +unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime); + +#endif diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 2dc56a5107..5df8f19729 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "addressbookpage.h" diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 2a6d6abc35..a448d5a9a0 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -37,7 +37,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : case Encrypt: // Ask passphrase x2 ui->passLabel1->hide(); ui->passEdit1->hide(); - ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>.")); + ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.")); setWindowTitle(tr("Encrypt wallet")); break; case Unlock: // Ask passphrase diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 387f6ede4b..89305e9f35 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "bitcoingui.h" @@ -546,7 +546,7 @@ int main(int argc, char *argv[]) if (!PaymentServer::ipcParseCommandLine(argc, argv)) exit(0); #endif - bool isaTestNet = Params().NetworkID() != CChainParams::MAIN; + bool isaTestNet = Params().NetworkID() != CBaseChainParams::MAIN; // Allow for separate UI settings for testnets if (isaTestNet) QApplication::setApplicationName(QAPP_APP_NAME_TESTNET); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 275fa35f39..e7a842df99 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -6,7 +6,7 @@ #define BITCOINGUI_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include <QMainWindow> diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 52bdf96731..c6a6150392 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -521,7 +521,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority); // Fee - int64_t nFee = payTxFee.GetFee(nBytes); + int64_t nFee = payTxFee.GetFee(max((unsigned int)1000, nBytes)); // Min Fee int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND); @@ -582,6 +582,13 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) l6->setText(sPriorityLabel); // Priority l7->setText(fDust ? tr("yes") : tr("no")); // Dust l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change + if (nPayFee > 0) + { + l3->setText("~" + l3->text()); + l4->setText("~" + l4->text()); + if (nChange > 0) + l8->setText("~" + l8->text()); + } // turn labels "red" l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000 @@ -599,12 +606,22 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minRelayTxFee.GetFee(546))); + // how many satoshis the estimated fee can vary per byte we guess wrong + double dFeeVary = (double)std::max(CTransaction::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000; + QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); + + l3->setToolTip(toolTip4); + l4->setToolTip(toolTip4); l5->setToolTip(toolTip1); l6->setToolTip(toolTip2); l7->setToolTip(toolTip3); + l8->setToolTip(toolTip4); + dialog->findChild<QLabel *>("labelCoinControlFeeText") ->setToolTip(l3->toolTip()); + dialog->findChild<QLabel *>("labelCoinControlAfterFeeText") ->setToolTip(l4->toolTip()); dialog->findChild<QLabel *>("labelCoinControlBytesText") ->setToolTip(l5->toolTip()); dialog->findChild<QLabel *>("labelCoinControlPriorityText") ->setToolTip(l6->toolTip()); dialog->findChild<QLabel *>("labelCoinControlLowOutputText")->setToolTip(l7->toolTip()); + dialog->findChild<QLabel *>("labelCoinControlChangeText") ->setToolTip(l8->toolTip()); // Insufficient funds QLabel *label = dialog->findChild<QLabel *>("labelCoinControlInsuffFunds"); diff --git a/src/qt/forms/helpmessagedialog.ui b/src/qt/forms/helpmessagedialog.ui index d8ab27c238..81dbd90b12 100644 --- a/src/qt/forms/helpmessagedialog.ui +++ b/src/qt/forms/helpmessagedialog.ui @@ -60,6 +60,9 @@ <property name="textFormat"> <enum>Qt::PlainText</enum> </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> <property name="textInteractionFlags"> <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> </property> diff --git a/src/qt/notificator.h b/src/qt/notificator.h index abab986992..3395e64350 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -6,7 +6,7 @@ #define NOTIFICATOR_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include <QIcon> diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index abfd4123e0..12d54dff64 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "optionsdialog.h" diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 4dafd9d2af..6d985abaf8 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "optionsmodel.h" diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 49923a1afc..fbb11617fe 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -199,10 +199,10 @@ bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { CBitcoinAddress address(r.address.toStdString()); - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); if (!address.IsValid()) { - SelectParams(CChainParams::TESTNET); + SelectParams(CBaseChainParams::TESTNET); } } } @@ -214,9 +214,9 @@ bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) if (readPaymentRequest(arg, request)) { if (request.getDetails().network() == "main") - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); else - SelectParams(CChainParams::TESTNET); + SelectParams(CBaseChainParams::TESTNET); } } else diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index d8dad15c0d..cc2f00916f 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -22,7 +22,7 @@ #endif #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" /* for USE_QRCODE */ +#include "config/bitcoin-config.h" /* for USE_QRCODE */ #endif #ifdef USE_QRCODE diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index 7dee7a9cda..e92a7d2b1a 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -56,6 +56,7 @@ static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsig void PaymentServerTests::paymentServerTests() { + SelectParams(CBaseChainParams::MAIN); OptionsModel optionsModel; PaymentServer* server = new PaymentServer(NULL, false); X509_STORE* caStore = X509_STORE_new(); diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 220da28cfe..03a2381c06 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -1,5 +1,5 @@ #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #ifdef ENABLE_WALLET diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 61da3373fd..e48dbcac9d 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -12,6 +12,7 @@ #include "main.h" #include "paymentserver.h" #include "transactionrecord.h" +#include "timedata.h" #include "ui_interface.h" #include "wallet.h" diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 5a3728f498..eec2b57e8c 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -5,6 +5,7 @@ #include "transactionrecord.h" #include "base58.h" +#include "timedata.h" #include "wallet.h" #include <stdint.h> diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 3a06e33016..30881b9b1a 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -72,6 +72,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri if (strMethod == "listtransactions" && n > 2) ConvertTo<int64_t>(params[2]); if (strMethod == "listaccounts" && n > 0) ConvertTo<int64_t>(params[0]); if (strMethod == "walletpassphrase" && n > 1) ConvertTo<int64_t>(params[1]); + if (strMethod == "prioritisetransaction" && n > 1) ConvertTo<double>(params[1]); + if (strMethod == "prioritisetransaction" && n > 2) ConvertTo<int64_t>(params[2]); if (strMethod == "getblocktemplate" && n > 0) ConvertTo<Object>(params[0]); if (strMethod == "listsinceblock" && n > 1) ConvertTo<int64_t>(params[1]); if (strMethod == "sendmany" && n > 1) ConvertTo<Object>(params[1]); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index a1410f0e41..98caf704ee 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -9,6 +9,7 @@ #include "net.h" #include "main.h" #include "miner.h" +#include "pow.h" #ifdef ENABLE_WALLET #include "db.h" #include "wallet.h" @@ -236,7 +237,7 @@ Value getmininginfo(const Array& params, bool fHelp) obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); - obj.push_back(Pair("testnet", Params().NetworkID() == CChainParams::TESTNET)); + obj.push_back(Pair("testnet", Params().NetworkID() == CBaseChainParams::TESTNET)); obj.push_back(Pair("chain", Params().NetworkIDString())); #ifdef ENABLE_WALLET obj.push_back(Pair("generate", getgenerate(params, false))); @@ -246,6 +247,20 @@ Value getmininginfo(const Array& params, bool fHelp) } +Value prioritisetransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "prioritisetransaction <txid> <priority delta> <fee delta>\n" + "Accepts the transaction into mined blocks at a higher (or lower) priority"); + + uint256 hash; + hash.SetHex(params[0].get_str()); + mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), params[2].get_int64()); + return true; +} + + Value getblocktemplate(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 5181aa23d8..a300de2680 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -9,6 +9,7 @@ #include "net.h" #include "netbase.h" #include "rpcserver.h" +#include "timedata.h" #include "util.h" #ifdef ENABLE_WALLET #include "wallet.h" @@ -73,7 +74,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("testnet", Params().NetworkID() == CChainParams::TESTNET)); + obj.push_back(Pair("testnet", Params().NetworkID() == CBaseChainParams::TESTNET)); #ifdef ENABLE_WALLET if (pwalletMain) { obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 6fc86eedfb..a54872ccc4 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -9,6 +9,7 @@ #include "netbase.h" #include "protocol.h" #include "sync.h" +#include "timedata.h" #include "util.h" #include <boost/foreach.hpp> diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 93da81e429..6552de8c49 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -254,6 +254,7 @@ static const CRPCCommand vRPCCommands[] = { "getblocktemplate", &getblocktemplate, true, false, false }, { "getmininginfo", &getmininginfo, true, false, false }, { "getnetworkhashps", &getnetworkhashps, true, false, false }, + { "prioritisetransaction", &prioritisetransaction, true, false, false }, { "submitblock", &submitblock, false, true, false }, /* Raw transactions */ @@ -600,7 +601,7 @@ void StartRPCThreads() std::vector<ip::tcp::endpoint> vEndpoints; bool bBindAny = false; - int defaultPort = GetArg("-rpcport", Params().RPCPort()); + int defaultPort = GetArg("-rpcport", BaseParams().RPCPort()); if (!mapArgs.count("-rpcallowip")) // Default to loopback if not allowing external IPs { vEndpoints.push_back(ip::tcp::endpoint(asio::ip::address_v6::loopback(), defaultPort)); diff --git a/src/rpcserver.h b/src/rpcserver.h index 5271542385..1966a65b50 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -130,6 +130,7 @@ extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHe extern json_spirit::Value getnetworkhashps(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gethashespersec(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value prioritisetransaction(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value estimatefee(const json_spirit::Array& params, bool fHelp); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index f376ab6b63..4f27cef087 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -8,6 +8,7 @@ #include "init.h" #include "net.h" #include "netbase.h" +#include "timedata.h" #include "util.h" #include "wallet.h" #include "walletdb.h" diff --git a/src/script.h b/src/script.h index ea988f0e40..7ab471f6e6 100644 --- a/src/script.h +++ b/src/script.h @@ -20,7 +20,7 @@ class CCoins; class CKeyStore; class CTransaction; -class CMutableTransaction; +struct CMutableTransaction; static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 3a45844411..5e17555e7a 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -11,6 +11,7 @@ #include "keystore.h" #include "main.h" #include "net.h" +#include "pow.h" #include "script.h" #include "serialize.h" @@ -230,91 +231,4 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) BOOST_CHECK(mapOrphanTransactionsByPrev.empty()); } -BOOST_AUTO_TEST_CASE(DoS_checkSig) -{ - // Test signature caching code (see key.cpp Verify() methods) - - CKey key; - key.MakeNewKey(true); - CBasicKeyStore keystore; - keystore.AddKey(key); - unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; - - // 100 orphan transactions: - static const int NPREV=100; - CMutableTransaction orphans[NPREV]; - for (int i = 0; i < NPREV; i++) - { - CMutableTransaction& tx = orphans[i]; - tx.vin.resize(1); - tx.vin[0].prevout.n = 0; - tx.vin[0].prevout.hash = GetRandHash(); - tx.vin[0].scriptSig << OP_1; - tx.vout.resize(1); - tx.vout[0].nValue = 1*CENT; - tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); - - AddOrphanTx(tx); - } - - // Create a transaction that depends on orphans: - CMutableTransaction tx; - tx.vout.resize(1); - tx.vout[0].nValue = 1*CENT; - tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); - tx.vin.resize(NPREV); - for (unsigned int j = 0; j < tx.vin.size(); j++) - { - tx.vin[j].prevout.n = 0; - tx.vin[j].prevout.hash = orphans[j].GetHash(); - } - // Creating signatures primes the cache: - boost::posix_time::ptime mst1 = boost::posix_time::microsec_clock::local_time(); - for (unsigned int j = 0; j < tx.vin.size(); j++) - BOOST_CHECK(SignSignature(keystore, orphans[j], tx, j)); - boost::posix_time::ptime mst2 = boost::posix_time::microsec_clock::local_time(); - boost::posix_time::time_duration msdiff = mst2 - mst1; - long nOneValidate = msdiff.total_milliseconds(); - if (fDebug) printf("DoS_Checksig sign: %ld\n", nOneValidate); - - // ... now validating repeatedly should be quick: - // 2.8GHz machine, -g build: Sign takes ~760ms, - // uncached Verify takes ~250ms, cached Verify takes ~50ms - // (for 100 single-signature inputs) - mst1 = boost::posix_time::microsec_clock::local_time(); - for (unsigned int i = 0; i < 5; i++) - for (unsigned int j = 0; j < tx.vin.size(); j++) - BOOST_CHECK(VerifySignature(CCoins(orphans[j], MEMPOOL_HEIGHT), tx, j, flags, SIGHASH_ALL)); - mst2 = boost::posix_time::microsec_clock::local_time(); - msdiff = mst2 - mst1; - long nManyValidate = msdiff.total_milliseconds(); - if (fDebug) printf("DoS_Checksig five: %ld\n", nManyValidate); - - BOOST_CHECK_MESSAGE(nManyValidate < nOneValidate, "Signature cache timing failed"); - - // Empty a signature, validation should fail: - CScript save = tx.vin[0].scriptSig; - tx.vin[0].scriptSig = CScript(); - BOOST_CHECK(!VerifySignature(CCoins(orphans[0], MEMPOOL_HEIGHT), tx, 0, flags, SIGHASH_ALL)); - tx.vin[0].scriptSig = save; - - // Swap signatures, validation should fail: - std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig); - BOOST_CHECK(!VerifySignature(CCoins(orphans[0], MEMPOOL_HEIGHT), tx, 0, flags, SIGHASH_ALL)); - BOOST_CHECK(!VerifySignature(CCoins(orphans[1], MEMPOOL_HEIGHT), tx, 1, flags, SIGHASH_ALL)); - std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig); - - // Exercise -maxsigcachesize code: - mapArgs["-maxsigcachesize"] = "10"; - // Generate a new, different signature for vin[0] to trigger cache clear: - CScript oldSig = tx.vin[0].scriptSig; - BOOST_CHECK(SignSignature(keystore, orphans[0], tx, 0)); - BOOST_CHECK(tx.vin[0].scriptSig != oldSig); - for (unsigned int j = 0; j < tx.vin.size(); j++) - BOOST_CHECK(VerifySignature(CCoins(orphans[j], MEMPOOL_HEIGHT), tx, j, flags, SIGHASH_ALL)); - mapArgs.erase("-maxsigcachesize"); - - LimitOrphanTxSize(0); -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index b81a19cfd8..0ac3e9a363 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -142,9 +142,9 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); bool isTestnet = find_value(metadata, "isTestnet").get_bool(); if (isTestnet) - SelectParams(CChainParams::TESTNET); + SelectParams(CBaseChainParams::TESTNET); else - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); if(isPrivkey) { bool isCompressed = find_value(metadata, "isCompressed").get_bool(); @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest); } } - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); } // Goal: check that generated keys match test vectors @@ -198,9 +198,9 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); bool isTestnet = find_value(metadata, "isTestnet").get_bool(); if (isTestnet) - SelectParams(CChainParams::TESTNET); + SelectParams(CBaseChainParams::TESTNET); else - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); if(isPrivkey) { bool isCompressed = find_value(metadata, "isCompressed").get_bool(); @@ -243,7 +243,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) CTxDestination nodest = CNoDestination(); BOOST_CHECK(!dummyAddr.Set(nodest)); - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); } // Goal: check that base58 parsing code is robust against a variety of corrupted data diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 2d993e24db..8cae0a4c34 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -31,6 +31,7 @@ struct TestingSetup { TestingSetup() { fPrintToDebugLog = false; // don't want to write to debug.log file + SelectParams(CBaseChainParams::MAIN); noui_connect(); #ifdef ENABLE_WALLET bitdb.MakeMock(); diff --git a/src/timedata.cpp b/src/timedata.cpp new file mode 100644 index 0000000000..8a095d26dc --- /dev/null +++ b/src/timedata.cpp @@ -0,0 +1,91 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "timedata.h" + +#include "netbase.h" +#include "sync.h" +#include "ui_interface.h" +#include "util.h" + +#include <boost/foreach.hpp> + +using namespace std; + +static CCriticalSection cs_nTimeOffset; +static int64_t nTimeOffset = 0; + +// +// "Never go to sea with two chronometers; take one or three." +// Our three time sources are: +// - System clock +// - Median of other nodes clocks +// - The user (asking the user to fix the system clock if the first two disagree) +// +// +int64_t GetTimeOffset() +{ + LOCK(cs_nTimeOffset); + return nTimeOffset; +} + +int64_t GetAdjustedTime() +{ + return GetTime() + GetTimeOffset(); +} + +void AddTimeData(const CNetAddr& ip, int64_t nTime) +{ + int64_t nOffsetSample = nTime - GetTime(); + + LOCK(cs_nTimeOffset); + // Ignore duplicates + static set<CNetAddr> setKnown; + if (!setKnown.insert(ip).second) + return; + + // Add data + static CMedianFilter<int64_t> vTimeOffsets(200,0); + vTimeOffsets.input(nOffsetSample); + 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(); + std::vector<int64_t> vSorted = vTimeOffsets.sorted(); + // Only let other nodes change our time by so much + if (abs64(nMedian) < 70 * 60) + { + nTimeOffset = nMedian; + } + else + { + nTimeOffset = 0; + + static bool fDone; + if (!fDone) + { + // If nobody has a time different than ours but within 5 minutes of ours, give a warning + bool fMatch = false; + BOOST_FOREACH(int64_t nOffset, vSorted) + if (nOffset != 0 && abs64(nOffset) < 5 * 60) + fMatch = true; + + if (!fMatch) + { + fDone = true; + string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly."); + strMiscWarning = strMessage; + LogPrintf("*** %s\n", strMessage); + uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING); + } + } + } + if (fDebug) { + BOOST_FOREACH(int64_t n, vSorted) + LogPrintf("%+d ", n); + LogPrintf("| "); + } + LogPrintf("nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60); + } +} diff --git a/src/timedata.h b/src/timedata.h new file mode 100644 index 0000000000..0e7bdc2c1f --- /dev/null +++ b/src/timedata.h @@ -0,0 +1,17 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TIMEDATA_H +#define BITCOIN_TIMEDATA_H + +#include <stdint.h> + +class CNetAddr; + +/* Functions to keep track of adjusted P2P time */ +int64_t GetTimeOffset(); +int64_t GetAdjustedTime(); +void AddTimeData(const CNetAddr& ip, int64_t nTime); + +#endif diff --git a/src/txdb.cpp b/src/txdb.cpp index 4eab8525a5..92137f71ff 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -6,6 +6,7 @@ #include "txdb.h" #include "core.h" +#include "pow.h" #include "uint256.h" #include <stdint.h> @@ -212,8 +213,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; - if (!pindexNew->CheckIndex()) - return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString()); + if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits)) + return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString()); pcursor->Next(); } else { diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 4bf01d4848..52f82ef040 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -447,6 +447,7 @@ void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned i std::list<CTransaction> dummy; remove(tx, dummy, false); removeConflicts(tx, conflicts); + ClearPrioritisation(tx.GetHash()); } } @@ -564,6 +565,34 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein) return true; } +void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, int64_t nFeeDelta) +{ + { + LOCK(cs); + std::pair<double, int64_t> &deltas = mapDeltas[hash]; + deltas.first += dPriorityDelta; + deltas.second += nFeeDelta; + } + LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash.c_str(), dPriorityDelta, nFeeDelta); +} + +void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta) +{ + LOCK(cs); + std::map<uint256, std::pair<double, int64_t> >::iterator pos = mapDeltas.find(hash); + if (pos == mapDeltas.end()) + return; + const std::pair<double, int64_t> &deltas = pos->second; + dPriorityDelta += deltas.first; + nFeeDelta += deltas.second; +} + +void CTxMemPool::ClearPrioritisation(const uint256 hash) +{ + LOCK(cs); + mapDeltas.erase(hash); +} + CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } diff --git a/src/txmempool.h b/src/txmempool.h index b2915aa842..f7dbb126a0 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -71,6 +71,7 @@ public: mutable CCriticalSection cs; std::map<uint256, CTxMemPoolEntry> mapTx; std::map<COutPoint, CInPoint> mapNextTx; + std::map<uint256, std::pair<double, int64_t> > mapDeltas; CTxMemPool(); ~CTxMemPool(); @@ -95,6 +96,11 @@ public: unsigned int GetTransactionsUpdated() const; void AddTransactionsUpdated(unsigned int n); + /** Affect CreateNewBlock prioritisation of transactions */ + void PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, int64_t nFeeDelta); + void ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta); + void ClearPrioritisation(const uint256 hash); + unsigned long size() { LOCK(cs); diff --git a/src/util.cpp b/src/util.cpp index a96963689a..9e4b2b787e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -5,8 +5,7 @@ #include "util.h" -#include "chainparams.h" -#include "netbase.h" +#include "chainparamsbase.h" #include "sync.h" #include "ui_interface.h" #include "uint256.h" @@ -934,7 +933,7 @@ boost::filesystem::path GetDefaultDataDir() #endif } -static boost::filesystem::path pathCached[CChainParams::MAX_NETWORK_TYPES+1]; +static boost::filesystem::path pathCached[CBaseChainParams::MAX_NETWORK_TYPES+1]; static CCriticalSection csPathCached; const boost::filesystem::path &GetDataDir(bool fNetSpecific) @@ -943,8 +942,8 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) LOCK(csPathCached); - int nNet = CChainParams::MAX_NETWORK_TYPES; - if (fNetSpecific) nNet = Params().NetworkID(); + int nNet = CBaseChainParams::MAX_NETWORK_TYPES; + if (fNetSpecific) nNet = BaseParams().NetworkID(); fs::path &path = pathCached[nNet]; @@ -963,7 +962,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) path = GetDefaultDataDir(); } if (fNetSpecific) - path /= Params().DataDir(); + path /= BaseParams().DataDir(); fs::create_directories(path); @@ -972,7 +971,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) void ClearDatadirCache() { - std::fill(&pathCached[0], &pathCached[CChainParams::MAX_NETWORK_TYPES+1], + std::fill(&pathCached[0], &pathCached[CBaseChainParams::MAX_NETWORK_TYPES+1], boost::filesystem::path()); } @@ -1172,13 +1171,6 @@ void ShrinkDebugFile() fclose(file); } -// -// "Never go to sea with two chronometers; take one or three." -// Our three time sources are: -// - System clock -// - Median of other nodes clocks -// - The user (asking the user to fix the system clock if the first two disagree) -// static int64_t nMockTime = 0; // For unit testing int64_t GetTime() @@ -1193,75 +1185,6 @@ void SetMockTime(int64_t nMockTimeIn) nMockTime = nMockTimeIn; } -static CCriticalSection cs_nTimeOffset; -static int64_t nTimeOffset = 0; - -int64_t GetTimeOffset() -{ - LOCK(cs_nTimeOffset); - return nTimeOffset; -} - -int64_t GetAdjustedTime() -{ - return GetTime() + GetTimeOffset(); -} - -void AddTimeData(const CNetAddr& ip, int64_t nTime) -{ - int64_t nOffsetSample = nTime - GetTime(); - - LOCK(cs_nTimeOffset); - // Ignore duplicates - static set<CNetAddr> setKnown; - if (!setKnown.insert(ip).second) - return; - - // Add data - static CMedianFilter<int64_t> vTimeOffsets(200,0); - vTimeOffsets.input(nOffsetSample); - 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(); - std::vector<int64_t> vSorted = vTimeOffsets.sorted(); - // Only let other nodes change our time by so much - if (abs64(nMedian) < 70 * 60) - { - nTimeOffset = nMedian; - } - else - { - nTimeOffset = 0; - - static bool fDone; - if (!fDone) - { - // If nobody has a time different than ours but within 5 minutes of ours, give a warning - bool fMatch = false; - BOOST_FOREACH(int64_t nOffset, vSorted) - if (nOffset != 0 && abs64(nOffset) < 5 * 60) - fMatch = true; - - if (!fMatch) - { - fDone = true; - string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly."); - strMiscWarning = strMessage; - LogPrintf("*** %s\n", strMessage); - uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING); - } - } - } - if (fDebug) { - BOOST_FOREACH(int64_t n, vSorted) - LogPrintf("%+d ", n); - LogPrintf("| "); - } - LogPrintf("nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60); - } -} - uint32_t insecure_rand_Rz = 11; uint32_t insecure_rand_Rw = 11; void seed_insecure_rand(bool fDeterministic) diff --git a/src/util.h b/src/util.h index da1810a3d3..6057c72e66 100644 --- a/src/util.h +++ b/src/util.h @@ -7,7 +7,7 @@ #define BITCOIN_UTIL_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "compat.h" @@ -32,7 +32,6 @@ #include <boost/filesystem/path.hpp> #include <boost/thread.hpp> -class CNetAddr; class uint256; static const int64_t COIN = 100000000; @@ -191,11 +190,8 @@ uint64_t GetRand(uint64_t nMax); uint256 GetRandHash(); int64_t GetTime(); void SetMockTime(int64_t nMockTimeIn); -int64_t GetAdjustedTime(); -int64_t GetTimeOffset(); std::string FormatFullVersion(); std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments); -void AddTimeData(const CNetAddr& ip, int64_t nTime); void runCommand(std::string strCommand); diff --git a/src/wallet.cpp b/src/wallet.cpp index 7664d6c25c..f6fd6e958d 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -9,6 +9,7 @@ #include "checkpoints.h" #include "coincontrol.h" #include "net.h" +#include "timedata.h" #include <boost/algorithm/string/replace.hpp> #include <openssl/rand.h> @@ -1514,11 +1515,11 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) } -DBErrors CWallet::ZapWalletTx() +DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx) { if (!fFileBacked) return DB_LOAD_OK; - DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this); + DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this, vWtx); if (nZapWalletTxRet == DB_NEED_REWRITE) { if (CDB::Rewrite(strWalletFile, "\x04pool")) diff --git a/src/wallet.h b/src/wallet.h index 424799b14e..8494ce9a34 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -341,7 +341,7 @@ public: void SetBestChain(const CBlockLocator& loc); DBErrors LoadWallet(bool& fFirstRunRet); - DBErrors ZapWalletTx(); + DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx); bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose); diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 80e9dded5f..3ce2ef019c 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -680,7 +680,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) return result; } -DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash) +DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash, vector<CWalletTx>& vWtx) { pwallet->vchDefaultKey = CPubKey(); CWalletScanState wss; @@ -725,7 +725,11 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash) uint256 hash; ssKey >> hash; + CWalletTx wtx; + ssValue >> wtx; + vTxHash.push_back(hash); + vWtx.push_back(wtx); } } pcursor->close(); @@ -743,11 +747,11 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash) return result; } -DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet) +DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector<CWalletTx>& vWtx) { // build list of wallet TXs vector<uint256> vTxHash; - DBErrors err = FindWalletTx(pwallet, vTxHash); + DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx); if (err != DB_LOAD_OK) return err; diff --git a/src/walletdb.h b/src/walletdb.h index 3bfb436050..8eb716acbb 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -122,8 +122,8 @@ public: DBErrors ReorderTransactions(CWallet*); DBErrors LoadWallet(CWallet* pwallet); - DBErrors FindWalletTx(CWallet* pwallet, std::vector<uint256>& vTxHash); - DBErrors ZapWalletTx(CWallet* pwallet); + DBErrors FindWalletTx(CWallet* pwallet, std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx); + DBErrors ZapWalletTx(CWallet* pwallet, std::vector<CWalletTx>& vWtx); static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, std::string filename); }; |