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"
15 #include <boost/thread.hpp>
17 static const char DB_COIN
= 'C';
18 static const char DB_COINS
= 'c';
19 static const char DB_BLOCK_FILES
= 'f';
20 static const char DB_TXINDEX
= 't';
21 static const char DB_BLOCK_INDEX
= 'b';
23 static const char DB_BEST_BLOCK
= 'B';
24 static const char DB_FLAG
= 'F';
25 static const char DB_REINDEX_FLAG
= 'R';
26 static const char DB_LAST_BLOCK
= 'l';
33 CoinEntry(const COutPoint
* ptr
) : outpoint(const_cast<COutPoint
*>(ptr
)), key(DB_COIN
) {}
35 template<typename Stream
>
36 void Serialize(Stream
&s
) const {
39 s
<< VARINT(outpoint
->n
);
42 template<typename Stream
>
43 void Unserialize(Stream
& s
) {
46 s
>> VARINT(outpoint
->n
);
52 CCoinsViewDB::CCoinsViewDB(size_t nCacheSize
, bool fMemory
, bool fWipe
) : db(GetDataDir() / "chainstate", nCacheSize
, fMemory
, fWipe
, true)
56 bool CCoinsViewDB::GetCoin(const COutPoint
&outpoint
, Coin
&coin
) const {
57 return db
.Read(CoinEntry(&outpoint
), coin
);
60 bool CCoinsViewDB::HaveCoin(const COutPoint
&outpoint
) const {
61 return db
.Exists(CoinEntry(&outpoint
));
64 uint256
CCoinsViewDB::GetBestBlock() const {
65 uint256 hashBestChain
;
66 if (!db
.Read(DB_BEST_BLOCK
, hashBestChain
))
71 bool CCoinsViewDB::BatchWrite(CCoinsMap
&mapCoins
, const uint256
&hashBlock
) {
75 for (CCoinsMap::iterator it
= mapCoins
.begin(); it
!= mapCoins
.end();) {
76 if (it
->second
.flags
& CCoinsCacheEntry::DIRTY
) {
77 CoinEntry
entry(&it
->first
);
78 if (it
->second
.coin
.IsSpent())
81 batch
.Write(entry
, it
->second
.coin
);
85 CCoinsMap::iterator itOld
= it
++;
86 mapCoins
.erase(itOld
);
88 if (!hashBlock
.IsNull())
89 batch
.Write(DB_BEST_BLOCK
, hashBlock
);
91 bool ret
= db
.WriteBatch(batch
);
92 LogPrint(BCLog::COINDB
, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed
, (unsigned int)count
);
96 size_t CCoinsViewDB::EstimateSize() const
98 return db
.EstimateSize(DB_COIN
, (char)(DB_COIN
+1));
101 CBlockTreeDB::CBlockTreeDB(size_t nCacheSize
, bool fMemory
, bool fWipe
) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize
, fMemory
, fWipe
) {
104 bool CBlockTreeDB::ReadBlockFileInfo(int nFile
, CBlockFileInfo
&info
) {
105 return Read(std::make_pair(DB_BLOCK_FILES
, nFile
), info
);
108 bool CBlockTreeDB::WriteReindexing(bool fReindexing
) {
110 return Write(DB_REINDEX_FLAG
, '1');
112 return Erase(DB_REINDEX_FLAG
);
115 bool CBlockTreeDB::ReadReindexing(bool &fReindexing
) {
116 fReindexing
= Exists(DB_REINDEX_FLAG
);
120 bool CBlockTreeDB::ReadLastBlockFile(int &nFile
) {
121 return Read(DB_LAST_BLOCK
, nFile
);
124 CCoinsViewCursor
*CCoinsViewDB::Cursor() const
126 CCoinsViewDBCursor
*i
= new CCoinsViewDBCursor(const_cast<CDBWrapper
*>(&db
)->NewIterator(), GetBestBlock());
127 /* It seems that there are no "const iterators" for LevelDB. Since we
128 only need read operations on it, use a const-cast to get around
130 i
->pcursor
->Seek(DB_COIN
);
131 // Cache key of first record
132 if (i
->pcursor
->Valid()) {
133 CoinEntry
entry(&i
->keyTmp
.second
);
134 i
->pcursor
->GetKey(entry
);
135 i
->keyTmp
.first
= entry
.key
;
137 i
->keyTmp
.first
= 0; // Make sure Valid() and GetKey() return false
142 bool CCoinsViewDBCursor::GetKey(COutPoint
&key
) const
145 if (keyTmp
.first
== DB_COIN
) {
152 bool CCoinsViewDBCursor::GetValue(Coin
&coin
) const
154 return pcursor
->GetValue(coin
);
157 unsigned int CCoinsViewDBCursor::GetValueSize() const
159 return pcursor
->GetValueSize();
162 bool CCoinsViewDBCursor::Valid() const
164 return keyTmp
.first
== DB_COIN
;
167 void CCoinsViewDBCursor::Next()
170 CoinEntry
entry(&keyTmp
.second
);
171 if (!pcursor
->Valid() || !pcursor
->GetKey(entry
)) {
172 keyTmp
.first
= 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
174 keyTmp
.first
= entry
.key
;
178 bool CBlockTreeDB::WriteBatchSync(const std::vector
<std::pair
<int, const CBlockFileInfo
*> >& fileInfo
, int nLastFile
, const std::vector
<const CBlockIndex
*>& blockinfo
) {
179 CDBBatch
batch(*this);
180 for (std::vector
<std::pair
<int, const CBlockFileInfo
*> >::const_iterator it
=fileInfo
.begin(); it
!= fileInfo
.end(); it
++) {
181 batch
.Write(std::make_pair(DB_BLOCK_FILES
, it
->first
), *it
->second
);
183 batch
.Write(DB_LAST_BLOCK
, nLastFile
);
184 for (std::vector
<const CBlockIndex
*>::const_iterator it
=blockinfo
.begin(); it
!= blockinfo
.end(); it
++) {
185 batch
.Write(std::make_pair(DB_BLOCK_INDEX
, (*it
)->GetBlockHash()), CDiskBlockIndex(*it
));
187 return WriteBatch(batch
, true);
190 bool CBlockTreeDB::ReadTxIndex(const uint256
&txid
, CDiskTxPos
&pos
) {
191 return Read(std::make_pair(DB_TXINDEX
, txid
), pos
);
194 bool CBlockTreeDB::WriteTxIndex(const std::vector
<std::pair
<uint256
, CDiskTxPos
> >&vect
) {
195 CDBBatch
batch(*this);
196 for (std::vector
<std::pair
<uint256
,CDiskTxPos
> >::const_iterator it
=vect
.begin(); it
!=vect
.end(); it
++)
197 batch
.Write(std::make_pair(DB_TXINDEX
, it
->first
), it
->second
);
198 return WriteBatch(batch
);
201 bool CBlockTreeDB::WriteFlag(const std::string
&name
, bool fValue
) {
202 return Write(std::make_pair(DB_FLAG
, name
), fValue
? '1' : '0');
205 bool CBlockTreeDB::ReadFlag(const std::string
&name
, bool &fValue
) {
207 if (!Read(std::make_pair(DB_FLAG
, name
), ch
))
213 bool CBlockTreeDB::LoadBlockIndexGuts(std::function
<CBlockIndex
*(const uint256
&)> insertBlockIndex
)
215 std::unique_ptr
<CDBIterator
> pcursor(NewIterator());
217 pcursor
->Seek(std::make_pair(DB_BLOCK_INDEX
, uint256()));
219 // Load mapBlockIndex
220 while (pcursor
->Valid()) {
221 boost::this_thread::interruption_point();
222 std::pair
<char, uint256
> key
;
223 if (pcursor
->GetKey(key
) && key
.first
== DB_BLOCK_INDEX
) {
224 CDiskBlockIndex diskindex
;
225 if (pcursor
->GetValue(diskindex
)) {
226 // Construct block index object
227 CBlockIndex
* pindexNew
= insertBlockIndex(diskindex
.GetBlockHash());
228 pindexNew
->pprev
= insertBlockIndex(diskindex
.hashPrev
);
229 pindexNew
->nHeight
= diskindex
.nHeight
;
230 pindexNew
->nFile
= diskindex
.nFile
;
231 pindexNew
->nDataPos
= diskindex
.nDataPos
;
232 pindexNew
->nUndoPos
= diskindex
.nUndoPos
;
233 pindexNew
->nVersion
= diskindex
.nVersion
;
234 pindexNew
->hashMerkleRoot
= diskindex
.hashMerkleRoot
;
235 pindexNew
->nTime
= diskindex
.nTime
;
236 pindexNew
->nBits
= diskindex
.nBits
;
237 pindexNew
->nNonce
= diskindex
.nNonce
;
238 pindexNew
->nStatus
= diskindex
.nStatus
;
239 pindexNew
->nTx
= diskindex
.nTx
;
241 if (!CheckProofOfWork(pindexNew
->GetBlockHash(), pindexNew
->nBits
, Params().GetConsensus()))
242 return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew
->ToString());
246 return error("LoadBlockIndex() : failed to read value");
258 //! Legacy class to deserialize pre-pertxout database entries without reindex.
262 //! whether transaction is a coinbase
265 //! unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
266 std::vector
<CTxOut
> vout
;
268 //! at which height this transaction was included in the active block chain
271 //! empty constructor
272 CCoins() : fCoinBase(false), vout(0), nHeight(0) { }
274 template<typename Stream
>
275 void Unserialize(Stream
&s
) {
276 unsigned int nCode
= 0;
279 ::Unserialize(s
, VARINT(nVersionDummy
));
281 ::Unserialize(s
, VARINT(nCode
));
282 fCoinBase
= nCode
& 1;
283 std::vector
<bool> vAvail(2, false);
284 vAvail
[0] = (nCode
& 2) != 0;
285 vAvail
[1] = (nCode
& 4) != 0;
286 unsigned int nMaskCode
= (nCode
/ 8) + ((nCode
& 6) != 0 ? 0 : 1);
288 while (nMaskCode
> 0) {
289 unsigned char chAvail
= 0;
290 ::Unserialize(s
, chAvail
);
291 for (unsigned int p
= 0; p
< 8; p
++) {
292 bool f
= (chAvail
& (1 << p
)) != 0;
299 vout
.assign(vAvail
.size(), CTxOut());
300 for (unsigned int i
= 0; i
< vAvail
.size(); i
++) {
302 ::Unserialize(s
, REF(CTxOutCompressor(vout
[i
])));
305 ::Unserialize(s
, VARINT(nHeight
));
311 /** Upgrade the database from older formats.
313 * Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout.
315 bool CCoinsViewDB::Upgrade() {
316 std::unique_ptr
<CDBIterator
> pcursor(db
.NewIterator());
317 pcursor
->Seek(std::make_pair(DB_COINS
, uint256()));
318 if (!pcursor
->Valid()) {
322 LogPrintf("Upgrading database...\n");
323 size_t batch_size
= 1 << 24;
325 while (pcursor
->Valid()) {
326 boost::this_thread::interruption_point();
327 std::pair
<unsigned char, uint256
> key
;
328 if (pcursor
->GetKey(key
) && key
.first
== DB_COINS
) {
330 if (!pcursor
->GetValue(old_coins
)) {
331 return error("%s: cannot parse CCoins record", __func__
);
333 COutPoint
outpoint(key
.second
, 0);
334 for (size_t i
= 0; i
< old_coins
.vout
.size(); ++i
) {
335 if (!old_coins
.vout
[i
].IsNull() && !old_coins
.vout
[i
].scriptPubKey
.IsUnspendable()) {
336 Coin
newcoin(std::move(old_coins
.vout
[i
]), old_coins
.nHeight
, old_coins
.fCoinBase
);
338 CoinEntry
entry(&outpoint
);
339 batch
.Write(entry
, newcoin
);
343 if (batch
.SizeEstimate() > batch_size
) {
344 db
.WriteBatch(batch
);
352 db
.WriteBatch(batch
);