Contractless/src/startup/remote_height.rs

44 lines
1.5 KiB
Rust

use crate::records::memory::response_channels::{reserve_entry_with_context, Command};
use crate::rpc::command_maps::RPC_BLOCK_HEIGHT;
use crate::rpc::responses::RpcResponse;
use crate::Arc;
use crate::Mutex;
use crate::TcpStream;
use crate::{timeout, Duration};
pub async fn request_remote_height(
stream: Arc<Mutex<TcpStream>>,
map: Arc<Mutex<Command>>,
connections_key: String,
) -> Result<u32, String> {
// request the remote node's current chain height using
// the standard reply-channel request/response flow
let (hashmap_key, _tx, rx) =
reserve_entry_with_context(map.clone(), Some(RPC_BLOCK_HEIGHT), Some(connections_key.clone()))
.await;
// message format is the height command plus the unique
// reply key used to route the response back here
let mut message = vec![RPC_BLOCK_HEIGHT];
message.extend_from_slice(&hashmap_key);
RpcResponse::send_raw(&stream, Some(&connections_key), &message).await;
// The response is routed back through the reserved hashmap receiver.
let mut rx = rx.lock().await;
let buffer = timeout(Duration::from_secs(15), rx.recv())
.await
.map_err(|_| "Timed out waiting for height response".to_string())?
.ok_or("No height response received")?;
if buffer.len() != 4 {
return Err(format!(
"Invalid height response length: expected 4, got {}",
buffer.len()
));
}
// Heights are encoded as exactly one little-endian u32.
Ok(u32::from_le_bytes(buffer.try_into().unwrap()))
}