Skip to content

Commit 6feeec1

Browse files
author
Jeff Garzik
committed
Merge pull request #6013
2 parents ddd8d80 + 70180b2 commit 6feeec1

4 files changed

Lines changed: 136 additions & 44 deletions

File tree

doc/REST-interface.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,20 @@ $ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff76
7777
}
7878
```
7979

80+
####Memory pool
81+
`GET /rest/mempool/info.json`
82+
83+
Returns various information about the TX mempool.
84+
Only supports JSON as output format.
85+
* size : (numeric) the number of transactions in the TX mempool
86+
* bytes : (numeric) size of the TX mempool in bytes
87+
* usage : (numeric) total TX mempool memory usage
88+
89+
`GET /rest/mempool/contents.json`
90+
91+
Returns transactions in the TX mempool.
92+
Only supports JSON as output format.
93+
8094
Risks
8195
-------------
8296
Running a web browser on the same node with a REST enabled bitcoind can be a risk. Accessing prepared XSS websites could read out tx/block data of your node by placing links like `<script src="http://127.0.0.1:8332/rest/tx/1234567890.json">` which might break the nodes privacy.

qa/rpc-tests/rest.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,19 @@ def run_test(self):
292292
txs.append(self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11))
293293
self.sync_all()
294294

295+
# check that there are exactly 3 transactions in the TX memory pool before generating the block
296+
json_string = http_get_call(url.hostname, url.port, '/rest/mempool/info'+self.FORMAT_SEPARATOR+'json')
297+
json_obj = json.loads(json_string)
298+
assert_equal(json_obj['size'], 3)
299+
# the size of the memory pool should be greater than 3x ~100 bytes
300+
assert_greater_than(json_obj['bytes'], 300)
301+
302+
# check that there are our submitted transactions in the TX memory pool
303+
json_string = http_get_call(url.hostname, url.port, '/rest/mempool/contents'+self.FORMAT_SEPARATOR+'json')
304+
json_obj = json.loads(json_string)
305+
for tx in txs:
306+
assert_equal(tx in json_obj, True)
307+
295308
# now mine the transactions
296309
newblockhash = self.nodes[1].generate(1)
297310
self.sync_all()

src/rest.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class RestErr
6565

6666
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
6767
extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
68+
extern UniValue mempoolInfoToJSON();
69+
extern UniValue mempoolToJSON(bool fVerbose = false);
6870
extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
6971
extern UniValue blockheaderToJSON(const CBlockIndex* blockindex);
7072

@@ -293,6 +295,58 @@ static bool rest_chaininfo(AcceptedConnection* conn,
293295
return true; // continue to process further HTTP reqs on this cxn
294296
}
295297

298+
static bool rest_mempool_info(AcceptedConnection* conn,
299+
const std::string& strURIPart,
300+
const std::string& strRequest,
301+
const std::map<std::string, std::string>& mapHeaders,
302+
bool fRun)
303+
{
304+
vector<string> params;
305+
const RetFormat rf = ParseDataFormat(params, strURIPart);
306+
307+
switch (rf) {
308+
case RF_JSON: {
309+
UniValue mempoolInfoObject = mempoolInfoToJSON();
310+
311+
string strJSON = mempoolInfoObject.write() + "\n";
312+
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
313+
return true;
314+
}
315+
default: {
316+
throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: json)");
317+
}
318+
}
319+
320+
// not reached
321+
return true; // continue to process further HTTP reqs on this cxn
322+
}
323+
324+
static bool rest_mempool_contents(AcceptedConnection* conn,
325+
const std::string& strURIPart,
326+
const std::string& strRequest,
327+
const std::map<std::string, std::string>& mapHeaders,
328+
bool fRun)
329+
{
330+
vector<string> params;
331+
const RetFormat rf = ParseDataFormat(params, strURIPart);
332+
333+
switch (rf) {
334+
case RF_JSON: {
335+
UniValue mempoolObject = mempoolToJSON(true);
336+
337+
string strJSON = mempoolObject.write() + "\n";
338+
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
339+
return true;
340+
}
341+
default: {
342+
throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: json)");
343+
}
344+
}
345+
346+
// not reached
347+
return true; // continue to process further HTTP reqs on this cxn
348+
}
349+
296350
static bool rest_tx(AcceptedConnection* conn,
297351
const std::string& strURIPart,
298352
const std::string& strRequest,
@@ -553,6 +607,8 @@ static const struct {
553607
{"/rest/block/notxdetails/", rest_block_notxdetails},
554608
{"/rest/block/", rest_block_extended},
555609
{"/rest/chaininfo", rest_chaininfo},
610+
{"/rest/mempool/info", rest_mempool_info},
611+
{"/rest/mempool/contents", rest_mempool_contents},
556612
{"/rest/headers/", rest_headers},
557613
{"/rest/getutxos", rest_getutxos},
558614
};

src/rpcblockchain.cpp

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -175,45 +175,8 @@ UniValue getdifficulty(const UniValue& params, bool fHelp)
175175
return GetDifficulty();
176176
}
177177

178-
179-
UniValue getrawmempool(const UniValue& params, bool fHelp)
178+
UniValue mempoolToJSON(bool fVerbose = false)
180179
{
181-
if (fHelp || params.size() > 1)
182-
throw runtime_error(
183-
"getrawmempool ( verbose )\n"
184-
"\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
185-
"\nArguments:\n"
186-
"1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
187-
"\nResult: (for verbose = false):\n"
188-
"[ (json array of string)\n"
189-
" \"transactionid\" (string) The transaction id\n"
190-
" ,...\n"
191-
"]\n"
192-
"\nResult: (for verbose = true):\n"
193-
"{ (json object)\n"
194-
" \"transactionid\" : { (json object)\n"
195-
" \"size\" : n, (numeric) transaction size in bytes\n"
196-
" \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
197-
" \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
198-
" \"height\" : n, (numeric) block height when transaction entered pool\n"
199-
" \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
200-
" \"currentpriority\" : n, (numeric) transaction priority now\n"
201-
" \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
202-
" \"transactionid\", (string) parent transaction id\n"
203-
" ... ]\n"
204-
" }, ...\n"
205-
"}\n"
206-
"\nExamples\n"
207-
+ HelpExampleCli("getrawmempool", "true")
208-
+ HelpExampleRpc("getrawmempool", "true")
209-
);
210-
211-
LOCK(cs_main);
212-
213-
bool fVerbose = false;
214-
if (params.size() > 0)
215-
fVerbose = params[0].get_bool();
216-
217180
if (fVerbose)
218181
{
219182
LOCK(mempool.cs);
@@ -261,6 +224,47 @@ UniValue getrawmempool(const UniValue& params, bool fHelp)
261224
}
262225
}
263226

227+
UniValue getrawmempool(const UniValue& params, bool fHelp)
228+
{
229+
if (fHelp || params.size() > 1)
230+
throw runtime_error(
231+
"getrawmempool ( verbose )\n"
232+
"\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
233+
"\nArguments:\n"
234+
"1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
235+
"\nResult: (for verbose = false):\n"
236+
"[ (json array of string)\n"
237+
" \"transactionid\" (string) The transaction id\n"
238+
" ,...\n"
239+
"]\n"
240+
"\nResult: (for verbose = true):\n"
241+
"{ (json object)\n"
242+
" \"transactionid\" : { (json object)\n"
243+
" \"size\" : n, (numeric) transaction size in bytes\n"
244+
" \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
245+
" \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
246+
" \"height\" : n, (numeric) block height when transaction entered pool\n"
247+
" \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
248+
" \"currentpriority\" : n, (numeric) transaction priority now\n"
249+
" \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
250+
" \"transactionid\", (string) parent transaction id\n"
251+
" ... ]\n"
252+
" }, ...\n"
253+
"}\n"
254+
"\nExamples\n"
255+
+ HelpExampleCli("getrawmempool", "true")
256+
+ HelpExampleRpc("getrawmempool", "true")
257+
);
258+
259+
LOCK(cs_main);
260+
261+
bool fVerbose = false;
262+
if (params.size() > 0)
263+
fVerbose = params[0].get_bool();
264+
265+
return mempoolToJSON(fVerbose);
266+
}
267+
264268
UniValue getblockhash(const UniValue& params, bool fHelp)
265269
{
266270
if (fHelp || params.size() != 1)
@@ -757,6 +761,16 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
757761
return res;
758762
}
759763

764+
UniValue mempoolInfoToJSON()
765+
{
766+
UniValue ret(UniValue::VOBJ);
767+
ret.push_back(Pair("size", (int64_t) mempool.size()));
768+
ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
769+
ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
770+
771+
return ret;
772+
}
773+
760774
UniValue getmempoolinfo(const UniValue& params, bool fHelp)
761775
{
762776
if (fHelp || params.size() != 0)
@@ -774,12 +788,7 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp)
774788
+ HelpExampleRpc("getmempoolinfo", "")
775789
);
776790

777-
UniValue ret(UniValue::VOBJ);
778-
ret.push_back(Pair("size", (int64_t) mempool.size()));
779-
ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
780-
ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
781-
782-
return ret;
791+
return mempoolInfoToJSON();
783792
}
784793

785794
UniValue invalidateblock(const UniValue& params, bool fHelp)

0 commit comments

Comments
 (0)