Skip to content

Commit 92be831

Browse files
committed
Merge bitcoin/bitcoin#25412: rest: add /deploymentinfo endpoint
a8250e3 doc: add release note about `/rest/deploymentinfo` (brunoerg) 5c96020 doc: add `/deploymentinfo` in REST-interface (brunoerg) 3e44bee test: add coverage for `/rest/deploymentinfo` (brunoerg) 9149703 rest: add `/deploymentinfo` (brunoerg) Pull request description: #23508 added a new RPC named `getdeploymentinfo`, it moved the softfork section from `getblockchaininfo` into this new one. In the REST interface, we have an endpoint named`/rest/chaininfo.json` (which refers to `getblockchaininfo`), so, this PR adds a new REST endpoint named `/deploymentinfo` which refers to `getdeploymentinfo`. You can use it by passing a block hash, e.g: '/rest/deploymentinfo/<BLOCKHASH>.json' or you can use it without passing a block hash to get the 'deploymentinfo' for the last block. ACKs for top commit: jonatack: re-ACK a8250e3 rebase-only since my last review at c65f82bb achow101: ACK a8250e3 stickies-v: re-ACK bitcoin/bitcoin@a8250e3 Tree-SHA512: 0735183b6828d51a72ed0e2be5a09b314ac4693f548982c6e9adaa0ef07a55aa428d3b2d1b1de70b83169811a663a8624b686166e5797f624dcc00178b9796e6
2 parents 0bac04b + a8250e3 commit 92be831

File tree

5 files changed

+70
-1
lines changed

5 files changed

+70
-1
lines changed

doc/REST-interface.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ Returns various state info regarding block chain processing.
8686
Only supports JSON as output format.
8787
Refer to the `getblockchaininfo` RPC help for details.
8888

89+
#### Deployment info
90+
`GET /rest/deploymentinfo.json`
91+
`GET /rest/deploymentinfo/<BLOCKHASH>.json`
92+
93+
Returns an object containing various state info regarding deployments of
94+
consensus changes at the current chain tip, or at <BLOCKHASH> if provided.
95+
Only supports JSON as output format.
96+
Refer to the `getdeploymentinfo` RPC help for details.
97+
8998
#### Query UTXO set
9099
- `GET /rest/getutxos/<TXID>-<N>/<TXID>-<N>/.../<TXID>-<N>.<bin|hex|json>`
91100
- `GET /rest/getutxos/checkmempool/<TXID>-<N>/<TXID>-<N>/.../<TXID>-<N>.<bin|hex|json>`

doc/release-notes-25412.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
New REST endpoint
2+
-----------------
3+
4+
- A new `/rest/deploymentinfo` endpoint has been added for fetching various
5+
state info regarding deployments of consensus changes. (#25412)

src/rest.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,48 @@ static bool rest_chaininfo(const std::any& context, HTTPRequest* req, const std:
590590
}
591591
}
592592

593+
594+
RPCHelpMan getdeploymentinfo();
595+
596+
static bool rest_deploymentinfo(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
597+
{
598+
if (!CheckWarmup(req)) return false;
599+
600+
std::string hash_str;
601+
const RESTResponseFormat rf = ParseDataFormat(hash_str, str_uri_part);
602+
603+
switch (rf) {
604+
case RESTResponseFormat::JSON: {
605+
JSONRPCRequest jsonRequest;
606+
jsonRequest.context = context;
607+
jsonRequest.params = UniValue(UniValue::VARR);
608+
609+
if (!hash_str.empty()) {
610+
uint256 hash;
611+
if (!ParseHashStr(hash_str, hash)) {
612+
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hash_str);
613+
}
614+
615+
const ChainstateManager* chainman = GetChainman(context, req);
616+
if (!chainman) return false;
617+
if (!WITH_LOCK(::cs_main, return chainman->m_blockman.LookupBlockIndex(ParseHashV(hash_str, "blockhash")))) {
618+
return RESTERR(req, HTTP_BAD_REQUEST, "Block not found");
619+
}
620+
621+
jsonRequest.params.pushKV("blockhash", hash_str);
622+
}
623+
624+
req->WriteHeader("Content-Type", "application/json");
625+
req->WriteReply(HTTP_OK, getdeploymentinfo().HandleRequest(jsonRequest).write() + "\n");
626+
return true;
627+
}
628+
default: {
629+
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
630+
}
631+
}
632+
633+
}
634+
593635
static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
594636
{
595637
if (!CheckWarmup(req))
@@ -939,6 +981,8 @@ static const struct {
939981
{"/rest/mempool/", rest_mempool},
940982
{"/rest/headers/", rest_headers},
941983
{"/rest/getutxos", rest_getutxos},
984+
{"/rest/deploymentinfo/", rest_deploymentinfo},
985+
{"/rest/deploymentinfo", rest_deploymentinfo},
942986
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
943987
};
944988

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager&
13071307
}
13081308
} // anon namespace
13091309

1310-
static RPCHelpMan getdeploymentinfo()
1310+
RPCHelpMan getdeploymentinfo()
13111311
{
13121312
return RPCHelpMan{"getdeploymentinfo",
13131313
"Returns an object containing various state info regarding deployments of consensus changes.",

test/functional/interface_rest.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,17 @@ def run_test(self):
387387
assert_equal(self.test_rest_request(f"/headers/{bb_hash}", query_params={"count": 1}), self.test_rest_request(f"/headers/1/{bb_hash}"))
388388
assert_equal(self.test_rest_request(f"/blockfilterheaders/basic/{bb_hash}", query_params={"count": 1}), self.test_rest_request(f"/blockfilterheaders/basic/5/{bb_hash}"))
389389

390+
self.log.info("Test the /deploymentinfo URI")
391+
392+
deployment_info = self.nodes[0].getdeploymentinfo()
393+
assert_equal(deployment_info, self.test_rest_request('/deploymentinfo'))
394+
395+
non_existing_blockhash = '42759cde25462784395a337460bde75f58e73d3f08bd31fdc3507cbac856a2c4'
396+
resp = self.test_rest_request(f'/deploymentinfo/{non_existing_blockhash}', ret_type=RetType.OBJ, status=400)
397+
assert_equal(resp.read().decode('utf-8').rstrip(), "Block not found")
398+
399+
resp = self.test_rest_request(f"/deploymentinfo/{INVALID_PARAM}", ret_type=RetType.OBJ, status=400)
400+
assert_equal(resp.read().decode('utf-8').rstrip(), f"Invalid hash: {INVALID_PARAM}")
390401

391402
if __name__ == '__main__':
392403
RESTTest().main()

0 commit comments

Comments
 (0)