diff options
90 files changed, 825 insertions, 585 deletions
diff --git a/.travis.yml b/.travis.yml index f7d94df646..eae07ead8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,9 +35,9 @@ matrix: - compiler: "true 5" env: HOST=x86_64-apple-darwin11 PACKAGES="gcc-multilib g++-multilib cmake libcap-dev libz-dev libbz2-dev" OSX_SDK=10.7 GOAL="deploy" - compiler: "true 6" - env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev" GOAL="deploy" + env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev wine" RUN_TESTS=true GOAL="deploy" - compiler: "true 7" - env: HOST=i686-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev" GOAL="deploy" + env: HOST=i686-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine" RUN_TESTS=true GOAL="deploy" install: - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-upgrade -qq $PACKAGES; fi diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index edfde4cd79..71b1484894 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -152,6 +152,13 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ fi CPPFLAGS=$TEMP_CPPFLAGS ]) + + if test x$use_pkgconfig$qt_bin_path = xyes; then + if test x$bitcoin_qt_got_major_vers = x5; then + qt_bin_path="`$PKG_CONFIG --variable=host_bins Qt5Core 2>/dev/null`" + fi + fi + BITCOIN_QT_PATH_PROGS([MOC], [moc-qt${bitcoin_qt_got_major_vers} moc${bitcoin_qt_got_major_vers} moc], $qt_bin_path) BITCOIN_QT_PATH_PROGS([UIC], [uic-qt${bitcoin_qt_got_major_vers} uic${bitcoin_qt_got_major_vers} uic], $qt_bin_path) BITCOIN_QT_PATH_PROGS([RCC], [rcc-qt${bitcoin_qt_got_major_vers} rcc${bitcoin_qt_got_major_vers} rcc], $qt_bin_path) diff --git a/configure.ac b/configure.ac index 0f9e78b74f..abf9f39e65 100644 --- a/configure.ac +++ b/configure.ac @@ -240,12 +240,25 @@ case $host in AC_CHECK_PROG([BREW],brew, brew) if test x$BREW = xbrew; then - dnl add default homebrew paths - openssl_prefix=`$BREW --prefix openssl` - bdb_prefix=`$BREW --prefix berkeley-db4` - export PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" - CPPFLAGS="$CPPFLAGS -I$bdb_prefix/include" - LIBS="$LIBS -L$bdb_prefix/lib" + dnl These Homebrew packages may be bottled, meaning that they won't be found + dnl in expected paths because they may conflict with system files. Ask + dnl Homebrew where each one is located, then adjust paths accordingly. + dnl It's safe to add these paths even if the functionality is disabled by + dnl the user (--without-wallet or --without-gui for example). + + openssl_prefix=`$BREW --prefix openssl 2>/dev/null` + bdb_prefix=`$BREW --prefix berkeley-db4 2>/dev/null` + qt5_prefix=`$BREW --prefix qt5 2>/dev/null` + if test x$openssl_prefix != x; then + export PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" + fi + if test x$bdb_prefix != x; then + CPPFLAGS="$CPPFLAGS -I$bdb_prefix/include" + LIBS="$LIBS -L$bdb_prefix/lib" + fi + if test x$qt5_prefix != x; then + export PKG_CONFIG_PATH="$qt5_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" + fi fi else case $build_os in @@ -793,7 +806,7 @@ AC_SUBST(BUILD_TEST) AC_SUBST(BUILD_QT) AC_SUBST(BUILD_TEST_QT) AC_SUBST(MINIUPNPC_CPPFLAGS) -AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist]) +AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/build-tests.sh],[chmod +x qa/pull-tester/build-tests.sh]) AC_OUTPUT diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index 5ab6a222dd..541136001f 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -283,8 +283,8 @@ def copyFramework(framework, path, verbose): if not framework.isDylib(): # Copy resources for real frameworks - linkfrom = os.path.join(path, "Contents/Frameworks/", framework.frameworkName, framework.binaryName) - linkto = os.path.join(framework.binaryPath) + linkfrom = os.path.join(path, "Contents","Frameworks", framework.frameworkName, "Versions", "Current") + linkto = framework.version if not os.path.exists(linkfrom): os.symlink(linkto, linkfrom) if verbose >= 2: @@ -292,7 +292,7 @@ def copyFramework(framework, path, verbose): fromResourcesDir = framework.sourceResourcesDirectory if os.path.exists(fromResourcesDir): toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory) - shutil.copytree(fromResourcesDir, toResourcesDir) + shutil.copytree(fromResourcesDir, toResourcesDir, symlinks=True) if verbose >= 3: print "Copied resources:", fromResourcesDir print " to:", toResourcesDir @@ -301,13 +301,8 @@ def copyFramework(framework, path, verbose): fromContentsDir = framework.sourceContentsDirectory if os.path.exists(fromContentsDir): toContentsDir = os.path.join(path, framework.destinationVersionContentsDirectory) - shutil.copytree(fromContentsDir, toContentsDir) + shutil.copytree(fromContentsDir, toContentsDir, symlinks=True) contentslinkfrom = os.path.join(path, framework.destinationContentsDirectory) - if not os.path.exists(contentslinkfrom): - contentslinkto = os.path.join("Versions/", framework.version, "Contents") - os.symlink(contentslinkto, contentslinkfrom) - if verbose >= 3: - print "Linked:", contentslinkfrom, "->", contentslinkto if verbose >= 3: print "Copied Contents:", fromContentsDir print " to:", toContentsDir @@ -315,7 +310,7 @@ def copyFramework(framework, path, verbose): qtMenuNibSourcePath = os.path.join(framework.frameworkDirectory, "Resources", "qt_menu.nib") qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib") if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath): - shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath) + shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath, symlinks=True) if verbose >= 3: print "Copied for libQtGui:", qtMenuNibSourcePath print " to:", qtMenuNibDestinationPath @@ -398,7 +393,7 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose): # Deploy the script plugins only if QtScript is in use if not deploymentInfo.usesFramework("QtScript"): continue - elif pluginDirectory == "qmltooling": + elif pluginDirectory == "qmltooling" or pluginDirectory == "qml1tooling": # Deploy the qml plugins only if QtDeclarative is in use if not deploymentInfo.usesFramework("QtDeclarative"): continue @@ -406,7 +401,23 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose): # Deploy the bearer plugins only if QtNetwork is in use if not deploymentInfo.usesFramework("QtNetwork"): continue - + elif pluginDirectory == "position": + # Deploy the position plugins only if QtPositioning is in use + if not deploymentInfo.usesFramework("QtPositioning"): + continue + elif pluginDirectory == "sensors" or pluginDirectory == "sensorgestures": + # Deploy the sensor plugins only if QtSensors is in use + if not deploymentInfo.usesFramework("QtSensors"): + continue + elif pluginDirectory == "audio" or pluginDirectory == "playlistformats": + # Deploy the audio plugins only if QtMultimedia is in use + if not deploymentInfo.usesFramework("QtMultimedia"): + continue + elif pluginDirectory == "mediaservice": + # Deploy the mediaservice plugins only if QtMultimediaWidgets is in use + if not deploymentInfo.usesFramework("QtMultimediaWidgets"): + continue + for pluginName in filenames: pluginPath = os.path.join(pluginDirectory, pluginName) if pluginName.endswith("_debug.dylib"): @@ -424,7 +435,11 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose): # Deploy the opengl graphicssystem plugin only if QtOpenGL is in use if not deploymentInfo.usesFramework("QtOpenGL"): continue - + elif pluginPath == "accessible/libqtaccessiblequick.dylib": + # Deploy the accessible qtquick plugin only if QtQuick is in use + if not deploymentInfo.usesFramework("QtQuick"): + continue + plugins.append((pluginDirectory, pluginName)) for pluginDirectory, pluginName in plugins: @@ -589,7 +604,7 @@ if verbose >= 3: print app_bundle, "->", target os.mkdir("dist") -shutil.copytree(app_bundle, target) +shutil.copytree(app_bundle, target, symlinks=True) applicationBundle = ApplicationBundleInfo(target) @@ -676,7 +691,7 @@ for p in config.add_resources: if verbose >= 3: print p, "->", t if os.path.isdir(p): - shutil.copytree(p, t) + shutil.copytree(p, t, symlinks=True) else: shutil.copy2(p, t) diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index 503409c5e5..f39925723b 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -6,7 +6,7 @@ $(package)_sha256_hash=12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b857327 $(package)_build_subdir=build_unix define $(package)_set_vars -$(package)_config_opts=--disable-shared --enable-cxx +$(package)_config_opts=--disable-shared --enable-cxx --disable-replication $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_x86_64_linux=--with-pic $(package)_config_opts_arm_linux=--with-pic diff --git a/depends/packages/native_comparisontool.mk b/depends/packages/native_comparisontool.mk index d9f7722190..4c40f8b123 100644 --- a/depends/packages/native_comparisontool.mk +++ b/depends/packages/native_comparisontool.mk @@ -1,8 +1,8 @@ package=native_comparisontool -$(package)_version=adfd3de7 -$(package)_download_path=https://github.com/TheBlueMatt/test-scripts/raw/10222bfdace65a0c5f3bd4a766eeb6b3a8b869fb/ +$(package)_version=5caed78 +$(package)_download_path=https://github.com/TheBlueMatt/test-scripts/raw/2d76ce92d68e6746988adde731318605a70e252c $(package)_file_name=pull-tests-$($(package)_version).jar -$(package)_sha256_hash=fd2282b112e35f339dbe3729b08a04834ad719f8c9c10eeec1178465e6d36a18 +$(package)_sha256_hash=b55a98828b17060e327c5dabe5e4631898f422c0cba07c46170930a9eaf5e7c0 $(package)_install_dirname=BitcoindComparisonTool_jar $(package)_install_filename=BitcoindComparisonTool.jar diff --git a/doc/build-osx.md b/doc/build-osx.md index 0364d3a01b..dc55f8259e 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -81,6 +81,10 @@ After exiting, you'll get a warning that the install is keg-only, which means it make check +4. (Optional) You can also install bitcoind to your path: + + make install + Creating a release build ------------------------ You can ignore this section if you are building `bitcoind` for your own use. diff --git a/doc/build-unix.md b/doc/build-unix.md index 8a76a8b2cd..fb5eaec431 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -15,9 +15,12 @@ the usage of the absolute path. To Build --------------------- - ./autogen.sh - ./configure - make +```bash +./autogen.sh +./configure +make +make install # optional +``` This will build bitcoin-qt as well if the dependencies are met. @@ -63,7 +66,7 @@ Build requirements: sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev -for Ubuntu 12.04 and later: +for Ubuntu 12.04 and later or Debian 7 and later libboost-all-dev has to be installed: sudo apt-get install libboost-all-dev diff --git a/doc/init.md b/doc/init.md index 3d14025ab4..1f0559d806 100644 --- a/doc/init.md +++ b/doc/init.md @@ -4,10 +4,10 @@ Sample init scripts and service configuration for bitcoind Sample scripts and configuration files for systemd, Upstart and OpenRC can be found in the contrib/init folder. -contrib/init/bitcoind.service: systemd service unit configuration -contrib/init/bitcoind.openrc: OpenRC compatible SysV style init script -contrib/init/bitcoind.openrcconf: OpenRC conf.d file -contrib/init/bitcoind.conf: Upstart service configuration file + contrib/init/bitcoind.service: systemd service unit configuration + contrib/init/bitcoind.openrc: OpenRC compatible SysV style init script + contrib/init/bitcoind.openrcconf: OpenRC conf.d file + contrib/init/bitcoind.conf: Upstart service configuration file 1. Service User --------------------------------- diff --git a/doc/release-process.md b/doc/release-process.md index 940f934baf..7699af90bd 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -154,6 +154,10 @@ repackage gitian builds for release as stand-alone zip/tar/installer exe zip -r bitcoin-${VERSION}-win.zip bitcoin-${VERSION}-win rm -rf bitcoin-${VERSION}-win +**Mac OS X .dmg:** + + mv Bitcoin-Qt.dmg bitcoin-${VERSION}-osx.dmg + ###Next steps: Commit your signature to gitian.sigs: diff --git a/qa/pull-tester/run-bitcoind-for-test.sh.in b/qa/pull-tester/run-bitcoind-for-test.sh.in index 67318e5a4c..210fc3c42f 100755 --- a/qa/pull-tester/run-bitcoind-for-test.sh.in +++ b/qa/pull-tester/run-bitcoind-for-test.sh.in @@ -29,4 +29,8 @@ fi kill $BITCOIND && wait $BITCOIND # timeout returns 124 on timeout, otherwise the return value of the child + +# If $RETURN is not 0, the test failed. Dump the tail of the debug log. +if [ $RETURN -ne 0 ]; then tail -n 200 $DATADIR/regtest/debug.log; fi + exit $RETURN diff --git a/src/Makefile.am b/src/Makefile.am index 2c64cb74a0..bd6f1ba0d5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,6 +65,7 @@ BITCOIN_CORE_H = \ addrman.h \ alert.h \ allocators.h \ + amount.h \ base58.h \ bloom.h \ chain.h \ diff --git a/src/amount.h b/src/amount.h new file mode 100644 index 0000000000..831fa1f6ca --- /dev/null +++ b/src/amount.h @@ -0,0 +1,13 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_AMOUNT_H +#define BITCOIN_AMOUNT_H + +#include <stdint.h> + +typedef int64_t CAmount; + +#endif // BITCOIN_AMOUNT_H diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index b6e7a6c540..a61b4fe29d 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -214,7 +214,7 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput) // extract and validate VALUE string strValue = strInput.substr(0, pos); - int64_t value; + CAmount value; if (!ParseMoney(strValue, value)) throw runtime_error("invalid TX output value"); @@ -242,7 +242,7 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput // extract and validate VALUE string strValue = strInput.substr(0, pos); - int64_t value; + CAmount value; if (!ParseMoney(strValue, value)) throw runtime_error("invalid TX output value"); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 179db5a818..31c67715c8 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -115,6 +115,7 @@ public: fAllowMinDifficultyBlocks = false; fRequireStandard = true; fMineBlocksOnDemand = false; + fSkipProofOfWorkCheck = false; } }; static CMainParams mainParams; @@ -214,8 +215,46 @@ public: }; static CRegTestParams regTestParams; +// +// Unit test +// +class CUnitTestParams : public CMainParams, public CModifiableParams { +public: + CUnitTestParams() { + networkID = CBaseChainParams::UNITTEST; + strNetworkID = "unittest"; + nDefaultPort = 18445; + vFixedSeeds.clear(); + vSeeds.clear(); // Regtest mode doesn't have any DNS seeds. + + fRequireRPCPassword = false; + fMiningRequiresPeers = false; + fDefaultCheckMemPool = true; + fAllowMinDifficultyBlocks = false; + fMineBlocksOnDemand = true; + } +public: + // Published setters to allow changing values in unit test cases + virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) { nSubsidyHalvingInterval=anSubsidyHalvingInterval; } + virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority) { nEnforceBlockUpgradeMajority=anEnforceBlockUpgradeMajority; } + virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority) { nRejectBlockOutdatedMajority=anRejectBlockOutdatedMajority; } + virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority) { nToCheckBlockUpgradeMajority=anToCheckBlockUpgradeMajority; } + virtual void setDefaultCheckMemPool(bool afDefaultCheckMemPool) { fDefaultCheckMemPool=afDefaultCheckMemPool; } + virtual void setAllowMinDifficultyBlocks(bool afAllowMinDifficultyBlocks) { fAllowMinDifficultyBlocks=afAllowMinDifficultyBlocks; } + virtual void setSkipProofOfWorkCheck(bool afSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = afSkipProofOfWorkCheck; } +}; +static CUnitTestParams unitTestParams; + + static CChainParams *pCurrentParams = 0; +CModifiableParams *ModifiableParams() +{ + assert(pCurrentParams); + assert(pCurrentParams==&unitTestParams); + return (CModifiableParams*)&unitTestParams; +} + const CChainParams &Params() { assert(pCurrentParams); return *pCurrentParams; @@ -229,6 +268,8 @@ CChainParams &Params(CBaseChainParams::Network network) { return testNetParams; case CBaseChainParams::REGTEST: return regTestParams; + case CBaseChainParams::UNITTEST: + return unitTestParams; default: assert(false && "Unimplemented network"); return mainParams; diff --git a/src/chainparams.h b/src/chainparams.h index e5dfc87c6d..50441a89f3 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -61,6 +61,8 @@ public: bool DefaultCheckMemPool() const { return fDefaultCheckMemPool; } /* Allow mining of a min-difficulty block */ bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; } + /* Skip proof-of-work check: allow mining of any difficulty block */ + bool SkipProofOfWorkCheck() const { return fSkipProofOfWorkCheck; } /* Make standard checks */ bool RequireStandard() const { return fRequireStandard; } int64_t TargetTimespan() const { return nTargetTimespan; } @@ -103,8 +105,27 @@ protected: bool fAllowMinDifficultyBlocks; bool fRequireStandard; bool fMineBlocksOnDemand; + bool fSkipProofOfWorkCheck; }; +/** Modifiable parameters interface is used by test cases to adapt the parameters in order +*** to test specific features more easily. Test cases should always restore the previous +*** values after finalization. +**/ + +class CModifiableParams { +public: + // Published setters to allow changing values in unit test cases + virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) =0; + virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority)=0; + virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority)=0; + virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority)=0; + virtual void setDefaultCheckMemPool(bool aDefaultCheckMemPool)=0; + virtual void setAllowMinDifficultyBlocks(bool aAllowMinDifficultyBlocks)=0; + virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck)=0; +}; + + /** * Return the currently selected parameters. This won't change after app startup * outside of the unit tests. @@ -114,6 +135,9 @@ const CChainParams &Params(); /** Return parameters for the given network. */ CChainParams &Params(CBaseChainParams::Network network); +/** Get modifyable network parameters (UNITTEST only) */ +CModifiableParams *ModifiableParams(); + /** Sets the params returned by Params() to those for the given network. */ void SelectParams(CBaseChainParams::Network network); diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 98bb5b855f..e9d63197bd 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -57,6 +57,20 @@ public: }; static CBaseRegTestParams regTestParams; +// +// Unit test +// +class CBaseUnitTestParams : public CBaseMainParams +{ +public: + CBaseUnitTestParams() + { + networkID = CBaseChainParams::UNITTEST; + strDataDir = "unittest"; + } +}; +static CBaseUnitTestParams unitTestParams; + static CBaseChainParams* pCurrentBaseParams = 0; const CBaseChainParams& BaseParams() @@ -77,6 +91,9 @@ void SelectBaseParams(CBaseChainParams::Network network) case CBaseChainParams::REGTEST: pCurrentBaseParams = ®TestParams; break; + case CBaseChainParams::UNITTEST: + pCurrentBaseParams = &unitTestParams; + break; default: assert(false && "Unimplemented network"); return; diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index c054f03f17..cc154cf501 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -19,6 +19,7 @@ public: MAIN, TESTNET, REGTEST, + UNITTEST, MAX_NETWORK_TYPES }; diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index c41deea7ce..9a6bc05e63 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -88,6 +88,8 @@ namespace Checkpoints { return dataTestnet; else if (Params().NetworkID() == CBaseChainParams::MAIN) return data; + else if (Params().NetworkID() == CBaseChainParams::UNITTEST) // UnitTest share the same checkpoints as MAIN + return data; else return dataRegtest; } diff --git a/src/coins.cpp b/src/coins.cpp index 34485db2bd..9b8d63d4e4 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -171,12 +171,12 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const return coins->vout[input.prevout.n]; } -int64_t CCoinsViewCache::GetValueIn(const CTransaction& tx) const +CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const { if (tx.IsCoinBase()) return 0; - int64_t nResult = 0; + CAmount nResult = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) nResult += GetOutputFor(tx.vin[i]).nValue; diff --git a/src/coins.h b/src/coins.h index bf61f55aac..2583475323 100644 --- a/src/coins.h +++ b/src/coins.h @@ -266,7 +266,7 @@ struct CCoinsStats uint64_t nTransactionOutputs; uint64_t nSerializedSize; uint256 hashSerialized; - int64_t nTotalAmount; + CAmount nTotalAmount; CCoinsStats() : nHeight(0), hashBlock(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), hashSerialized(0), nTotalAmount(0) {} }; @@ -367,7 +367,7 @@ public: @param[in] tx transaction for which we are checking input total @return Sum of value of all inputs (scriptSigs) */ - int64_t GetValueIn(const CTransaction& tx) const; + CAmount GetValueIn(const CTransaction& tx) const; // Check whether all prevouts of the transaction are present in the UTXO set represented by this view bool HaveInputs(const CTransaction& tx) const; diff --git a/src/core.cpp b/src/core.cpp index e52327ba8e..380b1c38e0 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -43,7 +43,7 @@ std::string CTxIn::ToString() const return str; } -CTxOut::CTxOut(int64_t nValueIn, CScript scriptPubKeyIn) +CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn) { nValue = nValueIn; scriptPubKey = scriptPubKeyIn; @@ -59,7 +59,7 @@ std::string CTxOut::ToString() const return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30)); } -CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize) +CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize) { if (nSize > 0) nSatoshisPerK = nFeePaid*1000/nSize; @@ -67,9 +67,9 @@ CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize) nSatoshisPerK = 0; } -int64_t CFeeRate::GetFee(size_t nSize) const +CAmount CFeeRate::GetFee(size_t nSize) const { - int64_t nFee = nSatoshisPerK*nSize / 1000; + CAmount nFee = nSatoshisPerK*nSize / 1000; if (nFee == 0 && nSatoshisPerK > 0) nFee = nSatoshisPerK; @@ -110,9 +110,9 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) { return *this; } -int64_t CTransaction::GetValueOut() const +CAmount CTransaction::GetValueOut() const { - int64_t nValueOut = 0; + CAmount nValueOut = 0; BOOST_FOREACH(const CTxOut& txout, vout) { nValueOut += txout.nValue; @@ -224,29 +224,66 @@ uint256 CBlockHeader::GetHash() const return Hash(BEGIN(nVersion), END(nNonce)); } -uint256 CBlock::BuildMerkleTree() const +uint256 CBlock::BuildMerkleTree(bool* fMutated) const { - // WARNING! If you're reading this because you're learning about crypto - // and/or designing a new system that will use merkle trees, keep in mind - // that the following merkle tree algorithm has a serious flaw related to - // duplicate txids, resulting in a vulnerability. (CVE-2012-2459) Bitcoin - // has since worked around the flaw, but for new applications you should - // use something different; don't just copy-and-paste this code without - // understanding the problem first. + /* WARNING! If you're reading this because you're learning about crypto + and/or designing a new system that will use merkle trees, keep in mind + that the following merkle tree algorithm has a serious flaw related to + duplicate txids, resulting in a vulnerability (CVE-2012-2459). + + The reason is that if the number of hashes in the list at a given time + is odd, the last one is duplicated before computing the next level (which + is unusual in Merkle trees). This results in certain sequences of + transactions leading to the same merkle root. For example, these two + trees: + + A A + / \ / \ + B C B C + / \ | / \ / \ + D E F D E F F + / \ / \ / \ / \ / \ / \ / \ + 1 2 3 4 5 6 1 2 3 4 5 6 5 6 + + for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and + 6 are repeated) result in the same root hash A (because the hash of both + of (F) and (F,F) is C). + + The vulnerability results from being able to send a block with such a + transaction list, with the same merkle root, and the same block hash as + the original without duplication, resulting in failed validation. If the + receiving node proceeds to mark that block as permanently invalid + however, it will fail to accept further unmodified (and thus potentially + valid) versions of the same block. We defend against this by detecting + the case where we would hash two identical hashes at the end of the list + together, and treating that identically to the block having an invalid + merkle root. Assuming no double-SHA256 collisions, this will detect all + known ways of changing the transactions without affecting the merkle + root. + */ vMerkleTree.clear(); + vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. BOOST_FOREACH(const CTransaction& tx, vtx) vMerkleTree.push_back(tx.GetHash()); int j = 0; + bool mutated = false; for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) { for (int i = 0; i < nSize; i += 2) { int i2 = std::min(i+1, nSize-1); + if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) { + // Two identical hashes at the end of the list at a particular level. + mutated = true; + } vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); } j += nSize; } + if (fMutated) { + *fMutated = mutated; + } return (vMerkleTree.empty() ? 0 : vMerkleTree.back()); } diff --git a/src/core.h b/src/core.h index 9a2ac47487..a348293578 100644 --- a/src/core.h +++ b/src/core.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_CORE_H #define BITCOIN_CORE_H +#include "amount.h" #include "script/compressor.h" #include "script/script.h" #include "serialize.h" @@ -19,8 +20,8 @@ static const int64_t COIN = 100000000; static const int64_t CENT = 1000000; /** No amount larger than this (in satoshi) is valid */ -static const int64_t MAX_MONEY = 21000000 * COIN; -inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } +static const CAmount MAX_MONEY = 21000000 * COIN; +inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } /** An outpoint - a combination of a transaction hash and an index n into its vout */ class COutPoint @@ -129,15 +130,15 @@ public: class CFeeRate { private: - int64_t nSatoshisPerK; // unit is satoshis-per-1,000-bytes + CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes public: CFeeRate() : nSatoshisPerK(0) { } - explicit CFeeRate(int64_t _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } - CFeeRate(int64_t nFeePaid, size_t nSize); + explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } + CFeeRate(const CAmount& nFeePaid, size_t nSize); CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } - int64_t GetFee(size_t size) const; // unit returned is satoshis - int64_t GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes + CAmount GetFee(size_t size) const; // unit returned is satoshis + CAmount GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; } friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; } @@ -161,7 +162,7 @@ public: class CTxOut { public: - int64_t nValue; + CAmount nValue; CScript scriptPubKey; CTxOut() @@ -169,7 +170,7 @@ public: SetNull(); } - CTxOut(int64_t nValueIn, CScript scriptPubKeyIn); + CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn); ADD_SERIALIZE_METHODS; @@ -276,7 +277,7 @@ public: } // Return sum of txouts. - int64_t GetValueOut() const; + CAmount GetValueOut() const; // GetValueIn() is a method on CCoinsViewCache, because // inputs must be known to compute value in. @@ -528,7 +529,11 @@ public: return block; } - uint256 BuildMerkleTree() const; + // Build the in-memory merkle tree for this block and return the merkle root. + // If non-NULL, *mutated is set to whether mutation was detected in the merkle + // tree (a duplication of transactions in the block leading to an identical + // merkle root). + uint256 BuildMerkleTree(bool* mutated = NULL) const; std::vector<uint256> GetMerkleBranch(int nIndex) const; static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex); diff --git a/src/init.cpp b/src/init.cpp index 85f4d360d2..980c589b29 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -45,7 +45,7 @@ using namespace boost; using namespace std; #ifdef ENABLE_WALLET -CWallet* pwalletMain; +CWallet* pwalletMain = NULL; #endif #ifdef WIN32 @@ -109,7 +109,7 @@ bool ShutdownRequested() return fRequestShutdown; } -static CCoinsViewDB *pcoinsdbview; +static CCoinsViewDB *pcoinsdbview = NULL; void Shutdown() { @@ -165,8 +165,8 @@ void Shutdown() #endif UnregisterAllWallets(); #ifdef ENABLE_WALLET - if (pwalletMain) - delete pwalletMain; + delete pwalletMain; + pwalletMain = NULL; #endif LogPrintf("%s: done\n", __func__); } @@ -662,7 +662,7 @@ bool AppInit2(boost::thread_group& threadGroup) // cost to you of processing a transaction. if (mapArgs.count("-minrelaytxfee")) { - int64_t n = 0; + CAmount n = 0; if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0) ::minRelayTxFee = CFeeRate(n); else @@ -672,7 +672,7 @@ bool AppInit2(boost::thread_group& threadGroup) #ifdef ENABLE_WALLET if (mapArgs.count("-mintxfee")) { - int64_t n = 0; + CAmount n = 0; if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) CWallet::minTxFee = CFeeRate(n); else @@ -680,7 +680,7 @@ bool AppInit2(boost::thread_group& threadGroup) } if (mapArgs.count("-paytxfee")) { - int64_t nFeePerK = 0; + CAmount nFeePerK = 0; if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"])); if (nFeePerK > nHighTransactionFeeWarning) @@ -701,6 +701,7 @@ bool AppInit2(boost::thread_group& threadGroup) fIsBareMultisigStd = GetArg("-permitbaremultisig", true) != 0; // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log + // Sanity check if (!InitSanityCheck()) return InitError(_("Initialization sanity check failed. Bitcoin Core is shutting down.")); diff --git a/src/main.cpp b/src/main.cpp index 9a4271eda2..83848bf849 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ #include "txmempool.h" #include "ui_interface.h" #include "util.h" +#include "utilmoneystr.h" #include <sstream> @@ -728,7 +729,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) REJECT_INVALID, "bad-txns-oversize"); // Check for negative or overflow output values - int64_t nValueOut = 0; + CAmount nValueOut = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { if (txout.nValue < 0) @@ -770,19 +771,19 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) return true; } -int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree) +CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree) { { LOCK(mempool.cs); uint256 hash = tx.GetHash(); double dPriorityDelta = 0; - int64_t nFeeDelta = 0; + CAmount nFeeDelta = 0; mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); if (dPriorityDelta > 0 || nFeeDelta > 0) return 0; } - int64_t nMinFee = ::minRelayTxFee.GetFee(nBytes); + CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes); if (fAllowFree) { @@ -845,7 +846,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa CCoinsView dummy; CCoinsViewCache view(dummy); - int64_t nValueIn = 0; + CAmount nValueIn = 0; { LOCK(pool.cs); CCoinsViewMemPool viewMemPool(*pcoinsTip, pool); @@ -897,15 +898,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa hash.ToString(), nSigOps, MAX_TX_SIGOPS), REJECT_NONSTANDARD, "bad-txns-too-many-sigops"); - int64_t nValueOut = tx.GetValueOut(); - int64_t nFees = nValueIn-nValueOut; + CAmount nValueOut = tx.GetValueOut(); + CAmount nFees = nValueIn-nValueOut; double dPriority = view.GetPriority(tx, chainActive.Height()); CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height()); unsigned int nSize = entry.GetTxSize(); // Don't accept it if it can't get into a block - int64_t txMinFee = GetMinRelayFee(tx, nSize, true); + CAmount txMinFee = GetMinRelayFee(tx, nSize, true); if (fLimitFree && nFees < txMinFee) return state.DoS(0, error("AcceptToMemoryPool : not enough fees %s, %d < %d", hash.ToString(), nFees, txMinFee), @@ -1125,7 +1126,7 @@ void static PruneOrphanBlocks() mapOrphanBlocks.erase(hash); } -int64_t GetBlockValue(int nHeight, int64_t nFees) +CAmount GetBlockValue(int nHeight, const CAmount& nFees) { int64_t nSubsidy = 50 * COIN; int halvings = nHeight / Params().SubsidyHalvingInterval(); @@ -1316,7 +1317,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach bool CScriptCheck::operator()() const { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; if (!VerifyScript(scriptSig, scriptPubKey, *ptxTo, nIn, nFlags)) - return error("CScriptCheck() : %s VerifySignature failed", ptxTo->GetHash().ToString()); + return error("CScriptCheck() : %s:%d VerifySignature failed", ptxTo->GetHash().ToString(), nIn); return true; } @@ -1336,8 +1337,8 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // This is also true for mempool checks. CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; int nSpendHeight = pindexPrev->nHeight + 1; - int64_t nValueIn = 0; - int64_t nFees = 0; + CAmount nValueIn = 0; + CAmount nFees = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { const COutPoint &prevout = tx.vin[i].prevout; @@ -1361,11 +1362,12 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi } if (nValueIn < tx.GetValueOut()) - return state.DoS(100, error("CheckInputs() : %s value in < value out", tx.GetHash().ToString()), + return state.DoS(100, error("CheckInputs() : %s value in (%s) < value out (%s)", + tx.GetHash().ToString(), FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())), REJECT_INVALID, "bad-txns-in-belowout"); // Tally transaction fees - int64_t nTxFee = nValueIn - tx.GetValueOut(); + CAmount nTxFee = nValueIn - tx.GetValueOut(); if (nTxFee < 0) return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString()), REJECT_INVALID, "bad-txns-fee-negative"); @@ -1605,7 +1607,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL); int64_t nTimeStart = GetTimeMicros(); - int64_t nFees = 0; + CAmount nFees = 0; int nInputs = 0; unsigned int nSigOps = 0; CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); @@ -2236,13 +2238,12 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo if (!CheckTransaction(tx, state)) return error("CheckBlock() : CheckTransaction failed"); - // Check for duplicate txids. This is caught by ConnectInputs(), - // but catching it earlier avoids a potential DoS attack: - set<uint256> uniqueTx; - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - uniqueTx.insert(tx.GetHash()); - } - if (uniqueTx.size() != block.vtx.size()) + // Check for merkle tree malleability (CVE-2012-2459): repeating sequences + // of transactions in a block without affecting the merkle root of a block, + // while still invalidating it. + bool mutated; + uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); + if (mutated) return state.DoS(100, error("CheckBlock() : duplicate transaction"), REJECT_INVALID, "bad-txns-duplicate", true); @@ -2256,7 +2257,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo REJECT_INVALID, "bad-blk-sigops", true); // Check merkle root - if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree()) + if (fCheckMerkleRoot && block.hashMerkleRoot != hashMerkleRoot2) return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"), REJECT_INVALID, "bad-txnmrklroot", true); @@ -2273,7 +2274,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex if (miSelf != mapBlockIndex.end()) { pindex = miSelf->second; if (pindex->nStatus & BLOCK_FAILED_MASK) - return state.Invalid(error("AcceptBlock() : block is marked invalid"), 0, "duplicate"); + return state.Invalid(error("%s : block is marked invalid", __func__), 0, "duplicate"); } CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); @@ -2283,12 +2284,12 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex int64_t deltaTime = block.GetBlockTime() - pcheckpoint->GetBlockTime(); if (deltaTime < 0) { - return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), + return state.DoS(100, error("%s : block with timestamp before last checkpoint", __func__), REJECT_CHECKPOINT, "time-too-old"); } if (!CheckMinWork(block.nBits, pcheckpoint->nBits, deltaTime)) { - return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"), + return state.DoS(100, error("%s : block with too little proof-of-work", __func__), REJECT_INVALID, "bad-diffbits"); } } @@ -2299,35 +2300,36 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex if (hash != Params().HashGenesisBlock()) { BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); if (mi == mapBlockIndex.end()) - return state.DoS(10, error("AcceptBlock() : prev block not found"), 0, "bad-prevblk"); + return state.DoS(10, error("%s : prev block not found", __func__), 0, "bad-prevblk"); pindexPrev = (*mi).second; nHeight = pindexPrev->nHeight+1; // Check proof of work - if (block.nBits != GetNextWorkRequired(pindexPrev, &block)) - return state.DoS(100, error("AcceptBlock() : incorrect proof of work"), + if ((!Params().SkipProofOfWorkCheck()) && + (block.nBits != GetNextWorkRequired(pindexPrev, &block))) + return state.DoS(100, error("%s : incorrect proof of work", __func__), REJECT_INVALID, "bad-diffbits"); // Check timestamp against prev if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) - return state.Invalid(error("AcceptBlock() : block's timestamp is too early"), + return state.Invalid(error("%s : block's timestamp is too early", __func__), REJECT_INVALID, "time-too-old"); // Check that the block chain matches the known block chain up to a checkpoint if (!Checkpoints::CheckBlock(nHeight, hash)) - return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight), + return state.DoS(100, error("%s : rejected by checkpoint lock-in at %d", __func__, nHeight), REJECT_CHECKPOINT, "checkpoint mismatch"); // Don't accept any forks from the main chain prior to last checkpoint CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); if (pcheckpoint && nHeight < pcheckpoint->nHeight) - return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight)); + return state.DoS(100, error("%s : forked chain older than last checkpoint (height %d)", __func__, nHeight)); // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: if (block.nVersion < 2 && CBlockIndex::IsSuperMajority(2, pindexPrev, Params().RejectBlockOutdatedMajority())) { - return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"), + return state.Invalid(error("%s : rejected nVersion=1 block", __func__), REJECT_OBSOLETE, "bad-version"); } } @@ -3083,6 +3085,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) int nLoaded = 0; try { + // This takes over fileIn and calls fclose() on it in the CBufferedFile destructor CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION); uint64_t nStartByte = 0; if (dbp) { @@ -3139,7 +3142,6 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) LogPrintf("%s : Deserialize or I/O error - %s", __func__, e.what()); } } - fclose(fileIn); } catch(std::runtime_error &e) { AbortNode(_("Error: system error: ") + e.what()); } diff --git a/src/main.h b/src/main.h index c75841538f..7e849505dd 100644 --- a/src/main.h +++ b/src/main.h @@ -172,7 +172,7 @@ std::string GetWarnings(std::string strFor); bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL); -int64_t GetBlockValue(int nHeight, int64_t nFees); +CAmount GetBlockValue(int nHeight, const CAmount& nFees); /** Create a new block index entry for a given block hash */ CBlockIndex * InsertBlockIndex(uint256 hash); @@ -220,7 +220,7 @@ struct CDiskTxPos : public CDiskBlockPos }; -int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); +CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); // // Check transaction inputs, and make sure any @@ -591,7 +591,7 @@ extern CBlockTreeDB *pblocktree; struct CBlockTemplate { CBlock block; - std::vector<int64_t> vTxFees; + std::vector<CAmount> vTxFees; std::vector<int64_t> vTxSigOps; }; diff --git a/src/miner.cpp b/src/miner.cpp index d05ddbeb1f..361a2bea41 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -111,7 +111,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); // Collect memory pool transactions into the block - int64_t nFees = 0; + CAmount nFees = 0; { LOCK2(cs_main, mempool.cs); @@ -135,7 +135,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) COrphan* porphan = NULL; double dPriority = 0; - int64_t nTotalIn = 0; + CAmount nTotalIn = 0; bool fMissingInputs = false; BOOST_FOREACH(const CTxIn& txin, tx.vin) { @@ -170,7 +170,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) const CCoins* coins = view.AccessCoins(txin.prevout.hash); assert(coins); - int64_t nValueIn = coins->vout[txin.prevout.n].nValue; + CAmount nValueIn = coins->vout[txin.prevout.n].nValue; nTotalIn += nValueIn; int nConf = pindexPrev->nHeight - coins->nHeight + 1; @@ -229,7 +229,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // Skip free transactions if we're past the minimum block size: const uint256& hash = tx.GetHash(); double dPriorityDelta = 0; - int64_t nFeeDelta = 0; + CAmount nFeeDelta = 0; mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) continue; @@ -247,7 +247,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (!view.HaveInputs(tx)) continue; - int64_t nTxFees = view.GetValueIn(tx)-tx.GetValueOut(); + CAmount nTxFees = view.GetValueIn(tx)-tx.GetValueOut(); nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) diff --git a/src/pow.cpp b/src/pow.cpp index 893f6c18be..d50222849c 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -81,6 +81,10 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) bool fNegative; bool fOverflow; uint256 bnTarget; + + if (Params().SkipProofOfWorkCheck()) + return true; + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range diff --git a/src/protocol.cpp b/src/protocol.cpp index 341de0602a..0e28f3abbd 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -24,7 +24,6 @@ CMessageHeader::CMessageHeader() { memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE); memset(pchCommand, 0, sizeof(pchCommand)); - pchCommand[1] = 1; nMessageSize = -1; nChecksum = 0; } @@ -32,6 +31,7 @@ CMessageHeader::CMessageHeader() CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) { memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE); + memset(pchCommand, 0, sizeof(pchCommand)); strncpy(pchCommand, pszCommand, COMMAND_SIZE); nMessageSize = nMessageSizeIn; nChecksum = 0; @@ -39,10 +39,7 @@ CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSize std::string CMessageHeader::GetCommand() const { - if (pchCommand[COMMAND_SIZE-1] == 0) - return std::string(pchCommand, pchCommand + strlen(pchCommand)); - else - return std::string(pchCommand, pchCommand + COMMAND_SIZE); + return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE)); } bool CMessageHeader::IsValid() const diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index bd686041c1..5e2fdc6c30 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -73,6 +73,7 @@ Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin); // Declare meta types used for QMetaObject::invokeMethod Q_DECLARE_METATYPE(bool*) +Q_DECLARE_METATYPE(CAmount) static void InitMessage(const std::string &message) { @@ -509,6 +510,9 @@ int main(int argc, char *argv[]) // Register meta types used for QMetaObject::invokeMethod qRegisterMetaType< bool* >(); + // Need to pass name here as CAmount is a typedef (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType) + // IMPORTANT if it is no longer a typedef use the normal variant above + qRegisterMetaType< CAmount >("CAmount"); /// 3. Application identification // must be set before OptionsModel is initialized or translations are loaded, diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index 6466039013..6e35bf17b3 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -44,7 +44,7 @@ public: void fixup(QString &input) const { bool valid = false; - qint64 val = parse(input, &valid); + CAmount val = parse(input, &valid); if(valid) { input = BitcoinUnits::format(currentUnit, val, false, BitcoinUnits::separatorAlways); @@ -52,12 +52,12 @@ public: } } - qint64 value(bool *valid_out=0) const + CAmount value(bool *valid_out=0) const { return parse(text(), valid_out); } - void setValue(qint64 value) + void setValue(const CAmount& value) { lineEdit()->setText(BitcoinUnits::format(currentUnit, value, false, BitcoinUnits::separatorAlways)); emit valueChanged(); @@ -66,9 +66,9 @@ public: void stepBy(int steps) { bool valid = false; - qint64 val = value(&valid); + CAmount val = value(&valid); val = val + steps * singleStep; - val = qMin(qMax(val, Q_INT64_C(0)), BitcoinUnits::maxMoney()); + val = qMin(qMax(val, CAmount(0)), BitcoinUnits::maxMoney()); setValue(val); } @@ -78,7 +78,7 @@ public: if(text().isEmpty()) // Allow step-up with empty field return StepUpEnabled; bool valid = false; - qint64 val = value(&valid); + CAmount val = value(&valid); if(valid) { if(val > 0) @@ -92,7 +92,7 @@ public: void setDisplayUnit(int unit) { bool valid = false; - qint64 val = value(&valid); + CAmount val = value(&valid); currentUnit = unit; @@ -102,7 +102,7 @@ public: clear(); } - void setSingleStep(qint64 step) + void setSingleStep(const CAmount& step) { singleStep = step; } @@ -140,7 +140,7 @@ public: } private: int currentUnit; - qint64 singleStep; + CAmount singleStep; mutable QSize cachedMinimumSizeHint; /** @@ -148,9 +148,9 @@ private: * return validity. * @note Must return 0 if !valid. */ - qint64 parse(const QString &text, bool *valid_out=0) const + CAmount parse(const QString &text, bool *valid_out=0) const { - qint64 val = 0; + CAmount val = 0; bool valid = BitcoinUnits::parse(currentUnit, text, &val); if(valid) { @@ -253,12 +253,12 @@ QWidget *BitcoinAmountField::setupTabChain(QWidget *prev) return unit; } -qint64 BitcoinAmountField::value(bool *valid_out) const +CAmount BitcoinAmountField::value(bool *valid_out) const { return amount->value(valid_out); } -void BitcoinAmountField::setValue(qint64 value) +void BitcoinAmountField::setValue(const CAmount& value) { amount->setValue(value); } @@ -285,7 +285,7 @@ void BitcoinAmountField::setDisplayUnit(int newUnit) unit->setValue(newUnit); } -void BitcoinAmountField::setSingleStep(qint64 step) +void BitcoinAmountField::setSingleStep(const CAmount& step) { amount->setSingleStep(step); } diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index 84795a7e7a..e52feeb46e 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -5,6 +5,8 @@ #ifndef BITCOINAMOUNTFIELD_H #define BITCOINAMOUNTFIELD_H +#include "amount.h" + #include <QWidget> class AmountSpinBox; @@ -19,16 +21,16 @@ class BitcoinAmountField: public QWidget { Q_OBJECT - Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY valueChanged USER true) + Q_PROPERTY(CAmount value READ value WRITE setValue NOTIFY valueChanged USER true) public: explicit BitcoinAmountField(QWidget *parent = 0); - qint64 value(bool *valid=0) const; - void setValue(qint64 value); + CAmount value(bool *value=0) const; + void setValue(const CAmount& value); /** Set single step in satoshis **/ - void setSingleStep(qint64 step); + void setSingleStep(const CAmount& step); /** Make read-only **/ void setReadOnly(bool fReadOnly); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 443bed14d7..7380fbd240 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -864,7 +864,7 @@ void BitcoinGUI::closeEvent(QCloseEvent *event) } #ifdef ENABLE_WALLET -void BitcoinGUI::incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address) +void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address) { // On new transaction, make an info balloon message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"), diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 30b05cb7d9..8af6eda867 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -9,6 +9,8 @@ #include "config/bitcoin-config.h" #endif +#include "amount.h" + #include <QLabel> #include <QMainWindow> #include <QMap> @@ -159,7 +161,7 @@ public slots: bool handlePaymentRequest(const SendCoinsRecipient& recipient); /** Show incoming transaction notification for new transactions. */ - void incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address); + void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address); #endif private slots: diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index 3215363fa0..423b559bf7 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -91,12 +91,13 @@ int BitcoinUnits::decimals(int unit) } } -QString BitcoinUnits::format(int unit, qint64 n, bool fPlus, SeparatorStyle separators) +QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators) { // Note: not using straight sprintf here because we do NOT want // localized number formatting. if(!valid(unit)) return QString(); // Refuse to format invalid unit + qint64 n = (qint64)nIn; qint64 coin = factor(unit); int num_decimals = decimals(unit); qint64 n_abs = (n > 0 ? n : -n); @@ -138,12 +139,12 @@ QString BitcoinUnits::format(int unit, qint64 n, bool fPlus, SeparatorStyle sepa // Please take care to use formatHtmlWithUnit instead, when // appropriate. -QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign, SeparatorStyle separators) +QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators) { return format(unit, amount, plussign, separators) + QString(" ") + name(unit); } -QString BitcoinUnits::formatHtmlWithUnit(int unit, qint64 amount, bool plussign, SeparatorStyle separators) +QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators) { QString str(formatWithUnit(unit, amount, plussign, separators)); str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML)); @@ -151,7 +152,7 @@ QString BitcoinUnits::formatHtmlWithUnit(int unit, qint64 amount, bool plussign, } -bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out) +bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out) { if(!valid(unit) || value.isEmpty()) return false; // Refuse to parse invalid unit or empty string @@ -182,7 +183,7 @@ bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out) { return false; // Longer numbers will exceed 63 bits } - qint64 retvalue = str.toLongLong(&ok); + CAmount retvalue(str.toLongLong(&ok)); if(val_out) { *val_out = retvalue; @@ -226,7 +227,7 @@ QVariant BitcoinUnits::data(const QModelIndex &index, int role) const return QVariant(); } -qint64 BitcoinUnits::maxMoney() +CAmount BitcoinUnits::maxMoney() { return MAX_MONEY; } diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h index be9dca6012..a392c42b9b 100644 --- a/src/qt/bitcoinunits.h +++ b/src/qt/bitcoinunits.h @@ -5,6 +5,8 @@ #ifndef BITCOINUNITS_H #define BITCOINUNITS_H +#include "amount.h" + #include <QAbstractListModel> #include <QString> @@ -85,12 +87,12 @@ public: //! Number of decimals left static int decimals(int unit); //! Format as string - static QString format(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard); + static QString format(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard); //! Format as string (with unit) - static QString formatWithUnit(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard); - static QString formatHtmlWithUnit(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard); + static QString formatWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard); + static QString formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard); //! Parse string to coin amount - static bool parse(int unit, const QString &value, qint64 *val_out); + static bool parse(int unit, const QString &value, CAmount *val_out); //! Gets title for amount column including current display unit if optionsModel reference available */ static QString getAmountColumnTitle(int unit); ///@} @@ -117,7 +119,7 @@ public: } //! Return maximum number of base units (Satoshis) - static qint64 maxMoney(); + static CAmount maxMoney(); private: QList<BitcoinUnits::Unit> unitlist; diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index d10463fd8f..ba0febe546 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -29,7 +29,7 @@ #include <QTreeWidgetItem> using namespace std; -QList<qint64> CoinControlDialog::payAmounts; +QList<CAmount> CoinControlDialog::payAmounts; CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); CoinControlDialog::CoinControlDialog(QWidget *parent) : @@ -443,10 +443,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) return; // nPayAmount - qint64 nPayAmount = 0; + CAmount nPayAmount = 0; bool fDust = false; CMutableTransaction txDummy; - foreach(const qint64 &amount, CoinControlDialog::payAmounts) + foreach(const CAmount &amount, CoinControlDialog::payAmounts) { nPayAmount += amount; @@ -460,10 +460,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) } QString sPriorityLabel = tr("none"); - int64_t nAmount = 0; - int64_t nPayFee = 0; - int64_t nAfterFee = 0; - int64_t nChange = 0; + CAmount nAmount = 0; + CAmount nPayFee = 0; + CAmount nAfterFee = 0; + CAmount nChange = 0; unsigned int nBytes = 0; unsigned int nBytesInputs = 0; double dPriority = 0; @@ -684,7 +684,7 @@ void CoinControlDialog::updateView() itemWalletAddress->setText(COLUMN_ADDRESS, sWalletAddress); } - int64_t nSum = 0; + CAmount nSum = 0; double dPrioritySum = 0; int nChildren = 0; int nInputSum = 0; diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index a6f239a898..9eaa8eb41d 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -5,6 +5,8 @@ #ifndef COINCONTROLDIALOG_H #define COINCONTROLDIALOG_H +#include "amount.h" + #include <QAbstractButton> #include <QAction> #include <QDialog> @@ -37,7 +39,7 @@ public: static void updateLabels(WalletModel*, QDialog*); static QString getPriorityLabel(const CTxMemPool& pool, double); - static QList<qint64> payAmounts; + static QList<CAmount> payAmounts; static CCoinControl *coinControl; private: diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index fc22871a6b..91bb10755a 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -221,7 +221,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info) return ret; } -bool isDust(const QString& address, qint64 amount) +bool isDust(const QString& address, const CAmount& amount) { CTxDestination dest = CBitcoinAddress(address.toStdString()).Get(); CScript script = GetScriptForDestination(dest); diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 67e11e59a0..0939c78f64 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -5,6 +5,8 @@ #ifndef GUIUTIL_H #define GUIUTIL_H +#include "amount.h" + #include <QHeaderView> #include <QMessageBox> #include <QObject> @@ -46,7 +48,7 @@ namespace GUIUtil QString formatBitcoinURI(const SendCoinsRecipient &info); // Returns true if given address+amount meets "dust" definition - bool isDust(const QString& address, qint64 amount); + bool isDust(const QString& address, const CAmount& amount); // HTML escaping for rich text controls QString HtmlEscape(const QString& str, bool fMultiLine=false); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index bd747faeb6..cb80bd0e3d 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -275,9 +275,9 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in #ifdef ENABLE_WALLET case Fee: { // core option - can be changed on-the-fly // Todo: Add is valid check and warn via message, if not - qint64 nTransactionFee = value.toLongLong(); + CAmount nTransactionFee(value.toLongLong()); payTxFee = CFeeRate(nTransactionFee, 1000); - settings.setValue("nTransactionFee", nTransactionFee); + settings.setValue("nTransactionFee", qint64(nTransactionFee)); emit transactionFeeChanged(nTransactionFee); break; } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 80adab89c8..42ea3bf8e5 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -5,6 +5,8 @@ #ifndef OPTIONSMODEL_H #define OPTIONSMODEL_H +#include "amount.h" + #include <QAbstractListModel> QT_BEGIN_NAMESPACE @@ -82,7 +84,7 @@ private: signals: void displayUnitChanged(int unit); - void transactionFeeChanged(qint64); + void transactionFeeChanged(const CAmount&); void coinControlFeaturesChanged(bool); }; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 90762bea5d..669d5474fd 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -146,7 +146,7 @@ OverviewPage::~OverviewPage() delete ui; } -void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance) +void OverviewPage::setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance) { int unit = walletModel->getOptionsModel()->getDisplayUnit(); currentBalance = balance; @@ -220,7 +220,7 @@ void OverviewPage::setWalletModel(WalletModel *model) // Keep up to date with wallet setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64))); + connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index f46374efba..03f239008f 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -5,6 +5,8 @@ #ifndef OVERVIEWPAGE_H #define OVERVIEWPAGE_H +#include "amount.h" + #include <QWidget> class ClientModel; @@ -34,8 +36,8 @@ public: void showOutOfSyncWarning(bool fShow); public slots: - void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, - qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); + void setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, + const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); signals: void transactionClicked(const QModelIndex &index); @@ -44,12 +46,12 @@ private: Ui::OverviewPage *ui; ClientModel *clientModel; WalletModel *walletModel; - qint64 currentBalance; - qint64 currentUnconfirmedBalance; - qint64 currentImmatureBalance; - qint64 currentWatchOnlyBalance; - qint64 currentWatchUnconfBalance; - qint64 currentWatchImmatureBalance; + CAmount currentBalance; + CAmount currentUnconfirmedBalance; + CAmount currentImmatureBalance; + CAmount currentWatchOnlyBalance; + CAmount currentWatchUnconfBalance; + CAmount currentWatchImmatureBalance; TxViewDelegate *txdelegate; TransactionFilterProxy *filter; diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index 7b7de49831..7aefffe24a 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -196,9 +196,9 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c return fResult; } -QList<std::pair<CScript,qint64> > PaymentRequestPlus::getPayTo() const +QList<std::pair<CScript,CAmount> > PaymentRequestPlus::getPayTo() const { - QList<std::pair<CScript,qint64> > result; + QList<std::pair<CScript,CAmount> > result; for (int i = 0; i < details.outputs_size(); i++) { const unsigned char* scriptStr = (const unsigned char*)details.outputs(i).script().data(); diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h index 3c4861a4d4..3d94d93269 100644 --- a/src/qt/paymentrequestplus.h +++ b/src/qt/paymentrequestplus.h @@ -33,7 +33,7 @@ public: bool getMerchant(X509_STORE* certStore, QString& merchant) const; // Returns list of outputs, amount - QList<std::pair<CScript,qint64> > getPayTo() const; + QList<std::pair<CScript,CAmount> > getPayTo() const; const payments::PaymentDetails& getDetails() const { return details; } diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index cc4478f39f..707de55290 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -532,10 +532,10 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins request.getMerchant(PaymentServer::certStore, recipient.authenticatedMerchant); - QList<std::pair<CScript, qint64> > sendingTos = request.getPayTo(); + QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo(); QStringList addresses; - foreach(const PAIRTYPE(CScript, qint64)& sendingTo, sendingTos) { + foreach(const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { // Extract and check destination addresses CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) { diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 25e3d2a0dc..ce94131cce 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -92,13 +92,13 @@ void SendCoinsDialog::setModel(WalletModel *model) setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64))); + connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); // Coin Control connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels())); connect(model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool))); - connect(model->getOptionsModel(), SIGNAL(transactionFeeChanged(qint64)), this, SLOT(coinControlUpdateLabels())); + connect(model->getOptionsModel(), SIGNAL(transactionFeeChanged(CAmount)), this, SLOT(coinControlUpdateLabels())); ui->frameCoinControl->setVisible(model->getOptionsModel()->getCoinControlFeatures()); coinControlUpdateLabels(); } @@ -203,7 +203,7 @@ void SendCoinsDialog::on_sendButton_clicked() return; } - qint64 txFee = currentTransaction.getTransactionFee(); + CAmount txFee = currentTransaction.getTransactionFee(); QString questionString = tr("Are you sure you want to send?"); questionString.append("<br /><br />%1"); @@ -218,7 +218,7 @@ void SendCoinsDialog::on_sendButton_clicked() // add total amount in all subdivision units questionString.append("<hr />"); - qint64 totalAmount = currentTransaction.getTotalTransactionAmount() + txFee; + CAmount totalAmount = currentTransaction.getTotalTransactionAmount() + txFee; QStringList alternativeUnits; foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) { @@ -384,8 +384,8 @@ bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) return true; } -void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, - qint64 watchBalance, qint64 watchUnconfirmedBalance, qint64 watchImmatureBalance) +void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, + const CAmount& watchBalance, const CAmount& watchUnconfirmedBalance, const CAmount& watchImmatureBalance) { Q_UNUSED(unconfirmedBalance); Q_UNUSED(immatureBalance); diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index a090fa42d5..74cc4bde56 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -47,8 +47,8 @@ public slots: void accept(); SendCoinsEntry *addEntry(); void updateTabsAndLabels(); - void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, - qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); + void setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, + const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); private: Ui::SendCoinsDialog *ui; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 4923718341..1efad8259b 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -56,9 +56,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(ISMINE_ALL); - int64_t nDebit = wtx.GetDebit(ISMINE_ALL); - int64_t nNet = nCredit - nDebit; + CAmount nCredit = wtx.GetCredit(ISMINE_ALL); + CAmount nDebit = wtx.GetDebit(ISMINE_ALL); + CAmount nNet = nCredit - nDebit; strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx); int nRequests = wtx.GetRequestCount(); @@ -132,7 +132,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // // Coinbase // - int64_t nUnmatured = 0; + CAmount nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) nUnmatured += wallet->GetCredit(txout, ISMINE_ALL); strHTML += "<b>" + tr("Credit") + ":</b> "; @@ -206,13 +206,13 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (fAllToMe) { // Payment to self - int64_t nChange = wtx.GetChange(); - int64_t nValue = nCredit - nChange; + CAmount nChange = wtx.GetChange(); + CAmount nValue = nCredit - nChange; strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>"; strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>"; } - int64_t nTxFee = nDebit - wtx.GetValueOut(); + CAmount nTxFee = nDebit - wtx.GetValueOut(); if (nTxFee > 0) strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>"; } diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index 6ab029173b..2a0f621d1e 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -78,7 +78,7 @@ void TransactionFilterProxy::setTypeFilter(quint32 modes) invalidateFilter(); } -void TransactionFilterProxy::setMinAmount(qint64 minimum) +void TransactionFilterProxy::setMinAmount(const CAmount& minimum) { this->minAmount = minimum; invalidateFilter(); diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h index f408317b53..ca31ee8f87 100644 --- a/src/qt/transactionfilterproxy.h +++ b/src/qt/transactionfilterproxy.h @@ -5,6 +5,8 @@ #ifndef TRANSACTIONFILTERPROXY_H #define TRANSACTIONFILTERPROXY_H +#include "amount.h" + #include <QDateTime> #include <QSortFilterProxyModel> @@ -38,7 +40,7 @@ public: @note Type filter takes a bit field created with TYPE() or ALL_TYPES */ void setTypeFilter(quint32 modes); - void setMinAmount(qint64 minimum); + void setMinAmount(const CAmount& minimum); void setWatchOnlyFilter(WatchOnlyFilter filter); /** Set maximum number of rows returned, -1 if unlimited. */ @@ -58,7 +60,7 @@ private: QString addrPrefix; quint32 typeFilter; WatchOnlyFilter watchOnlyFilter; - qint64 minAmount; + CAmount minAmount; int limitRows; bool showInactive; }; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 20c1449c92..afb343f349 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -32,9 +32,9 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * { QList<TransactionRecord> parts; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(true); - int64_t nDebit = wtx.GetDebit(ISMINE_ALL); - int64_t nNet = nCredit - nDebit; + CAmount nCredit = wtx.GetCredit(true); + CAmount nDebit = wtx.GetDebit(ISMINE_ALL); + CAmount nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map<std::string, std::string> mapValue = wtx.mapValue; @@ -97,7 +97,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * if (fAllFromMe && fAllToMe) { // Payment to self - int64_t nChange = wtx.GetChange(); + CAmount nChange = wtx.GetChange(); parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange)); @@ -108,7 +108,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * // // Debit // - int64_t nTxFee = nDebit - wtx.GetValueOut(); + CAmount nTxFee = nDebit - wtx.GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { @@ -138,7 +138,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet * sub.address = mapValue["to"]; } - int64_t nValue = txout.nValue; + CAmount nValue = txout.nValue; /* Add fee to first output */ if (nTxFee > 0) { diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 626b7654c6..9276c9f0af 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -5,6 +5,7 @@ #ifndef TRANSACTIONRECORD_H #define TRANSACTIONRECORD_H +#include "amount.h" #include "uint256.h" #include <QList> @@ -94,7 +95,7 @@ public: TransactionRecord(uint256 hash, qint64 time, Type type, const std::string &address, - qint64 debit, qint64 credit): + const CAmount& debit, const CAmount& credit): hash(hash), time(time), type(type), address(address), debit(debit), credit(credit), idx(0) { @@ -111,8 +112,8 @@ public: qint64 time; Type type; std::string address; - qint64 debit; - qint64 credit; + CAmount debit; + CAmount credit; /**@}*/ /** Subtransaction index, for sort key */ diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 2b869b4ea5..e34d776818 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -546,7 +546,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const case ToAddress: return formatTxToAddress(rec, true); case Amount: - return rec->credit + rec->debit; + return qint64(rec->credit + rec->debit); } break; case Qt::ToolTipRole: @@ -583,7 +583,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const case LabelRole: return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address)); case AmountRole: - return rec->credit + rec->debit; + return qint64(rec->credit + rec->debit); case TxIDRole: return rec->getTxID(); case TxHashRole: diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index a7ba100cd2..d153973872 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -304,7 +304,7 @@ void TransactionView::changedAmount(const QString &amount) { if(!transactionProxyModel) return; - qint64 amount_parsed = 0; + CAmount amount_parsed = 0; if(BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amount, &amount_parsed)) { transactionProxyModel->setMinAmount(amount_parsed); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ed90914ba7..b8701a23a6 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -55,11 +55,11 @@ WalletModel::~WalletModel() unsubscribeFromCoreSignals(); } -qint64 WalletModel::getBalance(const CCoinControl *coinControl) const +CAmount WalletModel::getBalance(const CCoinControl *coinControl) const { if (coinControl) { - qint64 nBalance = 0; + CAmount nBalance = 0; std::vector<COutput> vCoins; wallet->AvailableCoins(vCoins, true, coinControl); BOOST_FOREACH(const COutput& out, vCoins) @@ -72,12 +72,12 @@ qint64 WalletModel::getBalance(const CCoinControl *coinControl) const return wallet->GetBalance(); } -qint64 WalletModel::getUnconfirmedBalance() const +CAmount WalletModel::getUnconfirmedBalance() const { return wallet->GetUnconfirmedBalance(); } -qint64 WalletModel::getImmatureBalance() const +CAmount WalletModel::getImmatureBalance() const { return wallet->GetImmatureBalance(); } @@ -87,17 +87,17 @@ bool WalletModel::haveWatchOnly() const return fHaveWatchOnly; } -qint64 WalletModel::getWatchBalance() const +CAmount WalletModel::getWatchBalance() const { return wallet->GetWatchOnlyBalance(); } -qint64 WalletModel::getWatchUnconfirmedBalance() const +CAmount WalletModel::getWatchUnconfirmedBalance() const { return wallet->GetUnconfirmedWatchOnlyBalance(); } -qint64 WalletModel::getWatchImmatureBalance() const +CAmount WalletModel::getWatchImmatureBalance() const { return wallet->GetImmatureWatchOnlyBalance(); } @@ -137,12 +137,12 @@ void WalletModel::pollBalanceChanged() void WalletModel::checkBalanceChanged() { - qint64 newBalance = getBalance(); - qint64 newUnconfirmedBalance = getUnconfirmedBalance(); - qint64 newImmatureBalance = getImmatureBalance(); - qint64 newWatchOnlyBalance = 0; - qint64 newWatchUnconfBalance = 0; - qint64 newWatchImmatureBalance = 0; + CAmount newBalance = getBalance(); + CAmount newUnconfirmedBalance = getUnconfirmedBalance(); + CAmount newImmatureBalance = getImmatureBalance(); + CAmount newWatchOnlyBalance = 0; + CAmount newWatchUnconfBalance = 0; + CAmount newWatchImmatureBalance = 0; if (haveWatchOnly()) { newWatchOnlyBalance = getWatchBalance(); @@ -194,9 +194,9 @@ bool WalletModel::validateAddress(const QString &address) WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl) { - qint64 total = 0; + CAmount total = 0; QList<SendCoinsRecipient> recipients = transaction.getRecipients(); - std::vector<std::pair<CScript, int64_t> > vecSend; + std::vector<std::pair<CScript, CAmount> > vecSend; if(recipients.empty()) { @@ -211,7 +211,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact { if (rcp.paymentRequest.IsInitialized()) { // PaymentRequest... - int64_t subtotal = 0; + CAmount subtotal = 0; const payments::PaymentDetails& details = rcp.paymentRequest.getDetails(); for (int i = 0; i < details.outputs_size(); i++) { @@ -220,7 +220,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact subtotal += out.amount(); const unsigned char* scriptStr = (const unsigned char*)out.script().data(); CScript scriptPubKey(scriptStr, scriptStr+out.script().size()); - vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, out.amount())); + vecSend.push_back(std::pair<CScript, CAmount>(scriptPubKey, out.amount())); } if (subtotal <= 0) { @@ -242,7 +242,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact ++nAddresses; CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); - vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, rcp.amount)); + vecSend.push_back(std::pair<CScript, CAmount>(scriptPubKey, rcp.amount)); total += rcp.amount; } @@ -252,7 +252,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact return DuplicateAddress; } - qint64 nBalance = getBalance(coinControl); + CAmount nBalance = getBalance(coinControl); if(total > nBalance) { @@ -263,7 +263,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact LOCK2(cs_main, wallet->cs_wallet); transaction.newPossibleKeyChange(wallet); - int64_t nFeeRequired = 0; + CAmount nFeeRequired = 0; std::string strFailReason; CWalletTx *newTx = transaction.getTransaction(); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 111ae2178c..b1d0f28f12 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -37,7 +37,7 @@ class SendCoinsRecipient { public: explicit SendCoinsRecipient() : amount(0), nVersion(SendCoinsRecipient::CURRENT_VERSION) { } - explicit SendCoinsRecipient(const QString &addr, const QString &label, quint64 amount, const QString &message): + explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message): address(addr), label(label), amount(amount), message(message), nVersion(SendCoinsRecipient::CURRENT_VERSION) {} // If from an insecure payment request, this is used for storing @@ -47,7 +47,7 @@ public: // Todo: This is a hack, should be replaced with a cleaner solution! QString address; QString label; - qint64 amount; + CAmount amount; // If from a payment request, this is used for storing the memo QString message; @@ -125,13 +125,13 @@ public: TransactionTableModel *getTransactionTableModel(); RecentRequestsTableModel *getRecentRequestsTableModel(); - qint64 getBalance(const CCoinControl *coinControl = NULL) const; - qint64 getUnconfirmedBalance() const; - qint64 getImmatureBalance() const; + CAmount getBalance(const CCoinControl *coinControl = NULL) const; + CAmount getUnconfirmedBalance() const; + CAmount getImmatureBalance() const; bool haveWatchOnly() const; - qint64 getWatchBalance() const; - qint64 getWatchUnconfirmedBalance() const; - qint64 getWatchImmatureBalance() const; + CAmount getWatchBalance() const; + CAmount getWatchUnconfirmedBalance() const; + CAmount getWatchImmatureBalance() const; EncryptionStatus getEncryptionStatus() const; bool processingQueuedTransactions() { return fProcessingQueuedTransactions; } @@ -210,12 +210,12 @@ private: RecentRequestsTableModel *recentRequestsTableModel; // Cache some values to be able to detect changes - qint64 cachedBalance; - qint64 cachedUnconfirmedBalance; - qint64 cachedImmatureBalance; - qint64 cachedWatchOnlyBalance; - qint64 cachedWatchUnconfBalance; - qint64 cachedWatchImmatureBalance; + CAmount cachedBalance; + CAmount cachedUnconfirmedBalance; + CAmount cachedImmatureBalance; + CAmount cachedWatchOnlyBalance; + CAmount cachedWatchUnconfBalance; + CAmount cachedWatchImmatureBalance; EncryptionStatus cachedEncryptionStatus; int cachedNumBlocks; @@ -227,8 +227,8 @@ private: signals: // Signal that balance in wallet changed - void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, - qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); + void balanceChanged(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, + const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); // Encryption status of wallet changed void encryptionStatusChanged(int status); diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 943f13e208..ddd2d09bb5 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -31,19 +31,19 @@ CWalletTx *WalletModelTransaction::getTransaction() return walletTransaction; } -qint64 WalletModelTransaction::getTransactionFee() +CAmount WalletModelTransaction::getTransactionFee() { return fee; } -void WalletModelTransaction::setTransactionFee(qint64 newFee) +void WalletModelTransaction::setTransactionFee(const CAmount& newFee) { fee = newFee; } -qint64 WalletModelTransaction::getTotalTransactionAmount() +CAmount WalletModelTransaction::getTotalTransactionAmount() { - qint64 totalTransactionAmount = 0; + CAmount totalTransactionAmount = 0; foreach(const SendCoinsRecipient &rcp, recipients) { totalTransactionAmount += rcp.amount; diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h index b7e85bcd11..4eadfbe4d1 100644 --- a/src/qt/walletmodeltransaction.h +++ b/src/qt/walletmodeltransaction.h @@ -26,10 +26,10 @@ public: CWalletTx *getTransaction(); - void setTransactionFee(qint64 newFee); - qint64 getTransactionFee(); + void setTransactionFee(const CAmount& newFee); + CAmount getTransactionFee(); - qint64 getTotalTransactionAmount(); + CAmount getTotalTransactionAmount(); void newPossibleKeyChange(CWallet *wallet); CReserveKey *getPossibleKeyChange(); @@ -38,7 +38,7 @@ private: const QList<SendCoinsRecipient> recipients; CWalletTx *walletTransaction; CReserveKey *keyChange; - qint64 fee; + CAmount fee; }; #endif // WALLETMODELTRANSACTION_H diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index b40ddc0a2f..eff50593bd 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -92,7 +92,7 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui) connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int))); // Pass through transaction notifications - connect(this, SIGNAL(incomingTransaction(QString,int,qint64,QString,QString)), gui, SLOT(incomingTransaction(QString,int,qint64,QString,QString))); + connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString))); } } diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 9cfa8d6760..cafba517fd 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -5,6 +5,8 @@ #ifndef WALLETVIEW_H #define WALLETVIEW_H +#include "amount.h" + #include <QStackedWidget> class BitcoinGUI; @@ -111,7 +113,7 @@ signals: /** Encryption status of wallet changed */ void encryptionStatusChanged(int status); /** Notify that a new transaction appeared */ - void incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address); + void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address); }; #endif // WALLETVIEW_H diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 82eaf5d037..e794bf69e0 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -273,7 +273,7 @@ Value prioritisetransaction(const Array& params, bool fHelp) uint256 hash; hash.SetHex(params[0].get_str()); - int64_t nAmount = 0; + CAmount nAmount = 0; if (params[2].get_real() != 0.0) nAmount = AmountFromValue(params[2]); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index dbb0966ae2..bd87d77704 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -269,7 +269,7 @@ Value listunspent(const Array& params, bool fHelp) continue; } - int64_t nValue = out.tx->vout[out.i].nValue; + CAmount nValue = out.tx->vout[out.i].nValue; const CScript& pk = out.tx->vout[out.i].scriptPubKey; Object entry; entry.push_back(Pair("txid", out.tx->GetHash().GetHex())); @@ -367,7 +367,7 @@ Value createrawtransaction(const Array& params, bool fHelp) setAddress.insert(address); CScript scriptPubKey = GetScriptForDestination(address.Get()); - int64_t nAmount = AmountFromValue(s.value_); + CAmount nAmount = AmountFromValue(s.value_); CTxOut out(nAmount, scriptPubKey); rawTx.vout.push_back(out); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 190de62282..1a41344da5 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -88,18 +88,18 @@ static inline int64_t roundint64(double d) return (int64_t)(d > 0 ? d + 0.5 : d - 0.5); } -int64_t AmountFromValue(const Value& value) +CAmount AmountFromValue(const Value& value) { double dAmount = value.get_real(); if (dAmount <= 0.0 || dAmount > 21000000.0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); - int64_t nAmount = roundint64(dAmount * COIN); + CAmount nAmount = roundint64(dAmount * COIN); if (!MoneyRange(nAmount)) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); return nAmount; } -Value ValueFromAmount(int64_t amount) +Value ValueFromAmount(const CAmount& amount) { return (double)amount / (double)COIN; } diff --git a/src/rpcserver.h b/src/rpcserver.h index 820c1bc081..d440035f15 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -6,6 +6,7 @@ #ifndef _BITCOINRPC_SERVER_H_ #define _BITCOINRPC_SERVER_H_ +#include "amount.h" #include "uint256.h" #include "rpcprotocol.h" @@ -116,8 +117,8 @@ extern void InitRPCMining(); extern void ShutdownRPCMining(); extern int64_t nWalletUnlockTime; -extern int64_t AmountFromValue(const json_spirit::Value& value); -extern json_spirit::Value ValueFromAmount(int64_t amount); +extern CAmount AmountFromValue(const json_spirit::Value& value); +extern json_spirit::Value ValueFromAmount(const CAmount& amount); extern double GetDifficulty(const CBlockIndex* blockindex = NULL); extern std::string HelpRequiringPassphrase(); extern std::string HelpExampleCli(std::string methodname, std::string args); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 35637362a4..d7c0c0ef5c 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -230,15 +230,20 @@ Value setaccount(const Array& params, bool fHelp) if (params.size() > 1) strAccount = AccountFromValue(params[1]); - // Detect when changing the account of an address that is the 'unused current key' of another account: - if (pwalletMain->mapAddressBook.count(address.Get())) + // Only add the account if the address is yours. + if (IsMine(*pwalletMain, address.Get())) { - string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name; - if (address == GetAccountAddress(strOldAccount)) - GetAccountAddress(strOldAccount, true); + // Detect when changing the account of an address that is the 'unused current key' of another account: + if (pwalletMain->mapAddressBook.count(address.Get())) + { + string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name; + if (address == GetAccountAddress(strOldAccount)) + GetAccountAddress(strOldAccount, true); + } + pwalletMain->SetAddressBook(address.Get(), strAccount, "receive"); } - - pwalletMain->SetAddressBook(address.Get(), strAccount, "receive"); + else + throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address"); return Value::null; } @@ -331,7 +336,7 @@ Value sendtoaddress(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); // Amount - int64_t nAmount = AmountFromValue(params[1]); + CAmount nAmount = AmountFromValue(params[1]); // Wallet comments CWalletTx wtx; @@ -375,7 +380,7 @@ Value listaddressgroupings(const Array& params, bool fHelp) ); Array jsonGroupings; - map<CTxDestination, int64_t> balances = pwalletMain->GetAddressBalances(); + map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances(); BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings()) { Array jsonGrouping; @@ -483,7 +488,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) nMinDepth = params[1].get_int(); // Tally - int64_t nAmount = 0; + CAmount nAmount = 0; for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; @@ -532,7 +537,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount); // Tally - int64_t nAmount = 0; + CAmount nAmount = 0; for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; @@ -552,9 +557,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } -int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) +CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) { - int64_t nBalance = 0; + CAmount nBalance = 0; // Tally wallet transactions for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) @@ -563,7 +568,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) continue; - int64_t nReceived, nSent, nFee; + CAmount nReceived, nSent, nFee; wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) @@ -577,7 +582,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi return nBalance; } -int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) +CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) { CWalletDB walletdb(pwalletMain->strWalletFile); return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); @@ -627,14 +632,14 @@ Value getbalance(const Array& params, bool fHelp) // Calculate total balance a different way from GetBalance() // (GetBalance() sums up all unspent TxOuts) // getbalance and getbalance '*' 0 should return the same number - int64_t nBalance = 0; + CAmount nBalance = 0; for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0) continue; - int64_t allFee; + CAmount allFee; string strSentAccount; list<COutputEntry> listReceived; list<COutputEntry> listSent; @@ -653,7 +658,7 @@ Value getbalance(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, filter); + CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter); return ValueFromAmount(nBalance); } @@ -692,7 +697,7 @@ Value movecmd(const Array& params, bool fHelp) string strFrom = AccountFromValue(params[0]); string strTo = AccountFromValue(params[1]); - int64_t nAmount = AmountFromValue(params[2]); + CAmount nAmount = AmountFromValue(params[2]); if (params.size() > 3) // unused parameter, used to be nMinDepth, keep type-checking it though (void)params[3].get_int(); @@ -766,7 +771,7 @@ Value sendfrom(const Array& params, bool fHelp) CBitcoinAddress address(params[1].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - int64_t nAmount = AmountFromValue(params[2]); + CAmount nAmount = AmountFromValue(params[2]); int nMinDepth = 1; if (params.size() > 3) nMinDepth = params[3].get_int(); @@ -781,7 +786,7 @@ Value sendfrom(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); + CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -834,9 +839,9 @@ Value sendmany(const Array& params, bool fHelp) wtx.mapValue["comment"] = params[3].get_str(); set<CBitcoinAddress> setAddress; - vector<pair<CScript, int64_t> > vecSend; + vector<pair<CScript, CAmount> > vecSend; - int64_t totalAmount = 0; + CAmount totalAmount = 0; BOOST_FOREACH(const Pair& s, sendTo) { CBitcoinAddress address(s.name_); @@ -848,7 +853,7 @@ Value sendmany(const Array& params, bool fHelp) setAddress.insert(address); CScript scriptPubKey = GetScriptForDestination(address.Get()); - int64_t nAmount = AmountFromValue(s.value_); + CAmount nAmount = AmountFromValue(s.value_); totalAmount += nAmount; vecSend.push_back(make_pair(scriptPubKey, nAmount)); @@ -857,13 +862,13 @@ Value sendmany(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); + CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); // Send CReserveKey keyChange(pwalletMain); - int64_t nFeeRequired = 0; + CAmount nFeeRequired = 0; string strFailReason; bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason); if (!fCreated) @@ -923,7 +928,7 @@ Value addmultisigaddress(const Array& params, bool fHelp) struct tallyitem { - int64_t nAmount; + CAmount nAmount; int nConf; vector<uint256> txids; bool fIsWatchonly; @@ -995,7 +1000,7 @@ Value ListReceived(const Array& params, bool fByAccounts) if (it == mapTally.end() && !fIncludeEmpty) continue; - int64_t nAmount = 0; + CAmount nAmount = 0; int nConf = std::numeric_limits<int>::max(); bool fIsWatchonly = false; if (it != mapTally.end()) @@ -1038,7 +1043,7 @@ Value ListReceived(const Array& params, bool fByAccounts) { for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it) { - int64_t nAmount = (*it).second.nAmount; + CAmount nAmount = (*it).second.nAmount; int nConf = (*it).second.nConf; Object obj; if((*it).second.fIsWatchonly) @@ -1125,7 +1130,7 @@ static void MaybePushAddress(Object & entry, const CTxDestination &dest) void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter) { - int64_t nFee; + CAmount nFee; string strSentAccount; list<COutputEntry> listReceived; list<COutputEntry> listSent; @@ -1355,7 +1360,7 @@ Value listaccounts(const Array& params, bool fHelp) if(params[1].get_bool()) includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY; - map<string, int64_t> mapAccountBalances; + map<string, CAmount> mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me mapAccountBalances[entry.second.name] = 0; @@ -1364,7 +1369,7 @@ Value listaccounts(const Array& params, bool fHelp) for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - int64_t nFee; + CAmount nFee; string strSentAccount; list<COutputEntry> listReceived; list<COutputEntry> listSent; @@ -1391,7 +1396,7 @@ Value listaccounts(const Array& params, bool fHelp) mapAccountBalances[entry.strAccount] += entry.nCreditDebit; Object ret; - BOOST_FOREACH(const PAIRTYPE(string, int64_t)& accountBalance, mapAccountBalances) { + BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) { ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second))); } return ret; @@ -1534,10 +1539,10 @@ Value gettransaction(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); const CWalletTx& wtx = pwalletMain->mapWallet[hash]; - int64_t nCredit = wtx.GetCredit(filter != 0); - int64_t nDebit = wtx.GetDebit(filter); - int64_t nNet = nCredit - nDebit; - int64_t nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); + CAmount nCredit = wtx.GetCredit(filter != 0); + CAmount nDebit = wtx.GetDebit(filter); + CAmount nNet = nCredit - nDebit; + CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); if (wtx.IsFromMe(filter)) @@ -1937,7 +1942,7 @@ Value settxfee(const Array& params, bool fHelp) ); // Amount - int64_t nAmount = 0; + CAmount nAmount = 0; if (params[0].get_real() != 0.0) nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts diff --git a/src/serialize.h b/src/serialize.h index 68501facf2..ff11edc06c 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1154,7 +1154,7 @@ public: -/** Non-refcounted RAII wrapper for FILE*. +/** Non-refcounted RAII wrapper for FILE* * * Will automatically close the file when it goes out of scope if not null. * If you're returning the file pointer, return file.release(). @@ -1166,12 +1166,13 @@ private: // Disallow copies CAutoFile(const CAutoFile&); CAutoFile& operator=(const CAutoFile&); -protected: - FILE* file; -public: + int nType; int nVersion; + + FILE* file; +public: CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) { file = filenew; @@ -1186,9 +1187,10 @@ public: void fclose() { - if (file != NULL && file != stdin && file != stdout && file != stderr) + if (file) { ::fclose(file); - file = NULL; + file = NULL; + } } FILE* release() { FILE* ret = file; file = NULL; return ret; } @@ -1256,13 +1258,23 @@ public: } }; -/** Wrapper around a FILE* that implements a ring buffer to - * deserialize from. It guarantees the ability to rewind - * a given number of bytes. */ +/** Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to + * deserialize from. It guarantees the ability to rewind a given number of bytes. + * + * Will automatically close the file when it goes out of scope if not null. + * If you need to close the file early, use file.fclose() instead of fclose(file). + */ class CBufferedFile { private: - FILE *src; // source file + // Disallow copies + CBufferedFile(const CBufferedFile&); + CBufferedFile& operator=(const CBufferedFile&); + + int nType; + int nVersion; + + FILE *src; // source file uint64_t nSrcPos; // how many bytes have been read from source uint64_t nReadPos; // how many bytes have been read from this uint64_t nReadLimit; // up to which position we're allowed to read @@ -1289,12 +1301,25 @@ protected: } public: - int nType; - int nVersion; - CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : - src(fileIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0), - nType(nTypeIn), nVersion(nVersionIn) { + nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0) + { + src = fileIn; + nType = nTypeIn; + nVersion = nVersionIn; + } + + ~CBufferedFile() + { + fclose(); + } + + void fclose() + { + if (src) { + ::fclose(src); + src = NULL; + } } // check whether we're at the end of the source file diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index 4bee0f6b6e..af2a9a214f 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -15,7 +15,7 @@ extern CWallet* pwalletMain; BOOST_AUTO_TEST_SUITE(accounting_tests) static void -GetResults(CWalletDB& walletdb, std::map<int64_t, CAccountingEntry>& results) +GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results) { std::list<CAccountingEntry> aes; @@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) std::vector<CWalletTx*> vpwtx; CWalletTx wtx; CAccountingEntry ae; - std::map<int64_t, CAccountingEntry> results; + std::map<CAmount, CAccountingEntry> results; LOCK(pwalletMain->cs_wallet); diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 58fffb6df4..c298c805da 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest); } } - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::UNITTEST); } // Goal: check that generated keys match test vectors @@ -243,7 +243,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) CTxDestination nodest = CNoDestination(); BOOST_CHECK(!dummyAddr.Set(nodest)); - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::UNITTEST); } // Goal: check that base58 parsing code is robust against a variety of corrupted data diff --git a/src/test/bctest.py b/src/test/bctest.py index 1839f4fef4..ef461014ea 100644 --- a/src/test/bctest.py +++ b/src/test/bctest.py @@ -7,9 +7,11 @@ import os import json import sys -def bctest(testDir, testObj): - execargs = testObj['exec'] +def bctest(testDir, testObj, exeext): + execprog = testObj['exec'] + exeext + execargs = testObj['args'] + execrun = [execprog] + execargs stdinCfg = None inputData = None if "input" in testObj: @@ -22,12 +24,11 @@ def bctest(testDir, testObj): if "output_cmp" in testObj: outputFn = testObj['output_cmp'] outputData = open(testDir + "/" + outputFn).read() - - proc = subprocess.Popen(execargs, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True) try: outs = proc.communicate(input=inputData) except OSError: - print("OSError, Failed to execute " + execargs[0]) + print("OSError, Failed to execute " + execprog) sys.exit(1) if outputData and (outs[0] != outputData): @@ -41,13 +42,13 @@ def bctest(testDir, testObj): print("Return code mismatch for " + outputFn) sys.exit(1) -def bctester(testDir, input_basename): +def bctester(testDir, input_basename, buildenv): input_filename = testDir + "/" + input_basename raw_data = open(input_filename).read() input_data = json.loads(raw_data) for testObj in input_data: - bctest(testDir, testObj) + bctest(testDir, testObj, buildenv.exeext) sys.exit(0) diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py index 40690c2fed..0eece14cfe 100755 --- a/src/test/bitcoin-util-test.py +++ b/src/test/bitcoin-util-test.py @@ -5,8 +5,9 @@ import os import bctest +import buildenv if __name__ == '__main__': bctest.bctester(os.environ["srcdir"] + "/test/data", - "bitcoin-util-test.json") + "bitcoin-util-test.json",buildenv) diff --git a/src/test/buildenv.py.in b/src/test/buildenv.py.in new file mode 100644 index 0000000000..1618bdeb76 --- /dev/null +++ b/src/test/buildenv.py.in @@ -0,0 +1,2 @@ +#!/usr/bin/python +exeext="@EXEEXT@" diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json index cb74d73ef2..f8424b72a3 100644 --- a/src/test/data/bitcoin-util-test.json +++ b/src/test/data/bitcoin-util-test.json @@ -1,33 +1,41 @@ [ - { "exec": ["./bitcoin-tx", "-create"], + { "exec": "././bitcoin-tx", + "args": ["-create"], "output_cmp": "blanktx.hex" }, - { "exec": ["./bitcoin-tx", "-"], + { "exec": "./bitcoin-tx", + "args": ["-"], "input": "blanktx.hex", "output_cmp": "blanktx.hex" }, - { "exec": ["./bitcoin-tx", "-", "delin=1"], + { "exec": "./bitcoin-tx", + "args": ["-", "delin=1"], "input": "tx394b54bb.hex", "output_cmp": "tt-delin1-out.hex" }, - { "exec": ["./bitcoin-tx", "-", "delin=31"], + { "exec": "./bitcoin-tx", + "args": ["-", "delin=31"], "input": "tx394b54bb.hex", "return_code": 1 }, - { "exec": ["./bitcoin-tx", "-", "delout=1"], + { "exec": "./bitcoin-tx", + "args": ["-", "delout=1"], "input": "tx394b54bb.hex", "output_cmp": "tt-delout1-out.hex" }, - { "exec": ["./bitcoin-tx", "-", "delout=2"], + { "exec": "./bitcoin-tx", + "args": ["-", "delout=2"], "input": "tx394b54bb.hex", "return_code": 1 }, - { "exec": ["./bitcoin-tx", "-", "locktime=317000"], + { "exec": "./bitcoin-tx", + "args": ["-", "locktime=317000"], "input": "tx394b54bb.hex", "output_cmp": "tt-locktime317000-out.hex" }, - { "exec": - ["./bitcoin-tx", "-create", + { "exec": "./bitcoin-tx", + "args": + ["-create", "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", "in=bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c:18", "in=22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc:1", @@ -35,7 +43,8 @@ "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"], "output_cmp": "txcreate1.hex" }, - { "exec": ["./bitcoin-tx", "-create", "outscript=0:"], + { "exec": "./bitcoin-tx", + "args": ["-create", "outscript=0:"], "output_cmp": "txcreate2.hex" } ] diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 8863ba4004..70a800af51 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -11,9 +11,9 @@ BOOST_AUTO_TEST_SUITE(main_tests) BOOST_AUTO_TEST_CASE(subsidy_limit_test) { - uint64_t nSum = 0; + CAmount nSum = 0; for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) { - uint64_t nSubsidy = GetBlockValue(nHeight, 0); + CAmount nSubsidy = GetBlockValue(nHeight, 0); BOOST_CHECK(nSubsidy <= 50 * COIN); nSum += nSubsidy * 1000; BOOST_CHECK(MoneyRange(nSum)); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 9e4669eba9..bad5c13ac2 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -253,6 +253,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) chainActive.Tip()->nHeight--; SetMockTime(0); + mempool.clear(); BOOST_FOREACH(CTransaction *tx, txFirst) delete tx; diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 1dc2a3d82f..91da0c4420 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -14,7 +14,7 @@ using namespace std; using namespace json_spirit; -extern Array createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL); +extern Array createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL); extern Value CallRPC(string args); extern CWallet* pwalletMain; @@ -53,10 +53,10 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig) BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error); BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error); - string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing + string short1(address1Hex, address1Hex + sizeof(address1Hex) - 2); // last byte missing BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error); - string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing + string short2(address1Hex + 1, address1Hex + sizeof(address1Hex)); // first byte missing BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error); } @@ -68,26 +68,30 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) LOCK2(cs_main, pwalletMain->cs_wallet); CPubKey demoPubkey = pwalletMain->GenerateNewKey(); - CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); - Value retValue; - string strAccount = "walletDemoAccount"; - string strPurpose = "receive"; - BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ - CWalletDB walletdb(pwalletMain->strWalletFile); - CAccount account; - account.vchPubKey = demoPubkey; - pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose); - walletdb.WriteAccount(strAccount, account); - }); - - - /********************************* - * setaccount - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount")); - BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error); - /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */ - BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error); + CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); + Value retValue; + string strAccount = "walletDemoAccount"; + string strPurpose = "receive"; + BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ + CWalletDB walletdb(pwalletMain->strWalletFile); + CAccount account; + account.vchPubKey = demoPubkey; + pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose); + walletdb.WriteAccount(strAccount, account); + }); + + CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey(); + CBitcoinAddress setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID())); + + /********************************* + * setaccount + *********************************/ + BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount")); + /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ is not owned by the test wallet. */ + BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount"), runtime_error); + BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error); + /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */ + BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error); /********************************* * listunspent @@ -97,12 +101,12 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error); BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error); BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error); - BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []")); + BOOST_CHECK_NO_THROW(r = CallRPC("listunspent 0 1 []")); BOOST_CHECK(r.get_array().empty()); /********************************* - * listreceivedbyaddress - *********************************/ + * listreceivedbyaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress")); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0")); BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error); @@ -111,8 +115,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error); /********************************* - * listreceivedbyaccount - *********************************/ + * listreceivedbyaccount + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount")); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0")); BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error); @@ -121,59 +125,58 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error); /********************************* - * getrawchangeaddress - *********************************/ + * getrawchangeaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress")); /********************************* - * getnewaddress - *********************************/ + * getnewaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getnewaddress")); BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount")); /********************************* - * getaccountaddress - *********************************/ + * getaccountaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\"")); - BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account - BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount)); - BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); - - /********************************* - * getaccount - *********************************/ - BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); - - /********************************* - * signmessage + verifymessage - *********************************/ - BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); - BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error); - /* Should throw error because this address is not loaded in the wallet */ - BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error); - - /* missing arguments */ - BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString()), runtime_error); - BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str()), runtime_error); - /* Illegal address */ - BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error); - /* wrong address */ - BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false); - /* Correct address and signature but wrong message */ - BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false); - /* Correct address, message and signature*/ - BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); - - /********************************* - * getaddressesbyaccount - *********************************/ - BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error); - BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); - Array arr = retValue.get_array(); - BOOST_CHECK(arr.size() > 0); - BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); + BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account + BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount)); + BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); + /********************************* + * getaccount + *********************************/ + BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error); + BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); + + /********************************* + * signmessage + verifymessage + *********************************/ + BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); + BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error); + /* Should throw error because this address is not loaded in the wallet */ + BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error); + + /* missing arguments */ + BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), runtime_error); + BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), runtime_error); + /* Illegal address */ + BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error); + /* wrong address */ + BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false); + /* Correct address and signature but wrong message */ + BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false); + /* Correct address, message and signature*/ + BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); + + /********************************* + * getaddressesbyaccount + *********************************/ + BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error); + BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); + Array arr = retValue.get_array(); + BOOST_CHECK(arr.size() > 0); + BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 7f09b3daa1..48a5635d8f 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -70,7 +70,7 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) return txCredit; } -CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CTransaction& txCredit) +CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMutableTransaction& txCredit) { CMutableTransaction txSpend; txSpend.nVersion = 1; @@ -521,16 +521,8 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) CScript scriptPubKey12; scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG; - CMutableTransaction txFrom12; - txFrom12.vout.resize(1); - txFrom12.vout[0].scriptPubKey = scriptPubKey12; - - CMutableTransaction txTo12; - txTo12.vin.resize(1); - txTo12.vout.resize(1); - txTo12.vin[0].prevout.n = 0; - txTo12.vin[0].prevout.hash = txFrom12.GetHash(); - txTo12.vout[0].nValue = 1; + CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12); + CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, flags)); @@ -555,16 +547,8 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) CScript scriptPubKey23; scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG; - CMutableTransaction txFrom23; - txFrom23.vout.resize(1); - txFrom23.vout[0].scriptPubKey = scriptPubKey23; - - CMutableTransaction txTo23; - txTo23.vin.resize(1); - txTo23.vout.resize(1); - txTo23.vin[0].prevout.n = 0; - txTo23.vin[0].prevout.hash = txFrom23.GetHash(); - txTo23.vout[0].nValue = 1; + CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23); + CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23); std::vector<CKey> keys; keys.push_back(key1); keys.push_back(key2); @@ -626,17 +610,10 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) keystore.AddKey(key); } - CMutableTransaction txFrom; - txFrom.vout.resize(1); - txFrom.vout[0].scriptPubKey = GetScriptForDestination(keys[0].GetPubKey().GetID()); + CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID())); + CMutableTransaction txTo = BuildSpendingTransaction(CScript(), txFrom); CScript& scriptPubKey = txFrom.vout[0].scriptPubKey; - CMutableTransaction txTo; - txTo.vin.resize(1); - txTo.vout.resize(1); - txTo.vin[0].prevout.n = 0; - txTo.vin[0].prevout.hash = txFrom.GetHash(); CScript& scriptSig = txTo.vin[0].scriptSig; - txTo.vout[0].nValue = 1; CScript empty; CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 68fad8d038..6e5f0e3fac 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -31,7 +31,7 @@ struct TestingSetup { TestingSetup() { fPrintToDebugLog = false; // don't want to write to debug.log file - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::UNITTEST); noui_connect(); #ifdef ENABLE_WALLET bitdb.MakeMock(); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index e077c9de3b..6378bd0941 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -171,7 +171,7 @@ BOOST_AUTO_TEST_CASE(util_FormatMoney) BOOST_AUTO_TEST_CASE(util_ParseMoney) { - int64_t ret = 0; + CAmount ret = 0; BOOST_CHECK(ParseMoney("0.0", ret)); BOOST_CHECK_EQUAL(ret, 0); diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 3887efbd0d..90fc470e06 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_SUITE(wallet_tests) static CWallet wallet; static vector<COutput> vCoins; -static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) +static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) { static int nextLockTime = 0; CMutableTransaction tx; @@ -66,7 +66,7 @@ static bool equal_sets(CoinSet a, CoinSet b) BOOST_AUTO_TEST_CASE(coin_selection_tests) { CoinSet setCoinsRet, setCoinsRet2; - int64_t nValueRet; + CAmount nValueRet; LOCK(wallet.cs_wallet); diff --git a/src/txdb.cpp b/src/txdb.cpp index 79838b6116..d5f424fabd 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -117,7 +117,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = GetBestBlock(); ss << stats.hashBlock; - int64_t nTotalAmount = 0; + CAmount nTotalAmount = 0; while (pcursor->Valid()) { boost::this_thread::interruption_point(); try { diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 52d07bf6a0..d923c2204a 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -7,6 +7,7 @@ #include "core.h" #include "util.h" +#include "utilmoneystr.h" #include <boost/circular_buffer.hpp> @@ -18,7 +19,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(): nHeight = MEMPOOL_HEIGHT; } -CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, int64_t _nFee, +CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, int64_t _nTime, double _dPriority, unsigned int _nHeight): tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight) @@ -36,7 +37,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other) double CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const { - int64_t nValueIn = tx.GetValueOut()+nFee; + CAmount nValueIn = tx.GetValueOut()+nFee; double deltaPriority = ((double)(currentHeight-nHeight)*nValueIn)/nModSize; double dResult = dPriority + deltaPriority; return dResult; @@ -601,24 +602,24 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein) return true; } -void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, int64_t nFeeDelta) +void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, const CAmount& nFeeDelta) { { LOCK(cs); - std::pair<double, int64_t> &deltas = mapDeltas[hash]; + std::pair<double, CAmount> &deltas = mapDeltas[hash]; deltas.first += dPriorityDelta; deltas.second += nFeeDelta; } - LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, nFeeDelta); + LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, FormatMoney(nFeeDelta)); } -void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta) +void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta) { LOCK(cs); - std::map<uint256, std::pair<double, int64_t> >::iterator pos = mapDeltas.find(hash); + std::map<uint256, std::pair<double, CAmount> >::iterator pos = mapDeltas.find(hash); if (pos == mapDeltas.end()) return; - const std::pair<double, int64_t> &deltas = pos->second; + const std::pair<double, CAmount> &deltas = pos->second; dPriorityDelta += deltas.first; nFeeDelta += deltas.second; } diff --git a/src/txmempool.h b/src/txmempool.h index b9d50ee0bc..c35ea52d4e 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -29,7 +29,7 @@ class CTxMemPoolEntry { private: CTransaction tx; - int64_t nFee; // Cached to avoid expensive parent-transaction lookups + CAmount nFee; // Cached to avoid expensive parent-transaction lookups size_t nTxSize; // ... and avoid recomputing tx size size_t nModSize; // ... and modified size for priority int64_t nTime; // Local time when entering the mempool @@ -37,14 +37,14 @@ private: unsigned int nHeight; // Chain height when entering the mempool public: - CTxMemPoolEntry(const CTransaction& _tx, int64_t _nFee, + CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, int64_t _nTime, double _dPriority, unsigned int _nHeight); CTxMemPoolEntry(); CTxMemPoolEntry(const CTxMemPoolEntry& other); const CTransaction& GetTx() const { return this->tx; } double GetPriority(unsigned int currentHeight) const; - int64_t GetFee() const { return nFee; } + CAmount GetFee() const { return nFee; } size_t GetTxSize() const { return nTxSize; } int64_t GetTime() const { return nTime; } unsigned int GetHeight() const { return nHeight; } @@ -76,7 +76,7 @@ public: mutable CCriticalSection cs; std::map<uint256, CTxMemPoolEntry> mapTx; std::map<COutPoint, CInPoint> mapNextTx; - std::map<uint256, std::pair<double, int64_t> > mapDeltas; + std::map<uint256, std::pair<double, CAmount> > mapDeltas; CTxMemPool(const CFeeRate& _minRelayFee); ~CTxMemPool(); @@ -102,8 +102,8 @@ public: 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 PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, const CAmount& nFeeDelta); + void ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta); void ClearPrioritisation(const uint256 hash); unsigned long size() diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp index c169355f05..1a5635bfb8 100644 --- a/src/utilmoneystr.cpp +++ b/src/utilmoneystr.cpp @@ -10,7 +10,7 @@ using namespace std; -string FormatMoney(int64_t n, bool fPlus) +string FormatMoney(const CAmount& n, bool fPlus) { // Note: not using straight sprintf here because we do NOT want // localized number formatting. @@ -34,12 +34,12 @@ string FormatMoney(int64_t n, bool fPlus) } -bool ParseMoney(const string& str, int64_t& nRet) +bool ParseMoney(const string& str, CAmount& nRet) { return ParseMoney(str.c_str(), nRet); } -bool ParseMoney(const char* pszIn, int64_t& nRet) +bool ParseMoney(const char* pszIn, CAmount& nRet) { string strWhole; int64_t nUnits = 0; @@ -73,7 +73,7 @@ bool ParseMoney(const char* pszIn, int64_t& nRet) if (nUnits < 0 || nUnits > COIN) return false; int64_t nWhole = atoi64(strWhole); - int64_t nValue = nWhole*COIN + nUnits; + CAmount nValue = nWhole*COIN + nUnits; nRet = nValue; return true; diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h index f0c61aa138..65415afd3f 100644 --- a/src/utilmoneystr.h +++ b/src/utilmoneystr.h @@ -12,8 +12,10 @@ #include <stdint.h> #include <string> -std::string FormatMoney(int64_t n, bool fPlus=false); -bool ParseMoney(const std::string& str, int64_t& nRet); -bool ParseMoney(const char* pszIn, int64_t& nRet); +#include "amount.h" + +std::string FormatMoney(const CAmount& n, bool fPlus=false); +bool ParseMoney(const std::string& str, CAmount& nRet); +bool ParseMoney(const char* pszIn, CAmount& nRet); #endif // BITCOIN_UTILMONEYSTR_H diff --git a/src/wallet.cpp b/src/wallet.cpp index e69f59aacd..b20b0007ce 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -35,8 +35,8 @@ CFeeRate CWallet::minTxFee = CFeeRate(10000); // Override with -mintxfee struct CompareValueOnly { - bool operator()(const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t1, - const pair<int64_t, pair<const CWalletTx*, unsigned int> >& t2) const + bool operator()(const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t1, + const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t2) const { return t1.first < t2.first; } @@ -697,7 +697,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const return ISMINE_NO; } -int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const +CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const { { LOCK(cs_wallet); @@ -781,7 +781,7 @@ int CWalletTx::GetRequestCount() const } void CWalletTx::GetAmounts(list<COutputEntry>& listReceived, - list<COutputEntry>& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const + list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const { nFee = 0; listReceived.clear(); @@ -789,10 +789,10 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived, strSentAccount = strFromAccount; // Compute fee: - int64_t nDebit = GetDebit(filter); + CAmount nDebit = GetDebit(filter); if (nDebit > 0) // debit>0 means we signed/sent this transaction { - int64_t nValueOut = GetValueOut(); + CAmount nValueOut = GetValueOut(); nFee = nDebit - nValueOut; } @@ -835,12 +835,12 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived, } -void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee, const isminefilter& filter) const +void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived, + CAmount& nSent, CAmount& nFee, const isminefilter& filter) const { nReceived = nSent = nFee = 0; - int64_t allFee; + CAmount allFee; string strSentAccount; list<COutputEntry> listReceived; list<COutputEntry> listSent; @@ -1011,9 +1011,9 @@ void CWallet::ResendWalletTransactions() // -int64_t CWallet::GetBalance() const +CAmount CWallet::GetBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1027,9 +1027,9 @@ int64_t CWallet::GetBalance() const return nTotal; } -int64_t CWallet::GetUnconfirmedBalance() const +CAmount CWallet::GetUnconfirmedBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1042,9 +1042,9 @@ int64_t CWallet::GetUnconfirmedBalance() const return nTotal; } -int64_t CWallet::GetImmatureBalance() const +CAmount CWallet::GetImmatureBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1056,9 +1056,9 @@ int64_t CWallet::GetImmatureBalance() const return nTotal; } -int64_t CWallet::GetWatchOnlyBalance() const +CAmount CWallet::GetWatchOnlyBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1072,9 +1072,9 @@ int64_t CWallet::GetWatchOnlyBalance() const return nTotal; } -int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const +CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1087,9 +1087,9 @@ int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const return nTotal; } -int64_t CWallet::GetImmatureWatchOnlyBalance() const +CAmount CWallet::GetImmatureWatchOnlyBalance() const { - int64_t nTotal = 0; + CAmount nTotal = 0; { LOCK2(cs_main, cs_wallet); for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) @@ -1137,8 +1137,8 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const } } -static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > >vValue, int64_t nTotalLower, int64_t nTargetValue, - vector<char>& vfBest, int64_t& nBest, int iterations = 1000) +static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, + vector<char>& vfBest, CAmount& nBest, int iterations = 1000) { vector<char> vfIncluded; @@ -1150,7 +1150,7 @@ static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,uns for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++) { vfIncluded.assign(vValue.size(), false); - int64_t nTotal = 0; + CAmount nTotal = 0; bool fReachedTarget = false; for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++) { @@ -1183,18 +1183,18 @@ static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,uns } } -bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins, - set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const +bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins, + set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const { setCoinsRet.clear(); nValueRet = 0; // List of values less than target - pair<int64_t, pair<const CWalletTx*,unsigned int> > coinLowestLarger; - coinLowestLarger.first = std::numeric_limits<int64_t>::max(); + pair<CAmount, pair<const CWalletTx*,unsigned int> > coinLowestLarger; + coinLowestLarger.first = std::numeric_limits<CAmount>::max(); coinLowestLarger.second.first = NULL; - vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > > vValue; - int64_t nTotalLower = 0; + vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > > vValue; + CAmount nTotalLower = 0; random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); @@ -1209,9 +1209,9 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT continue; int i = output.i; - int64_t n = pcoin->vout[i].nValue; + CAmount n = pcoin->vout[i].nValue; - pair<int64_t,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i)); + pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i)); if (n == nTargetValue) { @@ -1252,7 +1252,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT // Solve subset sum by stochastic approximation sort(vValue.rbegin(), vValue.rend(), CompareValueOnly()); vector<char> vfBest; - int64_t nBest; + CAmount nBest; ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000); if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT) @@ -1284,7 +1284,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT return true; } -bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const +bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const { vector<COutput> vCoins; AvailableCoins(vCoins, true, coinControl); @@ -1310,11 +1310,11 @@ bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsign -bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) +bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend, + CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) { - int64_t nValue = 0; - BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) + CAmount nValue = 0; + BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend) { if (nValue < 0) { @@ -1343,10 +1343,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, txNew.vout.clear(); wtxNew.fFromMe = true; - int64_t nTotalValue = nValue + nFeeRet; + CAmount nTotalValue = nValue + nFeeRet; double dPriority = 0; // vouts to the payees - BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) + BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend) { CTxOut txout(s.second, s.first); if (txout.IsDust(::minRelayTxFee)) @@ -1359,7 +1359,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, // Choose coins to use set<pair<const CWalletTx*,unsigned int> > setCoins; - int64_t nValueIn = 0; + CAmount nValueIn = 0; if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl)) { strFailReason = _("Insufficient funds"); @@ -1367,14 +1367,14 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, } BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) { - int64_t nCredit = pcoin.first->vout[pcoin.second].nValue; + CAmount nCredit = pcoin.first->vout[pcoin.second].nValue; //The priority after the next block (depth+1) is used instead of the current, //reflecting an assumption the user would accept a bit more delay for //a chance at a free transaction. dPriority += (double)nCredit * (pcoin.first->GetDepthInMainChain()+1); } - int64_t nChange = nValueIn - nValue - nFeeRet; + CAmount nChange = nValueIn - nValue - nFeeRet; if (nChange > 0) { @@ -1450,7 +1450,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, } dPriority = wtxNew.ComputePriority(dPriority, nBytes); - int64_t nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); + CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); if (nFeeRet >= nFeeNeeded) break; // Done, enough fee included. @@ -1481,10 +1481,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, return true; } -bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) +bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue, + CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) { - vector< pair<CScript, int64_t> > vecSend; + vector< pair<CScript, CAmount> > vecSend; vecSend.push_back(make_pair(scriptPubKey, nValue)); return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl); } @@ -1539,7 +1539,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) -string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew) +string CWallet::SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew) { // Check amount if (nValue <= 0) @@ -1560,7 +1560,7 @@ string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWallet // Create and send the transaction CReserveKey reservekey(this); - int64_t nFeeRequired; + CAmount nFeeRequired; if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError)) { if (nValue + nFeeRequired > GetBalance()) @@ -1576,10 +1576,10 @@ string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWallet -int64_t CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) +CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) { // payTxFee is user-set "I want to pay this much" - int64_t nFeeNeeded = payTxFee.GetFee(nTxBytes); + CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes); // User didn't set: use -txconfirmtarget to estimate... if (nFeeNeeded == 0) nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes); @@ -1838,9 +1838,9 @@ int64_t CWallet::GetOldestKeyPoolTime() return keypool.nTime; } -std::map<CTxDestination, int64_t> CWallet::GetAddressBalances() +std::map<CTxDestination, CAmount> CWallet::GetAddressBalances() { - map<CTxDestination, int64_t> balances; + map<CTxDestination, CAmount> balances; { LOCK(cs_wallet); @@ -1866,7 +1866,7 @@ std::map<CTxDestination, int64_t> CWallet::GetAddressBalances() if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr)) continue; - int64_t n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue; + CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue; if (!balances.count(addr)) balances[addr] = 0; diff --git a/src/wallet.h b/src/wallet.h index fde87a8a2f..f3fffb2253 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -30,9 +30,9 @@ extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; // -paytxfee default -static const int64_t DEFAULT_TRANSACTION_FEE = 0; +static const CAmount DEFAULT_TRANSACTION_FEE = 0; // -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB -static const int nHighTransactionFeeWarning = 0.01 * COIN; +static const CAmount nHighTransactionFeeWarning = 0.01 * COIN; // Largest (in bytes) free transaction we're willing to create static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; @@ -98,7 +98,7 @@ public: class CWallet : public CCryptoKeyStore, public CWalletInterface { private: - bool SelectCoins(int64_t nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl = NULL) const; + bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const; CWalletDB *pwalletdbEncryption; @@ -182,7 +182,7 @@ public: bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const; - bool SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const; + bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const; bool IsSpent(const uint256& hash, unsigned int n) const; @@ -253,21 +253,21 @@ public: int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(); - int64_t GetBalance() const; - int64_t GetUnconfirmedBalance() const; - int64_t GetImmatureBalance() const; - int64_t GetWatchOnlyBalance() const; - int64_t GetUnconfirmedWatchOnlyBalance() const; - int64_t GetImmatureWatchOnlyBalance() const; - bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); - bool CreateTransaction(CScript scriptPubKey, int64_t nValue, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); + CAmount GetBalance() const; + CAmount GetUnconfirmedBalance() const; + CAmount GetImmatureBalance() const; + CAmount GetWatchOnlyBalance() const; + CAmount GetUnconfirmedWatchOnlyBalance() const; + CAmount GetImmatureWatchOnlyBalance() const; + bool CreateTransaction(const std::vector<std::pair<CScript, CAmount> >& vecSend, + CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); + bool CreateTransaction(CScript scriptPubKey, const CAmount& nValue, + CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); - std::string SendMoney(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew); + std::string SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew); static CFeeRate minTxFee; - static int64_t GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); + static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); bool NewKeyPool(); bool TopUpKeyPool(unsigned int kpSize = 0); @@ -279,24 +279,24 @@ public: void GetAllReserveKeys(std::set<CKeyID>& setAddress) const; std::set< std::set<CTxDestination> > GetAddressGroupings(); - std::map<CTxDestination, int64_t> GetAddressBalances(); + std::map<CTxDestination, CAmount> GetAddressBalances(); std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const; isminetype IsMine(const CTxIn& txin) const; - int64_t GetDebit(const CTxIn& txin, const isminefilter& filter) const; + CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const; isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout, const isminefilter& filter) const + CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); return ((IsMine(txout) & filter) ? txout.nValue : 0); } bool IsChange(const CTxOut& txout) const; - int64_t GetChange(const CTxOut& txout) const + CAmount GetChange(const CTxOut& txout) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetChange() : value out of range"); @@ -313,9 +313,9 @@ public: { return (GetDebit(tx, ISMINE_ALL) > 0); } - int64_t GetDebit(const CTransaction& tx, const isminefilter& filter) const + CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const { - int64_t nDebit = 0; + CAmount nDebit = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) { nDebit += GetDebit(txin, filter); @@ -324,9 +324,9 @@ public: } return nDebit; } - int64_t GetCredit(const CTransaction& tx, const isminefilter& filter) const + CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const { - int64_t nCredit = 0; + CAmount nCredit = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { nCredit += GetCredit(txout, filter); @@ -335,9 +335,9 @@ public: } return nCredit; } - int64_t GetChange(const CTransaction& tx) const + CAmount GetChange(const CTransaction& tx) const { - int64_t nChange = 0; + CAmount nChange = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { nChange += GetChange(txout); @@ -457,7 +457,7 @@ static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue) struct COutputEntry { CTxDestination destination; - int64_t amount; + CAmount amount; int vout; }; @@ -545,15 +545,15 @@ public: mutable bool fImmatureWatchCreditCached; mutable bool fAvailableWatchCreditCached; mutable bool fChangeCached; - mutable int64_t nDebitCached; - mutable int64_t nCreditCached; - mutable int64_t nImmatureCreditCached; - mutable int64_t nAvailableCreditCached; - mutable int64_t nWatchDebitCached; - mutable int64_t nWatchCreditCached; - mutable int64_t nImmatureWatchCreditCached; - mutable int64_t nAvailableWatchCreditCached; - mutable int64_t nChangeCached; + mutable CAmount nDebitCached; + mutable CAmount nCreditCached; + mutable CAmount nImmatureCreditCached; + mutable CAmount nAvailableCreditCached; + mutable CAmount nWatchDebitCached; + mutable CAmount nWatchCreditCached; + mutable CAmount nImmatureWatchCreditCached; + mutable CAmount nAvailableWatchCreditCached; + mutable CAmount nChangeCached; CWalletTx() { @@ -670,12 +670,12 @@ public: } // filter decides which addresses will count towards the debit - int64_t GetDebit(const isminefilter& filter) const + CAmount GetDebit(const isminefilter& filter) const { if (vin.empty()) return 0; - int64_t debit = 0; + CAmount debit = 0; if(filter & ISMINE_SPENDABLE) { if (fDebitCached) @@ -701,7 +701,7 @@ public: return debit; } - int64_t GetCredit(bool fUseCache=true) const + CAmount GetCredit(bool fUseCache=true) const { // Must wait until coinbase is safely deep enough in the chain before valuing it if (IsCoinBase() && GetBlocksToMaturity() > 0) @@ -715,7 +715,7 @@ public: return nCreditCached; } - int64_t GetImmatureCredit(bool fUseCache=true) const + CAmount GetImmatureCredit(bool fUseCache=true) const { if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain()) { @@ -729,7 +729,7 @@ public: return 0; } - int64_t GetAvailableCredit(bool fUseCache=true) const + CAmount GetAvailableCredit(bool fUseCache=true) const { if (pwallet == 0) return 0; @@ -741,7 +741,7 @@ public: if (fUseCache && fAvailableCreditCached) return nAvailableCreditCached; - int64_t nCredit = 0; + CAmount nCredit = 0; uint256 hashTx = GetHash(); for (unsigned int i = 0; i < vout.size(); i++) { @@ -759,7 +759,7 @@ public: return nCredit; } - int64_t GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const + CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const { if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain()) { @@ -773,7 +773,7 @@ public: return 0; } - int64_t GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const + CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const { if (pwallet == 0) return 0; @@ -785,7 +785,7 @@ public: if (fUseCache && fAvailableWatchCreditCached) return nAvailableWatchCreditCached; - int64_t nCredit = 0; + CAmount nCredit = 0; for (unsigned int i = 0; i < vout.size(); i++) { if (!pwallet->IsSpent(GetHash(), i)) @@ -802,7 +802,7 @@ public: return nCredit; } - int64_t GetChange() const + CAmount GetChange() const { if (fChangeCached) return nChangeCached; @@ -812,10 +812,10 @@ public: } void GetAmounts(std::list<COutputEntry>& listReceived, - std::list<COutputEntry>& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter) const; + std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const; - void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee, const isminefilter& filter) const; + void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived, + CAmount& nSent, CAmount& nFee, const isminefilter& filter) const; bool IsFromMe(const isminefilter& filter) const { @@ -949,7 +949,7 @@ class CAccountingEntry { public: std::string strAccount; - int64_t nCreditDebit; + CAmount nCreditDebit; int64_t nTime; std::string strOtherAccount; std::string strComment; diff --git a/src/walletdb.cpp b/src/walletdb.cpp index a84f44db01..3e5a664a5d 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -187,12 +187,12 @@ bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry) return WriteAccountingEntry(++nAccountingEntryNumber, acentry); } -int64_t CWalletDB::GetAccountCreditDebit(const string& strAccount) +CAmount CWalletDB::GetAccountCreditDebit(const string& strAccount) { list<CAccountingEntry> entries; ListAccountCreditDebit(strAccount, entries); - int64_t nCreditDebit = 0; + CAmount nCreditDebit = 0; BOOST_FOREACH (const CAccountingEntry& entry, entries) nCreditDebit += entry.nCreditDebit; @@ -391,13 +391,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, wss.fAnyUnordered = true; pwallet->AddToWallet(wtx, true); - //// debug print - //LogPrintf("LoadWallet %s\n", wtx.GetHash().ToString()); - //LogPrintf(" %12d %s %s %s\n", - // wtx.vout[0].nValue, - // DateTimeStrFormat("%Y-%m-%d %H:%M:%S", wtx.GetBlockTime()), - // wtx.hashBlock.ToString(), - // wtx.mapValue["message"]); } else if (strType == "acentry") { @@ -708,7 +701,6 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash, vector<CWalletTx>& vWtx) { pwallet->vchDefaultKey = CPubKey(); - CWalletScanState wss; bool fNoncriticalErrors = false; DBErrors result = DB_LOAD_OK; diff --git a/src/walletdb.h b/src/walletdb.h index 2c5b608f3d..f3d6e61f8b 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_WALLETDB_H #define BITCOIN_WALLETDB_H +#include "amount.h" #include "db.h" #include "key.h" #include "keystore.h" @@ -118,7 +119,7 @@ public: bool EraseDestData(const std::string &address, const std::string &key); bool WriteAccountingEntry(const CAccountingEntry& acentry); - int64_t GetAccountCreditDebit(const std::string& strAccount); + CAmount GetAccountCreditDebit(const std::string& strAccount); void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries); DBErrors ReorderTransactions(CWallet* pwallet); |