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 static bool
get_block_by_tx(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcblock_index); 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 * Functions
*/ */
@ -6209,6 +6214,12 @@ jstx_to_ctx(const Local<Object> jstx, CTransaction& ctx_) {
} }
#if USE_LDB_ADDR #if USE_LDB_ADDR
/**
LevelDB Parser
DB: blocks/blk/revXXXXX.dat
*/
static ctx_list * static ctx_list *
read_addr(const std::string addr, const int64_t blockheight, const int64_t blocktime) { read_addr(const std::string addr, const int64_t blockheight, const int64_t blocktime) {
ctx_list *head = new ctx_list(); 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: // Blockchain Index Structure:
// http://bitcoin.stackexchange.com/questions/28168 // 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 // Number of blocks stored in block file
// Size of block file: blocks/blkXXXXX.dat // Size of block file: blocks/blkXXXXX.dat
// Size of undo file: blocks/revXXXXX.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; goto next;
} }
// Last block file number used structure (Key: no key) // Last block file number used structure
// 'l'
// 4-byte file number // 4-byte file number
if (type == 'l') { if (type == 'l') {
goto next; goto next;
} }
// Reindexing structure (Key: no key) // Reindexing structure
// 'R'
// 1-byte Boolean (1 if reindexing) // 1-byte Boolean (1 if reindexing)
if (type == 'R') { if (type == 'R') {
goto next; 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) // 1-byte Boolean (key may be `txindex` if transaction index is enabled)
if (type == 'F') { if (type == 'F') {
goto next; goto next;
} }
// Block Structure: // Block Structure:
// CBlockHeader - headers // 'b' + 32-byte block hash
// nHeight // The block header
// nTx // The block height
// validation state // The number of transactions
// CDiskBlockPos - block file and pos // The block validation state
// CDiskBlockPos - undo file and pos // The block file and pos
// The undo file and pos
if (type == 'b') { if (type == 'b') {
leveldb::Slice slValue = pcursor->value(); 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; uint256 blockhash;
ssKey >> 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; CDiskBlockIndex index;
ssValue >> index; ssValue >> index;
//if (blockheight != -1 && index.nHeight < blockheight) {
// goto next;
//}
if (blocktime != -1 && index.GetBlockTime() < blocktime) { if (blocktime != -1 && index.GetBlockTime() < blocktime) {
goto next; goto next;
} }
// struct CDiskBlockPos {
// int nFile;
// unsigned int nPos;
// };
CDiskBlockPos blockPos; CDiskBlockPos blockPos;
blockPos.nFile = index.nFile; blockPos.nFile = index.nFile;
blockPos.nPos = index.nDataPos; blockPos.nPos = index.nDataPos;
@ -6353,9 +6393,10 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
} }
// Transaction Structure: // Transaction Structure:
// CDiskBlockPos.nFile - block file // 't' + 32-byte tx hash
// CDiskBlockPos.nPos - block pos // Which block file the tx is stored in
// CDiskTxPos.nTxOffset - offset from top of block // Which offset in the block file the tx resides
// The offset from the top of the block containing the tx
if (type == 't') { if (type == 't') {
leveldb::Slice slValue = pcursor->value(); 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; uint256 txhash;
ssKey >> txhash; ssKey >> txhash;
// CDiskBlockPos blockPos; // struct CDiskBlockPos {
// ssValue >> blockPos.nFile; // int nFile;
// ssValue >> blockPos.nPos; // unsigned int nPos;
// };
// CDiskTxPos txPos; // struct CDiskTxPos : public CDiskBlockPos {
// // ssValue >> txPos.nFile; // unsigned int nTxOffset;
// // ssValue >> txPos.nPos; // };
// txPos.nFile = blockPos.nFile;
// txPos.nPos = blockPos.nPos;
// ssValue >> txPos.nTxOffset;
CDiskTxPos txPos; CDiskTxPos txPos;
ssValue >> txPos; ssValue >> txPos;
@ -6453,13 +6491,9 @@ read_addr(const std::string addr, const int64_t blockheight, const int64_t block
next: next:
pcursor->Next(); pcursor->Next();
} catch (std::exception &e) { } 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() head->err_msg = std::string(e.what()
+ std::string(" : Deserialize error. Key: ") + std::string(" : Deserialize error. Key: ")
+ lastKeyHex); + pcursor->key().ToString());
delete pcursor; delete pcursor;
return head; return head;
} }
@ -6476,6 +6510,11 @@ error:
} }
#endif #endif
/**
LevelDB Parser
DB: blocks/blk/revXXXXX.dat
*/
static bool static bool
get_block_by_tx(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcblock_index) { get_block_by_tx(const std::string itxhash, CBlock& rcblock, CBlockIndex **rcblock_index) {
leveldb::Iterator* pcursor = pblocktree->pdb->NewIterator(pblocktree->iteroptions); 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; char type;
ssKey >> 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') { if (type == 't') {
uint256 txhash; uint256 txhash;
ssKey >> 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); CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
// CDiskBlockPos blockPos; // struct CDiskBlockPos {
// ssValue >> blockPos.nFile; // int nFile;
// ssValue >> blockPos.nPos; // unsigned int nPos;
// };
// CDiskTxPos txPos; // struct CDiskTxPos : public CDiskBlockPos {
// // ssValue >> txPos.nFile; // unsigned int nTxOffset;
// // ssValue >> txPos.nPos; // };
// txPos.nFile = blockPos.nFile;
// txPos.nPos = blockPos.nPos;
// ssValue >> txPos.nTxOffset;
CDiskTxPos txPos; CDiskTxPos txPos;
ssValue >> txPos; ssValue >> txPos;
@ -6559,6 +6603,96 @@ error:
return false; 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 static int64_t
SatoshiFromAmount(const CAmount& amount) { SatoshiFromAmount(const CAmount& amount) {
return (int64_t)amount; return (int64_t)amount;