Since Bitcoin Core v0.8, we’ve used a per-tx model for the chainstate database and its cache. This means that the database is effectively a map from txids to the list of unspent outputs for that transaction. This PR changes that to a map from outpoints ((txid,index) pairs) to just the individual unspent output for that outpoint.
The original reason for aggregating the outputs per transaction was to save space: this way, we could avoid duplicating the txid and transaction meta across the multiple outputs. However, LevelDB internally uses an encoding that omits repeated prefix bytes in keys, and because of that, duplicating the txids is not very significant.
There are many advantages for using a per-txout model:
- Simpler code.
- Avoiding the CPU overhead of deserializing and serializing the unused outputs.
- More predictable memory usage.
- More easily adaptable to various cache flushing strategies.
Downsides:
- Slightly larger on-disk representation, and sometimes larger in-memory representation (when there are multiple outputs for the same txid in the cache, which becomes optional).
This PR includes:
- The main commit from #10248. We’ll be dropping tx nVersion from the undo data later, so reserializing data from disk won’t roundtrip anymore. This change allows us to compute the checksum based on the written data rather than the reserialized data.
- #10249, as we’ll be using some c++11 methods of std::unordered_map which aren’t available in all versions of boost::unordered_map.
- #10250, as the new tests trigger the problem fixed there.
- A forward-compatible undo data format change (new versions can use old undo data, not the other way around).
- Switch to a new per-txout coinsview model with related database changes.
- Upgrade code to convert the old chainstate to a new chainstate (which is interruptible).
- Adapted unit and functional tests (thanks to @ryanofsky for adapting the unit tests).
Tests:
- All existing unit and functional tests pass.
- Manually verified that continuing a reindex started with old code succeeds (even when recovering from a crash in the middle of flushing while upgrading).
Commit links:
Preparation:
- e66dbde6d14cb5f253b3bf8850a98f4fda2d9f49: Add SizeEstimate to CDBBatch
- f54580e7e4f225bb615204daef32f72ab8688418: error() in disconnect for disk corruption, not inconsistency
- e484652fc36ef7135cf08ad380ea7142b6cbadc0: Introduce CHashVerifier to hash read data
- 7e0032290669fae5f52c256856c53038511c7db4: Add specialization of SipHash for 256 + 32 bit data
- d342424301013ec47dc146a4beb49d5c9319d80a: Remove/ignore tx version in utxo and undo
- c3aa0c11947dfd82702df276d39bb7f748dd83a1: Report on-disk size in gettxoutsetinfo
- 7d991b55dbf0b0f6e21c0680ee3ebd09df09012f: Store/allow tx metadata in all undo records
Switch to COutPoint/Coin instead of uint256/CCoins:
- 422634e2f5ac1ff74cd358144cecbac63007adc4: Introduce Coin, a single unspent output
- cb2c7fdac2dc74368ed24ae4717ed72178956b92: Replace CTxInUndo with Coin
- bd83111a0fcfdb97204a0180bcf861d3b53bb6c2: Optimization: Coin&& to ApplyTxInUndo
- 000391132608343c66488d62625c714814959bc9: Introduce new per-txout CCoinsViewCache functions
- f68cdfe92b37f5a75be612b7de3c1a03245696d0: Switch from per-tx to per-txout CCoinsViewCache methods in some places
- c87b957a32e03c09d410abadf661f87eb813bcdb: Only pass things committed to by tx’s witness hash to CScriptCheck
- 8b3868c1b4bf89c41b26ecb3a4b7c3a2557e3868: Switch CScriptCheck to use Coin instead of CCoins
- 961e4839793f8b4ad37d29672faf1695ff6ec03a: Switch tests from ModifyCoins to AddCoin/SpendCoin
- 05293f3cb75ad08ca23cba8e795e27d4d5e4d690: Remove ModifyCoins/ModifyNewCoins
- 13870b56fcd0bfacedce3ae42a3de3d5e9dc7bc1: Replace CCoins-based CTxMemPool::pruneSpent with isSpent
- 4ec0d9e794e3f338e1ebb8b644ae890d2c2da2ee: Refactor GetUTXOStats in preparation for per-COutPoint iteration
- 50830796889ecaa458871f1db878c255dd2554cb: Switch CCoinsView and chainstate db from per-txid to per-txout
Cleanup:
- ce23efaa5c2e8e50744a896424b01052db34a3d6: Extend coins_tests
- 97072d6685564dd50aab4c145b1758ccc10863b3: Remove unused CCoins methods
- 41aa5b79a3d79f8afe4c556b4f14fb1dc0cc3f9f: Pack Coin more tightly
- b2af357f39c7d17ab6ddb2938531155bf90126ec: Reduce reserved memory space for flushing
- 8b25d2c0ce64d7f8577a0c2e601e505c9f1140bf: Upgrade from per-tx database to per-txout
- 580b023092a28f444068b53792eb542f9d5e6892: [MOVEONLY] Move old CCoins class to txdb.cpp
- 119e552f7ccd49c0137a3c6b4f94018a84d69620: Merge CCoinsViewCache’s GetOutputFor and AccessCoin
- 73de2c1ff345ac38c098d7b1bef03176f3ea1f16: Rename CCoinsCacheEntry::coins to coin
- a5e02bc7f8a1af27fcafd892d8da651e8f1ab156: Increase travis unit test timeout
- 589827975f9f241e2f23eb674a7383592bff1cad: scripted-diff: various renames for per-utxo consistency