urma_node_client/client/
overlay.rs1use super::{Client, OPERATION_TIMEOUT, invalid, remaining};
4use crate::{
5 Error,
6 model::{BookEntry, Omission},
7};
8use serde::de::DeserializeOwned;
9use std::time::Instant;
10
11const MAX_OMISSIONS: usize = 1024;
12const MAX_BOOK: usize = 1024;
13const MAX_ADDRESSES: usize = 4;
14
15impl Client {
16 pub fn overlay_omissions(&self) -> Result<Vec<Omission>, Error> {
20 let omissions: Vec<Omission> = self.overlay_read("/v1/overlay/omissions", "omissions")?;
21 if omissions.len() > MAX_OMISSIONS {
22 return Err(invalid("local overlay omissions exceed 1024 entries"));
23 }
24 if omissions
25 .windows(2)
26 .any(|pair| pair[0].block.height > pair[1].block.height)
27 {
28 return Err(invalid("local overlay omissions are not ordered by height"));
29 }
30 Ok(omissions)
31 }
32
33 pub fn overlay_book(&self) -> Result<Vec<BookEntry>, Error> {
37 let book: Vec<BookEntry> = self.overlay_read("/v1/overlay/book", "book")?;
38 if book.len() > MAX_BOOK {
39 return Err(invalid("local overlay book exceeds 1024 entries"));
40 }
41 if book
42 .iter()
43 .any(|entry| entry.addrs.is_empty() || entry.addrs.len() > MAX_ADDRESSES)
44 {
45 return Err(invalid(
46 "local overlay book entry needs one to four addresses",
47 ));
48 }
49 Ok(book)
50 }
51
52 fn overlay_read<T: DeserializeOwned>(&self, path: &str, what: &str) -> Result<T, Error> {
53 let deadline = Instant::now() + OPERATION_TIMEOUT;
54 let (code, body) = self.request("GET", path, deadline)?;
55 match code {
56 200 => {
57 let value = serde_json::from_slice(&body)?;
58 remaining(deadline)?;
59 Ok(value)
60 }
61 404 => {
62 let _: serde_json::Value = serde_json::from_slice(&body)?;
63 remaining(deadline)?;
64 Err(invalid("overlay disabled"))
65 }
66 _ => Err(invalid(format!("local overlay {what} HTTP {code}"))),
67 }
68 }
69}