Skip to content

Commit ebf836d

Browse files
authored
Merge pull request #160 from instagibbs/feecleanup
[HF] Fee output logic cleanup, allow 0-value fees
2 parents 37ea542 + 987e98c commit ebf836d

File tree

5 files changed

+18
-27
lines changed

5 files changed

+18
-27
lines changed

src/main.cpp

+1-11
Original file line numberDiff line numberDiff line change
@@ -1773,8 +1773,6 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
17731773

17741774
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS);
17751775

1776-
if (!tx.HasValidFee())
1777-
return state.DoS(0, false, REJECT_INVALID, "bad-fees");
17781776
CAmount nFees = tx.GetFee()[policyAsset];
17791777

17801778
// nModifiedFees includes any fee deltas from PrioritiseTransaction
@@ -2621,9 +2619,6 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
26212619
}
26222620
}
26232621

2624-
// Tally transaction fees
2625-
if (!tx.HasValidFee())
2626-
return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange");
26272622
if (!VerifyAmounts(inputs, tx, pvChecks, cacheStore))
26282623
return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
26292624
strprintf("value in (%s) < value out", FormatMoney(nValueIn)));
@@ -2642,9 +2637,6 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
26422637
if (pvChecks)
26432638
pvChecks->reserve(tx.vin.size());
26442639

2645-
// Tally validity checked in CheckTxInputs
2646-
CAmountMap fee = tx.GetFee();
2647-
26482640
// The first loop above does all the inexpensive checks.
26492641
// Only if ALL inputs pass do we perform expensive ECDSA signature checks.
26502642
// Helps prevent CPU exhaustion attacks.
@@ -3290,8 +3282,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
32903282
mLocksCreated.insert(std::make_pair(txout.scriptPubKey.GetWithdrawLockGenesisHash(), std::make_pair(COutPoint(tx.GetHash(), j), txout.nValue.GetAmount())));
32913283
}
32923284
}
3293-
if (!tx.HasValidFee())
3294-
return state.DoS(100, error("ConnectBlock(): transaction fee overflowed"), REJECT_INVALID, "bad-fee-outofrange");
32953285
mapFees += tx.GetFee();
32963286
if (!MoneyRange(mapFees))
32973287
return state.DoS(100, error("ConnectBlock(): total block reward overflowed"), REJECT_INVALID, "bad-blockreward-outofrange");
@@ -3304,7 +3294,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
33043294
return state.DoS(100, error("ConnectBlock(): total block reward overflowed"), REJECT_INVALID, "bad-blockreward-outofrange");
33053295
if (!VerifyCoinbaseAmount(block.vtx[0], blockReward))
33063296
return state.DoS(100,
3307-
error("ConnectBlock(): coinbase pays too much (limit=%d)",
3297+
error("ConnectBlock(): coinbase pays too much, has fee or blinded outputs (limit=%d)",
33083298
blockReward[policyAsset]),
33093299
REJECT_INVALID, "bad-cb-amount");
33103300

src/primitives/transaction.cpp

-15
Original file line numberDiff line numberDiff line change
@@ -176,21 +176,6 @@ uint256 CTransaction::ComputeWitnessHash() const
176176
return ComputeFastMerkleRoot(leaves);
177177
}
178178

179-
bool CTransaction::HasValidFee() const
180-
{
181-
CAmountMap totalFee;
182-
for (unsigned int i = 0; i < vout.size(); i++) {
183-
CAmount fee = 0;
184-
if (vout[i].IsFee()) {
185-
fee = vout[i].nValue.GetAmount();
186-
if (fee == 0 || !MoneyRange(fee))
187-
return false;
188-
totalFee[vout[i].nAsset.GetAsset()] += fee;
189-
}
190-
}
191-
return MoneyRange(totalFee);
192-
}
193-
194179
CAmountMap CTransaction::GetFee() const
195180
{
196181
CAmountMap fee;

src/test/blind_tests.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
8585
tx3.vout.push_back(CTxOut(bitcoinID, 22, CScript()));
8686
BOOST_CHECK(VerifyAmounts(cache, tx3));
8787

88+
// Fees must have non-negative value
89+
tx3.vout.push_back(CTxOut(bitcoinID, 0, CScript()));
90+
BOOST_CHECK(VerifyAmounts(cache, tx3));
91+
92+
tx3.vout.push_back(CTxOut(bitcoinID, -1, CScript()));
93+
BOOST_CHECK(!VerifyAmounts(cache, tx3));
94+
95+
tx3.vout.pop_back();
96+
tx3.vout.pop_back();
97+
BOOST_CHECK(VerifyAmounts(cache, tx3));
98+
8899
// Try to blind with a single non-fee output, which fails as its blinding factor ends up being zero.
89100
std::vector<uint256> input_blinds;
90101
std::vector<uint256> input_asset_blinds;

src/test/verify_amounts_tests.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ BOOST_AUTO_TEST_CASE(verify_coinbase_test)
8888
tx.vout.push_back(CTxOut(CAsset(), 1, CScript() << OP_RETURN));
8989
BOOST_CHECK(!VerifyCoinbaseAmount(tx, mapFees));
9090
tx.vout.pop_back();
91+
92+
// Push fee output, must fail since coinbase cannot have fee
93+
tx.vout.push_back(CTxOut(CAsset(), 1, CScript()));
94+
BOOST_CHECK(!VerifyCoinbaseAmount(tx, mapFees));
95+
tx.vout.pop_back();
96+
9197
}
9298

9399
BOOST_AUTO_TEST_SUITE_END()

src/wallet/rpcwallet.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -2054,7 +2054,6 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
20542054

20552055
CAmountMap nCredit = wtx.GetCredit(filter);
20562056
CAmountMap nDebit = wtx.GetDebit(filter);
2057-
assert(wtx.HasValidFee());
20582057
CAmount nFee = (wtx.IsFromMe(filter) ? -wtx.GetFee()[policyAsset] : 0);
20592058
CAmountMap nNet = nCredit - nDebit;
20602059
nNet[policyAsset] -= nFee;

0 commit comments

Comments
 (0)