Remove CCoinsViewCache::GetValueIn(...)
.
Fixes #18858.
It seems like GetValueIn
was added in #748 (“Pay-to-script-hash (OP_EVAL replacement)”, merged in 2012) and the last use in validation code was removed in #8498 (“Near-Bugfix: Optimization: Minimize the number of times it is checked that no money…”, merged in 2017).
CCoinsViewCache::GetValueIn(…)
performs money summation like this:
0CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
1{
2 if (tx.IsCoinBase())
3 return 0;
4
5 CAmount nResult = 0;
6 for (unsigned int i = 0; i < tx.vin.size(); i++)
7 nResult += AccessCoin(tx.vin[i].prevout).out.nValue;
8
9 return nResult;
10}
Note that no check is done to make sure that the resulting nResult
is such that it stays within the money bounds (MoneyRange(nResult)
), or that the summation does not trigger a signed integer overflow.
Proof of concept output:
0coins.cpp:243:17: runtime error: signed integer overflow: 9223200000000000000 + 2100000000000000 cannot be represented in type 'long'
1GetValueIn = -9221444073709551616
Proof of concept code:
0CMutableTransaction mutable_transaction;
1mutable_transaction.vin.resize(4393);
2
3Coin coin;
4coin.out.nValue = MAX_MONEY;
5assert(MoneyRange(coin.out.nValue));
6
7CCoinsCacheEntry coins_cache_entry;
8coins_cache_entry.coin = coin;
9coins_cache_entry.flags = CCoinsCacheEntry::DIRTY;
10
11CCoinsView backend_coins_view;
12CCoinsViewCache coins_view_cache{&backend_coins_view};
13CCoinsMap coins_map;
14coins_map.emplace(COutPoint{}, std::move(coins_cache_entry));
15coins_view_cache.BatchWrite(coins_map, {});
16
17const CAmount total_value_in = coins_view_cache.GetValueIn(CTransaction{mutable_transaction});
18std::cout << "GetValueIn = " << total_value_in << std::endl;