revise leveldb parser. add chainstate parser.

This commit is contained in:
Christopher Jeffrey 2014-12-08 09:46:51 -08:00
parent b740185c69
commit 6970f8a593
1 changed files with 176 additions and 42 deletions

View File

@ -607,6 +607,11 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
static bool
get_block_by_tx(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcblock_index);
#if 0
static bool
get_block_by_tx_unspent(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcblock_index);
#endif
/**
* Functions
*/
@ -6209,6 +6214,12 @@ jstx_to_ctx(const Local<Object> jstx, CTransaction& ctx_) {
}
#if USE_LDB_ADDR
/**
LevelDB Parser
DB: blocks/blk/revXXXXX.dat
*/
static ctx_list *
read_addr(const std::string addr, const int64_t blockheight, const int64_t blocktime) {
ctx_list *head = new ctx_list();
@ -6235,7 +6246,8 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
// Blockchain Index Structure:
// http://bitcoin.stackexchange.com/questions/28168
// File info record structure (Key: 4-byte file number)
// File info record structure
// 'f' + 4-byte file number
// Number of blocks stored in block file
// Size of block file: blocks/blkXXXXX.dat
// Size of undo file: blocks/revXXXXX.dat
@ -6245,31 +6257,35 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
goto next;
}
// Last block file number used structure (Key: no key)
// Last block file number used structure
// 'l'
// 4-byte file number
if (type == 'l') {
goto next;
}
// Reindexing structure (Key: no key)
// Reindexing structure
// 'R'
// 1-byte Boolean (1 if reindexing)
if (type == 'R') {
goto next;
}
// Flags structure (Key: 1-byte flag name + flag name string)
// Flags structure
// 'F' + 1-byte flag name + flag name string
// 1-byte Boolean (key may be `txindex` if transaction index is enabled)
if (type == 'F') {
goto next;
}
// Block Structure:
// CBlockHeader - headers
// nHeight
// nTx
// validation state
// CDiskBlockPos - block file and pos
// CDiskBlockPos - undo file and pos
// 'b' + 32-byte block hash
// The block header
// The block height
// The number of transactions
// The block validation state
// The block file and pos
// The undo file and pos
if (type == 'b') {
leveldb::Slice slValue = pcursor->value();
@ -6278,17 +6294,41 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
uint256 blockhash;
ssKey >> blockhash;
// class CBlockIndex {
// const uint256* phashBlock;
// CBlockIndex* pprev;
// CBlockIndex* pskip;
// int nHeight;
// int nFile;
// unsigned int nDataPos;
// unsigned int nUndoPos;
// uint256 nChainWork;
// unsigned int nTx;
// unsigned int nChainTx;
// unsigned int nStatus;
// int nVersion;
// uint256 hashMerkleRoot;
// unsigned int nTime;
// unsigned int nBits;
// unsigned int nNonce;
// uint32_t nSequenceId;
// };
// class CDiskBlockIndex : public CBlockIndex {
// uint256 hashPrev;
// };
CDiskBlockIndex index;
ssValue >> index;
//if (blockheight != -1 && index.nHeight < blockheight) {
// goto next;
//}
if (blocktime != -1 && index.GetBlockTime() < blocktime) {
goto next;
}
// struct CDiskBlockPos {
// int nFile;
// unsigned int nPos;
// };
CDiskBlockPos blockPos;
blockPos.nFile = index.nFile;
blockPos.nPos = index.nDataPos;
@ -6353,9 +6393,10 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
}
// Transaction Structure:
// CDiskBlockPos.nFile - block file
// CDiskBlockPos.nPos - block pos
// CDiskTxPos.nTxOffset - offset from top of block
// 't' + 32-byte tx hash
// Which block file the tx is stored in
// Which offset in the block file the tx resides
// The offset from the top of the block containing the tx
if (type == 't') {
leveldb::Slice slValue = pcursor->value();
@ -6364,16 +6405,13 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
uint256 txhash;
ssKey >> txhash;
// CDiskBlockPos blockPos;
// ssValue >> blockPos.nFile;
// ssValue >> blockPos.nPos;
// CDiskTxPos txPos;
// // ssValue >> txPos.nFile;
// // ssValue >> txPos.nPos;
// txPos.nFile = blockPos.nFile;
// txPos.nPos = blockPos.nPos;
// ssValue >> txPos.nTxOffset;
// struct CDiskBlockPos {
// int nFile;
// unsigned int nPos;
// };
// struct CDiskTxPos : public CDiskBlockPos {
// unsigned int nTxOffset;
// };
CDiskTxPos txPos;
ssValue >> txPos;
@ -6453,13 +6491,9 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
next:
pcursor->Next();
} catch (std::exception &e) {
//pcursor->Next();
//continue;
leveldb::Slice lastKey = pcursor->key();
std::string lastKeyHex = HexStr(lastKey.ToString());
head->err_msg = std::string(e.what()
+ std::string(" : Deserialize error. Key: ")
+ lastKeyHex);
+ pcursor->key().ToString());
delete pcursor;
return head;
}
@ -6476,6 +6510,11 @@ error:
}
#endif
/**
LevelDB Parser
DB: blocks/blk/revXXXXX.dat
*/
static bool
get_block_by_tx(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcblock_index) {
leveldb::Iterator* pcursor = pblocktree->pdb->NewIterator(pblocktree->iteroptions);
@ -6492,6 +6531,14 @@ get_block_by_tx(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcbloc
char type;
ssKey >> type;
// Blockchain Index Structure:
// http://bitcoin.stackexchange.com/questions/28168
// Transaction Structure:
// 't' + 32-byte tx hash
// Which block file the tx is stored in
// Which offset in the block file the tx resides
// The offset from the top of the block containing the tx
if (type == 't') {
uint256 txhash;
ssKey >> txhash;
@ -6500,16 +6547,13 @@ get_block_by_tx(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcbloc
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
// CDiskBlockPos blockPos;
// ssValue >> blockPos.nFile;
// ssValue >> blockPos.nPos;
// CDiskTxPos txPos;
// // ssValue >> txPos.nFile;
// // ssValue >> txPos.nPos;
// txPos.nFile = blockPos.nFile;
// txPos.nPos = blockPos.nPos;
// ssValue >> txPos.nTxOffset;
// struct CDiskBlockPos {
// int nFile;
// unsigned int nPos;
// };
// struct CDiskTxPos : public CDiskBlockPos {
// unsigned int nTxOffset;
// };
CDiskTxPos txPos;
ssValue >> txPos;
@ -6559,6 +6603,96 @@ error:
return false;
}
#if 0
/**
LevelDB Parser
DB: chainstate*
*/
// XXX static - will not work:
// extern CCoinsViewDB *pcoinsdbview;
static bool
get_block_by_tx_unspent(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcblock_index) {
// XXX Will not work - db is protected property:
CCoinsViewDB *pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
bool fReindex = GetBoolArg("-reindex", false);
size_t nCoinDBCache = (GetArg("-dbcache", nDefaultDbCache) << 20) / 2;
nCoinCacheSize = nCoinDBCache / 300;
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&pcoinsdbview->db)->NewIterator());
pcursor->SeekToFirst();
while (pcursor->Valid()) {
boost::this_thread::interruption_point();
try {
leveldb::Slice slKey = pcursor->key();
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
char type;
ssKey >> type;
// Blockchain Index Structure:
// http://bitcoin.stackexchange.com/questions/28168
// Unspent Output Transaction Structure:
// 'c' + 32-byte tx hash
// Version of the tx
// Whether transaction was a coinbase
// Which height block contains the tx
// Which outputs of the tx are unspent
// The scriptPubKey and amount for these unspent outputs
if (type == 'c') {
uint256 txhash;
ssKey >> txhash;
if (txhash.GetHex() == itxhash) {
leveldb::Slice slValue = pcursor->value();
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
// class CCoins {
// bool fCoinBase;
// std::vector<CTxOut> vout;
// int nHeight;
// int nVersion;
// }
CCoins coins;
ssValue >> coins;
CBlockIndex* pblockindex = chainActive[coins.nHeight];
CBlock cblock;
if (ReadBlockFromDisk(cblock, pblockindex)) {
*rcblock_index = pblockindex;
return true;
}
goto error;
}
}
// Unspent Output Block Hash Structure
// 'B' + 32-byte block hash: The block hash up to which the db represents
// the unspent tx outputs
if (type == 'B') {
uint256 blockhash;
ssKey >> blockhash;
// CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
// uint256 blockhash;
// ssValue >> blockhash;
}
pcursor->Next();
} catch (std::exception &e) {
return false;
}
}
error:
return false;
}
#endif
static int64_t
SatoshiFromAmount(const CAmount& amount) {
return (int64_t)amount;