Skip to content

Commit 669af55

Browse files
committed
merge bitcoin#25412: add /deploymentinfo endpoint
1 parent 1364caf commit 669af55

File tree

5 files changed

+69
-1
lines changed

5 files changed

+69
-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-6888.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ Updated RPCs
99
a future release. Note that in either case, the `status` field
1010
now reflects the status of the current block rather than the next
1111
block.
12+
13+
New REST endpoint
14+
-----------------
15+
16+
- A new `/rest/deploymentinfo` endpoint has been added for fetching various
17+
state info regarding deployments of consensus changes.

src/rest.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,46 @@ static bool rest_chaininfo(const CoreContext& context, HTTPRequest* req, const s
623623
}
624624
}
625625

626+
RPCHelpMan getdeploymentinfo();
627+
628+
static bool rest_deploymentinfo(const CoreContext& context, HTTPRequest* req, const std::string& str_uri_part)
629+
{
630+
if (!CheckWarmup(req)) return false;
631+
632+
std::string hash_str;
633+
const RESTResponseFormat rf = ParseDataFormat(hash_str, str_uri_part);
634+
635+
switch (rf) {
636+
case RESTResponseFormat::JSON: {
637+
JSONRPCRequest jsonRequest;
638+
jsonRequest.context = context;
639+
jsonRequest.params = UniValue(UniValue::VARR);
640+
641+
if (!hash_str.empty()) {
642+
uint256 hash;
643+
if (!ParseHashStr(hash_str, hash)) {
644+
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hash_str);
645+
}
646+
647+
const ChainstateManager* chainman = GetChainman(context, req);
648+
if (!chainman) return false;
649+
if (!WITH_LOCK(::cs_main, return chainman->m_blockman.LookupBlockIndex(ParseHashV(hash_str, "blockhash")))) {
650+
return RESTERR(req, HTTP_BAD_REQUEST, "Block not found");
651+
}
652+
653+
jsonRequest.params.pushKV("blockhash", hash_str);
654+
}
655+
656+
req->WriteHeader("Content-Type", "application/json");
657+
req->WriteReply(HTTP_OK, getdeploymentinfo().HandleRequest(jsonRequest).write() + "\n");
658+
return true;
659+
}
660+
default: {
661+
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
662+
}
663+
}
664+
}
665+
626666
static bool rest_mempool(const CoreContext& context, HTTPRequest* req, const std::string& str_uri_part)
627667
{
628668
if (!CheckWarmup(req))
@@ -971,6 +1011,8 @@ static const struct {
9711011
{"/rest/mempool/", rest_mempool},
9721012
{"/rest/headers/", rest_headers},
9731013
{"/rest/getutxos", rest_getutxos},
1014+
{"/rest/deploymentinfo/", rest_deploymentinfo},
1015+
{"/rest/deploymentinfo", rest_deploymentinfo},
9741016
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
9751017
};
9761018

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1658,7 +1658,7 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const CMNHFManager::Signa
16581658
}
16591659
} // anonymous namespace
16601660

1661-
static RPCHelpMan getdeploymentinfo()
1661+
RPCHelpMan getdeploymentinfo()
16621662
{
16631663
return RPCHelpMan{"getdeploymentinfo",
16641664
"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
@@ -391,6 +391,17 @@ def run_test(self):
391391
assert_equal(self.test_rest_request(f"/headers/{bb_hash}", query_params={"count": 1}), self.test_rest_request(f"/headers/1/{bb_hash}"))
392392
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}"))
393393

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

395406
if __name__ == '__main__':
396407
RESTTest().main()

0 commit comments

Comments
 (0)