getTransactionWithBlockInfo
This commit is contained in:
parent
7e8d17ae13
commit
4a4e71797a
@ -304,4 +304,16 @@ describe('Daemon Binding Functionality', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('get transaction with block info', function() {
|
||||||
|
it('should include tx buffer, height and timestamp', function(done) {
|
||||||
|
bitcoind.getTransactionWithBlockInfo(utxo.txid, true, function(err, data) {
|
||||||
|
should.not.exist(err);
|
||||||
|
data.height.should.equal(151);
|
||||||
|
should.exist(data.timestamp);
|
||||||
|
should.exist(data.buffer);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -362,6 +362,10 @@ Daemon.prototype.getTransactionWithBlock = function(txid, blockhash, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Daemon.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, callback) {
|
||||||
|
return bitcoindjs.getTransactionWithBlockInfo(txid, queryMempool, callback);
|
||||||
|
};
|
||||||
|
|
||||||
Daemon.prototype.getMempoolOutputs = function(address) {
|
Daemon.prototype.getMempoolOutputs = function(address) {
|
||||||
return bitcoindjs.getMempoolOutputs(address);
|
return bitcoindjs.getMempoolOutputs(address);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -81,18 +81,17 @@ DB.prototype.getTransaction = function(txid, queryMempool, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DB.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, callback) {
|
DB.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, callback) {
|
||||||
this.getTransaction(txid, queryMempool, callback);
|
this.bitcoind.getTransactionWithBlockInfo(txid, queryMempool, function(err, obj) {
|
||||||
/*this.bitcoind.getTransactionWithBlockInfo(txid, queryMempool, function(err, obj) {
|
|
||||||
if(err) {
|
if(err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tx = Transaction().fromBuffer(obj.buffer);
|
var tx = Transaction().fromBuffer(obj.buffer);
|
||||||
tx.__blockHeight = obj.blockHeight;
|
tx.__height = obj.height;
|
||||||
tx.__timestamp = obj.timestamp;
|
tx.__timestamp = obj.timestamp;
|
||||||
|
|
||||||
callback(null, tx);
|
callback(null, tx);
|
||||||
});*/
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
DB.prototype.validateBlockData = function(block, callback) {
|
DB.prototype.validateBlockData = function(block, callback) {
|
||||||
|
|||||||
@ -74,6 +74,12 @@ async_get_tx(uv_work_t *req);
|
|||||||
static void
|
static void
|
||||||
async_get_tx_after(uv_work_t *req);
|
async_get_tx_after(uv_work_t *req);
|
||||||
|
|
||||||
|
static void
|
||||||
|
async_get_tx_and_info(uv_work_t *req);
|
||||||
|
|
||||||
|
static void
|
||||||
|
async_get_tx_and_info_after(uv_work_t *req);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
process_messages(CNode* pfrom);
|
process_messages(CNode* pfrom);
|
||||||
|
|
||||||
@ -156,6 +162,8 @@ struct async_tx_data {
|
|||||||
std::string err_msg;
|
std::string err_msg;
|
||||||
std::string txid;
|
std::string txid;
|
||||||
std::string blockhash;
|
std::string blockhash;
|
||||||
|
uint32_t nTime;
|
||||||
|
int64_t height;
|
||||||
bool queryMempool;
|
bool queryMempool;
|
||||||
CTransaction ctx;
|
CTransaction ctx;
|
||||||
Eternal<Function> callback;
|
Eternal<Function> callback;
|
||||||
@ -1018,7 +1026,7 @@ async_get_block_after(uv_work_t *req) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GetTransaction()
|
* GetTransaction()
|
||||||
* bitcoind.getTransaction(txid, callback)
|
* bitcoind.getTransaction(txid, queryMempool, callback)
|
||||||
* Read any transaction from disk asynchronously.
|
* Read any transaction from disk asynchronously.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1030,7 +1038,7 @@ NAN_METHOD(GetTransaction) {
|
|||||||
|| !args[1]->IsBoolean()
|
|| !args[1]->IsBoolean()
|
||||||
|| !args[2]->IsFunction()) {
|
|| !args[2]->IsFunction()) {
|
||||||
return NanThrowError(
|
return NanThrowError(
|
||||||
"Usage: bitcoindjs.getTransaction(txid, callback)");
|
"Usage: daemon.getTransaction(txid, queryMempool, callback)");
|
||||||
}
|
}
|
||||||
|
|
||||||
String::Utf8Value txid_(args[0]->ToString());
|
String::Utf8Value txid_(args[0]->ToString());
|
||||||
@ -1145,6 +1153,154 @@ async_get_tx_after(uv_work_t *req) {
|
|||||||
delete req;
|
delete req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetTransactionWithBlockInfo()
|
||||||
|
* bitcoind.getTransactionWithBlockInfo(txid, queryMempool, callback)
|
||||||
|
* Read any transaction from disk asynchronously with block timestamp and height.
|
||||||
|
*/
|
||||||
|
|
||||||
|
NAN_METHOD(GetTransactionWithBlockInfo) {
|
||||||
|
Isolate* isolate = Isolate::GetCurrent();
|
||||||
|
HandleScope scope(isolate);
|
||||||
|
if (args.Length() < 3
|
||||||
|
|| !args[0]->IsString()
|
||||||
|
|| !args[1]->IsBoolean()
|
||||||
|
|| !args[2]->IsFunction()) {
|
||||||
|
return NanThrowError(
|
||||||
|
"Usage: bitcoindjs.getTransactionWithBlockInfo(txid, queryMempool, callback)");
|
||||||
|
}
|
||||||
|
|
||||||
|
String::Utf8Value txid_(args[0]->ToString());
|
||||||
|
bool queryMempool = args[1]->BooleanValue();
|
||||||
|
Local<Function> callback = Local<Function>::Cast(args[2]);
|
||||||
|
|
||||||
|
async_tx_data *data = new async_tx_data();
|
||||||
|
|
||||||
|
data->err_msg = std::string("");
|
||||||
|
data->txid = std::string("");
|
||||||
|
|
||||||
|
std::string txid = std::string(*txid_);
|
||||||
|
|
||||||
|
data->txid = txid;
|
||||||
|
data->queryMempool = queryMempool;
|
||||||
|
Eternal<Function> eternal(isolate, callback);
|
||||||
|
data->callback = eternal;
|
||||||
|
|
||||||
|
uv_work_t *req = new uv_work_t();
|
||||||
|
req->data = data;
|
||||||
|
|
||||||
|
int status = uv_queue_work(uv_default_loop(),
|
||||||
|
req, async_get_tx_and_info,
|
||||||
|
(uv_after_work_cb)async_get_tx_and_info_after);
|
||||||
|
|
||||||
|
assert(status == 0);
|
||||||
|
|
||||||
|
NanReturnValue(Undefined(isolate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
async_get_tx_and_info(uv_work_t *req) {
|
||||||
|
async_tx_data* data = static_cast<async_tx_data*>(req->data);
|
||||||
|
|
||||||
|
uint256 hash = uint256S(data->txid);
|
||||||
|
uint256 blockHash;
|
||||||
|
CTransaction ctx;
|
||||||
|
|
||||||
|
if (data->queryMempool) {
|
||||||
|
LOCK(mempool.cs);
|
||||||
|
map<uint256, CTxMemPoolEntry>::const_iterator i = mempool.mapTx.find(hash);
|
||||||
|
if (i != mempool.mapTx.end()) {
|
||||||
|
data->ctx = i->second.GetTx();
|
||||||
|
data->nTime = i->second.GetTime();
|
||||||
|
data->height = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CDiskTxPos postx;
|
||||||
|
if (pblocktree->ReadTxIndex(hash, postx)) {
|
||||||
|
|
||||||
|
CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
|
if (file.IsNull()) {
|
||||||
|
data->err_msg = std::string("%s: OpenBlockFile failed", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBlockHeader blockHeader;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read header first to get block timestamp and hash
|
||||||
|
file >> blockHeader;
|
||||||
|
blockHash = blockHeader.GetHash();
|
||||||
|
data->nTime = blockHeader.nTime;
|
||||||
|
fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
|
||||||
|
file >> ctx;
|
||||||
|
data->ctx = ctx;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
data->err_msg = std::string("Deserialize or I/O error - %s", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get block height
|
||||||
|
CBlockIndex* blockIndex;
|
||||||
|
|
||||||
|
if (mapBlockIndex.count(blockHash) == 0) {
|
||||||
|
data->height = -1;
|
||||||
|
} else {
|
||||||
|
blockIndex = mapBlockIndex[blockHash];
|
||||||
|
data->height = blockIndex->nHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
async_get_tx_and_info_after(uv_work_t *req) {
|
||||||
|
Isolate* isolate = Isolate::GetCurrent();
|
||||||
|
HandleScope scope(isolate);
|
||||||
|
async_tx_data* data = static_cast<async_tx_data*>(req->data);
|
||||||
|
|
||||||
|
CTransaction ctx = data->ctx;
|
||||||
|
Local<Function> cb = data->callback.Get(isolate);
|
||||||
|
Local<Object> obj = NanNew<Object>();
|
||||||
|
|
||||||
|
if (data->err_msg != "") {
|
||||||
|
Local<Value> err = Exception::Error(NanNew<String>(data->err_msg));
|
||||||
|
const unsigned argc = 1;
|
||||||
|
Local<Value> argv[argc] = { err };
|
||||||
|
TryCatch try_catch;
|
||||||
|
cb->Call(isolate->GetCurrentContext()->Global(), argc, argv);
|
||||||
|
if (try_catch.HasCaught()) {
|
||||||
|
node::FatalException(try_catch);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
ssTx << ctx;
|
||||||
|
std::string stx = ssTx.str();
|
||||||
|
Local<Value> rawNodeBuffer = node::Buffer::New(isolate, stx.c_str(), stx.size());
|
||||||
|
|
||||||
|
obj->Set(NanNew<String>("height"), NanNew<Number>(data->height));
|
||||||
|
obj->Set(NanNew<String>("timestamp"), NanNew<Number>(data->nTime));
|
||||||
|
obj->Set(NanNew<String>("buffer"), rawNodeBuffer);
|
||||||
|
|
||||||
|
const unsigned argc = 2;
|
||||||
|
Local<Value> argv[argc] = {
|
||||||
|
Local<Value>::New(isolate, NanNull()),
|
||||||
|
obj
|
||||||
|
};
|
||||||
|
TryCatch try_catch;
|
||||||
|
cb->Call(isolate->GetCurrentContext()->Global(), argc, argv);
|
||||||
|
if (try_catch.HasCaught()) {
|
||||||
|
node::FatalException(try_catch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete data;
|
||||||
|
delete req;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IsSpent()
|
* IsSpent()
|
||||||
* bitcoindjs.isSpent()
|
* bitcoindjs.isSpent()
|
||||||
@ -1465,6 +1621,7 @@ init(Handle<Object> target) {
|
|||||||
NODE_SET_METHOD(target, "stopped", IsStopped);
|
NODE_SET_METHOD(target, "stopped", IsStopped);
|
||||||
NODE_SET_METHOD(target, "getBlock", GetBlock);
|
NODE_SET_METHOD(target, "getBlock", GetBlock);
|
||||||
NODE_SET_METHOD(target, "getTransaction", GetTransaction);
|
NODE_SET_METHOD(target, "getTransaction", GetTransaction);
|
||||||
|
NODE_SET_METHOD(target, "getTransactionWithBlockInfo", GetTransactionWithBlockInfo);
|
||||||
NODE_SET_METHOD(target, "getInfo", GetInfo);
|
NODE_SET_METHOD(target, "getInfo", GetInfo);
|
||||||
NODE_SET_METHOD(target, "isSpent", IsSpent);
|
NODE_SET_METHOD(target, "isSpent", IsSpent);
|
||||||
NODE_SET_METHOD(target, "getBlockIndex", GetBlockIndex);
|
NODE_SET_METHOD(target, "getBlockIndex", GetBlockIndex);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user