Transactions that have outputs value more then inputs value possible?

4

Transactions have 2 ways to get into blockchain in bitcoind:

  • mempool -> newblock

  • newblock no in mempool

lets check AcceptToMemoryPool function

https://github.com/bitcoin/bitcoin/blob/c719cefc417cc578f48b33069b764339a61054ce/src/main.cpp#L876

CAmount nFees = nValueIn-nValueOut;

in case outs > ins

nFees<0

if (mempoolRejectFee > 0 && nFees < mempoolRejectFee) {
        return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee));

negative nFees will be rejected all is good in this point

ok lets check Connectblock function

https://github.com/bitcoin/bitcoin/blob/c719cefc417cc578f48b33069b764339a61054ce/src/main.cpp#L1805

for each tx in block we do:

nFees += view.GetValueIn(tx)-tx.GetValueOut();

https://github.com/bitcoin/bitcoin/blob/c719cefc417cc578f48b33069b764339a61054ce/src/main.cpp#L1826

 CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus());
if (block.vtx[0].GetValueOut() > blockReward)
    return state.DoS(100,
                     error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
                           block.vtx[0].GetValueOut(), blockReward),
                           REJECT_INVALID, "bad-cb-amount");

At this point we calculate max possible reward for this block: all tx fees + mining reward

then we check that coinbase reward not more then this value

what if same miner create and include transaction that have inputs for 1 btc and have outputs for 2 btc, so fee for this tx will be -1 btc

then miner can set reward for coinbase transaction to 25 btc + all fees - 1 btc.

so this (block.vtx[0].GetValueOut() > blockReward) return True

as result we have Transaction, that create more coins then received, inside blockchain

Where is my error?

bitaps.com

Posted 2015-10-26T00:25:50.057

Reputation: 563

Answers

5

That isn't allowed, even within a block. Here is the code that checks for that:

main.cpp: ConnectBlock

    if (!CheckInputs(tx, state, view, fScriptChecks, flags, false, nScriptCheckThreads ? &vChecks : NULL))
        return error("ConnectBlock(): CheckInputs on %s failed with %s",
            tx.GetHash().ToString(), FormatStateMessage(state));

main.cpp: CheckInputs

if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs)))
    return false;

main.cpp: CheckTxInputs

for (unsigned int i = 0; i < tx.vin.size(); i++)
{
    const COutPoint &prevout = tx.vin[i].prevout;
    const CCoins *coins = inputs.AccessCoins(prevout.hash);
    // [11 lines snipped]
    nValueIn += coins->vout[prevout.n].nValue;
    // [3 lines snipped]
}

if (nValueIn < tx.GetValueOut())
    return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
        strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())));

Nick ODell

Posted 2015-10-26T00:25:50.057

Reputation: 26 536

main.cpp : line 1346 and line 1352 why checking 2 times?bitaps.com 2015-10-26T00:57:53.220

@bitaps Dunno. Why not, though?Nick ODell 2015-10-26T01:01:38.827