From 127dee6c6229131ed3542968f7d7cca8e84246e5 Mon Sep 17 00:00:00 2001 From: Johnathan Reale Date: Mon, 18 Aug 2025 09:48:19 -0400 Subject: [PATCH 01/10] Moving the JetBrains IDE entry w/other IDE entries --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ec874727c..7cb8fc0ec 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ wit/ **/wit-*/ **/*.wasm .vscode +/.idea .app-signing .DS_Store *.swp @@ -29,4 +30,3 @@ hyperdrive/packages/docs/pkg/ui hyperdrive/src/register-ui/build/ hyperdrive/src/register-ui/dist/ hyperdrive/packages/docs/pkg/ui -/.idea From a14f660f8564a13da091b59fd88dbc4a78ec964e Mon Sep 17 00:00:00 2001 From: Johnathan Reale Date: Mon, 18 Aug 2025 15:13:57 -0400 Subject: [PATCH 02/10] first hypermap binding cacher scaffold --- Cargo.toml | 2 +- .../packages/hypermap-cacher/Cargo.lock | 19 + .../packages/hypermap-cacher/Cargo.toml | 1 + .../api/hypermap-cacher:sys-v0.wit | 83 -- .../api/hypermap-cacher:sys-v1.wit | 162 ++ .../hypermap-binding-cacher/Cargo.toml | 33 + .../hypermap-binding-cacher/src/lib.rs | 1314 +++++++++++++++++ .../hypermap-cacher/src/lib.rs | 4 +- .../hypermap-cacher/pkg/manifest.json | 26 + .../hypermap-cacher/reset-cache/src/lib.rs | 2 +- .../hypermap-cacher/set-nodes/src/lib.rs | 2 +- .../start-providing/src/lib.rs | 2 +- .../hypermap-cacher/stop-providing/src/lib.rs | 2 +- 13 files changed, 1562 insertions(+), 90 deletions(-) delete mode 100644 hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v0.wit create mode 100644 hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v1.wit create mode 100644 hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/Cargo.toml create mode 100644 hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 798d6772a..bbf8e5304 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ members = [ "hyperdrive/packages/homepage/homepage", "hyperdrive/packages/hns-indexer/hns-indexer", "hyperdrive/packages/hns-indexer/get-block", "hyperdrive/packages/settings/settings", "hyperdrive/packages/hns-indexer/reset", "hyperdrive/packages/hns-indexer/node-info", "hyperdrive/packages/hns-indexer/state", - "hyperdrive/packages/hypermap-cacher/hypermap-cacher", "hyperdrive/packages/hypermap-cacher/reset-cache", "hyperdrive/packages/hypermap-cacher/set-nodes", + "hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher", "hyperdrive/packages/hypermap-cacher/hypermap-cacher", "hyperdrive/packages/hypermap-cacher/reset-cache", "hyperdrive/packages/hypermap-cacher/set-nodes", "hyperdrive/packages/hypermap-cacher/start-providing", "hyperdrive/packages/hypermap-cacher/stop-providing", "hyperdrive/packages/sign/sign", "hyperdrive/packages/terminal/terminal", "hyperdrive/packages/terminal/add-node-provider", "hyperdrive/packages/terminal/add-rpcurl-provider", diff --git a/hyperdrive/packages/hypermap-cacher/Cargo.lock b/hyperdrive/packages/hypermap-cacher/Cargo.lock index 4806c43a8..dc03c1c4a 100644 --- a/hyperdrive/packages/hypermap-cacher/Cargo.lock +++ b/hyperdrive/packages/hypermap-cacher/Cargo.lock @@ -1640,6 +1640,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "hypermap-binding-cacher" +version = "0.1.0" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-types", + "anyhow", + "chrono", + "hex", + "hyperware_process_lib", + "process_macros", + "rand 0.8.5", + "rmp-serde", + "serde", + "serde_json", + "wit-bindgen", +] + [[package]] name = "hypermap-cacher" version = "0.1.0" diff --git a/hyperdrive/packages/hypermap-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/Cargo.toml index ff6b64639..ef0fd2640 100644 --- a/hyperdrive/packages/hypermap-cacher/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/Cargo.toml @@ -1,6 +1,7 @@ [workspace] resolver = "2" members = [ + "hypermap-binding-cacher", "hypermap-cacher", "reset-cache", "set-nodes", diff --git a/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v0.wit b/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v0.wit deleted file mode 100644 index 21a3652ae..000000000 --- a/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v0.wit +++ /dev/null @@ -1,83 +0,0 @@ -interface hypermap-cacher { - // Metadata associated with a batch of Ethereum logs. - record logs-metadata { - chain-id: string, - from-block: string, - to-block: string, - time-created: string, - created-by: string, - signature: string, - } - - // Represents an item in the manifest, detailing a single log cache file. - record manifest-item { - metadata: logs-metadata, - is-empty: bool, - file-hash: string, - file-name: string, - } - - // The main manifest structure, listing all available log cache files. - // WIT does not support direct map types, so a list of key-value tuples is used. - record manifest { - // The key is the filename of the log cache. - items: list>, - manifest-filename: string, - chain-id: string, - protocol-version: string, - } - - record get-logs-by-range-request { - from-block: u64, - to-block: option, // If None, signifies to the latest available/relevant cached block. - } - - variant get-logs-by-range-ok-response { - logs(tuple), - latest(u64), - } - - // Defines the types of requests that can be sent to the Hypermap Cacher process. - variant cacher-request { - get-manifest, - get-log-cache-content(string), - get-status, - get-logs-by-range(get-logs-by-range-request), - start-providing, - stop-providing, - set-nodes(list), - reset(option>), - } - - // Represents the operational status of the cacher. - record cacher-status { - last-cached-block: u64, - chain-id: string, - protocol-version: string, - next-cache-attempt-in-seconds: option, - manifest-filename: string, - log-files-count: u32, - our-address: string, - is-providing: bool, - } - - // Defines the types of responses the Hypermap Cacher process can send. - variant cacher-response { - get-manifest(option), - get-log-cache-content(result, string>), - get-status(cacher-status), - get-logs-by-range(result), - start-providing(result), - stop-providing(result), - set-nodes(result), - reset(result), - rejected, - is-starting, - } -} - -world hypermap-cacher-sys-v0 { - import sign; - import hypermap-cacher; - include process-v1; -} diff --git a/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v1.wit b/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v1.wit new file mode 100644 index 000000000..31f65fc49 --- /dev/null +++ b/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v1.wit @@ -0,0 +1,162 @@ +interface hypermap-binding-cacher { + // Metadata associated with a batch of Ethereum logs. + record logs-metadata { + chain-id: string, + from-block: string, + to-block: string, + time-created: string, + created-by: string, + signature: string, + } + + // Represents an item in the manifest, detailing a single log cache file. + record manifest-item { + metadata: logs-metadata, + is-empty: bool, + file-hash: string, + file-name: string, + } + + // The main manifest structure, listing all available log cache files. + // WIT does not support direct map types, so a list of key-value tuples is used. + record manifest { + // The key is the filename of the log cache. + items: list>, + manifest-filename: string, + chain-id: string, + protocol-version: string, + } + + record get-logs-by-range-request { + from-block: u64, + to-block: option, // If None, signifies to the latest available/relevant cached block. + } + + variant get-logs-by-range-ok-response { + logs(tuple), + latest(u64), + } + + // Defines the types of requests that can be sent to the Hypermap Cacher process. + variant cacher-request { + get-manifest, + get-log-cache-content(string), + get-status, + get-logs-by-range(get-logs-by-range-request), + start-providing, + stop-providing, + set-nodes(list), + reset(option>), + } + + // Represents the operational status of the cacher. + record cacher-status { + last-cached-block: u64, + chain-id: string, + protocol-version: string, + next-cache-attempt-in-seconds: option, + manifest-filename: string, + log-files-count: u32, + our-address: string, + is-providing: bool, + } + + // Defines the types of responses the Hypermap Cacher process can send. + variant cacher-response { + get-manifest(option), + get-log-cache-content(result, string>), + get-status(cacher-status), + get-logs-by-range(result), + start-providing(result), + stop-providing(result), + set-nodes(result), + reset(result), + rejected, + is-starting, + } +} + +interface hypermap-cacher { + // Metadata associated with a batch of Ethereum logs. + record logs-metadata { + chain-id: string, + from-block: string, + to-block: string, + time-created: string, + created-by: string, + signature: string, + } + + // Represents an item in the manifest, detailing a single log cache file. + record manifest-item { + metadata: logs-metadata, + is-empty: bool, + file-hash: string, + file-name: string, + } + + // The main manifest structure, listing all available log cache files. + // WIT does not support direct map types, so a list of key-value tuples is used. + record manifest { + // The key is the filename of the log cache. + items: list>, + manifest-filename: string, + chain-id: string, + protocol-version: string, + } + + record get-logs-by-range-request { + from-block: u64, + to-block: option, // If None, signifies to the latest available/relevant cached block. + } + + variant get-logs-by-range-ok-response { + logs(tuple), + latest(u64), + } + + // Defines the types of requests that can be sent to the Hypermap Cacher process. + variant cacher-request { + get-manifest, + get-log-cache-content(string), + get-status, + get-logs-by-range(get-logs-by-range-request), + start-providing, + stop-providing, + set-nodes(list), + reset(option>), + } + + // Represents the operational status of the cacher. + record cacher-status { + last-cached-block: u64, + chain-id: string, + protocol-version: string, + next-cache-attempt-in-seconds: option, + manifest-filename: string, + log-files-count: u32, + our-address: string, + is-providing: bool, + } + + // Defines the types of responses the Hypermap Cacher process can send. + variant cacher-response { + get-manifest(option), + get-log-cache-content(result, string>), + get-status(cacher-status), + get-logs-by-range(result), + start-providing(result), + stop-providing(result), + set-nodes(result), + reset(result), + rejected, + is-starting, + } +} + +world hypermap-cacher-sys-v1 { + import sign; + import hypermap-binding-cacher; + import hypermap-cacher; + include process-v1; +} diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/Cargo.toml new file mode 100644 index 000000000..2deec97e6 --- /dev/null +++ b/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "hypermap-binding-cacher" +version = "0.1.0" +edition = "2021" +publish = false + +[features] +simulation-mode = ["hyperware_process_lib/simulation-mode"] + +[dependencies] +anyhow = "1.0" +alloy-primitives = "0.8.15" +alloy-sol-types = "0.8.15" +alloy = { version = "0.8.1", features = [ + "json-rpc", + "rpc-client", + "rpc-types", +] } +chrono = "0.4.41" +hex = "0.4.3" +hyperware_process_lib = { version = "2.1.0", features = ["logging"] } +process_macros = "0.1.0" +rand = "0.8" +rmp-serde = "1.1.2" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +wit-bindgen = "0.42.1" + +[lib] +crate-type = ["cdylib"] + +[package.metadata.component] +package = "hyperware:process" diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/src/lib.rs new file mode 100644 index 000000000..5e2003754 --- /dev/null +++ b/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/src/lib.rs @@ -0,0 +1,1314 @@ +use std::{ + cmp::{max, min}, + collections::HashMap, + str::FromStr, +}; + +use alloy::hex; +use alloy_primitives::keccak256; +use rand::seq::SliceRandom; +use rand::thread_rng; +use serde::{Deserialize, Serialize}; + +use crate::hyperware::process::hypermap_cacher::{ + CacherRequest, CacherResponse, CacherStatus, GetLogsByRangeOkResponse, GetLogsByRangeRequest, + LogsMetadata as WitLogsMetadata, Manifest as WitManifest, ManifestItem as WitManifestItem, +}; + +use hyperware_process_lib::{ + await_message, call_init, eth, get_state, http, hypermap, + logging::{debug, error, info, init_logging, warn, Level}, + net::{NetAction, NetResponse}, + our, set_state, sign, timer, vfs, Address, ProcessId, Request, Response, +}; + +wit_bindgen::generate!({ + path: "../target/wit", + world: "hypermap-cacher-sys-v1", + generate_unused_types: true, + additional_derives: [serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], +}); + +const PROTOCOL_VERSION: &str = "0"; +const DEFAULT_BLOCK_BATCH_SIZE: u64 = 500; +const DEFAULT_CACHE_INTERVAL_S: u64 = 2 * 500; // 500 blocks, 2s / block = 1000s; +const MAX_LOG_RETRIES: u8 = 3; +const RETRY_DELAY_S: u64 = 10; +const LOG_ITERATION_DELAY_MS: u64 = 200; + +#[cfg(not(feature = "simulation-mode"))] +const DEFAULT_NODES: &[&str] = &[ + "us-cacher-1.hypr", + "eu-cacher-1.hypr", + "nick.hypr", + "nick1udwig.os", +]; +#[cfg(feature = "simulation-mode")] +const DEFAULT_NODES: &[&str] = &["fake.os"]; + +// Internal representation of LogsMetadata, similar to WIT but for Rust logic. +#[derive(Serialize, Deserialize, Debug, Clone)] +struct LogsMetadataInternal { + #[serde(rename = "chainId")] + chain_id: String, + #[serde(rename = "fromBlock")] + from_block: String, + #[serde(rename = "toBlock")] + to_block: String, + #[serde(rename = "timeCreated")] + time_created: String, + #[serde(rename = "createdBy")] + created_by: String, + signature: String, // Keccak256 hash of the log file content. +} + +// Internal representation of a LogCache, containing metadata and actual logs. +#[derive(Serialize, Deserialize, Debug, Clone)] +struct LogCacheInternal { + metadata: LogsMetadataInternal, + logs: Vec, // The actual Ethereum logs. +} + +// Internal representation of a ManifestItem. +#[derive(Serialize, Deserialize, Debug, Clone)] +struct ManifestItemInternal { + metadata: LogsMetadataInternal, + #[serde(rename = "isEmpty")] + is_empty: bool, + #[serde(rename = "fileHash")] + file_hash: String, + #[serde(rename = "fileName")] + file_name: String, +} + +// Internal representation of the Manifest. +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +struct ManifestInternal { + items: HashMap, + manifest_filename: String, + chain_id: String, + protocol_version: String, +} + +// The main state structure for the Hypermap Binding Cacher process. +#[derive(Serialize, Deserialize, Debug)] +struct State { + hypermap_address: eth::Address, + manifest: ManifestInternal, + last_cached_block: u64, + chain_id: String, + protocol_version: String, + cache_interval_s: u64, + block_batch_size: u64, + is_cache_timer_live: bool, + drive_path: String, + is_providing: bool, + nodes: Vec, + #[serde(skip)] + is_starting: bool, +} + +// Generates a timestamp string. +fn get_current_timestamp_str() -> String { + let datetime = chrono::Utc::now(); + datetime.format("%Y%m%dT%H%M%SZ").to_string() +} + +fn is_local_request(our: &Address, source: &Address) -> bool { + our.node == source.node +} + +impl State { + fn new(drive_path: &str) -> Self { + let chain_id = hypermap::HYPERMAP_CHAIN_ID.to_string(); + let hypermap_address = eth::Address::from_str(hypermap::HYPERMAP_ADDRESS) + .expect("Failed to parse HYPERMAP_ADDRESS"); + + let manifest_filename = format!( + "manifest-chain{}-protocol{}.json", + chain_id, PROTOCOL_VERSION + ); + let initial_manifest = ManifestInternal { + items: HashMap::new(), + manifest_filename: manifest_filename.clone(), + chain_id: chain_id.clone(), + protocol_version: PROTOCOL_VERSION.to_string(), + }; + + State { + hypermap_address, + manifest: initial_manifest, + last_cached_block: hypermap::HYPERMAP_FIRST_BLOCK, + chain_id, + protocol_version: PROTOCOL_VERSION.to_string(), + cache_interval_s: DEFAULT_CACHE_INTERVAL_S, + block_batch_size: DEFAULT_BLOCK_BATCH_SIZE, + is_cache_timer_live: false, + drive_path: drive_path.to_string(), + is_providing: false, + nodes: DEFAULT_NODES.iter().map(|s| s.to_string()).collect(), + is_starting: true, + } + } + + fn load(drive_path: &str) -> Self { + match get_state() { + Some(state_bytes) => match serde_json::from_slice::(&state_bytes) { + Ok(mut loaded_state) => { + info!("Successfully loaded state from checkpoint."); + // Always start in starting mode to bootstrap from other nodes + // is_starting is not serialized, so it defaults to false and we set it to true + loaded_state.is_starting = true; + loaded_state.drive_path = drive_path.to_string(); + + // Validate state against manifest file on disk + if let Err(e) = loaded_state.validate_state_against_manifest() { + warn!("State validation failed: {:?}. Clearing drive and creating fresh state.", e); + if let Err(clear_err) = loaded_state.clear_drive() { + error!("Failed to clear drive: {:?}", clear_err); + } + return Self::new(drive_path); + } + + loaded_state + } + Err(e) => { + warn!( + "Failed to deserialize saved state: {:?}. Creating new state.", + e + ); + Self::new(drive_path) + } + }, + None => { + info!("No saved state found. Creating new state."); + Self::new(drive_path) + } + } + } + + fn save(&self) { + match serde_json::to_vec(self) { + Ok(state_bytes) => set_state(&state_bytes), + Err(e) => error!("Fatal: Failed to serialize state for saving: {:?}", e), + } + info!( + "State checkpoint saved. Last cached block: {}", + self.last_cached_block + ); + } + + // Core logic for fetching logs, creating cache files, and updating the manifest. + fn cache_logs_and_update_manifest( + &mut self, + hypermap: &hypermap::Hypermap, + ) -> anyhow::Result<()> { + let current_chain_head = match hypermap.provider.get_block_number() { + Ok(block_num) => block_num, + Err(e) => { + error!( + "Failed to get current block number: {:?}. Skipping cycle.", + e + ); + return Err(anyhow::anyhow!("Failed to get block number: {:?}", e)); + } + }; + + if self.last_cached_block >= current_chain_head { + info!( + "Already caught up to chain head ({}). Nothing to cache.", + current_chain_head + ); + return Ok(()); + } + + while self.last_cached_block != current_chain_head { + self.cache_logs_and_update_manifest_step(hypermap, Some(current_chain_head))?; + + std::thread::sleep(std::time::Duration::from_millis(LOG_ITERATION_DELAY_MS)); + } + + Ok(()) + } + + fn cache_logs_and_update_manifest_step( + &mut self, + hypermap: &hypermap::Hypermap, + to_block: Option, + ) -> anyhow::Result<()> { + info!( + "Starting caching cycle. From block: {}", + self.last_cached_block + 1 + ); + + let current_chain_head = match to_block { + Some(b) => b, + None => match hypermap.provider.get_block_number() { + Ok(block_num) => block_num, + Err(e) => { + error!( + "Failed to get current block number: {:?}. Skipping cycle.", + e + ); + return Err(anyhow::anyhow!("Failed to get block number: {:?}", e)); + } + }, + }; + + if self.last_cached_block >= current_chain_head { + info!( + "Already caught up to chain head ({}). Nothing to cache.", + current_chain_head + ); + return Ok(()); + } + + let from_block = self.last_cached_block + 1; + let mut to_block = from_block + self.block_batch_size - 1; + if to_block > current_chain_head { + to_block = current_chain_head; + } + + if from_block > to_block { + info!("From_block {} is greater than to_block {}. Chain might not have advanced enough. Skipping.", from_block, to_block); + return Ok(()); + } + + let filter = eth::Filter::new() + .address(self.hypermap_address) + .from_block(from_block) + .to_block(eth::BlockNumberOrTag::Number(to_block)); + + let logs = { + let mut attempt = 0; + loop { + match hypermap.provider.get_logs(&filter) { + Ok(logs) => break logs, + Err(e) => { + attempt += 1; + if attempt >= MAX_LOG_RETRIES { + error!( + "Failed to get logs after {} retries: {:?}", + MAX_LOG_RETRIES, e + ); + return Err(anyhow::anyhow!("Failed to get logs: {:?}", e)); + } + warn!( + "Error getting logs (attempt {}/{}): {:?}. Retrying in {}s...", + attempt, MAX_LOG_RETRIES, e, RETRY_DELAY_S + ); + std::thread::sleep(std::time::Duration::from_secs(RETRY_DELAY_S)); + } + } + } + }; + + info!( + "Fetched {} logs from block {} to {}.", + logs.len(), + from_block, + to_block + ); + + let our = our(); + + let metadata = LogsMetadataInternal { + chain_id: self.chain_id.clone(), + from_block: from_block.to_string(), + to_block: to_block.to_string(), + time_created: get_current_timestamp_str(), + created_by: our.to_string(), + signature: "".to_string(), + }; + + let mut log_cache = LogCacheInternal { + metadata, + logs: logs.clone(), + }; + + let mut logs_bytes_for_sig = serde_json::to_vec(&log_cache.logs).unwrap_or_default(); + logs_bytes_for_sig.extend_from_slice(&from_block.to_be_bytes()); + logs_bytes_for_sig.extend_from_slice(&to_block.to_be_bytes()); + let logs_hash_for_sig = keccak256(&logs_bytes_for_sig); + + let signature = sign::net_key_sign(logs_hash_for_sig.to_vec())?; + + log_cache.metadata.signature = format!("0x{}", hex::encode(signature)); + + // Final serialization of LogCacheInternal with the signature. + let final_log_cache_bytes = match serde_json::to_vec(&log_cache) { + Ok(bytes) => bytes, + Err(e) => { + error!( + "Failed to re-serialize LogCacheInternal with signature: {:?}", + e + ); + return Err(e.into()); + } + }; + + let file_hash_for_manifest = + format!("0x{}", hex::encode(keccak256(&final_log_cache_bytes))); + + let log_cache_filename = format!( + "{}-chain{}-from{}-to{}-protocol{}.json", + log_cache + .metadata + .time_created + .replace(":", "") + .replace("-", ""), // Make timestamp filename-safe + self.chain_id, + from_block, + to_block, + self.protocol_version + ); + + if !logs.is_empty() { + let log_cache_path = format!("{}/{}", self.drive_path, log_cache_filename); + let mut log_cache_file = vfs::open_file(&log_cache_path, true, None)?; + + if let Err(e) = log_cache_file.write_all(&final_log_cache_bytes) { + error!("Failed to write log cache file {}: {:?}", log_cache_path, e); + return Err(e.into()); + } + info!("Successfully wrote log cache file: {}", log_cache_path); + } + + let manifest_item = ManifestItemInternal { + metadata: log_cache.metadata.clone(), + is_empty: logs.is_empty(), + file_hash: file_hash_for_manifest, + file_name: if logs.is_empty() { + "".to_string() + } else { + log_cache_filename.clone() + }, + }; + self.manifest + .items + .insert(log_cache_filename.clone(), manifest_item); + self.manifest.chain_id = self.chain_id.clone(); + self.manifest.protocol_version = self.protocol_version.clone(); + + let manifest_bytes = match serde_json::to_vec(&self.manifest) { + Ok(bytes) => bytes, + Err(e) => { + error!("Failed to serialize manifest: {:?}", e); + return Err(e.into()); + } + }; + + let manifest_path = format!("{}/{}", self.drive_path, self.manifest.manifest_filename); + let manifest_file = vfs::open_file(&manifest_path, true, None)?; + + if let Err(e) = manifest_file.write(&manifest_bytes) { + error!("Failed to write manifest file {}: {:?}", manifest_path, e); + return Err(e.into()); + } + info!( + "Successfully updated and wrote manifest file: {}", + manifest_path + ); + + self.last_cached_block = to_block; + self.save(); + + Ok(()) + } + + // Validate that the in-memory state matches the manifest file on disk + fn validate_state_against_manifest(&self) -> anyhow::Result<()> { + let manifest_path = format!("{}/{}", self.drive_path, self.manifest.manifest_filename); + + // Check if manifest file exists + match vfs::open_file(&manifest_path, false, None) { + Ok(manifest_file) => { + match manifest_file.read() { + Ok(disk_manifest_bytes) => { + match serde_json::from_slice::(&disk_manifest_bytes) { + Ok(disk_manifest) => { + // Compare key aspects of the manifests + if self.manifest.chain_id != disk_manifest.chain_id { + return Err(anyhow::anyhow!( + "Chain ID mismatch: state has {}, disk has {}", + self.manifest.chain_id, + disk_manifest.chain_id + )); + } + + if self.manifest.protocol_version != disk_manifest.protocol_version + { + return Err(anyhow::anyhow!( + "Protocol version mismatch: state has {}, disk has {}", + self.manifest.protocol_version, + disk_manifest.protocol_version + )); + } + + // Check if all files mentioned in state manifest exist on disk + for (_filename, item) in &self.manifest.items { + if !item.file_name.is_empty() { + let file_path = + format!("{}/{}", self.drive_path, item.file_name); + if vfs::metadata(&file_path, None).is_err() { + return Err(anyhow::anyhow!( + "File {} mentioned in state manifest does not exist on disk", + item.file_name + )); + } + } + } + + // Check if disk manifest has more recent data than our state + let disk_max_block = disk_manifest + .items + .values() + .filter_map(|item| item.metadata.to_block.parse::().ok()) + .max() + .unwrap_or(0); + + let state_max_block = self + .manifest + .items + .values() + .filter_map(|item| item.metadata.to_block.parse::().ok()) + .max() + .unwrap_or(0); + + if disk_max_block > state_max_block { + return Err(anyhow::anyhow!( + "Disk manifest has more recent data (block {}) than state (block {})", + disk_max_block, state_max_block + )); + } + + info!("State validation passed - state matches manifest file"); + Ok(()) + } + Err(e) => { + Err(anyhow::anyhow!("Failed to parse manifest file: {:?}", e)) + } + } + } + Err(e) => Err(anyhow::anyhow!("Failed to read manifest file: {:?}", e)), + } + } + Err(_) => { + // Manifest file doesn't exist - this is okay for new installs + if self.manifest.items.is_empty() { + info!("No manifest file found, but state is also empty - validation passed"); + Ok(()) + } else { + Err(anyhow::anyhow!( + "State has manifest items but no manifest file exists on disk" + )) + } + } + } + } + + // Clear all files from the drive + fn clear_drive(&self) -> anyhow::Result<()> { + info!("Clearing all files from drive: {}", self.drive_path); + + // Remove the manifest file + let manifest_path = format!("{}/{}", self.drive_path, self.manifest.manifest_filename); + match vfs::remove_file(&manifest_path, None) { + Ok(_) => info!("Removed manifest file: {}", manifest_path), + Err(e) => warn!("Failed to remove manifest file {}: {:?}", manifest_path, e), + } + + // Remove all files mentioned in the manifest + for (_, item) in &self.manifest.items { + if !item.file_name.is_empty() { + let file_path = format!("{}/{}", self.drive_path, item.file_name); + match vfs::remove_file(&file_path, None) { + Ok(_) => info!("Removed cache file: {}", file_path), + Err(e) => warn!("Failed to remove cache file {}: {:?}", file_path, e), + } + } + } + + info!("Drive clearing completed"); + Ok(()) + } + + // Bootstrap state from other nodes, then fallback to RPC + fn bootstrap_state(&mut self, hypermap: &hypermap::Hypermap) -> anyhow::Result<()> { + info!("Starting state bootstrap process..."); + + // Try to bootstrap from other nodes first + if let Ok(()) = self.try_bootstrap_from_nodes() { + info!("Successfully bootstrapped from other nodes"); + } + + self.try_bootstrap_from_rpc(hypermap)?; + + // Mark as no longer starting + self.is_starting = false; + self.save(); + info!("Bootstrap process completed, cacher is now ready"); + Ok(()) + } + + // Try to bootstrap from other hypermap-binding-cacher nodes + fn try_bootstrap_from_nodes(&mut self) -> anyhow::Result<()> { + if self.nodes.is_empty() { + info!("No nodes configured for bootstrap, will fallback to RPC"); + return Err(anyhow::anyhow!("No nodes configured for bootstrap")); + } + + info!("Attempting to bootstrap from {} nodes", self.nodes.len()); + + let mut nodes = self.nodes.clone(); + + // If using default nodes, shuffle them for random order + let default_nodes: Vec = DEFAULT_NODES.iter().map(|s| s.to_string()).collect(); + if nodes == default_nodes { + nodes.shuffle(&mut thread_rng()); + } + + let mut nodes_not_yet_in_net = nodes.clone(); + let num_retries = 10; + for _ in 0..num_retries { + nodes_not_yet_in_net.retain(|node| { + let Ok(Ok(response)) = Request::new() + .target(("our", "net", "distro", "sys")) + .body(rmp_serde::to_vec(&NetAction::GetPeer(node.clone())).unwrap()) + .send_and_await_response(1) + else { + return true; // keep the node + }; + + !matches!( + rmp_serde::from_slice::(response.body()), + Ok(NetResponse::Peer(Some(_))), + ) + }); + if nodes_not_yet_in_net.is_empty() { + break; + } + std::thread::sleep(std::time::Duration::from_secs(1)); + } + if !nodes_not_yet_in_net.is_empty() { + error!("failed to get peering info for {nodes_not_yet_in_net:?}"); + } + + for node in nodes { + info!("Requesting logs from node: {}", node); + + let cacher_process_address = + Address::new(&node, ("hypermap-binding-cacher", "hypermap-cacher", "sys")); + + if cacher_process_address == our() { + continue; + } + + // ping node for quicker failure if not online/providing/... + let Ok(Ok(response)) = Request::to(cacher_process_address.clone()) + .body(CacherRequest::GetStatus) + .send_and_await_response(3) + else { + warn!("Node {node} failed to respond to ping; trying next one..."); + continue; + }; + let Ok(CacherResponse::GetStatus(_)) = response.body().try_into() else { + warn!("Node {node} failed to respond to ping with expected GetStatus; trying next one..."); + continue; + }; + + // get the logs + let get_logs_request = GetLogsByRangeRequest { + from_block: self.last_cached_block + 1, + to_block: None, // Get all available logs + }; + + match Request::to(cacher_process_address.clone()) + .body(CacherRequest::GetLogsByRange(get_logs_request)) + .send_and_await_response(15) + { + Ok(Ok(response_msg)) => match response_msg.body().try_into() { + Ok(CacherResponse::GetLogsByRange(Ok(get_logs))) => { + match get_logs { + GetLogsByRangeOkResponse::Logs((block, json_string)) => { + if let Ok(log_caches) = + serde_json::from_str::>(&json_string) + { + self.process_received_log_caches(log_caches)?; + } + if block > self.last_cached_block { + self.last_cached_block = block; + } + } + GetLogsByRangeOkResponse::Latest(block) => { + if block > self.last_cached_block { + self.last_cached_block = block; + } + } + } + return Ok(()); + } + Ok(CacherResponse::GetLogsByRange(Err(e))) => { + warn!("Node {} returned error: {}", cacher_process_address, e); + } + Ok(CacherResponse::IsStarting) => { + info!( + "Node {} is still starting, trying next node", + cacher_process_address + ); + } + Ok(CacherResponse::Rejected) => { + warn!("Node {} rejected our request", cacher_process_address); + } + Ok(_) => { + warn!( + "Node {} returned unexpected response type", + cacher_process_address + ); + } + Err(e) => { + warn!( + "Failed to parse response from {}: {:?}", + cacher_process_address, e + ); + } + }, + Ok(Err(e)) => { + warn!("Error response from {}: {:?}", cacher_process_address, e); + } + Err(e) => { + warn!( + "Failed to send request to {}: {:?}", + cacher_process_address, e + ); + } + } + } + + Err(anyhow::anyhow!("Failed to bootstrap from any node")) + } + + // Process received log caches and write them to VFS + fn process_received_log_caches( + &mut self, + log_caches: Vec, + ) -> anyhow::Result<()> { + info!("Processing {} received log caches", log_caches.len()); + + for log_cache in log_caches { + // Validate the log cache signature + if !self.validate_log_cache(&log_cache)? { + warn!("Invalid log cache signature, skipping"); + continue; + } + + // Generate filename from metadata + let filename = format!( + "{}-chain{}-from{}-to{}-protocol{}.json", + log_cache + .metadata + .time_created + .replace(":", "") + .replace("-", ""), + log_cache.metadata.chain_id, + log_cache.metadata.from_block, + log_cache.metadata.to_block, + PROTOCOL_VERSION + ); + + // Write log cache to VFS + let file_path = format!("{}/{}", self.drive_path, filename); + let log_cache_bytes = serde_json::to_vec(&log_cache)?; + + let mut file = vfs::open_file(&file_path, true, None)?; + file.write_all(&log_cache_bytes)?; + + info!("Wrote log cache file: {}", file_path); + + // Update manifest + let file_hash = format!("0x{}", hex::encode(keccak256(&log_cache_bytes))); + let manifest_item = ManifestItemInternal { + metadata: log_cache.metadata.clone(), + is_empty: log_cache.logs.is_empty(), + file_hash, + file_name: filename.clone(), + }; + + self.manifest.items.insert(filename, manifest_item); + + // Update last cached block if this cache goes beyond it + if let Ok(to_block) = log_cache.metadata.to_block.parse::() { + if to_block > self.last_cached_block { + self.last_cached_block = to_block; + } + } + } + + // Write updated manifest + self.write_manifest()?; + + Ok(()) + } + + // Validate a log cache signature + fn validate_log_cache(&self, log_cache: &LogCacheInternal) -> anyhow::Result { + let from_block = log_cache.metadata.from_block.parse::()?; + let to_block = log_cache.metadata.to_block.parse::()?; + + let mut bytes_to_verify = serde_json::to_vec(&log_cache.logs)?; + bytes_to_verify.extend_from_slice(&from_block.to_be_bytes()); + bytes_to_verify.extend_from_slice(&to_block.to_be_bytes()); + let hashed_data = keccak256(&bytes_to_verify); + + let signature_hex = log_cache.metadata.signature.trim_start_matches("0x"); + let signature_bytes = hex::decode(signature_hex)?; + + let created_by_address = log_cache.metadata.created_by.parse::
()?; + + Ok(sign::net_key_verify( + hashed_data.to_vec(), + &created_by_address, + signature_bytes, + )?) + } + + // Write manifest to VFS + fn write_manifest(&self) -> anyhow::Result<()> { + let manifest_bytes = serde_json::to_vec(&self.manifest)?; + let manifest_path = format!("{}/{}", self.drive_path, self.manifest.manifest_filename); + let manifest_file = vfs::open_file(&manifest_path, true, None)?; + manifest_file.write(&manifest_bytes)?; + info!("Updated manifest file: {}", manifest_path); + Ok(()) + } + + // Fallback to RPC bootstrap - catch up from where we left off + fn try_bootstrap_from_rpc(&mut self, hypermap: &hypermap::Hypermap) -> anyhow::Result<()> { + info!( + "Bootstrapping from RPC, starting from block {}", + self.last_cached_block + 1 + ); + + // Catch up remainder (or as fallback) using RPC + self.cache_logs_and_update_manifest(hypermap)?; + + // run it twice for fresh boot case: + // - initial bootstrap takes much time + // - in that time, the block you are updating to is no longer the head of the chain + // - so run again to get to the head of the chain + self.cache_logs_and_update_manifest(hypermap)?; + + Ok(()) + } + + fn to_wit_manifest(&self) -> WitManifest { + let items = self + .manifest + .items + .iter() + .map(|(k, v)| { + let wit_meta = WitLogsMetadata { + chain_id: v.metadata.chain_id.clone(), + from_block: v.metadata.from_block.clone(), + to_block: v.metadata.to_block.clone(), + time_created: v.metadata.time_created.clone(), + created_by: v.metadata.created_by.clone(), + signature: v.metadata.signature.clone(), + }; + let wit_item = WitManifestItem { + metadata: wit_meta, + is_empty: v.is_empty, + file_hash: v.file_hash.clone(), + file_name: v.file_name.clone(), + }; + (k.clone(), wit_item) + }) + .collect::>(); + + WitManifest { + items, + manifest_filename: self.manifest.manifest_filename.clone(), + chain_id: self.manifest.chain_id.clone(), + protocol_version: self.manifest.protocol_version.clone(), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +enum HttpApi { + GetManifest, + GetLogCacheFile(String), + GetStatus, +} + +fn http_handler( + state: &mut State, + path: &str, +) -> anyhow::Result<(http::server::HttpResponse, Vec)> { + let response = http::server::HttpResponse::new(http::StatusCode::OK) + .header("Content-Type", "application/json"); + + // Basic routing based on path + Ok(if path == "/manifest" || path == "/manifest.json" { + let manifest_path = format!("{}/{}", state.drive_path, state.manifest.manifest_filename); + let manifest_file = vfs::open_file(&manifest_path, true, None)?; + match manifest_file.read() { + Ok(content) => (response, content), + Err(e) => { + error!( + "HTTP: Failed to read manifest file {}: {:?}", + manifest_path, e + ); + ( + http::server::HttpResponse::new(http::StatusCode::NOT_FOUND), + b"Manifest not found".to_vec(), + ) + } + } + } else if path.starts_with("/log-cache/") { + let filename = path.trim_start_matches("/log-cache/"); + if filename.is_empty() || filename.contains("..") { + // Basic security check + return Ok(( + http::server::HttpResponse::new(http::StatusCode::BAD_REQUEST), + b"Invalid filename".to_vec(), + )); + } + let log_cache_path = format!("{}/{}", state.drive_path, filename); + let log_cache_file = vfs::open_file(&log_cache_path, true, None)?; + match log_cache_file.read() { + Ok(content) => (response, content), + Err(e) => { + error!( + "HTTP: Failed to read log cache file {}: {:?}", + log_cache_path, e + ); + ( + http::server::HttpResponse::new(http::StatusCode::NOT_FOUND), + b"Log cache file not found".to_vec(), + ) + } + } + } else if path == "/status" { + let status_info = CacherStatus { + last_cached_block: state.last_cached_block, + chain_id: state.chain_id.clone(), + protocol_version: state.protocol_version.clone(), + next_cache_attempt_in_seconds: if state.is_cache_timer_live { + Some(state.cache_interval_s) + } else { + None + }, + manifest_filename: state.manifest.manifest_filename.clone(), + log_files_count: state.manifest.items.len() as u32, + our_address: our().to_string(), + is_providing: state.is_providing, + }; + match serde_json::to_vec(&status_info) { + Ok(body) => (response, body), + Err(e) => { + error!("HTTP: Failed to serialize status: {:?}", e); + ( + http::server::HttpResponse::new(http::StatusCode::INTERNAL_SERVER_ERROR), + b"Error serializing status".to_vec(), + ) + } + } + } else { + ( + http::server::HttpResponse::new(http::StatusCode::NOT_FOUND), + b"Not Found".to_vec(), + ) + }) +} + +fn handle_request( + our: &Address, + source: &Address, + state: &mut State, + request: CacherRequest, +) -> anyhow::Result<()> { + let is_local = is_local_request(our, source); + + // If we're still starting, respond with IsStarting to all requests + if state.is_starting { + Response::new().body(CacherResponse::IsStarting).send()?; + return Ok(()); + } + + if !is_local && source.process.to_string() != "hypermap-binding-cacher:hypermap-binding-cacher:sys" { + warn!("Rejecting remote request from non-hypermap-binding-cacher: {source}"); + Response::new().body(CacherResponse::Rejected).send()?; + return Ok(()); + } + + if !is_local + && !state.is_providing + && source.process.to_string() == "hypermap-binding-cacher:hypermap-cacher:sys" + { + warn!("Rejecting remote request from {source} - not in provider mode"); + Response::new().body(CacherResponse::Rejected).send()?; + return Ok(()); + } + let response_body = match request { + CacherRequest::GetManifest => { + let manifest_path = + format!("{}/{}", state.drive_path, state.manifest.manifest_filename); + if state.manifest.items.is_empty() && vfs::metadata(&manifest_path, None).is_err() { + CacherResponse::GetManifest(None) + } else { + // Ensure manifest is loaded from VFS if state is fresh and manifest file exists + // This is usually handled by State::load, but as a fallback: + if state.manifest.items.is_empty() { + // If manifest in memory is empty, try to load it + let manifest_file = vfs::open_file(&manifest_path, true, None)?; + if let Ok(bytes) = manifest_file.read() { + if let Ok(disk_manifest) = + serde_json::from_slice::(&bytes) + { + state.manifest = disk_manifest; + } + } + } + CacherResponse::GetManifest(Some(state.to_wit_manifest())) + } + } + CacherRequest::GetLogCacheContent(filename) => { + let log_cache_path = format!("{}/{}", state.drive_path, filename); + let log_cache_file = vfs::open_file(&log_cache_path, true, None)?; + match log_cache_file.read() { + Ok(content_bytes) => { + // Content is raw JSON bytes of LogCacheInternal. + // The WIT expects a string. + match String::from_utf8(content_bytes) { + Ok(content_str) => { + CacherResponse::GetLogCacheContent(Ok(Some(content_str))) + } + Err(e) => { + error!("Failed to convert log cache content to UTF-8 string: {}", e); + CacherResponse::GetLogCacheContent(Err(format!( + "File content not valid UTF-8: {}", + e + ))) + } + } + } + Err(_) => CacherResponse::GetLogCacheContent(Ok(None)), + } + } + CacherRequest::GetStatus => { + let status = CacherStatus { + last_cached_block: state.last_cached_block, + chain_id: state.chain_id.clone(), + protocol_version: state.protocol_version.clone(), + next_cache_attempt_in_seconds: if state.is_cache_timer_live { + Some(state.cache_interval_s) + } else { + None + }, + manifest_filename: state.manifest.manifest_filename.clone(), + log_files_count: state.manifest.items.len() as u32, + our_address: our.to_string(), + is_providing: state.is_providing, + }; + CacherResponse::GetStatus(status) + } + CacherRequest::GetLogsByRange(req_params) => { + let mut relevant_caches: Vec = Vec::new(); + let req_from_block = req_params.from_block; + // If req_params.to_block is None, we effectively want to go up to the highest block available in caches. + // For simplicity in overlap calculation, we can treat None as u64::MAX here. + let effective_req_to_block = req_params.to_block.unwrap_or(u64::MAX); + + for item in state.manifest.items.values() { + // Skip items that don't have an actual file (e.g., empty log ranges not written to disk). + if item.file_name.is_empty() { + continue; + } + + let cache_from = match item.metadata.from_block.parse::() { + Ok(b) => b, + Err(_) => { + warn!( + "Could not parse from_block for cache item {}: {}", + item.file_name, item.metadata.from_block + ); + continue; + } + }; + let cache_to = match item.metadata.to_block.parse::() { + Ok(b) => b, + Err(_) => { + warn!( + "Could not parse to_block for cache item {}: {}", + item.file_name, item.metadata.to_block + ); + continue; + } + }; + + // Check for overlap: max(start1, start2) <= min(end1, end2) + if max(req_from_block, cache_from) <= min(effective_req_to_block, cache_to) { + // This cache file overlaps with the requested range. + let file_vfs_path = format!("{}/{}", state.drive_path, item.file_name); + match vfs::open_file(&file_vfs_path, false, None) { + Ok(file) => match file.read() { + Ok(content_bytes) => { + match serde_json::from_slice::(&content_bytes) { + Ok(log_cache) => relevant_caches.push(log_cache), + Err(e) => { + error!( + "Failed to deserialize LogCacheInternal from {}: {:?}", + item.file_name, e + ); + // Decide: return error or skip this cache? For now, skip. + } + } + } + Err(e) => error!("Failed to read VFS file {}: {:?}", item.file_name, e), + }, + Err(e) => error!("Failed to open VFS file {}: {e:?}", item.file_name), + } + } + } + + // Sort caches by their from_block. + relevant_caches + .sort_by_key(|cache| cache.metadata.from_block.parse::().unwrap_or(0)); + + if relevant_caches.is_empty() { + CacherResponse::GetLogsByRange(Ok(GetLogsByRangeOkResponse::Latest( + state.last_cached_block, + ))) + } else { + match serde_json::to_string(&relevant_caches) { + Ok(json_string) => CacherResponse::GetLogsByRange(Ok( + GetLogsByRangeOkResponse::Logs((state.last_cached_block, json_string)), + )), + Err(e) => CacherResponse::GetLogsByRange(Err(format!( + "Failed to serialize relevant caches: {e}" + ))), + } + } + } + CacherRequest::StartProviding => { + if !is_local { + // should never happen: should be caught in check above + Response::new().body(CacherResponse::Rejected).send()?; + return Ok(()); + } + state.is_providing = true; + state.save(); + info!("Provider mode enabled"); + CacherResponse::StartProviding(Ok("Provider mode enabled".to_string())) + } + CacherRequest::StopProviding => { + if !is_local { + Response::new().body(CacherResponse::Rejected).send()?; + warn!("Rejecting remote request from {source} to alter provider mode"); + return Ok(()); + } + state.is_providing = false; + state.save(); + info!("Provider mode disabled"); + CacherResponse::StopProviding(Ok("Provider mode disabled".to_string())) + } + CacherRequest::SetNodes(new_nodes) => { + if !is_local { + Response::new().body(CacherResponse::Rejected).send()?; + warn!("Rejecting remote request from {source} to set nodes"); + return Ok(()); + } + state.nodes = new_nodes; + state.save(); + info!("Nodes updated to: {:?}", state.nodes); + CacherResponse::SetNodes(Ok("Nodes updated successfully".to_string())) + } + CacherRequest::Reset(custom_nodes) => { + if !is_local { + Response::new().body(CacherResponse::Rejected).send()?; + warn!("Rejecting remote request from {source} to reset"); + return Ok(()); + } + + info!("Resetting hypermap-binding-cacher state and clearing VFS..."); + + // Clear all files from the drive + if let Err(e) = state.clear_drive() { + error!("Failed to clear drive during reset: {:?}", e); + CacherResponse::Reset(Err(format!("Failed to clear drive: {:?}", e))) + } else { + // Create new state with custom nodes if provided, otherwise use defaults + let nodes = match custom_nodes { + Some(nodes) => nodes, + None => DEFAULT_NODES.iter().map(|s| s.to_string()).collect(), + }; + + *state = State::new(&state.drive_path); + state.nodes = nodes; + state.save(); + + info!( + "Hypermap-binding-cacher reset complete. New nodes: {:?}", + state.nodes + ); + CacherResponse::Reset(Ok( + "Reset completed successfully. Binding Cacher will restart with new settings." + .to_string(), + )) + } + } + }; + + Response::new().body(response_body).send()?; + Ok(()) +} + +fn main_loop( + our: &Address, + state: &mut State, + hypermap: &hypermap::Hypermap, + server: &http::server::HttpServer, +) -> anyhow::Result<()> { + info!("Hypermap Binding Cacher main_loop started. Our address: {}", our); + info!( + "Monitoring Hypermap contract: {}", + state.hypermap_address.to_string() + ); + info!( + "Chain ID: {}, Protocol Version: {}", + state.chain_id, state.protocol_version + ); + info!("Last cached block: {}", state.last_cached_block); + + // Always bootstrap on start to get latest state from other nodes or RPC + while state.is_starting { + match state.bootstrap_state(hypermap) { + Ok(_) => info!("Bootstrap process completed successfully."), + Err(e) => { + error!("Error during bootstrap process: {:?}", e); + std::thread::sleep(std::time::Duration::from_secs(RETRY_DELAY_S)); + } + } + } + + // Set up the main caching timer. + info!( + "Setting cache timer for {} seconds.", + state.cache_interval_s + ); + timer::set_timer(state.cache_interval_s * 1000, Some(b"cache_cycle".to_vec())); + state.is_cache_timer_live = true; + state.save(); + + loop { + let Ok(message) = await_message() else { + warn!("Failed to get message, continuing loop."); + continue; + }; + let source = message.source(); + + if message.is_request() { + if source.process == ProcessId::from_str("http-server:distro:sys").unwrap() { + // HTTP request from the system's HTTP server process + let Ok(http::server::HttpServerRequest::Http(http_request)) = + server.parse_request(message.body()) + else { + error!("Failed to parse HTTP request from http-server:distro:sys"); + // Potentially send an error response back if possible/expected + continue; + }; + let (http_response, body) = http_handler(state, &http_request.path()?)?; + Response::new() + .body(serde_json::to_vec(&http_response).unwrap()) + .blob_bytes(body) + .send()?; + } else { + // Standard process-to-process request + match serde_json::from_slice::(message.body()) { + Ok(request) => { + if let Err(e) = handle_request(our, &source, state, request) { + error!("Error handling request from {:?}: {:?}", source, e); + } + } + Err(e) => { + error!( + "Failed to deserialize CacherRequest from {:?}: {:?}", + source, e + ); + } + } + } + } else { + // It's a Response or other kind of message + if source.process == ProcessId::from_str("timer:distro:sys").unwrap() { + if message.context() == Some(b"cache_cycle") { + info!("Cache timer triggered."); + state.is_cache_timer_live = false; + match state.cache_logs_and_update_manifest(hypermap) { + Ok(_) => info!("Periodic cache cycle complete."), + Err(e) => error!("Error during periodic cache cycle: {:?}", e), + } + // Reset the timer for the next cycle + if !state.is_cache_timer_live { + timer::set_timer( + state.cache_interval_s * 1000, + Some(b"cache_cycle".to_vec()), + ); + state.is_cache_timer_live = true; + state.save(); + } + } + } else { + debug!( + "Received unhandled response or other message from {:?}.", + source + ); + } + } + } +} + +call_init!(init); +fn init(our: Address) { + init_logging(Level::INFO, Level::DEBUG, None, None, None).unwrap(); + info!("Hypermap Binding Cacher process starting..."); + + let drive_path = vfs::create_drive(our.package_id(), "hypermap-binding-cache", None).unwrap(); + + let bind_config = http::server::HttpBindingConfig::default().authenticated(false); + let mut server = http::server::HttpServer::new(5); + + let hypermap_provider = hypermap::Hypermap::default(60); + + server + .bind_http_path("/manifest", bind_config.clone()) + .expect("Failed to bind /manifest"); + server + .bind_http_path("/manifest.json", bind_config.clone()) + .expect("Failed to bind /manifest.json"); + server + .bind_http_path("/log-cache/*", bind_config.clone()) + .expect("Failed to bind /log-cache/*"); + server + .bind_http_path("/status", bind_config.clone()) + .expect("Failed to bind /status"); + info!("Bound HTTP paths: /manifest, /log-cache/*, /status"); + + let mut state = State::load(&drive_path); + + loop { + match main_loop(&our, &mut state, &hypermap_provider, &server) { + Ok(()) => { + // main_loop should not exit with Ok in normal operation as it's an infinite loop. + error!("main_loop exited unexpectedly with Ok. Restarting."); + } + Err(e) => { + error!("main_loop exited with error: {:?}. Restarting.", e); + std::thread::sleep(std::time::Duration::from_secs(5)); + } + } + // Reload state in case of restart, or re-initialize if necessary. + state = State::load(&drive_path); + } +} diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs index 5125b9a11..a98430838 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs @@ -24,7 +24,7 @@ use hyperware_process_lib::{ wit_bindgen::generate!({ path: "../target/wit", - world: "hypermap-cacher-sys-v0", + world: "hypermap-cacher-sys-v1", generate_unused_types: true, additional_derives: [serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], }); @@ -1274,7 +1274,7 @@ fn init(our: Address) { init_logging(Level::INFO, Level::DEBUG, None, None, None).unwrap(); info!("Hypermap Cacher process starting..."); - let drive_path = vfs::create_drive(our.package_id(), "cache", None).unwrap(); + let drive_path = vfs::create_drive(our.package_id(), "hypermap-cache", None).unwrap(); let bind_config = http::server::HttpBindingConfig::default().authenticated(false); let mut server = http::server::HttpServer::new(5); diff --git a/hyperdrive/packages/hypermap-cacher/pkg/manifest.json b/hyperdrive/packages/hypermap-cacher/pkg/manifest.json index ec498453e..9edbcac0c 100644 --- a/hyperdrive/packages/hypermap-cacher/pkg/manifest.json +++ b/hyperdrive/packages/hypermap-cacher/pkg/manifest.json @@ -1,4 +1,30 @@ [ + { + "process_name": "hypermap-binding-cacher", + "process_wasm_path": "/hypermap-binding-cacher.wasm", + "on_exit": "Restart", + "request_networking": true, + "request_capabilities": [ + "eth:distro:sys", + "http-server:distro:sys", + "net:distro:sys", + "sign:sign:sys", + "terminal:terminal:sys", + "timer:distro:sys", + "vfs:distro:sys" + ], + "grant_capabilities": [ + "eth:distro:sys", + "http-server:distro:sys", + "net:distro:sys", + "sign:sign:sys", + "terminal:terminal:sys", + "timer:distro:sys", + "vfs:distro:sys" + ], + "public": false, + "wit_version": 1 + }, { "process_name": "hypermap-cacher", "process_wasm_path": "/hypermap-cacher.wasm", diff --git a/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs b/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs index 45adadd23..9db8ccb28 100644 --- a/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs @@ -17,7 +17,7 @@ use hyperware_process_lib::{await_next_message_body, call_init, println, Address wit_bindgen::generate!({ path: "../target/wit", - world: "hypermap-cacher-sys-v0", + world: "hypermap-cacher-sys-v1", generate_unused_types: true, additional_derives: [serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], }); diff --git a/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs b/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs index 9236ca28e..84c68d56f 100644 --- a/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs @@ -15,7 +15,7 @@ use hyperware_process_lib::{await_next_message_body, call_init, println, Address wit_bindgen::generate!({ path: "../target/wit", - world: "hypermap-cacher-sys-v0", + world: "hypermap-cacher-sys-v1", generate_unused_types: true, additional_derives: [serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], }); diff --git a/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs b/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs index 8162c77ab..e1db09301 100644 --- a/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs @@ -3,7 +3,7 @@ use hyperware_process_lib::{call_init, println, Address, Request}; wit_bindgen::generate!({ path: "../target/wit", - world: "hypermap-cacher-sys-v0", + world: "hypermap-cacher-sys-v1", generate_unused_types: true, additional_derives: [serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], }); diff --git a/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs b/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs index bf4491ca7..0afabb2cf 100644 --- a/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs @@ -3,7 +3,7 @@ use hyperware_process_lib::{call_init, println, Address, Request}; wit_bindgen::generate!({ path: "../target/wit", - world: "hypermap-cacher-sys-v0", + world: "hypermap-cacher-sys-v1", generate_unused_types: true, additional_derives: [serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], }); From 285c4863cfa7cd43ad8276e9254342bfb2a64559 Mon Sep 17 00:00:00 2001 From: Johnathan Reale Date: Mon, 25 Aug 2025 10:30:15 -0400 Subject: [PATCH 03/10] binding-cacher separate requests/responses --- Cargo.lock | 65 ++++++++++++++++--- Cargo.toml | 2 +- .../packages/hypermap-cacher/Cargo.lock | 43 ++++++------ .../packages/hypermap-cacher/Cargo.toml | 2 +- .../api/hypermap-cacher:sys-v1.wit | 36 +++++----- .../Cargo.toml | 5 +- .../src/lib.rs | 36 +++++----- .../hypermap-cacher/Cargo.toml | 3 +- .../hypermap-cacher/src/lib.rs | 4 +- .../hypermap-cacher/pkg/manifest.json | 4 +- .../packages/hypermap-cacher/pkg/scripts.json | 8 +++ .../hypermap-cacher/reset-cache/Cargo.toml | 3 +- .../hypermap-cacher/reset-cache/src/lib.rs | 32 ++++++++- .../hypermap-cacher/set-nodes/Cargo.toml | 3 +- .../hypermap-cacher/set-nodes/src/lib.rs | 30 ++++++++- .../start-providing/Cargo.toml | 3 +- .../start-providing/src/lib.rs | 29 ++++++++- .../hypermap-cacher/stop-providing/Cargo.toml | 3 +- .../hypermap-cacher/stop-providing/src/lib.rs | 29 ++++++++- 19 files changed, 255 insertions(+), 85 deletions(-) rename hyperdrive/packages/hypermap-cacher/{hypermap-binding-cacher => binding-cacher}/Cargo.toml (73%) rename hyperdrive/packages/hypermap-cacher/{hypermap-binding-cacher => binding-cacher}/src/lib.rs (97%) diff --git a/Cargo.lock b/Cargo.lock index 12af32c87..c4375c36d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1174,6 +1174,25 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "binding-cacher" +version = "0.1.0" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-types", + "anyhow", + "chrono", + "hex", + "hyperware_process_lib 2.2.0", + "process_macros", + "rand 0.8.5", + "rmp-serde", + "serde", + "serde_json", + "wit-bindgen 0.42.1", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -3291,7 +3310,7 @@ dependencies = [ [[package]] name = "hyperdrive" -version = "1.6.0" +version = "1.6.1" dependencies = [ "aes-gcm", "alloy", @@ -3346,7 +3365,7 @@ dependencies = [ [[package]] name = "hyperdrive_lib" -version = "1.6.0" +version = "1.6.1" dependencies = [ "lib", ] @@ -3361,7 +3380,7 @@ dependencies = [ "anyhow", "chrono", "hex", - "hyperware_process_lib 2.1.0", + "hyperware_process_lib 2.2.0", "process_macros", "rand 0.8.5", "rmp-serde", @@ -3472,6 +3491,36 @@ dependencies = [ "wit-bindgen 0.42.1", ] +[[package]] +name = "hyperware_process_lib" +version = "2.2.0" +source = "git+https://github.com/hyperware-ai/process_lib?rev=8b6c2e5#8b6c2e5c32b543cc6358465ebd8cf51932b4b633" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-macro", + "alloy-sol-types", + "anyhow", + "base64 0.22.1", + "bincode", + "color-eyre", + "hex", + "http 1.3.1", + "mime_guess", + "rand 0.8.5", + "regex", + "rmp-serde", + "serde", + "serde_json", + "sha3", + "thiserror 1.0.69", + "tracing", + "tracing-error", + "tracing-subscriber", + "url", + "wit-bindgen 0.42.1", +] + [[package]] name = "iana-time-zone" version = "0.1.63" @@ -3972,7 +4021,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "lib" -version = "1.6.0" +version = "1.6.1" dependencies = [ "alloy", "anyhow", @@ -5301,7 +5350,7 @@ dependencies = [ name = "reset-cache" version = "0.1.0" dependencies = [ - "hyperware_process_lib 2.1.0", + "hyperware_process_lib 2.2.0", "process_macros", "serde", "serde_json", @@ -5795,7 +5844,7 @@ dependencies = [ name = "set-nodes" version = "0.1.0" dependencies = [ - "hyperware_process_lib 2.1.0", + "hyperware_process_lib 2.2.0", "process_macros", "serde", "serde_json", @@ -6024,7 +6073,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "start-providing" version = "0.1.0" dependencies = [ - "hyperware_process_lib 2.1.0", + "hyperware_process_lib 2.2.0", "process_macros", "serde", "serde_json", @@ -6069,7 +6118,7 @@ dependencies = [ name = "stop-providing" version = "0.1.0" dependencies = [ - "hyperware_process_lib 2.1.0", + "hyperware_process_lib 2.2.0", "process_macros", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index bbf8e5304..bc6e9c9e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ members = [ "hyperdrive/packages/homepage/homepage", "hyperdrive/packages/hns-indexer/hns-indexer", "hyperdrive/packages/hns-indexer/get-block", "hyperdrive/packages/settings/settings", "hyperdrive/packages/hns-indexer/reset", "hyperdrive/packages/hns-indexer/node-info", "hyperdrive/packages/hns-indexer/state", - "hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher", "hyperdrive/packages/hypermap-cacher/hypermap-cacher", "hyperdrive/packages/hypermap-cacher/reset-cache", "hyperdrive/packages/hypermap-cacher/set-nodes", + "hyperdrive/packages/hypermap-cacher/binding-cacher", "hyperdrive/packages/hypermap-cacher/hypermap-cacher", "hyperdrive/packages/hypermap-cacher/reset-cache", "hyperdrive/packages/hypermap-cacher/set-nodes", "hyperdrive/packages/hypermap-cacher/start-providing", "hyperdrive/packages/hypermap-cacher/stop-providing", "hyperdrive/packages/sign/sign", "hyperdrive/packages/terminal/terminal", "hyperdrive/packages/terminal/add-node-provider", "hyperdrive/packages/terminal/add-rpcurl-provider", diff --git a/hyperdrive/packages/hypermap-cacher/Cargo.lock b/hyperdrive/packages/hypermap-cacher/Cargo.lock index dc03c1c4a..7ae5737d8 100644 --- a/hyperdrive/packages/hypermap-cacher/Cargo.lock +++ b/hyperdrive/packages/hypermap-cacher/Cargo.lock @@ -817,6 +817,25 @@ dependencies = [ "serde", ] +[[package]] +name = "binding-cacher" +version = "0.1.0" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-types", + "anyhow", + "chrono", + "hex", + "hyperware_process_lib", + "process_macros", + "rand 0.8.5", + "rmp-serde", + "serde", + "serde_json", + "wit-bindgen", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -1640,25 +1659,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "hypermap-binding-cacher" -version = "0.1.0" -dependencies = [ - "alloy", - "alloy-primitives", - "alloy-sol-types", - "anyhow", - "chrono", - "hex", - "hyperware_process_lib", - "process_macros", - "rand 0.8.5", - "rmp-serde", - "serde", - "serde_json", - "wit-bindgen", -] - [[package]] name = "hypermap-cacher" version = "0.1.0" @@ -1680,9 +1680,8 @@ dependencies = [ [[package]] name = "hyperware_process_lib" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3abd008d22c3b96ee43300c4c8dffbf1d072a680a13635b5f9da11a0ce9395" +version = "2.2.0" +source = "git+https://github.com/hyperware-ai/process_lib?rev=8b6c2e5#8b6c2e5c32b543cc6358465ebd8cf51932b4b633" dependencies = [ "alloy", "alloy-primitives", diff --git a/hyperdrive/packages/hypermap-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/Cargo.toml index ef0fd2640..ff4a19f1f 100644 --- a/hyperdrive/packages/hypermap-cacher/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "2" members = [ - "hypermap-binding-cacher", + "binding-cacher", "hypermap-cacher", "reset-cache", "set-nodes", diff --git a/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v1.wit b/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v1.wit index 31f65fc49..c8e88743a 100644 --- a/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v1.wit +++ b/hyperdrive/packages/hypermap-cacher/api/hypermap-cacher:sys-v1.wit @@ -1,6 +1,6 @@ -interface hypermap-binding-cacher { +interface binding-cacher { // Metadata associated with a batch of Ethereum logs. - record logs-metadata { + record binding-logs-metadata { chain-id: string, from-block: string, to-block: string, @@ -10,8 +10,8 @@ interface hypermap-binding-cacher { } // Represents an item in the manifest, detailing a single log cache file. - record manifest-item { - metadata: logs-metadata, + record binding-manifest-item { + metadata: binding-logs-metadata, is-empty: bool, file-hash: string, file-name: string, @@ -19,38 +19,38 @@ interface hypermap-binding-cacher { // The main manifest structure, listing all available log cache files. // WIT does not support direct map types, so a list of key-value tuples is used. - record manifest { + record binding-manifest { // The key is the filename of the log cache. - items: list>, + items: list>, manifest-filename: string, chain-id: string, protocol-version: string, } - record get-logs-by-range-request { + record binding-get-logs-by-range-request { from-block: u64, to-block: option, // If None, signifies to the latest available/relevant cached block. } - variant get-logs-by-range-ok-response { + variant binding-get-logs-by-range-ok-response { logs(tuple), latest(u64), } // Defines the types of requests that can be sent to the Hypermap Cacher process. - variant cacher-request { + variant binding-cacher-request { get-manifest, get-log-cache-content(string), get-status, - get-logs-by-range(get-logs-by-range-request), + get-logs-by-range(binding-get-logs-by-range-request), + reset(option>), start-providing, stop-providing, set-nodes(list), - reset(option>), } // Represents the operational status of the cacher. - record cacher-status { + record binding-cacher-status { last-cached-block: u64, chain-id: string, protocol-version: string, @@ -62,11 +62,11 @@ interface hypermap-binding-cacher { } // Defines the types of responses the Hypermap Cacher process can send. - variant cacher-response { - get-manifest(option), + variant binding-cacher-response { + get-manifest(option), get-log-cache-content(result, string>), - get-status(cacher-status), - get-logs-by-range(result), + get-status(binding-cacher-status), + get-logs-by-range(result), start-providing(result), stop-providing(result), set-nodes(result), @@ -121,10 +121,10 @@ interface hypermap-cacher { get-log-cache-content(string), get-status, get-logs-by-range(get-logs-by-range-request), + reset(option>), start-providing, stop-providing, set-nodes(list), - reset(option>), } // Represents the operational status of the cacher. @@ -156,7 +156,7 @@ interface hypermap-cacher { world hypermap-cacher-sys-v1 { import sign; - import hypermap-binding-cacher; + import binding-cacher; import hypermap-cacher; include process-v1; } diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml similarity index 73% rename from hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/Cargo.toml rename to hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml index 2deec97e6..734b1963e 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "hypermap-binding-cacher" +name = "binding-cacher" version = "0.1.0" edition = "2021" publish = false @@ -18,7 +18,8 @@ alloy = { version = "0.8.1", features = [ ] } chrono = "0.4.41" hex = "0.4.3" -hyperware_process_lib = { version = "2.1.0", features = ["logging"] } +#hyperware_process_lib = { version = "2.1.0", features = ["logging"] } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5", features = ["logging"] } process_macros = "0.1.0" rand = "0.8" rmp-serde = "1.1.2" diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs similarity index 97% rename from hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/src/lib.rs rename to hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs index 5e2003754..a5e410d88 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-binding-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs @@ -10,9 +10,9 @@ use rand::seq::SliceRandom; use rand::thread_rng; use serde::{Deserialize, Serialize}; -use crate::hyperware::process::hypermap_cacher::{ - CacherRequest, CacherResponse, CacherStatus, GetLogsByRangeOkResponse, GetLogsByRangeRequest, - LogsMetadata as WitLogsMetadata, Manifest as WitManifest, ManifestItem as WitManifestItem, +use crate::hyperware::process::binding_cacher::{ + BindingCacherRequest as CacherRequest, BindingCacherResponse as CacherResponse, BindingCacherStatus as CacherStatus, BindingGetLogsByRangeOkResponse as GetLogsByRangeOkResponse, BindingGetLogsByRangeRequest as GetLogsByRangeRequest, + BindingLogsMetadata as WitLogsMetadata, BindingManifest as WitManifest, BindingManifestItem as WitManifestItem, }; use hyperware_process_lib::{ @@ -93,7 +93,7 @@ struct ManifestInternal { // The main state structure for the Hypermap Binding Cacher process. #[derive(Serialize, Deserialize, Debug)] struct State { - hypermap_address: eth::Address, + hypermap_binding_address: eth::Address, manifest: ManifestInternal, last_cached_block: u64, chain_id: String, @@ -121,8 +121,8 @@ fn is_local_request(our: &Address, source: &Address) -> bool { impl State { fn new(drive_path: &str) -> Self { let chain_id = hypermap::HYPERMAP_CHAIN_ID.to_string(); - let hypermap_address = eth::Address::from_str(hypermap::HYPERMAP_ADDRESS) - .expect("Failed to parse HYPERMAP_ADDRESS"); + let hypermap_binding_address = eth::Address::from_str(hypermap::HYPERMAP_BINDING_ADDRESS) + .expect("Failed to parse HYPERMAP_BINDING_ADDRESS"); let manifest_filename = format!( "manifest-chain{}-protocol{}.json", @@ -136,7 +136,7 @@ impl State { }; State { - hypermap_address, + hypermap_binding_address, manifest: initial_manifest, last_cached_block: hypermap::HYPERMAP_FIRST_BLOCK, chain_id, @@ -275,7 +275,7 @@ impl State { } let filter = eth::Filter::new() - .address(self.hypermap_address) + .address(self.hypermap_binding_address) .from_block(from_block) .to_block(eth::BlockNumberOrTag::Number(to_block)); @@ -551,7 +551,7 @@ impl State { Ok(()) } - // Try to bootstrap from other hypermap-binding-cacher nodes + // Try to bootstrap from other binding-cacher nodes fn try_bootstrap_from_nodes(&mut self) -> anyhow::Result<()> { if self.nodes.is_empty() { info!("No nodes configured for bootstrap, will fallback to RPC"); @@ -598,7 +598,7 @@ impl State { info!("Requesting logs from node: {}", node); let cacher_process_address = - Address::new(&node, ("hypermap-binding-cacher", "hypermap-cacher", "sys")); + Address::new(&node, ("binding-cacher", "hypermap-cacher", "sys")); if cacher_process_address == our() { continue; @@ -936,15 +936,15 @@ fn handle_request( return Ok(()); } - if !is_local && source.process.to_string() != "hypermap-binding-cacher:hypermap-binding-cacher:sys" { - warn!("Rejecting remote request from non-hypermap-binding-cacher: {source}"); + if !is_local && source.process.to_string() != "binding-cacher:hypermap-cacher:sys" { + warn!("Rejecting remote request from non-binding-cacher: {source}"); Response::new().body(CacherResponse::Rejected).send()?; return Ok(()); } if !is_local && !state.is_providing - && source.process.to_string() == "hypermap-binding-cacher:hypermap-cacher:sys" + && source.process.to_string() == "binding-cacher:hypermap-cacher:sys" { warn!("Rejecting remote request from {source} - not in provider mode"); Response::new().body(CacherResponse::Rejected).send()?; @@ -1131,7 +1131,7 @@ fn handle_request( return Ok(()); } - info!("Resetting hypermap-binding-cacher state and clearing VFS..."); + info!("Resetting binding-cacher state and clearing VFS..."); // Clear all files from the drive if let Err(e) = state.clear_drive() { @@ -1149,7 +1149,7 @@ fn handle_request( state.save(); info!( - "Hypermap-binding-cacher reset complete. New nodes: {:?}", + "binding-cacher reset complete. New nodes: {:?}", state.nodes ); CacherResponse::Reset(Ok( @@ -1172,8 +1172,8 @@ fn main_loop( ) -> anyhow::Result<()> { info!("Hypermap Binding Cacher main_loop started. Our address: {}", our); info!( - "Monitoring Hypermap contract: {}", - state.hypermap_address.to_string() + "Monitoring Binding contract: {}", + state.hypermap_binding_address.to_string() ); info!( "Chain ID: {}, Protocol Version: {}", @@ -1274,7 +1274,7 @@ fn init(our: Address) { init_logging(Level::INFO, Level::DEBUG, None, None, None).unwrap(); info!("Hypermap Binding Cacher process starting..."); - let drive_path = vfs::create_drive(our.package_id(), "hypermap-binding-cache", None).unwrap(); + let drive_path = vfs::create_drive(our.package_id(), "binding-cache", None).unwrap(); let bind_config = http::server::HttpBindingConfig::default().authenticated(false); let mut server = http::server::HttpServer::new(5); diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml index bb9b33d5d..6b8f831d2 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml @@ -18,7 +18,8 @@ alloy = { version = "0.8.1", features = [ ] } chrono = "0.4.41" hex = "0.4.3" -hyperware_process_lib = { version = "2.1.0", features = ["logging"] } +#hyperware_process_lib = { version = "2.1.0", features = ["logging"] } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5", features = ["logging"] } process_macros = "0.1.0" rand = "0.8" rmp-serde = "1.1.2" diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs index a98430838..4ba60f385 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs @@ -1149,11 +1149,11 @@ fn handle_request( state.save(); info!( - "Hypermap-cacher reset complete. New nodes: {:?}", + "hypermap-cacher reset complete. New nodes: {:?}", state.nodes ); CacherResponse::Reset(Ok( - "Reset completed successfully. Cacher will restart with new settings." + "Reset completed successfully. Hypermap Cacher will restart with new settings." .to_string(), )) } diff --git a/hyperdrive/packages/hypermap-cacher/pkg/manifest.json b/hyperdrive/packages/hypermap-cacher/pkg/manifest.json index 9edbcac0c..c4a734dcd 100644 --- a/hyperdrive/packages/hypermap-cacher/pkg/manifest.json +++ b/hyperdrive/packages/hypermap-cacher/pkg/manifest.json @@ -1,7 +1,7 @@ [ { - "process_name": "hypermap-binding-cacher", - "process_wasm_path": "/hypermap-binding-cacher.wasm", + "process_name": "binding-cacher", + "process_wasm_path": "/binding-cacher.wasm", "on_exit": "Restart", "request_networking": true, "request_capabilities": [ diff --git a/hyperdrive/packages/hypermap-cacher/pkg/scripts.json b/hyperdrive/packages/hypermap-cacher/pkg/scripts.json index aab9de842..5b1bfaefe 100644 --- a/hyperdrive/packages/hypermap-cacher/pkg/scripts.json +++ b/hyperdrive/packages/hypermap-cacher/pkg/scripts.json @@ -4,9 +4,11 @@ "public": false, "request_networking": false, "request_capabilities": [ + "binding-cacher:hypermap-cacher:sys", "hypermap-cacher:hypermap-cacher:sys" ], "grant_capabilities": [ + "binding-cacher:hypermap-cacher:sys", "hypermap-cacher:hypermap-cacher:sys" ], "wit_version": 1 @@ -16,9 +18,11 @@ "public": false, "request_networking": false, "request_capabilities": [ + "binding-cacher:hypermap-cacher:sys", "hypermap-cacher:hypermap-cacher:sys" ], "grant_capabilities": [ + "binding-cacher:hypermap-cacher:sys", "hypermap-cacher:hypermap-cacher:sys" ], "wit_version": 1 @@ -28,9 +32,11 @@ "public": false, "request_networking": false, "request_capabilities": [ + "binding-cacher:hypermap-cacher:sys", "hypermap-cacher:hypermap-cacher:sys" ], "grant_capabilities": [ + "binding-cacher:hypermap-cacher:sys", "hypermap-cacher:hypermap-cacher:sys" ], "wit_version": 1 @@ -40,9 +46,11 @@ "public": false, "request_networking": false, "request_capabilities": [ + "binding-cacher:hypermap-cacher:sys", "hypermap-cacher:hypermap-cacher:sys" ], "grant_capabilities": [ + "binding-cacher:hypermap-cacher:sys", "hypermap-cacher:hypermap-cacher:sys" ], "wit_version": 1 diff --git a/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml b/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml index 64c780831..b715b17e5 100644 --- a/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml @@ -5,7 +5,8 @@ edition = "2021" publish = false [dependencies] -hyperware_process_lib = "2.1.0" +#hyperware_process_lib = "2.1.0" +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs b/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs index 9db8ccb28..56d55af9d 100644 --- a/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs @@ -13,6 +13,7 @@ //! reset:hypermap-cacher:sys alice.os bob.os # Reset with custom nodes use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; +use crate::hyperware::process::binding_cacher::{BindingCacherRequest, BindingCacherResponse}; use hyperware_process_lib::{await_next_message_body, call_init, println, Address, Request}; wit_bindgen::generate!({ @@ -33,13 +34,14 @@ fn init(_our: Address) { let parts: Vec<&str> = args.split_whitespace().collect(); let custom_nodes = if parts.is_empty() { - println!("Resetting hypermap-cacher with default nodes..."); + println!("Resetting cachers with default nodes..."); None } else { let nodes: Vec = parts.iter().map(|s| s.to_string()).collect(); - println!("Resetting hypermap-cacher with custom nodes: {:?}", nodes); + println!("Resetting cachers with custom nodes: {:?}", nodes); Some(nodes) }; + let binding_custom_nodes = custom_nodes.clone(); let response = Request::to(("our", "hypermap-cacher", "hypermap-cacher", "sys")) .body(CacherRequest::Reset(custom_nodes)) @@ -51,7 +53,7 @@ fn init(_our: Address) { println!("✓ {}", msg); } Ok(CacherResponse::Reset(Err(err))) => { - println!("✗ Failed to reset: {}", err); + println!("✗ Failed to reset hypermap-cacher: {}", err); } _ => { println!("✗ Unexpected response from hypermap-cacher"); @@ -64,4 +66,28 @@ fn init(_our: Address) { println!("✗ Communication error: {:?}", err); } } + + let response = Request::to(("our", "binding-cacher", "hypermap-cacher", "sys")) + .body(BindingCacherRequest::Reset(binding_custom_nodes)) + .send_and_await_response(10); // Give it more time for reset operations + + match response { + Ok(Ok(message)) => match message.body().try_into() { + Ok(BindingCacherResponse::Reset(Ok(msg))) => { + println!("✓ {}", msg); + } + Ok(BindingCacherResponse::Reset(Err(err))) => { + println!("✗ Failed to reset binding-cacher: {}", err); + } + _ => { + println!("✗ Unexpected response from binding-cacher"); + } + }, + Ok(Err(err)) => { + println!("✗ Request failed: {:?}", err); + } + Err(err) => { + println!("✗ Communication error: {:?}", err); + } + } } diff --git a/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml b/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml index 6a00070f2..9a60fa5e7 100644 --- a/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml @@ -5,7 +5,8 @@ edition = "2021" publish = false [dependencies] -hyperware_process_lib = "2.1.0" +#hyperware_process_lib = "2.1.0" +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs b/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs index 84c68d56f..8521aebf7 100644 --- a/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs @@ -11,6 +11,7 @@ //! set-nodes:hypermap-cacher:sys alice.os bob.os charlie.os use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; +use crate::hyperware::process::binding_cacher::{BindingCacherRequest, BindingCacherResponse}; use hyperware_process_lib::{await_next_message_body, call_init, println, Address, Request}; wit_bindgen::generate!({ @@ -37,6 +38,7 @@ fn init(_our: Address) { } let nodes: Vec = parts.iter().map(|s| s.to_string()).collect(); + let binding_nodes = nodes.clone(); println!("Setting hypermap-cacher nodes to: {:?}", nodes); @@ -50,7 +52,7 @@ fn init(_our: Address) { println!("✓ {}", msg); } Ok(CacherResponse::SetNodes(Err(err))) => { - println!("✗ Failed to set nodes: {}", err); + println!("✗ Failed to set nodes for hypermap-cacher: {}", err); } _ => { println!("✗ Unexpected response from hypermap-cacher"); @@ -63,4 +65,30 @@ fn init(_our: Address) { println!("✗ Communication error: {:?}", err); } } + + println!("Setting binding-cacher nodes to: {:?}", binding_nodes); + + let response = Request::to(("our", "binding-cacher", "hypermap-cacher", "sys")) + .body(BindingCacherRequest::SetNodes(binding_nodes)) + .send_and_await_response(5); + + match response { + Ok(Ok(message)) => match message.body().try_into() { + Ok(BindingCacherResponse::SetNodes(Ok(msg))) => { + println!("✓ {}", msg); + } + Ok(BindingCacherResponse::SetNodes(Err(err))) => { + println!("✗ Failed to set nodes for binding-cacher: {}", err); + } + _ => { + println!("✗ Unexpected response from binding-cacher"); + } + }, + Ok(Err(err)) => { + println!("✗ Request failed: {:?}", err); + } + Err(err) => { + println!("✗ Communication error: {:?}", err); + } + } } diff --git a/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml b/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml index fd508eefc..a013f0e23 100644 --- a/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml @@ -5,7 +5,8 @@ edition = "2021" publish = false [dependencies] -hyperware_process_lib = "2.1.0" +#hyperware_process_lib = "2.1.0" +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs b/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs index e1db09301..c4b90f897 100644 --- a/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs @@ -1,4 +1,5 @@ use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; +use crate::hyperware::process::binding_cacher::{BindingCacherRequest, BindingCacherResponse}; use hyperware_process_lib::{call_init, println, Address, Request}; wit_bindgen::generate!({ @@ -22,7 +23,7 @@ fn init(_our: Address) { println!("✓ {}", msg); } Ok(CacherResponse::StartProviding(Err(err))) => { - println!("✗ Failed to enable provider mode: {}", err); + println!("✗ Failed to enable hypermap-cacher provider mode: {}", err); } _ => { println!("✗ Unexpected response from hypermap-cacher"); @@ -35,4 +36,30 @@ fn init(_our: Address) { println!("✗ Communication error: {:?}", err); } } + + println!("Enabling binding-cacher provider mode..."); + + let response = Request::to(("our", "binding-cacher", "hypermap-cacher", "sys")) + .body(BindingCacherRequest::StartProviding) + .send_and_await_response(5); + + match response { + Ok(Ok(message)) => match message.body().try_into() { + Ok(BindingCacherResponse::StartProviding(Ok(msg))) => { + println!("✓ {}", msg); + } + Ok(BindingCacherResponse::StartProviding(Err(err))) => { + println!("✗ Failed to enable binding-cacher provider mode: {}", err); + } + _ => { + println!("✗ Unexpected response from binding-cacher"); + } + }, + Ok(Err(err)) => { + println!("✗ Request failed: {:?}", err); + } + Err(err) => { + println!("✗ Communication error: {:?}", err); + } + } } diff --git a/hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml b/hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml index dfbc1efcf..11d12f593 100644 --- a/hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml @@ -5,7 +5,8 @@ edition = "2021" publish = false [dependencies] -hyperware_process_lib = "2.1.0" +#hyperware_process_lib = "2.1.0" +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs b/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs index 0afabb2cf..c298a7f06 100644 --- a/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs @@ -1,4 +1,5 @@ use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; +use crate::hyperware::process::binding_cacher::{BindingCacherRequest, BindingCacherResponse}; use hyperware_process_lib::{call_init, println, Address, Request}; wit_bindgen::generate!({ @@ -22,7 +23,7 @@ fn init(_our: Address) { println!("✓ {}", msg); } Ok(CacherResponse::StopProviding(Err(err))) => { - println!("✗ Failed to disable provider mode: {}", err); + println!("✗ Failed to disable hypermap-cacher provider mode: {}", err); } _ => { println!("✗ Unexpected response from hypermap-cacher"); @@ -35,4 +36,30 @@ fn init(_our: Address) { println!("✗ Communication error: {:?}", err); } } + + println!("Disabling binding-cacher provider mode..."); + + let response = Request::to(("our", "binding-cacher", "hypermap-cacher", "sys")) + .body(BindingCacherRequest::StopProviding) + .send_and_await_response(5); + + match response { + Ok(Ok(message)) => match message.body().try_into() { + Ok(BindingCacherResponse::StopProviding(Ok(msg))) => { + println!("✓ {}", msg); + } + Ok(BindingCacherResponse::StopProviding(Err(err))) => { + println!("✗ Failed to disable binding-cacher provider mode: {}", err); + } + _ => { + println!("✗ Unexpected response from binding-cacher"); + } + }, + Ok(Err(err)) => { + println!("✗ Request failed: {:?}", err); + } + Err(err) => { + println!("✗ Communication error: {:?}", err); + } + } } From c758a06e5d297f2e73fffcd0edf465dd06e542d5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 14:31:09 +0000 Subject: [PATCH 04/10] Format Rust code using rustfmt --- .../hypermap-cacher/binding-cacher/src/lib.rs | 12 +++++++++--- .../packages/hypermap-cacher/reset-cache/src/lib.rs | 2 +- .../packages/hypermap-cacher/set-nodes/src/lib.rs | 2 +- .../hypermap-cacher/start-providing/src/lib.rs | 2 +- .../hypermap-cacher/stop-providing/src/lib.rs | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs index a5e410d88..47f81ab43 100644 --- a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs @@ -11,8 +11,11 @@ use rand::thread_rng; use serde::{Deserialize, Serialize}; use crate::hyperware::process::binding_cacher::{ - BindingCacherRequest as CacherRequest, BindingCacherResponse as CacherResponse, BindingCacherStatus as CacherStatus, BindingGetLogsByRangeOkResponse as GetLogsByRangeOkResponse, BindingGetLogsByRangeRequest as GetLogsByRangeRequest, - BindingLogsMetadata as WitLogsMetadata, BindingManifest as WitManifest, BindingManifestItem as WitManifestItem, + BindingCacherRequest as CacherRequest, BindingCacherResponse as CacherResponse, + BindingCacherStatus as CacherStatus, + BindingGetLogsByRangeOkResponse as GetLogsByRangeOkResponse, + BindingGetLogsByRangeRequest as GetLogsByRangeRequest, BindingLogsMetadata as WitLogsMetadata, + BindingManifest as WitManifest, BindingManifestItem as WitManifestItem, }; use hyperware_process_lib::{ @@ -1170,7 +1173,10 @@ fn main_loop( hypermap: &hypermap::Hypermap, server: &http::server::HttpServer, ) -> anyhow::Result<()> { - info!("Hypermap Binding Cacher main_loop started. Our address: {}", our); + info!( + "Hypermap Binding Cacher main_loop started. Our address: {}", + our + ); info!( "Monitoring Binding contract: {}", state.hypermap_binding_address.to_string() diff --git a/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs b/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs index 56d55af9d..495847667 100644 --- a/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/reset-cache/src/lib.rs @@ -12,8 +12,8 @@ //! reset:hypermap-cacher:sys # Reset with default nodes //! reset:hypermap-cacher:sys alice.os bob.os # Reset with custom nodes -use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; use crate::hyperware::process::binding_cacher::{BindingCacherRequest, BindingCacherResponse}; +use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; use hyperware_process_lib::{await_next_message_body, call_init, println, Address, Request}; wit_bindgen::generate!({ diff --git a/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs b/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs index 8521aebf7..c8479ef9e 100644 --- a/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/set-nodes/src/lib.rs @@ -10,8 +10,8 @@ //! Example: //! set-nodes:hypermap-cacher:sys alice.os bob.os charlie.os -use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; use crate::hyperware::process::binding_cacher::{BindingCacherRequest, BindingCacherResponse}; +use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; use hyperware_process_lib::{await_next_message_body, call_init, println, Address, Request}; wit_bindgen::generate!({ diff --git a/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs b/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs index c4b90f897..f74f7abe7 100644 --- a/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/start-providing/src/lib.rs @@ -1,5 +1,5 @@ -use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; use crate::hyperware::process::binding_cacher::{BindingCacherRequest, BindingCacherResponse}; +use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; use hyperware_process_lib::{call_init, println, Address, Request}; wit_bindgen::generate!({ diff --git a/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs b/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs index c298a7f06..e6d55b831 100644 --- a/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/stop-providing/src/lib.rs @@ -1,5 +1,5 @@ -use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; use crate::hyperware::process::binding_cacher::{BindingCacherRequest, BindingCacherResponse}; +use crate::hyperware::process::hypermap_cacher::{CacherRequest, CacherResponse}; use hyperware_process_lib::{call_init, println, Address, Request}; wit_bindgen::generate!({ From 6e0c82c2ad94d7ee8ab4595f8e3ff0309b51bbf0 Mon Sep 17 00:00:00 2001 From: Johnathan Reale Date: Mon, 25 Aug 2025 12:05:41 -0400 Subject: [PATCH 05/10] using the new bindings import --- hyperdrive/packages/hypermap-cacher/Cargo.lock | 2 +- hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml | 2 +- hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs | 4 ++-- .../packages/hypermap-cacher/hypermap-cacher/Cargo.toml | 2 +- hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml | 2 +- hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml | 2 +- .../packages/hypermap-cacher/start-providing/Cargo.toml | 2 +- hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hyperdrive/packages/hypermap-cacher/Cargo.lock b/hyperdrive/packages/hypermap-cacher/Cargo.lock index 7ae5737d8..1cb89be77 100644 --- a/hyperdrive/packages/hypermap-cacher/Cargo.lock +++ b/hyperdrive/packages/hypermap-cacher/Cargo.lock @@ -1681,7 +1681,7 @@ dependencies = [ [[package]] name = "hyperware_process_lib" version = "2.2.0" -source = "git+https://github.com/hyperware-ai/process_lib?rev=8b6c2e5#8b6c2e5c32b543cc6358465ebd8cf51932b4b633" +source = "git+https://github.com/hyperware-ai/process_lib?rev=f18eb71#f18eb712b7cff47b90b5506e79e716a82d32ffa6" dependencies = [ "alloy", "alloy-primitives", diff --git a/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml index 734b1963e..c88777f82 100644 --- a/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml @@ -19,7 +19,7 @@ alloy = { version = "0.8.1", features = [ chrono = "0.4.41" hex = "0.4.3" #hyperware_process_lib = { version = "2.1.0", features = ["logging"] } -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5", features = ["logging"] } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71", features = ["logging"] } process_macros = "0.1.0" rand = "0.8" rmp-serde = "1.1.2" diff --git a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs index 47f81ab43..c7169213a 100644 --- a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs @@ -19,7 +19,7 @@ use crate::hyperware::process::binding_cacher::{ }; use hyperware_process_lib::{ - await_message, call_init, eth, get_state, http, hypermap, + await_message, bindings, call_init, eth, get_state, http, hypermap, logging::{debug, error, info, init_logging, warn, Level}, net::{NetAction, NetResponse}, our, set_state, sign, timer, vfs, Address, ProcessId, Request, Response, @@ -124,7 +124,7 @@ fn is_local_request(our: &Address, source: &Address) -> bool { impl State { fn new(drive_path: &str) -> Self { let chain_id = hypermap::HYPERMAP_CHAIN_ID.to_string(); - let hypermap_binding_address = eth::Address::from_str(hypermap::HYPERMAP_BINDING_ADDRESS) + let hypermap_binding_address = eth::Address::from_str(bindings::HYPERMAP_BINDING_ADDRESS) .expect("Failed to parse HYPERMAP_BINDING_ADDRESS"); let manifest_filename = format!( diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml index 6b8f831d2..6146d82a7 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml @@ -19,7 +19,7 @@ alloy = { version = "0.8.1", features = [ chrono = "0.4.41" hex = "0.4.3" #hyperware_process_lib = { version = "2.1.0", features = ["logging"] } -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5", features = ["logging"] } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71", features = ["logging"] } process_macros = "0.1.0" rand = "0.8" rmp-serde = "1.1.2" diff --git a/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml b/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml index b715b17e5..11c63f510 100644 --- a/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] #hyperware_process_lib = "2.1.0" -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5" } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml b/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml index 9a60fa5e7..7418750d7 100644 --- a/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] #hyperware_process_lib = "2.1.0" -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5" } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml b/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml index a013f0e23..8664cea1d 100644 --- a/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] #hyperware_process_lib = "2.1.0" -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5" } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml b/hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml index 11d12f593..9e4c6a287 100644 --- a/hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/stop-providing/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] #hyperware_process_lib = "2.1.0" -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "8b6c2e5" } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" From 77ff740dd2e2dd992c57aaf0bd661f066c530684 Mon Sep 17 00:00:00 2001 From: Johnathan Reale Date: Mon, 25 Aug 2025 16:41:30 -0400 Subject: [PATCH 06/10] updated constants and commit refs --- Cargo.lock | 57 ++++++++++++++++--- .../packages/hypermap-cacher/Cargo.lock | 40 ++++++++++--- .../hypermap-cacher/binding-cacher/Cargo.toml | 2 +- .../hypermap-cacher/binding-cacher/src/lib.rs | 8 +-- .../hypermap-cacher/Cargo.toml | 2 +- .../hypermap-cacher/reset-cache/Cargo.toml | 2 +- .../hypermap-cacher/set-nodes/Cargo.toml | 2 +- .../start-providing/Cargo.toml | 2 +- 8 files changed, 92 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a087b1142..90c75a246 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1184,7 +1184,7 @@ dependencies = [ "anyhow", "chrono", "hex", - "hyperware_process_lib 2.2.0", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "rand 0.8.5", "rmp-serde", @@ -1342,6 +1342,22 @@ dependencies = [ "serde", ] +[[package]] +name = "caller-utils" +version = "0.1.0" +dependencies = [ + "anyhow", + "futures", + "futures-util", + "hyperware_app_common", + "once_cell", + "process_macros", + "serde", + "serde_json", + "uuid 1.17.0", + "wit-bindgen 0.41.0", +] + [[package]] name = "camino" version = "1.1.10" @@ -2514,6 +2530,7 @@ name = "explorer" version = "0.1.0" dependencies = [ "anyhow", + "caller-utils", "hyperprocess_macro", "hyperware_app_common", "md5", @@ -3391,7 +3408,7 @@ dependencies = [ "anyhow", "chrono", "hex", - "hyperware_process_lib 2.2.0", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "rand 0.8.5", "rmp-serde", @@ -3505,7 +3522,7 @@ dependencies = [ [[package]] name = "hyperware_process_lib" version = "2.2.0" -source = "git+https://github.com/hyperware-ai/process_lib?rev=8b6c2e5#8b6c2e5c32b543cc6358465ebd8cf51932b4b633" +source = "git+https://github.com/hyperware-ai/process_lib?rev=e11d17c#e11d17cad18618117f1ef83520e71d46275f0504" dependencies = [ "alloy", "alloy-primitives", @@ -3532,6 +3549,32 @@ dependencies = [ "wit-bindgen 0.42.1", ] +[[package]] +name = "hyperware_process_lib" +version = "2.2.0" +source = "git+https://github.com/hyperware-ai/process_lib?rev=f18eb71#f18eb712b7cff47b90b5506e79e716a82d32ffa6" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-macro", + "alloy-sol-types", + "anyhow", + "base64 0.22.1", + "bincode", + "hex", + "http 1.3.1", + "mime_guess", + "rand 0.8.5", + "regex", + "rmp-serde", + "serde", + "serde_json", + "sha3", + "thiserror 1.0.69", + "url", + "wit-bindgen 0.42.1", +] + [[package]] name = "iana-time-zone" version = "0.1.63" @@ -5361,7 +5404,7 @@ dependencies = [ name = "reset-cache" version = "0.1.0" dependencies = [ - "hyperware_process_lib 2.2.0", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "serde", "serde_json", @@ -5855,7 +5898,7 @@ dependencies = [ name = "set-nodes" version = "0.1.0" dependencies = [ - "hyperware_process_lib 2.2.0", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "serde", "serde_json", @@ -6084,7 +6127,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "start-providing" version = "0.1.0" dependencies = [ - "hyperware_process_lib 2.2.0", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "serde", "serde_json", @@ -6129,7 +6172,7 @@ dependencies = [ name = "stop-providing" version = "0.1.0" dependencies = [ - "hyperware_process_lib 2.2.0", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=f18eb71)", "process_macros", "serde", "serde_json", diff --git a/hyperdrive/packages/hypermap-cacher/Cargo.lock b/hyperdrive/packages/hypermap-cacher/Cargo.lock index 1cb89be77..0a1ce7c2b 100644 --- a/hyperdrive/packages/hypermap-cacher/Cargo.lock +++ b/hyperdrive/packages/hypermap-cacher/Cargo.lock @@ -827,7 +827,7 @@ dependencies = [ "anyhow", "chrono", "hex", - "hyperware_process_lib", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "rand 0.8.5", "rmp-serde", @@ -1669,7 +1669,7 @@ dependencies = [ "anyhow", "chrono", "hex", - "hyperware_process_lib", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "rand 0.8.5", "rmp-serde", @@ -1681,7 +1681,7 @@ dependencies = [ [[package]] name = "hyperware_process_lib" version = "2.2.0" -source = "git+https://github.com/hyperware-ai/process_lib?rev=f18eb71#f18eb712b7cff47b90b5506e79e716a82d32ffa6" +source = "git+https://github.com/hyperware-ai/process_lib?rev=e11d17c#e11d17cad18618117f1ef83520e71d46275f0504" dependencies = [ "alloy", "alloy-primitives", @@ -1708,6 +1708,32 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "hyperware_process_lib" +version = "2.2.0" +source = "git+https://github.com/hyperware-ai/process_lib?rev=f18eb71#f18eb712b7cff47b90b5506e79e716a82d32ffa6" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-macro", + "alloy-sol-types", + "anyhow", + "base64", + "bincode", + "hex", + "http", + "mime_guess", + "rand 0.8.5", + "regex", + "rmp-serde", + "serde", + "serde_json", + "sha3", + "thiserror 1.0.69", + "url", + "wit-bindgen", +] + [[package]] name = "iana-time-zone" version = "0.1.63" @@ -2671,7 +2697,7 @@ dependencies = [ name = "reset-cache" version = "0.1.0" dependencies = [ - "hyperware_process_lib", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "serde", "serde_json", @@ -2979,7 +3005,7 @@ dependencies = [ name = "set-nodes" version = "0.1.0" dependencies = [ - "hyperware_process_lib", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "serde", "serde_json", @@ -3090,7 +3116,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "start-providing" version = "0.1.0" dependencies = [ - "hyperware_process_lib", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=e11d17c)", "process_macros", "serde", "serde_json", @@ -3107,7 +3133,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" name = "stop-providing" version = "0.1.0" dependencies = [ - "hyperware_process_lib", + "hyperware_process_lib 2.2.0 (git+https://github.com/hyperware-ai/process_lib?rev=f18eb71)", "process_macros", "serde", "serde_json", diff --git a/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml index c88777f82..78a220a6f 100644 --- a/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/Cargo.toml @@ -19,7 +19,7 @@ alloy = { version = "0.8.1", features = [ chrono = "0.4.41" hex = "0.4.3" #hyperware_process_lib = { version = "2.1.0", features = ["logging"] } -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71", features = ["logging"] } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "e11d17c", features = ["logging"] } process_macros = "0.1.0" rand = "0.8" rmp-serde = "1.1.2" diff --git a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs index c7169213a..bae68f415 100644 --- a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs @@ -123,9 +123,9 @@ fn is_local_request(our: &Address, source: &Address) -> bool { impl State { fn new(drive_path: &str) -> Self { - let chain_id = hypermap::HYPERMAP_CHAIN_ID.to_string(); - let hypermap_binding_address = eth::Address::from_str(bindings::HYPERMAP_BINDING_ADDRESS) - .expect("Failed to parse HYPERMAP_BINDING_ADDRESS"); + let chain_id = bindings::BINDINGS_CHAIN_ID.to_string(); + let hypermap_binding_address = eth::Address::from_str(bindings::BINDINGS_ADDRESS) + .expect("Failed to parse BINDINGS_ADDRESS"); let manifest_filename = format!( "manifest-chain{}-protocol{}.json", @@ -141,7 +141,7 @@ impl State { State { hypermap_binding_address, manifest: initial_manifest, - last_cached_block: hypermap::HYPERMAP_FIRST_BLOCK, + last_cached_block: bindings::BINDINGS_FIRST_BLOCK, chain_id, protocol_version: PROTOCOL_VERSION.to_string(), cache_interval_s: DEFAULT_CACHE_INTERVAL_S, diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml index 6146d82a7..89141ef63 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/Cargo.toml @@ -19,7 +19,7 @@ alloy = { version = "0.8.1", features = [ chrono = "0.4.41" hex = "0.4.3" #hyperware_process_lib = { version = "2.1.0", features = ["logging"] } -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71", features = ["logging"] } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "e11d17c", features = ["logging"] } process_macros = "0.1.0" rand = "0.8" rmp-serde = "1.1.2" diff --git a/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml b/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml index 11c63f510..3a46e6076 100644 --- a/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/reset-cache/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] #hyperware_process_lib = "2.1.0" -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71" } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "e11d17c" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml b/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml index 7418750d7..4ce65b7a0 100644 --- a/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/set-nodes/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] #hyperware_process_lib = "2.1.0" -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71" } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "e11d17c" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml b/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml index 8664cea1d..e58b19be0 100644 --- a/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml +++ b/hyperdrive/packages/hypermap-cacher/start-providing/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] #hyperware_process_lib = "2.1.0" -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "f18eb71" } +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", rev = "e11d17c" } process_macros = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" From 06fd2c7d0ab6e98e1951653c5d5f94e387952446 Mon Sep 17 00:00:00 2001 From: Johnathan Reale Date: Mon, 25 Aug 2025 16:43:13 -0400 Subject: [PATCH 07/10] accidentally let caller-utils bleed in --- Cargo.lock | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90c75a246..5e97464cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1342,22 +1342,6 @@ dependencies = [ "serde", ] -[[package]] -name = "caller-utils" -version = "0.1.0" -dependencies = [ - "anyhow", - "futures", - "futures-util", - "hyperware_app_common", - "once_cell", - "process_macros", - "serde", - "serde_json", - "uuid 1.17.0", - "wit-bindgen 0.41.0", -] - [[package]] name = "camino" version = "1.1.10" @@ -2530,7 +2514,6 @@ name = "explorer" version = "0.1.0" dependencies = [ "anyhow", - "caller-utils", "hyperprocess_macro", "hyperware_app_common", "md5", From 15f808de3f04d50851a167c7974628918b116301 Mon Sep 17 00:00:00 2001 From: Johnathan Reale Date: Thu, 28 Aug 2025 11:40:16 -0400 Subject: [PATCH 08/10] cache source and RPC source overrides --- .../hypermap-cacher/binding-cacher/src/lib.rs | 49 +++++++++++++++---- .../hypermap-cacher/default_nodes.json | 6 +++ .../default_nodes_simulation.json | 3 ++ .../hypermap-cacher/src/lib.rs | 49 +++++++++++++++---- .../default_simulation_mode_providers.json | 22 +++++++++ hyperdrive/src/main.rs | 12 +++++ 6 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 hyperdrive/packages/hypermap-cacher/default_nodes.json create mode 100644 hyperdrive/packages/hypermap-cacher/default_nodes_simulation.json create mode 100644 hyperdrive/src/eth/default_simulation_mode_providers.json diff --git a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs index bae68f415..383c690b6 100644 --- a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs @@ -40,14 +40,25 @@ const RETRY_DELAY_S: u64 = 10; const LOG_ITERATION_DELAY_MS: u64 = 200; #[cfg(not(feature = "simulation-mode"))] -const DEFAULT_NODES: &[&str] = &[ - "us-cacher-1.hypr", - "eu-cacher-1.hypr", - "nick.hypr", - "nick1udwig.os", -]; +const DEFAULT_NODES_JSON: &str = include_str!("../../default_nodes.json"); + #[cfg(feature = "simulation-mode")] -const DEFAULT_NODES: &[&str] = &["fake.os"]; +const DEFAULT_NODES_JSON: &str = include_str!("../../default_nodes_simulation.json"); + +fn load_cache_sources(config_path: Option<&str>) -> Result, Box> { + if let Some(path) = config_path { + // Load from user-provided file + let config_content = std::fs::read_to_string(path) + .map_err(|e| format!("Failed to read cache config file {}: {}", path, e))?; + + serde_json::from_str::>(&config_content) + .map_err(|e| format!("Failed to parse cache config JSON: {}", e).into()) + } else { + // Fall back to embedded defaults + serde_json::from_str::>(DEFAULT_NODES_JSON) + .map_err(|e| format!("Failed to parse embedded default cache nodes: {}", e).into()) + } +} // Internal representation of LogsMetadata, similar to WIT but for Rust logic. #[derive(Serialize, Deserialize, Debug, Clone)] @@ -149,7 +160,7 @@ impl State { is_cache_timer_live: false, drive_path: drive_path.to_string(), is_providing: false, - nodes: DEFAULT_NODES.iter().map(|s| s.to_string()).collect(), + nodes: cache_sources.iter().map(|s| s.to_string()).collect(), is_starting: true, } } @@ -566,7 +577,7 @@ impl State { let mut nodes = self.nodes.clone(); // If using default nodes, shuffle them for random order - let default_nodes: Vec = DEFAULT_NODES.iter().map(|s| s.to_string()).collect(); + let default_nodes: Vec = cache_sources.iter().map(|s| s.to_string()).collect(); if nodes == default_nodes { nodes.shuffle(&mut thread_rng()); } @@ -1144,7 +1155,7 @@ fn handle_request( // Create new state with custom nodes if provided, otherwise use defaults let nodes = match custom_nodes { Some(nodes) => nodes, - None => DEFAULT_NODES.iter().map(|s| s.to_string()).collect(), + None => cache_sources.iter().map(|s| s.to_string()).collect(), }; *state = State::new(&state.drive_path); @@ -1283,6 +1294,22 @@ fn init(our: Address) { let drive_path = vfs::create_drive(our.package_id(), "binding-cache", None).unwrap(); let bind_config = http::server::HttpBindingConfig::default().authenticated(false); + + // Read the config path from environment variable (None if not set) + let cache_source_config_path = std::env::var("CACHE_SOURCE_CONFIG_PATH").ok(); + + // Load cache sources - this handles both user config and embedded defaults + let cache_sources = load_cache_sources(cache_source_config_path.as_deref()) + .unwrap_or_else(|e| { + // Only print error if a config was actually specified + if cache_source_config_path.is_some() { + println!("hypermap-cacher: Error loading cache sources: {}, falling back to defaults", e); + } + // Parse embedded defaults as final fallback + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }); + let mut server = http::server::HttpServer::new(5); let hypermap_provider = hypermap::Hypermap::default(60); @@ -1303,6 +1330,8 @@ fn init(our: Address) { let mut state = State::load(&drive_path); + state.nodes = cache_sources; + loop { match main_loop(&our, &mut state, &hypermap_provider, &server) { Ok(()) => { diff --git a/hyperdrive/packages/hypermap-cacher/default_nodes.json b/hyperdrive/packages/hypermap-cacher/default_nodes.json new file mode 100644 index 000000000..9cb2b94bb --- /dev/null +++ b/hyperdrive/packages/hypermap-cacher/default_nodes.json @@ -0,0 +1,6 @@ +[ + "us-cacher-1.hypr", + "eu-cacher-1.hypr", + "nick.hypr", + "nick1udwig.os" +] \ No newline at end of file diff --git a/hyperdrive/packages/hypermap-cacher/default_nodes_simulation.json b/hyperdrive/packages/hypermap-cacher/default_nodes_simulation.json new file mode 100644 index 000000000..2a0f27424 --- /dev/null +++ b/hyperdrive/packages/hypermap-cacher/default_nodes_simulation.json @@ -0,0 +1,3 @@ +[ + "fake.os" +] \ No newline at end of file diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs index 4ba60f385..2d522809d 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs @@ -37,14 +37,25 @@ const RETRY_DELAY_S: u64 = 10; const LOG_ITERATION_DELAY_MS: u64 = 200; #[cfg(not(feature = "simulation-mode"))] -const DEFAULT_NODES: &[&str] = &[ - "us-cacher-1.hypr", - "eu-cacher-1.hypr", - "nick.hypr", - "nick1udwig.os", -]; +const DEFAULT_NODES_JSON: &str = include_str!("../../default_nodes.json"); + #[cfg(feature = "simulation-mode")] -const DEFAULT_NODES: &[&str] = &["fake.os"]; +const DEFAULT_NODES_JSON: &str = include_str!("../../default_nodes_simulation.json"); + +fn load_cache_sources(config_path: Option<&str>) -> Result, Box> { + if let Some(path) = config_path { + // Load from user-provided file + let config_content = std::fs::read_to_string(path) + .map_err(|e| format!("Failed to read cache config file {}: {}", path, e))?; + + serde_json::from_str::>(&config_content) + .map_err(|e| format!("Failed to parse cache config JSON: {}", e).into()) + } else { + // Fall back to embedded defaults + serde_json::from_str::>(DEFAULT_NODES_JSON) + .map_err(|e| format!("Failed to parse embedded default cache nodes: {}", e).into()) + } +} // Internal representation of LogsMetadata, similar to WIT but for Rust logic. #[derive(Serialize, Deserialize, Debug, Clone)] @@ -146,7 +157,7 @@ impl State { is_cache_timer_live: false, drive_path: drive_path.to_string(), is_providing: false, - nodes: DEFAULT_NODES.iter().map(|s| s.to_string()).collect(), + nodes: cache_sources.iter().map(|s| s.to_string()).collect(), is_starting: true, } } @@ -563,7 +574,7 @@ impl State { let mut nodes = self.nodes.clone(); // If using default nodes, shuffle them for random order - let default_nodes: Vec = DEFAULT_NODES.iter().map(|s| s.to_string()).collect(); + let default_nodes: Vec = cache_sources.iter().map(|s| s.to_string()).collect(); if nodes == default_nodes { nodes.shuffle(&mut thread_rng()); } @@ -1141,7 +1152,7 @@ fn handle_request( // Create new state with custom nodes if provided, otherwise use defaults let nodes = match custom_nodes { Some(nodes) => nodes, - None => DEFAULT_NODES.iter().map(|s| s.to_string()).collect(), + None => cache_sources.iter().map(|s| s.to_string()).collect(), }; *state = State::new(&state.drive_path); @@ -1277,6 +1288,22 @@ fn init(our: Address) { let drive_path = vfs::create_drive(our.package_id(), "hypermap-cache", None).unwrap(); let bind_config = http::server::HttpBindingConfig::default().authenticated(false); + + // Read the config path from environment variable (None if not set) + let cache_source_config_path = std::env::var("CACHE_SOURCE_CONFIG_PATH").ok(); + + // Load cache sources - this handles both user config and embedded defaults + let cache_sources = load_cache_sources(cache_source_config_path.as_deref()) + .unwrap_or_else(|e| { + // Only print error if a config was actually specified + if cache_source_config_path.is_some() { + println!("hypermap-cacher: Error loading cache sources: {}, falling back to defaults", e); + } + // Parse embedded defaults as final fallback + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }); + let mut server = http::server::HttpServer::new(5); let hypermap_provider = hypermap::Hypermap::default(60); @@ -1297,6 +1324,8 @@ fn init(our: Address) { let mut state = State::load(&drive_path); + state.nodes = cache_sources; + loop { match main_loop(&our, &mut state, &hypermap_provider, &server) { Ok(()) => { diff --git a/hyperdrive/src/eth/default_simulation_mode_providers.json b/hyperdrive/src/eth/default_simulation_mode_providers.json new file mode 100644 index 000000000..a455c53af --- /dev/null +++ b/hyperdrive/src/eth/default_simulation_mode_providers.json @@ -0,0 +1,22 @@ +[ + { + "chain_id": 31337, + "trusted": false, + "provider": { + "Node": { + "hns_update": { + "name": "fake.os", + "public_key": "0xd7732d194e46ac4b0dfb8958816e16c05512aa802e20b99613fbc15c79ea10fa", + "ips": [ + "127.0.0.1" + ], + "ports": { + "ws": 9000 + }, + "routers": [] + }, + "use_as_provider": true + } + } + } +] diff --git a/hyperdrive/src/main.rs b/hyperdrive/src/main.rs index e9bb037f4..277344d70 100644 --- a/hyperdrive/src/main.rs +++ b/hyperdrive/src/main.rs @@ -52,7 +52,10 @@ const DEFAULT_MAX_PEERS: u64 = 32; const DEFAULT_MAX_PASSTHROUGHS: u64 = 0; /// default routers as a eth-provider fallback +#[cfg(not(feature = "simulation-mode"))] const DEFAULT_ETH_PROVIDERS: &str = include_str!("eth/default_providers_mainnet.json"); +#[cfg(feature = "simulation-mode")] +const DEFAULT_ETH_PROVIDERS: &str = include_str!("eth/default_simulation_mode_providers.json"); #[cfg(not(feature = "simulation-mode"))] pub const CHAIN_ID: u64 = 8453; // base #[cfg(feature = "simulation-mode")] @@ -83,6 +86,9 @@ async fn main() { let verbose_mode = *matches .get_one::("verbosity") .expect("verbosity required"); + let cache_source_config = matches.get_one::("cache-source-config").map(|p| { + std::fs::canonicalize(&p).expect(&format!("specified cache-source-config path {p} not found")) + }); let rpc = matches.get_one::("rpc"); let rpc_config = matches.get_one::("rpc-config").map(|p| { std::fs::canonicalize(&p).expect(&format!("specified rpc-config path {p} not found")) @@ -113,6 +119,11 @@ async fn main() { let expose_local = *matches.get_one::("expose-local").unwrap(); + // Set environment variable for the WASM process to read + if let Some(config_path) = cache_source_config { + std::env::set_var("CACHE_SOURCE_CONFIG_PATH", config_path); + } + #[cfg(feature = "simulation-mode")] let (fake_node_name, fakechain_port) = ( matches.get_one::("fake-node-name"), @@ -775,6 +786,7 @@ fn build_command() -> Command { arg!(-d --detached "Run in detached mode (don't accept input)") .action(clap::ArgAction::SetTrue), ) + .arg(arg!(--"cache-source-config" "Add cache source nodes for hypermap and bindings contract logs")) .arg(arg!(--rpc "Add a WebSockets RPC URL at boot")) .arg(arg!(--"rpc-config" "Add WebSockets RPC URLs specified in config at boot")) .arg(arg!(--password "Node password (in double quotes)")) From 19272adfa099f4992223e1e25c567e979f596949 Mon Sep 17 00:00:00 2001 From: Johnathan Reale Date: Thu, 28 Aug 2025 12:07:18 -0400 Subject: [PATCH 09/10] proper referencing --- .../hypermap-cacher/binding-cacher/src/lib.rs | 18 +++++++++++++++--- .../hypermap-cacher/hypermap-cacher/src/lib.rs | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs index 383c690b6..b35ee3593 100644 --- a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs @@ -160,7 +160,11 @@ impl State { is_cache_timer_live: false, drive_path: drive_path.to_string(), is_providing: false, - nodes: cache_sources.iter().map(|s| s.to_string()).collect(), + nodes: load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }), is_starting: true, } } @@ -577,7 +581,11 @@ impl State { let mut nodes = self.nodes.clone(); // If using default nodes, shuffle them for random order - let default_nodes: Vec = cache_sources.iter().map(|s| s.to_string()).collect(); + let default_nodes: Vec = load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }); if nodes == default_nodes { nodes.shuffle(&mut thread_rng()); } @@ -1155,7 +1163,11 @@ fn handle_request( // Create new state with custom nodes if provided, otherwise use defaults let nodes = match custom_nodes { Some(nodes) => nodes, - None => cache_sources.iter().map(|s| s.to_string()).collect(), + None => load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }), }; *state = State::new(&state.drive_path); diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs index 2d522809d..d39efbf15 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs @@ -157,7 +157,11 @@ impl State { is_cache_timer_live: false, drive_path: drive_path.to_string(), is_providing: false, - nodes: cache_sources.iter().map(|s| s.to_string()).collect(), + nodes: load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }), is_starting: true, } } @@ -574,7 +578,11 @@ impl State { let mut nodes = self.nodes.clone(); // If using default nodes, shuffle them for random order - let default_nodes: Vec = cache_sources.iter().map(|s| s.to_string()).collect(); + let default_nodes: Vec = load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }); if nodes == default_nodes { nodes.shuffle(&mut thread_rng()); } @@ -1152,7 +1160,11 @@ fn handle_request( // Create new state with custom nodes if provided, otherwise use defaults let nodes = match custom_nodes { Some(nodes) => nodes, - None => cache_sources.iter().map(|s| s.to_string()).collect(), + None => load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }), }; *state = State::new(&state.drive_path); From 35926cea8eba54791643454a6b1fa29ae2224e76 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:08:18 +0000 Subject: [PATCH 10/10] Format Rust code using rustfmt --- .../hypermap-cacher/binding-cacher/src/lib.rs | 36 +++++++++++-------- .../hypermap-cacher/src/lib.rs | 36 +++++++++++-------- hyperdrive/src/main.rs | 3 +- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs index b35ee3593..20534dae1 100644 --- a/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/binding-cacher/src/lib.rs @@ -45,7 +45,9 @@ const DEFAULT_NODES_JSON: &str = include_str!("../../default_nodes.json"); #[cfg(feature = "simulation-mode")] const DEFAULT_NODES_JSON: &str = include_str!("../../default_nodes_simulation.json"); -fn load_cache_sources(config_path: Option<&str>) -> Result, Box> { +fn load_cache_sources( + config_path: Option<&str>, +) -> Result, Box> { if let Some(path) = config_path { // Load from user-provided file let config_content = std::fs::read_to_string(path) @@ -581,11 +583,12 @@ impl State { let mut nodes = self.nodes.clone(); // If using default nodes, shuffle them for random order - let default_nodes: Vec = load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) - .unwrap_or_else(|_| { - serde_json::from_str::>(DEFAULT_NODES_JSON) - .expect("Failed to parse embedded default cache nodes") - }); + let default_nodes: Vec = + load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }); if nodes == default_nodes { nodes.shuffle(&mut thread_rng()); } @@ -1163,11 +1166,13 @@ fn handle_request( // Create new state with custom nodes if provided, otherwise use defaults let nodes = match custom_nodes { Some(nodes) => nodes, - None => load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) - .unwrap_or_else(|_| { - serde_json::from_str::>(DEFAULT_NODES_JSON) - .expect("Failed to parse embedded default cache nodes") - }), + None => load_cache_sources( + std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref(), + ) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }), }; *state = State::new(&state.drive_path); @@ -1311,11 +1316,14 @@ fn init(our: Address) { let cache_source_config_path = std::env::var("CACHE_SOURCE_CONFIG_PATH").ok(); // Load cache sources - this handles both user config and embedded defaults - let cache_sources = load_cache_sources(cache_source_config_path.as_deref()) - .unwrap_or_else(|e| { + let cache_sources = + load_cache_sources(cache_source_config_path.as_deref()).unwrap_or_else(|e| { // Only print error if a config was actually specified if cache_source_config_path.is_some() { - println!("hypermap-cacher: Error loading cache sources: {}, falling back to defaults", e); + println!( + "hypermap-cacher: Error loading cache sources: {}, falling back to defaults", + e + ); } // Parse embedded defaults as final fallback serde_json::from_str::>(DEFAULT_NODES_JSON) diff --git a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs index d39efbf15..78ecbc8a5 100644 --- a/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs +++ b/hyperdrive/packages/hypermap-cacher/hypermap-cacher/src/lib.rs @@ -42,7 +42,9 @@ const DEFAULT_NODES_JSON: &str = include_str!("../../default_nodes.json"); #[cfg(feature = "simulation-mode")] const DEFAULT_NODES_JSON: &str = include_str!("../../default_nodes_simulation.json"); -fn load_cache_sources(config_path: Option<&str>) -> Result, Box> { +fn load_cache_sources( + config_path: Option<&str>, +) -> Result, Box> { if let Some(path) = config_path { // Load from user-provided file let config_content = std::fs::read_to_string(path) @@ -578,11 +580,12 @@ impl State { let mut nodes = self.nodes.clone(); // If using default nodes, shuffle them for random order - let default_nodes: Vec = load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) - .unwrap_or_else(|_| { - serde_json::from_str::>(DEFAULT_NODES_JSON) - .expect("Failed to parse embedded default cache nodes") - }); + let default_nodes: Vec = + load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }); if nodes == default_nodes { nodes.shuffle(&mut thread_rng()); } @@ -1160,11 +1163,13 @@ fn handle_request( // Create new state with custom nodes if provided, otherwise use defaults let nodes = match custom_nodes { Some(nodes) => nodes, - None => load_cache_sources(std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref()) - .unwrap_or_else(|_| { - serde_json::from_str::>(DEFAULT_NODES_JSON) - .expect("Failed to parse embedded default cache nodes") - }), + None => load_cache_sources( + std::env::var("CACHE_SOURCE_CONFIG_PATH").ok().as_deref(), + ) + .unwrap_or_else(|_| { + serde_json::from_str::>(DEFAULT_NODES_JSON) + .expect("Failed to parse embedded default cache nodes") + }), }; *state = State::new(&state.drive_path); @@ -1305,11 +1310,14 @@ fn init(our: Address) { let cache_source_config_path = std::env::var("CACHE_SOURCE_CONFIG_PATH").ok(); // Load cache sources - this handles both user config and embedded defaults - let cache_sources = load_cache_sources(cache_source_config_path.as_deref()) - .unwrap_or_else(|e| { + let cache_sources = + load_cache_sources(cache_source_config_path.as_deref()).unwrap_or_else(|e| { // Only print error if a config was actually specified if cache_source_config_path.is_some() { - println!("hypermap-cacher: Error loading cache sources: {}, falling back to defaults", e); + println!( + "hypermap-cacher: Error loading cache sources: {}, falling back to defaults", + e + ); } // Parse embedded defaults as final fallback serde_json::from_str::>(DEFAULT_NODES_JSON) diff --git a/hyperdrive/src/main.rs b/hyperdrive/src/main.rs index 277344d70..e2ea7cabd 100644 --- a/hyperdrive/src/main.rs +++ b/hyperdrive/src/main.rs @@ -87,7 +87,8 @@ async fn main() { .get_one::("verbosity") .expect("verbosity required"); let cache_source_config = matches.get_one::("cache-source-config").map(|p| { - std::fs::canonicalize(&p).expect(&format!("specified cache-source-config path {p} not found")) + std::fs::canonicalize(&p) + .expect(&format!("specified cache-source-config path {p} not found")) }); let rpc = matches.get_one::("rpc"); let rpc_config = matches.get_one::("rpc-config").map(|p| {