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;
As far as I can tell CCoinsViewCache::GetValueIn
is unused outside of tests:
0$ git grep GetValueIn ":(exclude)src/test/" ":(exclude)src/bench/"
1src/coins.cpp:CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
2src/coins.h: CAmount GetValueIn(const CTransaction& tx) const;
3src/primitives/transaction.h: // GetValueIn() is a method on CCoinsViewCache, because
I suggest we drop the unused CCoinsViewCache::GetValueIn(…)
.
Any objections? :)