add get_tx_ldb.
This commit is contained in:
parent
e1bb7bb666
commit
83048eef33
@ -405,8 +405,10 @@ Bitcoin.prototype.getTx = function(txid, blockhash, callback) {
|
|||||||
if (blockhash && typeof blockhash === 'string') {
|
if (blockhash && typeof blockhash === 'string') {
|
||||||
return bitcoindjs.getTransaction(txid, blockhash, traverse, function(err, tx) {
|
return bitcoindjs.getTransaction(txid, blockhash, traverse, function(err, tx) {
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
bitcoin.db.set('tx-block/' + txid,
|
if (tx.blockhash) {
|
||||||
{ hash: blockhash }, utils.NOOP);
|
bitcoin.db.set('tx-block/' + txid,
|
||||||
|
{ hash: tx.blockhash }, utils.NOOP);
|
||||||
|
}
|
||||||
return callback(null, bitcoin.tx(tx));
|
return callback(null, bitcoin.tx(tx));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -414,7 +416,7 @@ Bitcoin.prototype.getTx = function(txid, blockhash, callback) {
|
|||||||
// Will traverse blockchain if no block - slow:
|
// Will traverse blockchain if no block - slow:
|
||||||
return bitcoinjs.getTransaction(txid, block ? block.hash : '', traverse, function(err, tx) {
|
return bitcoinjs.getTransaction(txid, block ? block.hash : '', traverse, function(err, tx) {
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
if (!block) {
|
if (!block && tx.blockhash) {
|
||||||
bitcoin.db.set('tx-block/' + txid,
|
bitcoin.db.set('tx-block/' + txid,
|
||||||
{ hash: tx.blockhash }, utils.NOOP);
|
{ hash: tx.blockhash }, utils.NOOP);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -189,6 +189,8 @@ using namespace v8;
|
|||||||
// LevelDB options
|
// LevelDB options
|
||||||
#define USE_LDB_ADDR 0
|
#define USE_LDB_ADDR 0
|
||||||
#define USE_LDB_TX 0
|
#define USE_LDB_TX 0
|
||||||
|
#define USE_LDB_GETTX 1
|
||||||
|
#define USE_LDB_GETTX_MAIN 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node.js Exposed Function Templates
|
* Node.js Exposed Function Templates
|
||||||
@ -606,6 +608,11 @@ 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);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_LDB_GETTX) || defined(USE_LDB_GETTX_MAIN)
|
||||||
|
static bool
|
||||||
|
get_tx_ldb(const uint256 itxid, CTransaction& rctx, uint256& rblockhash);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if USE_LDB_TX
|
#if USE_LDB_TX
|
||||||
static bool
|
static bool
|
||||||
get_block_by_tx(const std::string itxid, CBlock& rcblock, CBlockIndex **rcblock_index);
|
get_block_by_tx(const std::string itxid, CBlock& rcblock, CBlockIndex **rcblock_index);
|
||||||
@ -1169,12 +1176,21 @@ async_get_tx(uv_work_t *req) {
|
|||||||
uint256 blockhash(data->blockhash);
|
uint256 blockhash(data->blockhash);
|
||||||
CTransaction ctx;
|
CTransaction ctx;
|
||||||
|
|
||||||
|
#if USE_LDB_GETTX_MAIN
|
||||||
|
if (get_tx_ldb(hash, ctx, blockhash)) {
|
||||||
|
data->ctx = ctx;
|
||||||
|
data->blockhash = blockhash.GetHex();
|
||||||
|
} else {
|
||||||
|
data->err_msg = std::string("get_tx(): failed.");
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (get_tx(hash, blockhash, data->traverse, ctx)) {
|
if (get_tx(hash, blockhash, data->traverse, ctx)) {
|
||||||
data->ctx = ctx;
|
data->ctx = ctx;
|
||||||
data->blockhash = blockhash.GetHex();
|
data->blockhash = blockhash.GetHex();
|
||||||
} else {
|
} else {
|
||||||
data->err_msg = std::string("get_tx(): failed.");
|
data->err_msg = std::string("get_tx(): failed.");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -5849,6 +5865,9 @@ get_tx(uint256 txid, uint256& blockhash, const bool traverse, CTransaction& ctx)
|
|||||||
if (GetTransaction(txid, ctx, blockhash, true)) {
|
if (GetTransaction(txid, ctx, blockhash, true)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (traverse && blockhash != 0) {
|
} else if (traverse && blockhash != 0) {
|
||||||
|
#if USE_LDB_GETTX
|
||||||
|
get_tx_ldb(txid, ctx, blockhash);
|
||||||
|
#else
|
||||||
CBlock block;
|
CBlock block;
|
||||||
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
|
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
|
||||||
if (ReadBlockFromDisk(block, pblockindex)) {
|
if (ReadBlockFromDisk(block, pblockindex)) {
|
||||||
@ -5860,6 +5879,7 @@ get_tx(uint256 txid, uint256& blockhash, const bool traverse, CTransaction& ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -6508,6 +6528,107 @@ error:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_LDB_GETTX) || defined(USE_LDB_GETTX_MAIN)
|
||||||
|
/**
|
||||||
|
LevelDB Parser
|
||||||
|
DB: blocks/blk/revXXXXX.dat
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool
|
||||||
|
get_tx_ldb(const uint256 itxid, CTransaction& rctx, uint256& rblockhash) {
|
||||||
|
leveldb::Iterator* pcursor = pblocktree->pdb->NewIterator(pblocktree->iteroptions);
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// 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 txid;
|
||||||
|
ssKey >> txid;
|
||||||
|
if (txid == itxid) {
|
||||||
|
leveldb::Slice slValue = pcursor->value();
|
||||||
|
|
||||||
|
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
|
// struct CDiskBlockPos {
|
||||||
|
// int nFile;
|
||||||
|
// unsigned int nPos;
|
||||||
|
// };
|
||||||
|
// struct CDiskTxPos : public CDiskBlockPos {
|
||||||
|
// unsigned int nTxOffset;
|
||||||
|
// };
|
||||||
|
|
||||||
|
CDiskTxPos txPos;
|
||||||
|
ssValue >> txPos;
|
||||||
|
|
||||||
|
CTransaction ctx;
|
||||||
|
uint256 blockhash;
|
||||||
|
|
||||||
|
if (!pblocktree->ReadTxIndex(txid, txPos)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAutoFile file(OpenBlockFile(txPos, true), SER_DISK, CLIENT_VERSION);
|
||||||
|
CBlockHeader header;
|
||||||
|
try {
|
||||||
|
file >> header;
|
||||||
|
fseek(file.Get(), txPos.nTxOffset, SEEK_CUR);
|
||||||
|
file >> ctx;
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (ctx.GetHash() != txid) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
blockhash = header.GetHash();
|
||||||
|
|
||||||
|
CBlock cblock;
|
||||||
|
CBlockIndex* pblockindex = mapBlockIndex[blockhash];
|
||||||
|
if (ReadBlockFromDisk(cblock, pblockindex)) {
|
||||||
|
BOOST_FOREACH(const CTransaction& ctx, cblock.vtx) {
|
||||||
|
if (ctx.GetHash() == itxid) {
|
||||||
|
rblockhash = blockhash;
|
||||||
|
rctx = ctx;
|
||||||
|
delete pcursor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pcursor->Next();
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
delete pcursor;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
delete pcursor;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
LevelDB Parser
|
LevelDB Parser
|
||||||
DB: blocks/blk/revXXXXX.dat
|
DB: blocks/blk/revXXXXX.dat
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user