diff --git a/src/amount.h b/src/amount.h index 69b7ca77a1..dae859719d 100644 --- a/src/amount.h +++ b/src/amount.h @@ -1,173 +1,172 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers // Copyright (c) 2017-2019 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 #include #include #include #include struct Amount { private: int64_t amount; explicit constexpr Amount(int64_t _amount) : amount(_amount) {} public: constexpr Amount() : amount(0) {} constexpr Amount(const Amount &other) : amount(other.amount) {} /** * Assignement operator. */ constexpr Amount &operator=(const Amount &other) { amount = other.amount; return *this; } static constexpr Amount zero() { return Amount(0); } static constexpr Amount satoshi() { return Amount(1); } /** * Implement standard operators */ Amount &operator+=(const Amount a) { amount += a.amount; return *this; } Amount &operator-=(const Amount a) { amount -= a.amount; return *this; } /** * Equality */ friend constexpr bool operator==(const Amount a, const Amount b) { return a.amount == b.amount; } friend constexpr bool operator!=(const Amount a, const Amount b) { return !(a == b); } /** * Comparison */ friend constexpr bool operator<(const Amount a, const Amount b) { return a.amount < b.amount; } friend constexpr bool operator>(const Amount a, const Amount b) { return b < a; } friend constexpr bool operator<=(const Amount a, const Amount b) { return !(a > b); } friend constexpr bool operator>=(const Amount a, const Amount b) { return !(a < b); } /** * Unary minus */ constexpr Amount operator-() const { return Amount(-amount); } /** * Addition and subtraction. */ friend constexpr Amount operator+(const Amount a, const Amount b) { return Amount(a.amount + b.amount); } friend constexpr Amount operator-(const Amount a, const Amount b) { return a + -b; } /** * Multiplication */ friend constexpr Amount operator*(const int64_t a, const Amount b) { return Amount(a * b.amount); } friend constexpr Amount operator*(const int a, const Amount b) { return Amount(a * b.amount); } /** * Division */ constexpr int64_t operator/(const Amount b) const { return amount / b.amount; } constexpr Amount operator/(const int64_t b) const { return Amount(amount / b); } constexpr Amount operator/(const int b) const { return Amount(amount / b); } Amount &operator/=(const int64_t n) { amount /= n; return *this; } /** * Modulus */ constexpr Amount operator%(const Amount b) const { return Amount(amount % b.amount); } constexpr Amount operator%(const int64_t b) const { return Amount(amount % b); } constexpr Amount operator%(const int b) const { return Amount(amount % b); } /** * Do not implement double ops to get an error with double and ensure * casting to integer is explicit. */ friend constexpr Amount operator*(const double a, const Amount b) = delete; constexpr Amount operator/(const double b) const = delete; constexpr Amount operator%(const double b) const = delete; // ostream support friend std::ostream &operator<<(std::ostream &stream, const Amount &ca) { return stream << ca.amount; } std::string ToString() const; // serialization support ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream &s, Operation ser_action) { READWRITE(amount); } }; static constexpr Amount SATOSHI = Amount::satoshi(); static constexpr Amount CASH = 100 * SATOSHI; static constexpr Amount COIN = 100000000 * SATOSHI; -static constexpr Amount CENT = COIN / 100; extern const std::string CURRENCY_UNIT; /** * No amount larger than this (in satoshi) is valid. * * Note that this constant is *not* the total money supply, which in Bitcoin * currently happens to be less than 21,000,000 BCH for various reasons, but * rather a sanity check. As this sanity check is used by consensus-critical * validation code, the exact value of the MAX_MONEY constant is consensus * critical; in unusual circumstances like a(nother) overflow bug that allowed * for the creation of coins out of thin air modification could lead to a fork. */ static const Amount MAX_MONEY = 21000000 * COIN; inline bool MoneyRange(const Amount nValue) { return nValue >= Amount::zero() && nValue <= MAX_MONEY; } #endif // BITCOIN_AMOUNT_H diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp index 5a25523c91..1ec1210f2e 100644 --- a/src/bench/ccoins_caching.cpp +++ b/src/bench/ccoins_caching.cpp @@ -1,91 +1,91 @@ // Copyright (c) 2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include // FIXME: Dedup with SetupDummyInputs in test/transaction_tests.cpp. // // Helper: create two dummy transactions, each with -// two outputs. The first has 11 and 50 CENT outputs -// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs +// two outputs. The first has 11 and 50 COIN outputs +// paid to a TX_PUBKEY, the second 21 and 22 COIN outputs // paid to a TX_PUBKEYHASH. // static std::vector SetupDummyInputs(CBasicKeyStore &keystoreRet, CCoinsViewCache &coinsRet) { std::vector dummyTransactions; dummyTransactions.resize(2); // Add some keys to the keystore: CKey key[4]; for (int i = 0; i < 4; i++) { key[i].MakeNewKey(i % 2); keystoreRet.AddKey(key[i]); } // Create some dummy input transactions dummyTransactions[0].vout.resize(2); - dummyTransactions[0].vout[0].nValue = 11 * CENT; + dummyTransactions[0].vout[0].nValue = 11 * COIN; dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG; - dummyTransactions[0].vout[1].nValue = 50 * CENT; + dummyTransactions[0].vout[1].nValue = 50 * COIN; dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG; AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0); dummyTransactions[1].vout.resize(2); - dummyTransactions[1].vout[0].nValue = 21 * CENT; + dummyTransactions[1].vout[0].nValue = 21 * COIN; dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID()); - dummyTransactions[1].vout[1].nValue = 22 * CENT; + dummyTransactions[1].vout[1].nValue = 22 * COIN; dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID()); AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0); return dummyTransactions; } // Microbenchmark for simple accesses to a CCoinsViewCache database. Note from // laanwj, "replicating the actual usage patterns of the client is hard though, // many times micro-benchmarks of the database showed completely different // characteristics than e.g. reindex timings. But that's not a requirement of // every benchmark." // (https://github.com/bitcoin/bitcoin/issues/7883#issuecomment-224807484) static void CCoinsCaching(benchmark::State &state) { CBasicKeyStore keystore; CCoinsView coinsDummy; CCoinsViewCache coins(&coinsDummy); std::vector dummyTransactions = SetupDummyInputs(keystore, coins); CMutableTransaction t1; t1.vin.resize(3); t1.vin[0].prevout = COutPoint(dummyTransactions[0].GetId(), 1); t1.vin[0].scriptSig << std::vector(65, 0); t1.vin[1].prevout = COutPoint(dummyTransactions[1].GetId(), 0); t1.vin[1].scriptSig << std::vector(65, 0) << std::vector(33, 4); t1.vin[2].prevout = COutPoint(dummyTransactions[1].GetId(), 1); t1.vin[2].scriptSig << std::vector(65, 0) << std::vector(33, 4); t1.vout.resize(2); - t1.vout[0].nValue = 90 * CENT; + t1.vout[0].nValue = 90 * COIN; t1.vout[0].scriptPubKey << OP_1; // Benchmark. while (state.KeepRunning()) { CTransaction t(t1); bool success = AreInputsStandard(t, coins, STANDARD_SCRIPT_VERIFY_FLAGS); assert(success); Amount value = coins.GetValueIn(t); - assert(value == (50 + 21 + 22) * CENT); + assert(value == (50 + 21 + 22) * COIN); } } BENCHMARK(CCoinsCaching, 170 * 1000); diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index edbae395d6..6aa47c341a 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -1,44 +1,44 @@ // Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include static void AddTx(const CTransactionRef &tx, const Amount &fee, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) { LockPoints lp; pool.addUnchecked(CTxMemPoolEntry(tx, fee, /* time */ 0, /* height */ 1, /* spendsCoinbase */ false, /* sigOpCount */ 1, lp)); } static void RpcMempool(benchmark::State &state) { CTxMemPool pool; LOCK2(cs_main, pool.cs); for (int i = 0; i < 1000; ++i) { CMutableTransaction tx = CMutableTransaction(); tx.vin.resize(1); tx.vin[0].scriptSig = CScript() << OP_1; tx.vout.resize(1); tx.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; - tx.vout[0].nValue = i * CENT; + tx.vout[0].nValue = i * COIN; const CTransactionRef tx_r{MakeTransactionRef(tx)}; - AddTx(tx_r, /* fee */ i * CENT, pool); + AddTx(tx_r, /* fee */ i * COIN, pool); } while (state.KeepRunning()) { (void)MempoolToJSON(pool, /*verbose*/ true); } } BENCHMARK(RpcMempool, 40); diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index 44fb9d27af..bab1eeca6f 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -1,162 +1,164 @@ // Copyright (c) 2015-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_TEST_TEST_BITCOIN_H #define BITCOIN_TEST_TEST_BITCOIN_H #include #include #include #include #include #include #include #include /** * Version of Boost::test prior to 1.64 have issues when dealing with nullptr_t. * In order to work around this, we ensure that the null pointers are typed in a * way that Boost will like better. * * TODO: Use nullptr directly once the minimum version of boost is 1.64 or more. */ #define NULLPTR(T) static_cast(nullptr) /** * This global and the helpers that use it are not thread-safe. * * If thread-safety is needed, the global could be made thread_local (given * that thread_local is supported on all architectures we support) or a * per-thread instance could be used in the multi-threaded test. */ extern FastRandomContext g_insecure_rand_ctx; /** * Flag to make GetRand in random.h return the same number */ extern bool g_mock_deterministic_tests; static inline void SeedInsecureRand(bool deterministic = false) { g_insecure_rand_ctx = FastRandomContext(deterministic); } static inline uint32_t InsecureRand32() { return g_insecure_rand_ctx.rand32(); } static inline uint256 InsecureRand256() { return g_insecure_rand_ctx.rand256(); } static inline uint64_t InsecureRandBits(int bits) { return g_insecure_rand_ctx.randbits(bits); } static inline uint64_t InsecureRandRange(uint64_t range) { return g_insecure_rand_ctx.randrange(range); } static inline bool InsecureRandBool() { return g_insecure_rand_ctx.randbool(); } +static constexpr Amount CENT(COIN / 100); + /** * Basic testing setup. * This just configures logging and chain parameters. */ struct BasicTestingSetup { ECCVerifyHandle globalVerifyHandle; explicit BasicTestingSetup( const std::string &chainName = CBaseChainParams::MAIN); ~BasicTestingSetup(); fs::path SetDataDir(const std::string &name); private: const fs::path m_path_root; }; /** * Testing setup that configures a complete environment. * Included are data directory, coins database, script check threads setup. */ struct TestingSetup : public BasicTestingSetup { boost::thread_group threadGroup; CScheduler scheduler; explicit TestingSetup( const std::string &chainName = CBaseChainParams::MAIN); ~TestingSetup(); }; class CBlock; class CMutableTransaction; class CScript; // // Testing fixture that pre-creates a // 100-block REGTEST-mode block chain // struct TestChain100Setup : public TestingSetup { TestChain100Setup(); // Create a new block with just given transactions, coinbase paying to // scriptPubKey, and try to add it to the current chain. CBlock CreateAndProcessBlock(const std::vector &txns, const CScript &scriptPubKey); ~TestChain100Setup(); // For convenience, coinbase transactions. std::vector m_coinbase_txns; // private/public key needed to spend coinbase transactions. CKey coinbaseKey; }; class CTxMemPoolEntry; struct TestMemPoolEntryHelper { // Default values Amount nFee; int64_t nTime; unsigned int nHeight; bool spendsCoinbase; unsigned int nSigOpCount; TestMemPoolEntryHelper() : nFee(), nTime(0), nHeight(1), spendsCoinbase(false), nSigOpCount(1) {} CTxMemPoolEntry FromTx(const CMutableTransaction &tx); CTxMemPoolEntry FromTx(const CTransactionRef &tx); // Change the default value TestMemPoolEntryHelper &Fee(Amount _fee) { nFee = _fee; return *this; } TestMemPoolEntryHelper &Time(int64_t _time) { nTime = _time; return *this; } TestMemPoolEntryHelper &Height(unsigned int _height) { nHeight = _height; return *this; } TestMemPoolEntryHelper &SpendsCoinbase(bool _flag) { spendsCoinbase = _flag; return *this; } TestMemPoolEntryHelper &SigOpCount(unsigned int _nSigOpCount) { nSigOpCount = _nSigOpCount; return *this; } }; enum class ScriptError; // define implicit conversions here so that these types may be used in // BOOST_*_EQUAL std::ostream &operator<<(std::ostream &os, const uint256 &num); std::ostream &operator<<(std::ostream &os, const ScriptError &err); CBlock getBlock13b8a(); #endif // BITCOIN_TEST_TEST_BITCOIN_H diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp index 7011f520ee..2971d4ebb6 100644 --- a/src/util/moneystr.cpp +++ b/src/util/moneystr.cpp @@ -1,80 +1,80 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include std::string FormatMoney(const Amount amt) { // Note: not using straight sprintf here because we do NOT want localized // number formatting. Amount amt_abs = amt > Amount::zero() ? amt : -amt; std::string str = strprintf("%d.%08d", amt_abs / COIN, (amt_abs % COIN) / SATOSHI); // Right-trim excess zeros before the decimal point: int nTrim = 0; for (int i = str.size() - 1; (str[i] == '0' && isdigit(str[i - 2])); --i) { ++nTrim; } if (nTrim) { str.erase(str.size() - nTrim, nTrim); } if (amt < Amount::zero()) { str.insert((unsigned int)0, 1, '-'); } return str; } bool ParseMoney(const std::string &str, Amount &nRet) { return ParseMoney(str.c_str(), nRet); } bool ParseMoney(const char *pszIn, Amount &nRet) { std::string strWhole; Amount nUnits = Amount::zero(); const char *p = pszIn; while (IsSpace(*p)) { p++; } for (; *p; p++) { if (*p == '.') { p++; - Amount nMult = 10 * CENT; + Amount nMult = COIN / 10; while (isdigit(*p) && (nMult > Amount::zero())) { nUnits += (*p++ - '0') * nMult; nMult /= 10; } break; } if (IsSpace(*p)) { break; } if (!isdigit(*p)) { return false; } strWhole.insert(strWhole.end(), *p); } for (; *p; p++) { if (!IsSpace(*p)) { return false; } } // guard against 63 bit overflow if (strWhole.size() > 10) { return false; } if (nUnits < Amount::zero() || nUnits > COIN) { return false; } Amount nWhole = atoi64(strWhole) * COIN; nRet = nWhole + Amount(nUnits); return true; } diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h index f9977f388a..26c1051a75 100644 --- a/src/wallet/coinselection.h +++ b/src/wallet/coinselection.h @@ -1,113 +1,113 @@ // Copyright (c) 2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_WALLET_COINSELECTION_H #define BITCOIN_WALLET_COINSELECTION_H #include #include #include //! target minimum change amount -static const Amount MIN_CHANGE = CENT; +static constexpr Amount MIN_CHANGE{COIN / 100}; //! final minimum change amount after paying for fees static const Amount MIN_FINAL_CHANGE = MIN_CHANGE / 2; class CInputCoin { public: CInputCoin(const CTransactionRef &tx, unsigned int i) { if (!tx) { throw std::invalid_argument("tx should not be null"); } if (i >= tx->vout.size()) { throw std::out_of_range("The output index is out of range"); } outpoint = COutPoint(tx->GetId(), i); txout = tx->vout[i]; effective_value = txout.nValue; } CInputCoin(const CTransactionRef &tx, unsigned int i, int input_bytes) : CInputCoin(tx, i) { m_input_bytes = input_bytes; } COutPoint outpoint; CTxOut txout; Amount effective_value; /** * Pre-computed estimated size of this output as a fully-signed input in a * transaction. Can be -1 if it could not be calculated. */ int m_input_bytes{-1}; bool operator<(const CInputCoin &rhs) const { return outpoint < rhs.outpoint; } bool operator!=(const CInputCoin &rhs) const { return outpoint != rhs.outpoint; } bool operator==(const CInputCoin &rhs) const { return outpoint == rhs.outpoint; } }; struct CoinEligibilityFilter { const int conf_mine; const int conf_theirs; const uint64_t max_ancestors; const uint64_t max_descendants; CoinEligibilityFilter(int conf_mine_, int conf_theirs_, uint64_t max_ancestors_) : conf_mine(conf_mine_), conf_theirs(conf_theirs_), max_ancestors(max_ancestors_), max_descendants(max_ancestors_) {} CoinEligibilityFilter(int conf_mine_, int conf_theirs_, uint64_t max_ancestors_, uint64_t max_descendants_) : conf_mine(conf_mine_), conf_theirs(conf_theirs_), max_ancestors(max_ancestors_), max_descendants(max_descendants_) {} }; struct OutputGroup { std::vector m_outputs; bool m_from_me{true}; Amount m_value = Amount::zero(); int m_depth{999}; size_t m_ancestors{0}; size_t m_descendants{0}; Amount effective_value = Amount::zero(); Amount fee = Amount::zero(); Amount long_term_fee = Amount::zero(); OutputGroup() {} OutputGroup(std::vector &&outputs, bool from_me, Amount value, int depth, size_t ancestors, size_t descendants) : m_outputs(std::move(outputs)), m_from_me(from_me), m_value(value), m_depth(depth), m_ancestors(ancestors), m_descendants(descendants) {} OutputGroup(const CInputCoin &output, int depth, bool from_me, size_t ancestors, size_t descendants) : OutputGroup() { Insert(output, depth, from_me, ancestors, descendants); } void Insert(const CInputCoin &output, int depth, bool from_me, size_t ancestors, size_t descendants); std::vector::iterator Discard(const CInputCoin &output); bool EligibleForSpending(const CoinEligibilityFilter &eligibility_filter) const; }; bool SelectCoinsBnB(std::vector &utxo_pool, const Amount &target_value, const Amount &cost_of_change, std::set &out_set, Amount &value_ret, const Amount not_input_fees); // Original coin selection algorithm as a fallback bool KnapsackSolver(const Amount nTargetValue, std::vector &groups, std::set &setCoinsRet, Amount &nValueRet); #endif // BITCOIN_WALLET_COINSELECTION_H