From 553cdeea0063a323abddeae0a3bdfe2f70775b26 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 12 Dec 2016 15:44:47 -0500 Subject: [PATCH] Greatly simplify coinbase balance checking --- src/validation.cpp | 25 ++++++++++++++++--------- src/validation.h | 5 +++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 765bd9059d..c7b157acda 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -654,6 +654,7 @@ bool CSurjectionCheck::operator()() bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, const CAmount& excess, const uint256& excessID, std::vector* pvChecks, const bool cacheStore) { + assert(!tx.IsCoinBase()); std::vector vData; std::vector vpCommitsIn, vpCommitsOut; @@ -790,14 +791,6 @@ bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, const C } } - // Blinded assets and surjection proofs not supported for coinbase - if (tx.IsCoinBase()) { - for (size_t i = 0; i < tx.vout.size(); i++) { - if (!tx.vout[i].nAsset.IsAssetID() || !tx.vout[i].nAsset.vchSurjectionproof.empty()) - return false; - } - return true; - } //Surjection proof checking of ephemeral asset keys std::vector ephemeral_input_tags; @@ -845,6 +838,20 @@ bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, const C return true; } +bool VerifyCoinbaseAmount(const CTransaction& tx, const CAmount& fees, const uint256& feeID) +{ + assert(tx.IsCoinBase()); + CAmount remaining = fees; + for (unsigned int i = 0; i < tx.vout.size(); i++) { + if (!tx.vout[i].nValue.IsAmount() || !tx.vout[i].nAsset.IsAssetID()) + return false; + if (feeID != BITCOINID) + return false; + remaining -= tx.vout[i].nValue.GetAmount(); + } + return MoneyRange(remaining); +} + void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) { int expired = pool.Expire(GetTime() - age); if (expired != 0) @@ -2572,7 +2579,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CAmount blockReward = nFees; if (!MoneyRange(blockReward)) return state.DoS(100, error("ConnectBlock(): total block reward overflowed"), REJECT_INVALID, "bad-blockreward-outofrange"); - if (!VerifyAmounts(view, *(block.vtx[0]), -blockReward, BITCOINID)) + if (!VerifyCoinbaseAmount(*(block.vtx[0]), -blockReward, BITCOINID)) return state.DoS(100, error("ConnectBlock(): coinbase pays too much (limit=%d)", blockReward), diff --git a/src/validation.h b/src/validation.h index 036c3c1e8f..736e7b3b86 100644 --- a/src/validation.h +++ b/src/validation.h @@ -408,6 +408,11 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins */ bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, const CAmount& excess, const uint256& excessID, std::vector* pvChecks = NULL, const bool cacheStore = false); +/** + * Verify the amounts of coinbase transactions. It will fail for any blinded amount or type. + * Each output must be IsAmount && IsAssetID. +*/ +bool VerifyCoinbaseAmount(const CTransaction& tx, const CAmount& fees, const uint256& feeID); /** * Check if transaction is final and can be included in a block with the