Browse Source

Merge pull request #5391

932ef50 [REST] JSON output: remove block infos from tx details if it is nested in block (Jonas Schnelli)
cae5486 [REST] added /rest/block/notxdetails/<hash> into REST-interface.md documentation (Jonas Schnelli)
73351c3 [REST] /rest/block response with full tx details (Jonas Schnelli)
pull/1/head
Wladimir J. van der Laan 8 years ago
parent
commit
5e521d3e4e
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 3
      doc/REST-interface.md
  2. 29
      qa/rpc-tests/rest.py
  3. 26
      src/rest.cpp
  4. 14
      src/rpcblockchain.cpp

3
doc/REST-interface.md

@ -11,12 +11,15 @@ Given a transaction hash, @@ -11,12 +11,15 @@ Given a transaction hash,
Returns a transaction, in binary, hex-encoded binary or JSON formats.
`GET /rest/block/BLOCK-HASH.{bin|hex|json}`
`GET /rest/block/notxdetails/BLOCK-HASH.{bin|hex|json}`
Given a block hash,
Returns a block, in binary, hex-encoded binary or JSON formats.
The HTTP request and response are both handled entirely in-memory, thus making maximum memory usage at least 2.66MB (1 MB max block, plus hex encoding) per request.
With the /notxdetails/ option JSON response will only contain the transaction hash instead of the complete transaction details. The option only affects the JSON response.
For full TX query capability, one must enable the transaction index via "txindex=1" command line / configuration option.
Risks

29
qa/rpc-tests/rest.py

@ -48,7 +48,7 @@ class RESTTest (BitcoinTestFramework): @@ -48,7 +48,7 @@ class RESTTest (BitcoinTestFramework):
assert_equal(json_obj['hash'], bb_hash)
# do tx test
tx_hash = json_obj['tx'][0];
tx_hash = json_obj['tx'][0]['txid'];
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"json")
json_obj = json.loads(json_string)
assert_equal(json_obj['txid'], tx_hash)
@ -57,6 +57,33 @@ class RESTTest (BitcoinTestFramework): @@ -57,6 +57,33 @@ class RESTTest (BitcoinTestFramework):
hex_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"hex", True)
assert_equal(response.status, 200)
assert_greater_than(int(response.getheader('content-length')), 10)
# check block tx details
# let's make 3 tx and mine them on node 1
txs = []
txs.append(self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11))
txs.append(self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11))
txs.append(self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11))
self.sync_all()
# now mine the transactions
newblockhash = self.nodes[1].setgenerate(True, 1)
self.sync_all()
#check if the 3 tx show up in the new block
json_string = http_get_call(url.hostname, url.port, '/rest/block/'+newblockhash[0]+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
for tx in json_obj['tx']:
if not 'coinbase' in tx['vin'][0]: #exclude coinbase
assert_equal(tx['txid'] in txs, True)
#check the same but without tx details
json_string = http_get_call(url.hostname, url.port, '/rest/block/notxdetails/'+newblockhash[0]+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
for tx in txs:
assert_equal(tx in json_obj['tx'], True)
if __name__ == '__main__':
RESTTest ().main ()

26
src/rest.cpp

@ -42,7 +42,7 @@ public: @@ -42,7 +42,7 @@ public:
};
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
extern Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex);
extern Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
static RestErr RESTERR(enum HTTPStatusCode status, string message)
{
@ -92,7 +92,8 @@ static bool ParseHashStr(const string& strReq, uint256& v) @@ -92,7 +92,8 @@ static bool ParseHashStr(const string& strReq, uint256& v)
static bool rest_block(AcceptedConnection* conn,
string& strReq,
map<string, string>& mapHeaders,
bool fRun)
bool fRun,
bool showTxDetails)
{
vector<string> params;
enum RetFormat rf = ParseDataFormat(params, strReq);
@ -131,7 +132,7 @@ static bool rest_block(AcceptedConnection* conn, @@ -131,7 +132,7 @@ static bool rest_block(AcceptedConnection* conn,
}
case RF_JSON: {
Object objBlock = blockToJSON(block, pblockindex);
Object objBlock = blockToJSON(block, pblockindex, showTxDetails);
string strJSON = write_string(Value(objBlock), false) + "\n";
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
return true;
@ -146,6 +147,22 @@ static bool rest_block(AcceptedConnection* conn, @@ -146,6 +147,22 @@ static bool rest_block(AcceptedConnection* conn,
return true; // continue to process further HTTP reqs on this cxn
}
static bool rest_block_extended(AcceptedConnection* conn,
string& strReq,
map<string, string>& mapHeaders,
bool fRun)
{
return rest_block(conn, strReq, mapHeaders, fRun, true);
}
static bool rest_block_notxdetails(AcceptedConnection* conn,
string& strReq,
map<string, string>& mapHeaders,
bool fRun)
{
return rest_block(conn, strReq, mapHeaders, fRun, false);
}
static bool rest_tx(AcceptedConnection* conn,
string& strReq,
map<string, string>& mapHeaders,
@ -205,7 +222,8 @@ static const struct { @@ -205,7 +222,8 @@ static const struct {
bool fRun);
} uri_prefixes[] = {
{"/rest/tx/", rest_tx},
{"/rest/block/", rest_block},
{"/rest/block/notxdetails/", rest_block_notxdetails},
{"/rest/block/", rest_block_extended},
};
bool HTTPReq_REST(AcceptedConnection* conn,

14
src/rpcblockchain.cpp

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
using namespace json_spirit;
using namespace std;
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
double GetDifficulty(const CBlockIndex* blockindex)
@ -50,7 +51,7 @@ double GetDifficulty(const CBlockIndex* blockindex) @@ -50,7 +51,7 @@ double GetDifficulty(const CBlockIndex* blockindex)
}
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
{
Object result;
result.push_back(Pair("hash", block.GetHash().GetHex()));
@ -65,7 +66,16 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) @@ -65,7 +66,16 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
Array txs;
BOOST_FOREACH(const CTransaction&tx, block.vtx)
txs.push_back(tx.GetHash().GetHex());
{
if(txDetails)
{
Object objTx;
TxToJSON(tx, uint256(0), objTx);
txs.push_back(objTx);
}
else
txs.push_back(tx.GetHash().GetHex());
}
result.push_back(Pair("tx", txs));
result.push_back(Pair("time", block.GetBlockTime()));
result.push_back(Pair("nonce", (uint64_t)block.nNonce));

Loading…
Cancel
Save