aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chow <github@achow101.com>2022-10-13 13:30:47 -0400
committerAndrew Chow <github@achow101.com>2022-10-13 13:30:55 -0400
commit92be831847e31833f5162a431882b27a2ac3f4ee (patch)
tree499b0a985ab679f2180d9c1d423d462b5ba82c98
parent0bac04b7585017508425b21d402fd3c52e6a13d5 (diff)
parenta8250e30f16f2919ea5aa122b2880b076bd398a3 (diff)
downloadbitcoin-92be831847e31833f5162a431882b27a2ac3f4ee.tar.xz
Merge bitcoin/bitcoin#25412: rest: add `/deploymentinfo` endpoint
a8250e30f16f2919ea5aa122b2880b076bd398a3 doc: add release note about `/rest/deploymentinfo` (brunoerg) 5c960200242d237f2cf74309b8fd29e8162682ed doc: add `/deploymentinfo` in REST-interface (brunoerg) 3e44bee08eb93e086179b92007649d47652aa439 test: add coverage for `/rest/deploymentinfo` (brunoerg) 91497031cbd74a0665b7fc31eb6b73bfb7bd0d40 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 a8250e30f16f2919ea5aa122b2880b076bd398a3 rebase-only since my last review at c65f82bb achow101: ACK a8250e30f16f2919ea5aa122b2880b076bd398a3 stickies-v: re-ACK https://github.com/bitcoin/bitcoin/commit/a8250e30f16f2919ea5aa122b2880b076bd398a3 Tree-SHA512: 0735183b6828d51a72ed0e2be5a09b314ac4693f548982c6e9adaa0ef07a55aa428d3b2d1b1de70b83169811a663a8624b686166e5797f624dcc00178b9796e6
-rw-r--r--doc/REST-interface.md9
-rw-r--r--doc/release-notes-25412.md5
-rw-r--r--src/rest.cpp44
-rw-r--r--src/rpc/blockchain.cpp2
-rwxr-xr-xtest/functional/interface_rest.py11
5 files changed, 70 insertions, 1 deletions
diff --git a/doc/REST-interface.md b/doc/REST-interface.md
index 0035dfcd8e..a704b969df 100644
--- a/doc/REST-interface.md
+++ b/doc/REST-interface.md
@@ -86,6 +86,15 @@ Returns various state info regarding block chain processing.
Only supports JSON as output format.
Refer to the `getblockchaininfo` RPC help for details.
+#### Deployment info
+`GET /rest/deploymentinfo.json`
+`GET /rest/deploymentinfo/<BLOCKHASH>.json`
+
+Returns an object containing various state info regarding deployments of
+consensus changes at the current chain tip, or at <BLOCKHASH> if provided.
+Only supports JSON as output format.
+Refer to the `getdeploymentinfo` RPC help for details.
+
#### Query UTXO set
- `GET /rest/getutxos/<TXID>-<N>/<TXID>-<N>/.../<TXID>-<N>.<bin|hex|json>`
- `GET /rest/getutxos/checkmempool/<TXID>-<N>/<TXID>-<N>/.../<TXID>-<N>.<bin|hex|json>`
diff --git a/doc/release-notes-25412.md b/doc/release-notes-25412.md
new file mode 100644
index 0000000000..b11fe73d45
--- /dev/null
+++ b/doc/release-notes-25412.md
@@ -0,0 +1,5 @@
+New REST endpoint
+-----------------
+
+- A new `/rest/deploymentinfo` endpoint has been added for fetching various
+ state info regarding deployments of consensus changes. (#25412)
diff --git a/src/rest.cpp b/src/rest.cpp
index 7f00db2222..a10d8a433f 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -590,6 +590,48 @@ static bool rest_chaininfo(const std::any& context, HTTPRequest* req, const std:
}
}
+
+RPCHelpMan getdeploymentinfo();
+
+static bool rest_deploymentinfo(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
+{
+ if (!CheckWarmup(req)) return false;
+
+ std::string hash_str;
+ const RESTResponseFormat rf = ParseDataFormat(hash_str, str_uri_part);
+
+ switch (rf) {
+ case RESTResponseFormat::JSON: {
+ JSONRPCRequest jsonRequest;
+ jsonRequest.context = context;
+ jsonRequest.params = UniValue(UniValue::VARR);
+
+ if (!hash_str.empty()) {
+ uint256 hash;
+ if (!ParseHashStr(hash_str, hash)) {
+ return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hash_str);
+ }
+
+ const ChainstateManager* chainman = GetChainman(context, req);
+ if (!chainman) return false;
+ if (!WITH_LOCK(::cs_main, return chainman->m_blockman.LookupBlockIndex(ParseHashV(hash_str, "blockhash")))) {
+ return RESTERR(req, HTTP_BAD_REQUEST, "Block not found");
+ }
+
+ jsonRequest.params.pushKV("blockhash", hash_str);
+ }
+
+ req->WriteHeader("Content-Type", "application/json");
+ req->WriteReply(HTTP_OK, getdeploymentinfo().HandleRequest(jsonRequest).write() + "\n");
+ return true;
+ }
+ default: {
+ return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
+ }
+ }
+
+}
+
static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
{
if (!CheckWarmup(req))
@@ -939,6 +981,8 @@ static const struct {
{"/rest/mempool/", rest_mempool},
{"/rest/headers/", rest_headers},
{"/rest/getutxos", rest_getutxos},
+ {"/rest/deploymentinfo/", rest_deploymentinfo},
+ {"/rest/deploymentinfo", rest_deploymentinfo},
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
};
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index cddd85bcb5..f8ba822f54 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1307,7 +1307,7 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager&
}
} // anon namespace
-static RPCHelpMan getdeploymentinfo()
+RPCHelpMan getdeploymentinfo()
{
return RPCHelpMan{"getdeploymentinfo",
"Returns an object containing various state info regarding deployments of consensus changes.",
diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py
index 610a28c56b..24252610be 100755
--- a/test/functional/interface_rest.py
+++ b/test/functional/interface_rest.py
@@ -387,6 +387,17 @@ class RESTTest (BitcoinTestFramework):
assert_equal(self.test_rest_request(f"/headers/{bb_hash}", query_params={"count": 1}), self.test_rest_request(f"/headers/1/{bb_hash}"))
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}"))
+ self.log.info("Test the /deploymentinfo URI")
+
+ deployment_info = self.nodes[0].getdeploymentinfo()
+ assert_equal(deployment_info, self.test_rest_request('/deploymentinfo'))
+
+ non_existing_blockhash = '42759cde25462784395a337460bde75f58e73d3f08bd31fdc3507cbac856a2c4'
+ resp = self.test_rest_request(f'/deploymentinfo/{non_existing_blockhash}', ret_type=RetType.OBJ, status=400)
+ assert_equal(resp.read().decode('utf-8').rstrip(), "Block not found")
+
+ resp = self.test_rest_request(f"/deploymentinfo/{INVALID_PARAM}", ret_type=RetType.OBJ, status=400)
+ assert_equal(resp.read().decode('utf-8').rstrip(), f"Invalid hash: {INVALID_PARAM}")
if __name__ == '__main__':
RESTTest().main()