From 599effdeab4d6687da783de04f8edf1d88959169 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sun, 14 Dec 2025 09:57:11 +0100 Subject: [PATCH 1/6] rest: reformat `uri_prefixes` initializer list There was an extra indentation level (found during #33657): ``` $ git show -U0 07135290c1 | ./contrib/devtools/clang-format-diff.py -p1 -i -v ``` --- src/rest.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/rest.cpp b/src/rest.cpp index 06da3906649..b91b229a1f0 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -1142,20 +1142,20 @@ static const struct { const char* prefix; bool (*handler)(const std::any& context, HTTPRequest* req, const std::string& strReq); } uri_prefixes[] = { - {"/rest/tx/", rest_tx}, - {"/rest/block/notxdetails/", rest_block_notxdetails}, - {"/rest/block/", rest_block_extended}, - {"/rest/blockpart/", rest_block_part}, - {"/rest/blockfilter/", rest_block_filter}, - {"/rest/blockfilterheaders/", rest_filter_header}, - {"/rest/chaininfo", rest_chaininfo}, - {"/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}, - {"/rest/spenttxouts/", rest_spent_txouts}, + {"/rest/tx/", rest_tx}, + {"/rest/block/notxdetails/", rest_block_notxdetails}, + {"/rest/block/", rest_block_extended}, + {"/rest/blockpart/", rest_block_part}, + {"/rest/blockfilter/", rest_block_filter}, + {"/rest/blockfilterheaders/", rest_filter_header}, + {"/rest/chaininfo", rest_chaininfo}, + {"/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}, + {"/rest/spenttxouts/", rest_spent_txouts}, }; void StartREST(const std::any& context) From 41118e17f87561afc8cbe1f3dd528624f06906a7 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sun, 14 Dec 2025 10:17:07 +0100 Subject: [PATCH 2/6] blockstorage: simplify partial block read validation Use `SaturatingAdd` following https://github.com/bitcoin/bitcoin/pull/33657#discussion_r2610832092. --- src/node/blockstorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 22c8f619e60..e39b4163fc5 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -1083,7 +1083,7 @@ BlockManager::ReadRawBlockResult BlockManager::ReadRawBlock(const FlatFilePos& p if (block_part) { const auto [offset, size]{*block_part}; - if (size == 0 || offset >= blk_size || size > blk_size - offset) { + if (size == 0 || SaturatingAdd(offset, size) > blk_size) { return util::Unexpected{ReadRawError::BadPartRange}; // Avoid logging - offset/size come from untrusted REST input } filein.seek(offset, SEEK_CUR); From 89eb531024d9921f5c825d390b90c0a7bd3756cc Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sun, 14 Dec 2025 12:41:07 +0100 Subject: [PATCH 3/6] rest: update release notes for `/blockpart/` endpoint --- doc/release-notes-33657.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release-notes-33657.md b/doc/release-notes-33657.md index f9e6841bf74..a9821323356 100644 --- a/doc/release-notes-33657.md +++ b/doc/release-notes-33657.md @@ -1,5 +1,5 @@ New REST API ------------ -- A new REST API endpoint (`/rest/blockpart/BLOCKHASH.bin?offset=X&size=Y`) has been introduced - for efficiently fetching a range of bytes from block `BLOCKHASH`. +- A new REST API endpoint (`/rest/blockpart/.?offset=&size=`) has been introduced + for efficiently fetching a range of bytes from block ``. From 55d0d19b5c02a65d8dfafd99f352769224ab51a4 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sun, 14 Dec 2025 12:44:59 +0100 Subject: [PATCH 4/6] rest: deduplicate `interface_rest.py` negative tests --- test/functional/interface_rest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index be5bb78b10e..6b4bb7970f7 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -485,7 +485,6 @@ class RESTTest (BitcoinTestFramework): get_block_part(status=400, query_params={"offset": 0, "size": 0}) get_block_part(status=400, query_params={"offset": len(block_bin), "size": 0}) - get_block_part(status=400, query_params={"offset": len(block_bin) + 1, "size": 1}) get_block_part(status=400, query_params={"offset": len(block_bin), "size": 1}) get_block_part(status=400, query_params={"offset": len(block_bin) + 1, "size": 1}) get_block_part(status=400, query_params={"offset": 0, "size": len(block_bin) + 1}) From 7fe94a04934a89b63f1248cb46d59f0ab45439b5 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Mon, 15 Dec 2025 23:34:11 +0100 Subject: [PATCH 5/6] rest: add a test for unsuported `/blockpart/` request type --- test/functional/interface_rest.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index 6b4bb7970f7..2e9617d0c20 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -489,7 +489,11 @@ class RESTTest (BitcoinTestFramework): get_block_part(status=400, query_params={"offset": len(block_bin) + 1, "size": 1}) get_block_part(status=400, query_params={"offset": 0, "size": len(block_bin) + 1}) - self.test_rest_request(f"/blockpart/{blockhash}", status=400, req_type=ReqType.JSON, ret_type=RetType.OBJ) + res = self.test_rest_request(f"/blockpart/{blockhash}", status=400, req_type=ReqType.BIN, ret_type=RetType.OBJ) + assert res.read().decode().startswith("Block part offset missing or invalid") + + res = self.test_rest_request(f"/blockpart/{blockhash}", query_params={"offset":0, "size":1}, status=400, req_type=ReqType.JSON, ret_type=RetType.OBJ) + assert res.read().decode().startswith("JSON output is not supported for this request type") self.log.info("Missing block data should cause REST API to fail") From 59b93f11e8600d5224359f4d05619c0f56aef1e6 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Tue, 16 Dec 2025 23:13:48 +0100 Subject: [PATCH 6/6] rest: print also HTTP response reason in case of an error --- test/functional/interface_rest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index 2e9617d0c20..f27921692df 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -84,7 +84,7 @@ class RESTTest (BitcoinTestFramework): conn.request('POST', rest_uri, body) resp = conn.getresponse() - assert resp.status == status, f"Expected: {status}, Got: {resp.status} - Response: {str(resp.read())}" + assert resp.status == status, f"Expected: {status}, Got: {resp.status} ({resp.reason}) - Response: {str(resp.read())}" if ret_type == RetType.OBJ: return resp