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?

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())));
  • main.cpp : line 1346 and line 1352 why checking 2 times? – bitaps.com Oct 26 '15 at 0:57
  • @bitaps Dunno. Why not, though? – Nick ODell Oct 26 '15 at 1:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.