1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
8 #include "chainparams.h"
17 #include <boost/thread.hpp>
19 static const char DB_COIN
= 'C';
20 static const char DB_COINS
= 'c';
21 static const char DB_BLOCK_FILES
= 'f';
22 static const char DB_TXINDEX
= 't';
23 static const char DB_BLOCK_INDEX
= 'b';
25 static const char DB_BEST_BLOCK
= 'B';
26 static const char DB_HEAD_BLOCKS
= 'H';
27 static const char DB_FLAG
= 'F';
28 static const char DB_REINDEX_FLAG
= 'R';
29 static const char DB_LAST_BLOCK
= 'l';
36 CoinEntry(const COutPoint
* ptr
) : outpoint(const_cast<COutPoint
*>(ptr
)), key(DB_COIN
) {}
38 template<typename Stream
>
39 void Serialize(Stream
&s
) const {
42 s
<< VARINT(outpoint
->n
);
45 template<typename Stream
>
46 void Unserialize(Stream
& s
) {
49 s
>> VARINT(outpoint
->n
);
55 CCoinsViewDB::CCoinsViewDB(size_t nCacheSize
, bool fMemory
, bool fWipe
) : db(GetDataDir() / "chainstate", nCacheSize
, fMemory
, fWipe
, true)
59 bool CCoinsViewDB::GetCoin(const COutPoint
&outpoint
, Coin
&coin
) const {
60 return db
.Read(CoinEntry(&outpoint
), coin
);
63 bool CCoinsViewDB::HaveCoin(const COutPoint
&outpoint
) const {
64 return db
.Exists(CoinEntry(&outpoint
));
67 uint256
CCoinsViewDB::GetBestBlock() const {
68 uint256 hashBestChain
;
69 if (!db
.Read(DB_BEST_BLOCK
, hashBestChain
))
74 std::vector
<uint256
> CCoinsViewDB::GetHeadBlocks() const {
75 std::vector
<uint256
> vhashHeadBlocks
;
76 if (!db
.Read(DB_HEAD_BLOCKS
, vhashHeadBlocks
)) {
77 return std::vector
<uint256
>();
79 return vhashHeadBlocks
;
82 bool CCoinsViewDB::BatchWrite(CCoinsMap
&mapCoins
, const uint256
&hashBlock
) {
86 size_t batch_size
= (size_t)GetArg("-dbbatchsize", nDefaultDbBatchSize
);
87 int crash_simulate
= GetArg("-dbcrashratio", 0);
88 assert(!hashBlock
.IsNull());
90 uint256 old_tip
= GetBestBlock();
91 if (old_tip
.IsNull()) {
92 // We may be in the middle of replaying.
93 std::vector
<uint256
> old_heads
= GetHeadBlocks();
94 if (old_heads
.size() == 2) {
95 assert(old_heads
[0] == hashBlock
);
96 old_tip
= old_heads
[1];
100 // In the first batch, mark the database as being in the middle of a
101 // transition from old_tip to hashBlock.
102 // A vector is used for future extensibility, as we may want to support
103 // interrupting after partial writes from multiple independent reorgs.
104 batch
.Erase(DB_BEST_BLOCK
);
105 batch
.Write(DB_HEAD_BLOCKS
, std::vector
<uint256
>{hashBlock
, old_tip
});
107 for (CCoinsMap::iterator it
= mapCoins
.begin(); it
!= mapCoins
.end();) {
108 if (it
->second
.flags
& CCoinsCacheEntry::DIRTY
) {
109 CoinEntry
entry(&it
->first
);
110 if (it
->second
.coin
.IsSpent())
113 batch
.Write(entry
, it
->second
.coin
);
117 CCoinsMap::iterator itOld
= it
++;
118 mapCoins
.erase(itOld
);
119 if (batch
.SizeEstimate() > batch_size
) {
120 LogPrint(BCLog::COINDB
, "Writing partial batch of %.2f MiB\n", batch
.SizeEstimate() * (1.0 / 1048576.0));
121 db
.WriteBatch(batch
);
123 if (crash_simulate
) {
124 static FastRandomContext rng
;
125 if (rng
.randrange(crash_simulate
) == 0) {
126 LogPrintf("Simulating a crash. Goodbye.\n");
133 // In the last batch, mark the database as consistent with hashBlock again.
134 batch
.Erase(DB_HEAD_BLOCKS
);
135 batch
.Write(DB_BEST_BLOCK
, hashBlock
);
137 LogPrint(BCLog::COINDB
, "Writing final batch of %.2f MiB\n", batch
.SizeEstimate() * (1.0 / 1048576.0));
138 bool ret
= db
.WriteBatch(batch
);
139 LogPrint(BCLog::COINDB
, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed
, (unsigned int)count
);
143 size_t CCoinsViewDB::EstimateSize() const
145 return db
.EstimateSize(DB_COIN
, (char)(DB_COIN
+1));
148 CBlockTreeDB::CBlockTreeDB(size_t nCacheSize
, bool fMemory
, bool fWipe
) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize
, fMemory
, fWipe
) {
151 bool CBlockTreeDB::ReadBlockFileInfo(int nFile
, CBlockFileInfo
&info
) {
152 return Read(std::make_pair(DB_BLOCK_FILES
, nFile
), info
);
155 bool CBlockTreeDB::WriteReindexing(bool fReindexing
) {
157 return Write(DB_REINDEX_FLAG
, '1');
159 return Erase(DB_REINDEX_FLAG
);
162 bool CBlockTreeDB::ReadReindexing(bool &fReindexing
) {
163 fReindexing
= Exists(DB_REINDEX_FLAG
);
167 bool CBlockTreeDB::ReadLastBlockFile(int &nFile
) {
168 return Read(DB_LAST_BLOCK
, nFile
);
171 CCoinsViewCursor
*CCoinsViewDB::Cursor() const
173 CCoinsViewDBCursor
*i
= new CCoinsViewDBCursor(const_cast<CDBWrapper
*>(&db
)->NewIterator(), GetBestBlock());
174 /* It seems that there are no "const iterators" for LevelDB. Since we
175 only need read operations on it, use a const-cast to get around
177 i
->pcursor
->Seek(DB_COIN
);
178 // Cache key of first record
179 if (i
->pcursor
->Valid()) {
180 CoinEntry
entry(&i
->keyTmp
.second
);
181 i
->pcursor
->GetKey(entry
);
182 i
->keyTmp
.first
= entry
.key
;
184 i
->keyTmp
.first
= 0; // Make sure Valid() and GetKey() return false
189 bool CCoinsViewDBCursor::GetKey(COutPoint
&key
) const
192 if (keyTmp
.first
== DB_COIN
) {
199 bool CCoinsViewDBCursor::GetValue(Coin
&coin
) const
201 return pcursor
->GetValue(coin
);
204 unsigned int CCoinsViewDBCursor::GetValueSize() const
206 return pcursor
->GetValueSize();
209 bool CCoinsViewDBCursor::Valid() const
211 return keyTmp
.first
== DB_COIN
;
214 void CCoinsViewDBCursor::Next()
217 CoinEntry
entry(&keyTmp
.second
);
218 if (!pcursor
->Valid() || !pcursor
->GetKey(entry
)) {
219 keyTmp
.first
= 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
221 keyTmp
.first
= entry
.key
;
225 bool CBlockTreeDB::WriteBatchSync(const std::vector
<std::pair
<int, const CBlockFileInfo
*> >& fileInfo
, int nLastFile
, const std::vector
<const CBlockIndex
*>& blockinfo
) {
226 CDBBatch
batch(*this);
227 for (std::vector
<std::pair
<int, const CBlockFileInfo
*> >::const_iterator it
=fileInfo
.begin(); it
!= fileInfo
.end(); it
++) {
228 batch
.Write(std::make_pair(DB_BLOCK_FILES
, it
->first
), *it
->second
);
230 batch
.Write(DB_LAST_BLOCK
, nLastFile
);
231 for (std::vector
<const CBlockIndex
*>::const_iterator it
=blockinfo
.begin(); it
!= blockinfo
.end(); it
++) {
232 batch
.Write(std::make_pair(DB_BLOCK_INDEX
, (*it
)->GetBlockHash()), CDiskBlockIndex(*it
));
234 return WriteBatch(batch
, true);
237 bool CBlockTreeDB::ReadTxIndex(const uint256
&txid
, CDiskTxPos
&pos
) {
238 return Read(std::make_pair(DB_TXINDEX
, txid
), pos
);
241 bool CBlockTreeDB::WriteTxIndex(const std::vector
<std::pair
<uint256
, CDiskTxPos
> >&vect
) {
242 CDBBatch
batch(*this);
243 for (std::vector
<std::pair
<uint256
,CDiskTxPos
> >::const_iterator it
=vect
.begin(); it
!=vect
.end(); it
++)
244 batch
.Write(std::make_pair(DB_TXINDEX
, it
->first
), it
->second
);
245 return WriteBatch(batch
);
248 bool CBlockTreeDB::WriteFlag(const std::string
&name
, bool fValue
) {
249 return Write(std::make_pair(DB_FLAG
, name
), fValue
? '1' : '0');
252 bool CBlockTreeDB::ReadFlag(const std::string
&name
, bool &fValue
) {
254 if (!Read(std::make_pair(DB_FLAG
, name
), ch
))
260 bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params
& consensusParams
, std::function
<CBlockIndex
*(const uint256
&)> insertBlockIndex
)
262 std::unique_ptr
<CDBIterator
> pcursor(NewIterator());
264 pcursor
->Seek(std::make_pair(DB_BLOCK_INDEX
, uint256()));
266 // Load mapBlockIndex
267 while (pcursor
->Valid()) {
268 boost::this_thread::interruption_point();
269 std::pair
<char, uint256
> key
;
270 if (pcursor
->GetKey(key
) && key
.first
== DB_BLOCK_INDEX
) {
271 CDiskBlockIndex diskindex
;
272 if (pcursor
->GetValue(diskindex
)) {
273 // Construct block index object
274 CBlockIndex
* pindexNew
= insertBlockIndex(diskindex
.GetBlockHash());
275 pindexNew
->pprev
= insertBlockIndex(diskindex
.hashPrev
);
276 pindexNew
->nHeight
= diskindex
.nHeight
;
277 pindexNew
->nFile
= diskindex
.nFile
;
278 pindexNew
->nDataPos
= diskindex
.nDataPos
;
279 pindexNew
->nUndoPos
= diskindex
.nUndoPos
;
280 pindexNew
->nVersion
= diskindex
.nVersion
;
281 pindexNew
->hashMerkleRoot
= diskindex
.hashMerkleRoot
;
282 pindexNew
->nTime
= diskindex
.nTime
;
283 pindexNew
->nBits
= diskindex
.nBits
;
284 pindexNew
->nNonce
= diskindex
.nNonce
;
285 pindexNew
->nStatus
= diskindex
.nStatus
;
286 pindexNew
->nTx
= diskindex
.nTx
;
288 if (!CheckProofOfWork(pindexNew
->GetBlockHash(), pindexNew
->nBits
, consensusParams
))
289 return error("%s: CheckProofOfWork failed: %s", __func__
, pindexNew
->ToString());
293 return error("%s: failed to read value", __func__
);
305 //! Legacy class to deserialize pre-pertxout database entries without reindex.
309 //! whether transaction is a coinbase
312 //! unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
313 std::vector
<CTxOut
> vout
;
315 //! at which height this transaction was included in the active block chain
318 //! empty constructor
319 CCoins() : fCoinBase(false), vout(0), nHeight(0) { }
321 template<typename Stream
>
322 void Unserialize(Stream
&s
) {
323 unsigned int nCode
= 0;
326 ::Unserialize(s
, VARINT(nVersionDummy
));
328 ::Unserialize(s
, VARINT(nCode
));
329 fCoinBase
= nCode
& 1;
330 std::vector
<bool> vAvail(2, false);
331 vAvail
[0] = (nCode
& 2) != 0;
332 vAvail
[1] = (nCode
& 4) != 0;
333 unsigned int nMaskCode
= (nCode
/ 8) + ((nCode
& 6) != 0 ? 0 : 1);
335 while (nMaskCode
> 0) {
336 unsigned char chAvail
= 0;
337 ::Unserialize(s
, chAvail
);
338 for (unsigned int p
= 0; p
< 8; p
++) {
339 bool f
= (chAvail
& (1 << p
)) != 0;
346 vout
.assign(vAvail
.size(), CTxOut());
347 for (unsigned int i
= 0; i
< vAvail
.size(); i
++) {
349 ::Unserialize(s
, REF(CTxOutCompressor(vout
[i
])));
352 ::Unserialize(s
, VARINT(nHeight
));
358 /** Upgrade the database from older formats.
360 * Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout.
362 bool CCoinsViewDB::Upgrade() {
363 std::unique_ptr
<CDBIterator
> pcursor(db
.NewIterator());
364 pcursor
->Seek(std::make_pair(DB_COINS
, uint256()));
365 if (!pcursor
->Valid()) {
369 LogPrintf("Upgrading database...\n");
370 size_t batch_size
= 1 << 24;
372 while (pcursor
->Valid()) {
373 boost::this_thread::interruption_point();
374 std::pair
<unsigned char, uint256
> key
;
375 if (pcursor
->GetKey(key
) && key
.first
== DB_COINS
) {
377 if (!pcursor
->GetValue(old_coins
)) {
378 return error("%s: cannot parse CCoins record", __func__
);
380 COutPoint
outpoint(key
.second
, 0);
381 for (size_t i
= 0; i
< old_coins
.vout
.size(); ++i
) {
382 if (!old_coins
.vout
[i
].IsNull() && !old_coins
.vout
[i
].scriptPubKey
.IsUnspendable()) {
383 Coin
newcoin(std::move(old_coins
.vout
[i
]), old_coins
.nHeight
, old_coins
.fCoinBase
);
385 CoinEntry
entry(&outpoint
);
386 batch
.Write(entry
, newcoin
);
390 if (batch
.SizeEstimate() > batch_size
) {
391 db
.WriteBatch(batch
);
399 db
.WriteBatch(batch
);