Skip to content

Commit 72a02cd

Browse files
author
Oleksandr Fedorenko
committed
fix error handling for GET /block/:hash/txs/:index
1 parent 0f348b8 commit 72a02cd

3 files changed

Lines changed: 74 additions & 6 deletions

File tree

src/new_index/schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,11 @@ impl ChainQuery {
515515

516516
pub fn get_block_txs(
517517
&self,
518+
txids: Vec<Txid>,
518519
hash: &BlockHash,
519520
start_index: usize,
520521
limit: usize,
521522
) -> Result<Vec<Transaction>> {
522-
let txids = self.get_block_txids(hash).chain_err(|| "block not found")?;
523523
ensure!(start_index < txids.len(), "start index out of range");
524524

525525
let txids_with_blockhash = txids

src/rest.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,10 +792,15 @@ fn handle_request(
792792

793793
// The BlockId would not be available for stale blocks
794794
let blockid = query.chain().blockid_by_hash(&hash);
795+
796+
let txids = query
797+
.chain()
798+
.get_block_txids(&hash)
799+
.ok_or_else(|| HttpError::not_found("Block not found".to_string()))?;
795800

796801
let txs = query
797802
.chain()
798-
.get_block_txs(&hash, start_index, CHAIN_TXS_PER_PAGE)?
803+
.get_block_txs(txids, &hash, start_index, CHAIN_TXS_PER_PAGE)?
799804
.into_iter()
800805
.map(|tx| (tx, blockid))
801806
.collect();

tests/rest.rs

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,22 @@ fn test_rest_block() -> Result<()> {
328328
tester.node_client().call::<String>("getblock", &[blockhash.to_string().into(), 0.into()])?;
329329
assert_eq!(rest_rawblock, Vec::from_hex(&node_hexblock).unwrap());
330330

331+
// Test GET /block/:hash/txid/:index
332+
let res = get_plain(rest_addr, &format!("/block/{}/txid/1", blockhash))?;
333+
assert_eq!(res, txid.to_string());
334+
335+
rest_handle.stop();
336+
Ok(())
337+
}
338+
339+
#[test]
340+
fn test_rest_block_txs() -> Result<()> {
341+
let (rest_handle, rest_addr, mut tester) = common::init_rest_tester().unwrap();
342+
343+
let addr1 = tester.newaddress()?;
344+
let txid = tester.send(&addr1, "0.98765432 BTC".parse().unwrap())?;
345+
let blockhash = tester.mine()?;
346+
331347
// Test GET /block/:hash/txs
332348
let res = get_json(rest_addr, &format!("/block/{}/txs", blockhash))?;
333349
let block_txs = res.as_array().expect("list of txs");
@@ -338,14 +354,61 @@ fn test_rest_block() -> Result<()> {
338354
Some(txid.to_string().as_str())
339355
);
340356

341-
// Test GET /block/:hash/txid/:index
342-
let res = get_plain(rest_addr, &format!("/block/{}/txid/1", blockhash))?;
343-
assert_eq!(res, txid.to_string());
357+
// Test GET /block/:hash/txs/:index
358+
let res = get_json(rest_addr, &format!("/block/{}/txs/0", blockhash))?;
359+
let block_txs = res.as_array().expect("list of txs");
360+
assert_eq!(block_txs.len(), 2);
361+
assert_eq!(block_txs[0]["vin"][0]["is_coinbase"].as_bool(), Some(true));
362+
assert_eq!(
363+
block_txs[1]["txid"].as_str(),
364+
Some(txid.to_string().as_str())
365+
);
366+
367+
// Test GET /block/:hash/txs/:index
368+
// Should fail with 404 code when block isn't found
369+
let invalid_resp = ureq::get(&format!("http://{}/block/{}/txs/0", rest_addr, "0000000000000000000000000000000000000000000000000000000000000000"))
370+
.config()
371+
.http_status_as_error(false)
372+
.build()
373+
.call()?;
374+
assert_eq!(invalid_resp.status(), 404);
375+
assert_eq!(invalid_resp.into_body().read_to_string()?, "Block not found");
376+
377+
// Test GET /block/:hash/txs/:index
378+
// Should fail with 400 code when block hash is invalid
379+
let invalid_resp = ureq::get(&format!("http://{}/block/{}/txs/0", rest_addr, "invalid_hash"))
380+
.config()
381+
.http_status_as_error(false)
382+
.build()
383+
.call()?;
384+
assert_eq!(invalid_resp.status(), 400);
385+
assert_eq!(invalid_resp.into_body().read_to_string()?, "Invalid hex string");
386+
387+
// Test GET /block/:hash/txs/:index
388+
// Should fail with 400 code when `(index % 25) != 0`
389+
let invalid_hash_resp = ureq::get(&format!("http://{}/block/{}/txs/1", rest_addr, blockhash))
390+
.config()
391+
.http_status_as_error(false)
392+
.build()
393+
.call()?;
394+
assert_eq!(invalid_hash_resp.status(), 400);
395+
assert_eq!(invalid_hash_resp.into_body().read_to_string()?, "start index must be a multipication of 25");
396+
397+
// Test GET /block/:hash/txs/:index
398+
// Should fail with 400 code when index is out of range
399+
let invalid_hash_resp = ureq::get(&format!("http://{}/block/{}/txs/25", rest_addr, blockhash))
400+
.config()
401+
.http_status_as_error(false)
402+
.build()
403+
.call()?;
404+
assert_eq!(invalid_hash_resp.status(), 400);
405+
assert_eq!(invalid_hash_resp.into_body().read_to_string()?, "start index out of range");
344406

345407
rest_handle.stop();
346408
Ok(())
347409
}
348410

411+
349412
#[test]
350413
fn test_rest_mempool() -> Result<()> {
351414
let (rest_handle, rest_addr, mut tester) = common::init_rest_tester().unwrap();
@@ -1043,7 +1106,7 @@ fn test_rest_reorg() -> Result<()> {
10431106
#[cfg(not(feature = "liquid"))]
10441107
#[test]
10451108
fn test_rest_submit_package() -> Result<()> {
1046-
let (rest_handle, rest_addr, mut tester) = common::init_rest_tester().unwrap();
1109+
let (rest_handle, rest_addr, tester) = common::init_rest_tester().unwrap();
10471110

10481111
// Test with a real transaction package - create parent-child transactions
10491112
// submitpackage requires between 2 and 25 transactions with proper dependencies

0 commit comments

Comments
 (0)