1use crate::eth::{
2 BlockNumberOrTag, EthError, Filter as EthFilter, FilterBlockOption, Log as EthLog, Provider,
3};
4use crate::hypermap::contract::getCall;
5use crate::hyperware::process::hypermap_cacher::{
6 CacherRequest, CacherResponse, CacherStatus, GetLogsByRangeOkResponse, GetLogsByRangeRequest,
7 LogsMetadata, Manifest, ManifestItem,
8};
9use crate::{net, sign};
10use crate::{print_to_terminal, Address as HyperAddress, Request};
11use alloy::hex;
12use alloy::rpc::types::request::{TransactionInput, TransactionRequest};
13use alloy_primitives::{keccak256, Address, Bytes, FixedBytes, B256};
14use alloy_sol_types::{SolCall, SolEvent, SolValue};
15use contract::tokenCall;
16use serde::{
17 self,
18 de::{self, MapAccess, Visitor},
19 ser::{SerializeMap, SerializeStruct},
20 Deserialize, Deserializer, Serialize, Serializer,
21};
22use std::error::Error;
23use std::fmt;
24use std::str::FromStr;
25
26pub const HYPERMAP_ADDRESS: &'static str = "0x000000000044C6B8Cb4d8f0F889a3E47664EAeda";
28#[cfg(not(feature = "simulation-mode"))]
30pub const HYPERMAP_CHAIN_ID: u64 = 8453; #[cfg(feature = "simulation-mode")]
32pub const HYPERMAP_CHAIN_ID: u64 = 31337; #[cfg(not(feature = "simulation-mode"))]
35pub const HYPERMAP_FIRST_BLOCK: u64 = 27_270_411;
36#[cfg(feature = "simulation-mode")]
37pub const HYPERMAP_FIRST_BLOCK: u64 = 0;
38pub const HYPERMAP_ROOT_HASH: &'static str =
40 "0x0000000000000000000000000000000000000000000000000000000000000000";
41
42#[derive(Serialize, Deserialize, Debug, Clone)]
43pub struct LogCache {
44 pub metadata: LogsMetadata,
45 pub logs: Vec<EthLog>,
46}
47
48const CACHER_REQUEST_TIMEOUT_S: u64 = 15;
49
50pub mod contract {
52 use alloy_sol_macro::sol;
53
54 sol! {
55 event Mint(
61 bytes32 indexed parenthash,
62 bytes32 indexed childhash,
63 bytes indexed labelhash,
64 bytes label
65 );
66
67 event Fact(
76 bytes32 indexed parenthash,
77 bytes32 indexed facthash,
78 bytes indexed labelhash,
79 bytes label,
80 bytes data
81 );
82
83 event Note(
92 bytes32 indexed parenthash,
93 bytes32 indexed notehash,
94 bytes indexed labelhash,
95 bytes label,
96 bytes data
97 );
98
99 event Gene(bytes32 indexed entry, address indexed gene);
105
106 event Zero(address indexed zeroTba);
110
111 event Transfer(
117 address indexed from,
118 address indexed to,
119 uint256 indexed id
120 );
121
122 event Approval(
127 address indexed owner,
128 address indexed spender,
129 uint256 indexed id
130 );
131
132 event ApprovalForAll(
138 address indexed owner,
139 address indexed operator,
140 bool approved
141 );
142
143 function get(
153 bytes32 namehash
154 ) external view returns (address tba, address owner, bytes memory data);
155
156 function mint(
171 address who,
172 bytes calldata label,
173 bytes calldata initialization,
174 bytes calldata erc721Data,
175 address implementation
176 ) external returns (address tba);
177
178 function gene(address _gene) external;
182
183 function fact(
191 bytes calldata fact,
192 bytes calldata data
193 ) external returns (bytes32 facthash);
194
195 function note(
202 bytes calldata note,
203 bytes calldata data
204 ) external returns (bytes32 notehash);
205
206 function tbaOf(uint256 entry) external view returns (address tba);
213
214 function balanceOf(address owner) external view returns (uint256);
215
216 function getApproved(uint256 entry) external view returns (address);
217
218 function isApprovedForAll(
219 address owner,
220 address operator
221 ) external view returns (bool);
222
223 function ownerOf(uint256 entry) external view returns (address);
224
225 function setApprovalForAll(address operator, bool approved) external;
226
227 function approve(address spender, uint256 entry) external;
228
229 function safeTransferFrom(address from, address to, uint256 id) external;
230
231 function safeTransferFrom(
232 address from,
233 address to,
234 uint256 id,
235 bytes calldata data
236 ) external;
237
238 function transferFrom(address from, address to, uint256 id) external;
239
240 function supportsInterface(bytes4 interfaceId) external view returns (bool);
241
242 function token()
252 external
253 view
254 returns (uint256 chainId, address tokenContract, uint256 tokenId);
255 }
256}
257
258#[derive(Clone, Debug, Deserialize, Serialize)]
261pub struct Mint {
262 pub name: String,
263 pub parent_path: String,
264}
265
266#[derive(Clone, Debug, Deserialize, Serialize)]
269pub struct Note {
270 pub note: String,
271 pub parent_path: String,
272 pub data: Bytes,
273}
274
275#[derive(Clone, Debug, Deserialize, Serialize)]
278pub struct Fact {
279 pub fact: String,
280 pub parent_path: String,
281 pub data: Bytes,
282}
283
284#[derive(Clone, Debug, Deserialize, Serialize)]
287pub enum DecodeLogError {
288 UnexpectedTopic(B256),
290 InvalidName(String),
292 DecodeError(String),
294 UnresolvedParent(String),
296}
297
298impl fmt::Display for DecodeLogError {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 match self {
301 DecodeLogError::UnexpectedTopic(topic) => write!(f, "Unexpected topic: {:?}", topic),
302 DecodeLogError::InvalidName(name) => write!(f, "Invalid name: {}", name),
303 DecodeLogError::DecodeError(err) => write!(f, "Decode error: {}", err),
304 DecodeLogError::UnresolvedParent(parent) => {
305 write!(f, "Could not resolve parent: {}", parent)
306 }
307 }
308 }
309}
310
311impl Error for DecodeLogError {}
312
313pub fn valid_entry(entry: &str, note: bool, fact: bool) -> bool {
318 if note && fact {
319 return false;
320 }
321 if note {
322 valid_note(entry)
323 } else if fact {
324 valid_fact(entry)
325 } else {
326 valid_name(entry)
327 }
328}
329
330pub fn valid_name(name: &str) -> bool {
331 name.is_ascii()
332 && name.len() >= 1
333 && name
334 .chars()
335 .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')
336}
337
338pub fn valid_note(note: &str) -> bool {
339 note.is_ascii()
340 && note.len() >= 2
341 && note.chars().next() == Some('~')
342 && note
343 .chars()
344 .skip(1)
345 .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')
346}
347
348pub fn valid_fact(fact: &str) -> bool {
349 fact.is_ascii()
350 && fact.len() >= 2
351 && fact.chars().next() == Some('!')
352 && fact
353 .chars()
354 .skip(1)
355 .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')
356}
357
358pub fn namehash(name: &str) -> String {
360 let mut node = B256::default();
361
362 let mut labels: Vec<&str> = name.split('.').collect();
363 labels.reverse();
364
365 for label in labels.iter() {
366 let l = keccak256(label);
367 node = keccak256((node, l).abi_encode_packed());
368 }
369 format!("0x{}", hex::encode(node))
370}
371
372pub fn decode_mint_log(log: &crate::eth::Log) -> Result<Mint, DecodeLogError> {
376 let contract::Note::SIGNATURE_HASH = log.topics()[0] else {
377 return Err(DecodeLogError::UnexpectedTopic(log.topics()[0]));
378 };
379 let decoded = contract::Mint::decode_log_data(log.data(), true)
380 .map_err(|e| DecodeLogError::DecodeError(e.to_string()))?;
381 let name = String::from_utf8_lossy(&decoded.label).to_string();
382 if !valid_name(&name) {
383 return Err(DecodeLogError::InvalidName(name));
384 }
385 match resolve_parent(log, None) {
386 Some(parent_path) => Ok(Mint { name, parent_path }),
387 None => Err(DecodeLogError::UnresolvedParent(name)),
388 }
389}
390
391pub fn decode_note_log(log: &crate::eth::Log) -> Result<Note, DecodeLogError> {
395 let contract::Note::SIGNATURE_HASH = log.topics()[0] else {
396 return Err(DecodeLogError::UnexpectedTopic(log.topics()[0]));
397 };
398 let decoded = contract::Note::decode_log_data(log.data(), true)
399 .map_err(|e| DecodeLogError::DecodeError(e.to_string()))?;
400 let note = String::from_utf8_lossy(&decoded.label).to_string();
401 if !valid_note(¬e) {
402 return Err(DecodeLogError::InvalidName(note));
403 }
404 match resolve_parent(log, None) {
405 Some(parent_path) => Ok(Note {
406 note,
407 parent_path,
408 data: decoded.data,
409 }),
410 None => Err(DecodeLogError::UnresolvedParent(note)),
411 }
412}
413
414pub fn decode_fact_log(log: &crate::eth::Log) -> Result<Fact, DecodeLogError> {
415 let contract::Fact::SIGNATURE_HASH = log.topics()[0] else {
416 return Err(DecodeLogError::UnexpectedTopic(log.topics()[0]));
417 };
418 let decoded = contract::Fact::decode_log_data(log.data(), true)
419 .map_err(|e| DecodeLogError::DecodeError(e.to_string()))?;
420 let fact = String::from_utf8_lossy(&decoded.label).to_string();
421 if !valid_fact(&fact) {
422 return Err(DecodeLogError::InvalidName(fact));
423 }
424 match resolve_parent(log, None) {
425 Some(parent_path) => Ok(Fact {
426 fact,
427 parent_path,
428 data: decoded.data,
429 }),
430 None => Err(DecodeLogError::UnresolvedParent(fact)),
431 }
432}
433
434pub fn resolve_parent(log: &crate::eth::Log, timeout: Option<u64>) -> Option<String> {
437 let parent_hash = log.topics()[1].to_string();
438 net::get_name(&parent_hash, log.block_number, timeout)
439}
440
441pub fn resolve_full_name(log: &crate::eth::Log, timeout: Option<u64>) -> Option<String> {
446 let parent_hash = log.topics()[1].to_string();
447 let parent_name = net::get_name(&parent_hash, log.block_number, timeout)?;
448 let log_name = match log.topics()[0] {
449 contract::Mint::SIGNATURE_HASH => {
450 let decoded = contract::Mint::decode_log_data(log.data(), true).unwrap();
451 decoded.label
452 }
453 contract::Note::SIGNATURE_HASH => {
454 let decoded = contract::Note::decode_log_data(log.data(), true).unwrap();
455 decoded.label
456 }
457 contract::Fact::SIGNATURE_HASH => {
458 let decoded = contract::Fact::decode_log_data(log.data(), true).unwrap();
459 decoded.label
460 }
461 _ => return None,
462 };
463 let name = String::from_utf8_lossy(&log_name);
464 if !valid_entry(
465 &name,
466 log.topics()[0] == contract::Note::SIGNATURE_HASH,
467 log.topics()[0] == contract::Fact::SIGNATURE_HASH,
468 ) {
469 return None;
470 }
471 Some(format!("{name}.{parent_name}"))
472}
473
474pub fn eth_apply_filter(logs: &[EthLog], filter: &EthFilter) -> Vec<EthLog> {
475 let mut matched_logs = Vec::new();
476
477 let (filter_from_block, filter_to_block) = match filter.block_option {
478 FilterBlockOption::Range {
479 from_block,
480 to_block,
481 } => {
482 let parse_block_num = |bn: Option<BlockNumberOrTag>| -> Option<u64> {
483 match bn {
484 Some(BlockNumberOrTag::Number(n)) => Some(n),
485 _ => None,
486 }
487 };
488 (parse_block_num(from_block), parse_block_num(to_block))
489 }
490 _ => (None, None),
491 };
492
493 for log in logs.iter() {
494 let mut match_address = filter.address.is_empty();
495 if !match_address {
496 if filter.address.matches(&log.address()) {
497 match_address = true;
498 }
499 }
500 if !match_address {
501 continue;
502 }
503
504 if let Some(log_bn) = log.block_number {
505 if let Some(filter_from) = filter_from_block {
506 if log_bn < filter_from {
507 continue;
508 }
509 }
510 if let Some(filter_to) = filter_to_block {
511 if log_bn > filter_to {
512 continue;
513 }
514 }
515 } else {
516 if filter_from_block.is_some() || filter_to_block.is_some() {
517 continue;
518 }
519 }
520
521 let mut match_topics = true;
522 for (i, filter_topic_alternatives) in filter.topics.iter().enumerate() {
523 if filter_topic_alternatives.is_empty() {
524 continue;
525 }
526
527 let log_topic = log.topics().get(i);
528 let mut current_topic_matched = false;
529 for filter_topic in filter_topic_alternatives.iter() {
530 if log_topic == Some(filter_topic) {
531 current_topic_matched = true;
532 break;
533 }
534 }
535 if !current_topic_matched {
536 match_topics = false;
537 break;
538 }
539 }
540
541 if match_topics {
542 matched_logs.push(log.clone());
543 }
544 }
545 matched_logs
546}
547
548#[derive(Clone, Debug, Deserialize, Serialize)]
550pub struct Hypermap {
551 pub provider: Provider,
552 address: Address,
553}
554
555impl Hypermap {
556 pub fn new(provider: Provider, address: Address) -> Self {
562 Self { provider, address }
563 }
564
565 pub fn default(timeout: u64) -> Self {
567 let provider = Provider::new(HYPERMAP_CHAIN_ID, timeout);
568 Self::new(provider, Address::from_str(HYPERMAP_ADDRESS).unwrap())
569 }
570
571 pub fn address(&self) -> &Address {
573 &self.address
574 }
575
576 pub fn get(&self, path: &str) -> Result<(Address, Address, Option<Bytes>), EthError> {
584 let get_call = getCall {
585 namehash: FixedBytes::<32>::from_str(&namehash(path))
586 .map_err(|_| EthError::InvalidParams)?,
587 }
588 .abi_encode();
589
590 let tx_req = TransactionRequest::default()
591 .input(TransactionInput::new(get_call.into()))
592 .to(self.address);
593
594 let res_bytes = self.provider.call(tx_req, None)?;
595
596 let res = getCall::abi_decode_returns(&res_bytes, false)
597 .map_err(|_| EthError::RpcMalformedResponse)?;
598
599 let note_data = if res.data == Bytes::default() {
600 None
601 } else {
602 Some(res.data)
603 };
604
605 Ok((res.tba, res.owner, note_data))
606 }
607
608 pub fn get_hash(&self, entryhash: &str) -> Result<(Address, Address, Option<Bytes>), EthError> {
616 let get_call = getCall {
617 namehash: FixedBytes::<32>::from_str(entryhash).map_err(|_| EthError::InvalidParams)?,
618 }
619 .abi_encode();
620
621 let tx_req = TransactionRequest::default()
622 .input(TransactionInput::new(get_call.into()))
623 .to(self.address);
624
625 let res_bytes = self.provider.call(tx_req, None)?;
626
627 let res = getCall::abi_decode_returns(&res_bytes, false)
628 .map_err(|_| EthError::RpcMalformedResponse)?;
629
630 let note_data = if res.data == Bytes::default() {
631 None
632 } else {
633 Some(res.data)
634 };
635
636 Ok((res.tba, res.owner, note_data))
637 }
638
639 pub fn get_namehash_from_tba(&self, tba: Address) -> Result<String, EthError> {
646 let token_call = tokenCall {}.abi_encode();
647
648 let tx_req = TransactionRequest::default()
649 .input(TransactionInput::new(token_call.into()))
650 .to(tba);
651
652 let res_bytes = self.provider.call(tx_req, None)?;
653
654 let res = tokenCall::abi_decode_returns(&res_bytes, false)
655 .map_err(|_| EthError::RpcMalformedResponse)?;
656
657 let namehash: FixedBytes<32> = res.tokenId.into();
658 Ok(format!("0x{}", hex::encode(namehash)))
659 }
660
661 pub fn mint_filter(&self) -> crate::eth::Filter {
663 crate::eth::Filter::new()
664 .address(self.address)
665 .event(contract::Mint::SIGNATURE)
666 }
667
668 pub fn note_filter(&self) -> crate::eth::Filter {
670 crate::eth::Filter::new()
671 .address(self.address)
672 .event(contract::Note::SIGNATURE)
673 }
674
675 pub fn fact_filter(&self) -> crate::eth::Filter {
677 crate::eth::Filter::new()
678 .address(self.address)
679 .event(contract::Fact::SIGNATURE)
680 }
681
682 pub fn notes_filter(&self, notes: &[&str]) -> crate::eth::Filter {
690 self.note_filter().topic3(
691 notes
692 .into_iter()
693 .map(|note| keccak256(note))
694 .collect::<Vec<_>>(),
695 )
696 }
697
698 pub fn facts_filter(&self, facts: &[&str]) -> crate::eth::Filter {
706 self.fact_filter().topic3(
707 facts
708 .into_iter()
709 .map(|fact| keccak256(fact))
710 .collect::<Vec<_>>(),
711 )
712 }
713
714 fn get_bootstrap_log_cache_inner(
715 &self,
716 cacher_request: &CacherRequest,
717 cacher_process_address: &HyperAddress,
718 attempt: u64,
719 request_from_block_val: u64,
720 retry_delay_s: u64,
721 retry_count: Option<u64>,
722 chain: &Option<String>,
723 ) -> anyhow::Result<Option<(u64, Vec<LogCache>)>> {
724 let retry_count_str = retry_count
725 .map(|r| r.to_string())
726 .unwrap_or_else(|| "inf".to_string());
727 print_to_terminal(
728 2,
729 &format!("Attempt {attempt}/{retry_count_str} to query local hypermap-cacher"),
730 );
731
732 let response_msg = match Request::to(cacher_process_address.clone())
733 .body(serde_json::to_vec(cacher_request)?)
734 .send_and_await_response(CACHER_REQUEST_TIMEOUT_S)
735 {
736 Ok(Ok(msg)) => msg,
737 Ok(Err(e)) => {
738 print_to_terminal(
739 1,
740 &format!(
741 "Error response from local cacher (attempt {}): {:?}",
742 attempt, e
743 ),
744 );
745 if retry_count.is_none() || attempt < retry_count.unwrap() {
746 std::thread::sleep(std::time::Duration::from_secs(retry_delay_s));
747 return Ok(None);
748 } else {
749 return Err(anyhow::anyhow!(
750 "Error response from local cacher after {retry_count_str} attempts: {e:?}"
751 ));
752 }
753 }
754 Err(e) => {
755 print_to_terminal(
756 1,
757 &format!(
758 "Failed to send request to local cacher (attempt {}): {:?}",
759 attempt, e
760 ),
761 );
762 if retry_count.is_none() || attempt < retry_count.unwrap() {
763 std::thread::sleep(std::time::Duration::from_secs(retry_delay_s));
764 return Ok(None);
765 } else {
766 return Err(anyhow::anyhow!(
767 "Failed to send request to local cacher after {retry_count_str} attempts: {e:?}"
768 ));
769 }
770 }
771 };
772
773 match serde_json::from_slice::<CacherResponse>(response_msg.body())? {
774 CacherResponse::GetLogsByRange(res) => {
775 match res {
776 Ok(GetLogsByRangeOkResponse::Latest(block)) => {
777 return Ok(Some((block, vec![])));
778 }
779 Ok(GetLogsByRangeOkResponse::Logs((block, json_string_of_vec_log_cache))) => {
780 if json_string_of_vec_log_cache.is_empty()
781 || json_string_of_vec_log_cache == "[]"
782 {
783 print_to_terminal(
784 2,
785 &format!(
786 "Local cacher returned no log caches for the range from block {}.",
787 request_from_block_val,
788 ),
789 );
790 return Ok(Some((block, vec![])));
791 }
792 match serde_json::from_str::<Vec<LogCache>>(&json_string_of_vec_log_cache) {
793 Ok(retrieved_caches) => {
794 let target_chain_id = chain
795 .clone()
796 .unwrap_or_else(|| self.provider.get_chain_id().to_string());
797 let mut filtered_caches = vec![];
798
799 for log_cache in retrieved_caches {
800 if log_cache.metadata.chain_id == target_chain_id {
801 let cache_from = log_cache
804 .metadata
805 .from_block
806 .parse::<u64>()
807 .unwrap_or(u64::MAX);
808 let cache_to =
809 log_cache.metadata.to_block.parse::<u64>().unwrap_or(0);
810
811 if cache_to >= request_from_block_val {
812 filtered_caches.push(log_cache);
814 } else {
815 print_to_terminal(3, &format!("Cache from local cacher ({} to {}) does not meet request_from_block {}",
816 cache_from, cache_to, request_from_block_val));
817 }
818 } else {
819 print_to_terminal(1,&format!("LogCache from local cacher has mismatched chain_id (expected {}, got {}). Skipping.",
820 target_chain_id, log_cache.metadata.chain_id));
821 }
822 }
823
824 print_to_terminal(
825 2,
826 &format!(
827 "Retrieved {} log caches from local hypermap-cacher.",
828 filtered_caches.len(),
829 ),
830 );
831 return Ok(Some((block, filtered_caches)));
832 }
833 Err(e) => {
834 return Err(anyhow::anyhow!(
835 "Failed to deserialize Vec<LogCache> from local cacher: {:?}. JSON: {:.100}",
836 e, json_string_of_vec_log_cache
837 ));
838 }
839 }
840 }
841 Err(e_str) => {
842 return Err(anyhow::anyhow!(
843 "Local cacher reported error for GetLogsByRange: {}",
844 e_str,
845 ));
846 }
847 }
848 }
849 CacherResponse::IsStarting => {
850 print_to_terminal(
851 2,
852 &format!(
853 "Local hypermap-cacher is still starting (attempt {}/{}). Retrying in {}s...",
854 attempt, retry_count_str, retry_delay_s
855 ),
856 );
857 if retry_count.is_none() || attempt < retry_count.unwrap() {
858 std::thread::sleep(std::time::Duration::from_secs(retry_delay_s));
859 return Ok(None);
860 } else {
861 return Err(anyhow::anyhow!(
862 "Local hypermap-cacher is still starting after {retry_count_str} attempts"
863 ));
864 }
865 }
866 CacherResponse::Rejected => {
867 return Err(anyhow::anyhow!(
868 "Local hypermap-cacher rejected our request"
869 ));
870 }
871 _ => {
872 return Err(anyhow::anyhow!(
873 "Unexpected response type from local hypermap-cacher"
874 ));
875 }
876 }
877 }
878
879 pub fn get_bootstrap_log_cache(
880 &self,
881 from_block: Option<u64>,
882 retry_params: Option<(u64, Option<u64>)>,
883 chain: Option<String>,
884 ) -> anyhow::Result<(u64, Vec<LogCache>)> {
885 print_to_terminal(2,
886 &format!("get_bootstrap_log_cache (using local hypermap-cacher): from_block={:?}, retry_params={:?}, chain={:?}",
887 from_block, retry_params, chain)
888 );
889
890 let (retry_delay_s, retry_count) = retry_params.ok_or_else(|| {
891 anyhow::anyhow!("IsStarted check requires retry parameters (delay_s, max_tries)")
892 })?;
893
894 let cacher_process_address =
895 HyperAddress::new("our", ("hypermap-cacher", "hypermap-cacher", "sys"));
896
897 print_to_terminal(
898 2,
899 &format!(
900 "Querying local cacher with GetLogsByRange: {}",
901 cacher_process_address.to_string(),
902 ),
903 );
904
905 let request_from_block_val = from_block.unwrap_or(0);
906
907 let get_logs_by_range_payload = GetLogsByRangeRequest {
908 from_block: request_from_block_val,
909 to_block: None, };
911 let cacher_request = CacherRequest::GetLogsByRange(get_logs_by_range_payload);
912
913 if let Some(retry_count) = retry_count {
914 for attempt in 1..=retry_count {
915 if let Some(return_vals) = self.get_bootstrap_log_cache_inner(
916 &cacher_request,
917 &cacher_process_address,
918 attempt,
919 request_from_block_val,
920 retry_delay_s,
921 Some(retry_count),
922 &chain,
923 )? {
924 return Ok(return_vals);
925 }
926 }
927 } else {
928 let mut attempt = 1;
929 loop {
930 if let Some(return_vals) = self.get_bootstrap_log_cache_inner(
931 &cacher_request,
932 &cacher_process_address,
933 attempt,
934 request_from_block_val,
935 retry_delay_s,
936 None,
937 &chain,
938 )? {
939 return Ok(return_vals);
940 }
941 attempt += 1;
942 }
943 }
944
945 Err(anyhow::anyhow!(
946 "Failed to get response from local hypermap-cacher after {retry_count:?} attempts"
947 ))
948 }
949
950 pub fn validate_log_cache(&self, log_cache: &LogCache) -> anyhow::Result<bool> {
951 let from_block = log_cache.metadata.from_block.parse::<u64>().map_err(|_| {
952 anyhow::anyhow!(
953 "Invalid from_block in metadata: {}",
954 log_cache.metadata.from_block
955 )
956 })?;
957 let to_block = log_cache.metadata.to_block.parse::<u64>().map_err(|_| {
958 anyhow::anyhow!(
959 "Invalid to_block in metadata: {}",
960 log_cache.metadata.to_block
961 )
962 })?;
963
964 let mut bytes_to_verify = serde_json::to_vec(&log_cache.logs)
965 .map_err(|e| anyhow::anyhow!("Failed to serialize logs for validation: {:?}", e))?;
966 bytes_to_verify.extend_from_slice(&from_block.to_be_bytes());
967 bytes_to_verify.extend_from_slice(&to_block.to_be_bytes());
968 let hashed_data = keccak256(&bytes_to_verify);
969
970 let signature_hex = log_cache.metadata.signature.trim_start_matches("0x");
971 let signature_bytes = hex::decode(signature_hex)
972 .map_err(|e| anyhow::anyhow!("Failed to decode hex signature: {:?}", e))?;
973
974 Ok(sign::net_key_verify(
975 hashed_data.to_vec(),
976 &log_cache.metadata.created_by.parse::<HyperAddress>()?,
977 signature_bytes,
978 )?)
979 }
980
981 pub fn get_bootstrap(
982 &self,
983 from_block: Option<u64>,
984 retry_params: Option<(u64, Option<u64>)>,
985 chain: Option<String>,
986 ) -> anyhow::Result<(u64, Vec<EthLog>)> {
987 print_to_terminal(
988 2,
989 &format!(
990 "get_bootstrap: from_block={:?}, retry_params={:?}, chain={:?}",
991 from_block, retry_params, chain,
992 ),
993 );
994 let (block, log_caches) = self.get_bootstrap_log_cache(from_block, retry_params, chain)?;
995
996 let mut all_valid_logs: Vec<EthLog> = Vec::new();
997 let request_from_block_val = from_block.unwrap_or(0);
998
999 for log_cache in log_caches {
1000 match self.validate_log_cache(&log_cache) {
1001 Ok(true) => {
1002 for log in log_cache.logs {
1003 if let Some(log_block_number) = log.block_number {
1004 if log_block_number >= request_from_block_val {
1005 all_valid_logs.push(log);
1006 }
1007 } else {
1008 if from_block.is_none() {
1009 all_valid_logs.push(log);
1010 }
1011 }
1012 }
1013 }
1014 Ok(false) => {
1015 print_to_terminal(
1016 1,
1017 &format!("LogCache validation failed for cache created by {}. Discarding {} logs.",
1018 log_cache.metadata.created_by,
1019 log_cache.logs.len())
1020 );
1021 }
1022 Err(e) => {
1023 print_to_terminal(
1024 1,
1025 &format!(
1026 "Error validating LogCache from {}: {:?}. Discarding.",
1027 log_cache.metadata.created_by, e,
1028 ),
1029 );
1030 }
1031 }
1032 }
1033
1034 all_valid_logs.sort_by(|a, b| {
1035 let block_cmp = a.block_number.cmp(&b.block_number);
1036 if block_cmp == std::cmp::Ordering::Equal {
1037 std::cmp::Ordering::Equal
1038 } else {
1039 block_cmp
1040 }
1041 });
1042
1043 let mut unique_logs = Vec::new();
1044 for log in all_valid_logs {
1045 if !unique_logs.contains(&log) {
1046 unique_logs.push(log);
1047 }
1048 }
1049
1050 print_to_terminal(
1051 2,
1052 &format!(
1053 "get_bootstrap: Consolidated {} unique logs.",
1054 unique_logs.len(),
1055 ),
1056 );
1057 Ok((block, unique_logs))
1058 }
1059
1060 pub fn bootstrap(
1061 &self,
1062 from_block: Option<u64>,
1063 filters: Vec<EthFilter>,
1064 retry_params: Option<(u64, Option<u64>)>,
1065 chain: Option<String>,
1066 ) -> anyhow::Result<(u64, Vec<Vec<EthLog>>)> {
1067 print_to_terminal(
1068 2,
1069 &format!(
1070 "bootstrap: from_block={:?}, num_filters={}, retry_params={:?}, chain={:?}",
1071 from_block,
1072 filters.len(),
1073 retry_params,
1074 chain,
1075 ),
1076 );
1077
1078 let (block, consolidated_logs) = self.get_bootstrap(from_block, retry_params, chain)?;
1079
1080 if consolidated_logs.is_empty() {
1081 print_to_terminal(2,"bootstrap: No logs retrieved after consolidation. Returning empty results for filters.");
1082 return Ok((block, filters.iter().map(|_| Vec::new()).collect()));
1083 }
1084
1085 let mut results_per_filter: Vec<Vec<EthLog>> = Vec::new();
1086 for filter in filters {
1087 let filtered_logs = eth_apply_filter(&consolidated_logs, &filter);
1088 results_per_filter.push(filtered_logs);
1089 }
1090
1091 print_to_terminal(
1092 2,
1093 &format!(
1094 "bootstrap: Applied {} filters to bootstrapped logs.",
1095 results_per_filter.len(),
1096 ),
1097 );
1098 Ok((block, results_per_filter))
1099 }
1100}
1101
1102impl Serialize for ManifestItem {
1103 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1104 where
1105 S: Serializer,
1106 {
1107 let mut state = serializer.serialize_struct("ManifestItem", 4)?;
1108 state.serialize_field("metadata", &self.metadata)?;
1109 state.serialize_field("is_empty", &self.is_empty)?;
1110 state.serialize_field("file_hash", &self.file_hash)?;
1111 state.serialize_field("file_name", &self.file_name)?;
1112 state.end()
1113 }
1114}
1115
1116impl<'de> Deserialize<'de> for ManifestItem {
1117 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1118 where
1119 D: Deserializer<'de>,
1120 {
1121 #[derive(Deserialize)]
1122 #[serde(field_identifier, rename_all = "snake_case")]
1123 enum Field {
1124 Metadata,
1125 IsEmpty,
1126 FileHash,
1127 FileName,
1128 }
1129
1130 struct ManifestItemVisitor;
1131
1132 impl<'de> Visitor<'de> for ManifestItemVisitor {
1133 type Value = ManifestItem;
1134
1135 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1136 formatter.write_str("struct ManifestItem")
1137 }
1138
1139 fn visit_map<V>(self, mut map: V) -> Result<ManifestItem, V::Error>
1140 where
1141 V: MapAccess<'de>,
1142 {
1143 let mut metadata = None;
1144 let mut is_empty = None;
1145 let mut file_hash = None;
1146 let mut file_name = None;
1147
1148 while let Some(key) = map.next_key()? {
1149 match key {
1150 Field::Metadata => {
1151 if metadata.is_some() {
1152 return Err(de::Error::duplicate_field("metadata"));
1153 }
1154 metadata = Some(map.next_value()?);
1155 }
1156 Field::IsEmpty => {
1157 if is_empty.is_some() {
1158 return Err(de::Error::duplicate_field("is_empty"));
1159 }
1160 is_empty = Some(map.next_value()?);
1161 }
1162 Field::FileHash => {
1163 if file_hash.is_some() {
1164 return Err(de::Error::duplicate_field("file_hash"));
1165 }
1166 file_hash = Some(map.next_value()?);
1167 }
1168 Field::FileName => {
1169 if file_name.is_some() {
1170 return Err(de::Error::duplicate_field("file_name"));
1171 }
1172 file_name = Some(map.next_value()?);
1173 }
1174 }
1175 }
1176
1177 let metadata = metadata.ok_or_else(|| de::Error::missing_field("metadata"))?;
1178 let is_empty = is_empty.ok_or_else(|| de::Error::missing_field("is_empty"))?;
1179 let file_hash = file_hash.ok_or_else(|| de::Error::missing_field("file_hash"))?;
1180 let file_name = file_name.ok_or_else(|| de::Error::missing_field("file_name"))?;
1181
1182 Ok(ManifestItem {
1183 metadata,
1184 is_empty,
1185 file_hash,
1186 file_name,
1187 })
1188 }
1189 }
1190
1191 deserializer.deserialize_struct(
1192 "ManifestItem",
1193 &["metadata", "is_empty", "file_hash", "file_name"],
1194 ManifestItemVisitor,
1195 )
1196 }
1197}
1198
1199impl Serialize for Manifest {
1200 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1201 where
1202 S: Serializer,
1203 {
1204 let mut state = serializer.serialize_struct("Manifest", 4)?;
1205 state.serialize_field("items", &self.items)?;
1206 state.serialize_field("manifest_filename", &self.manifest_filename)?;
1207 state.serialize_field("chain_id", &self.chain_id)?;
1208 state.serialize_field("protocol_version", &self.protocol_version)?;
1209 state.end()
1210 }
1211}
1212
1213impl<'de> Deserialize<'de> for Manifest {
1214 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1215 where
1216 D: Deserializer<'de>,
1217 {
1218 #[derive(Deserialize)]
1219 #[serde(field_identifier, rename_all = "snake_case")]
1220 enum Field {
1221 Items,
1222 ManifestFilename,
1223 ChainId,
1224 ProtocolVersion,
1225 }
1226
1227 struct ManifestVisitor;
1228
1229 impl<'de> Visitor<'de> for ManifestVisitor {
1230 type Value = Manifest;
1231
1232 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1233 formatter.write_str("struct Manifest")
1234 }
1235
1236 fn visit_map<V>(self, mut map: V) -> Result<Manifest, V::Error>
1237 where
1238 V: MapAccess<'de>,
1239 {
1240 let mut items = None;
1241 let mut manifest_filename = None;
1242 let mut chain_id = None;
1243 let mut protocol_version = None;
1244
1245 while let Some(key) = map.next_key()? {
1246 match key {
1247 Field::Items => {
1248 if items.is_some() {
1249 return Err(de::Error::duplicate_field("items"));
1250 }
1251 items = Some(map.next_value()?);
1252 }
1253 Field::ManifestFilename => {
1254 if manifest_filename.is_some() {
1255 return Err(de::Error::duplicate_field("manifest_filename"));
1256 }
1257 manifest_filename = Some(map.next_value()?);
1258 }
1259 Field::ChainId => {
1260 if chain_id.is_some() {
1261 return Err(de::Error::duplicate_field("chain_id"));
1262 }
1263 chain_id = Some(map.next_value()?);
1264 }
1265 Field::ProtocolVersion => {
1266 if protocol_version.is_some() {
1267 return Err(de::Error::duplicate_field("protocol_version"));
1268 }
1269 protocol_version = Some(map.next_value()?);
1270 }
1271 }
1272 }
1273
1274 let items = items.ok_or_else(|| de::Error::missing_field("items"))?;
1275 let manifest_filename = manifest_filename
1276 .ok_or_else(|| de::Error::missing_field("manifest_filename"))?;
1277 let chain_id = chain_id.ok_or_else(|| de::Error::missing_field("chain_id"))?;
1278 let protocol_version =
1279 protocol_version.ok_or_else(|| de::Error::missing_field("protocol_version"))?;
1280
1281 Ok(Manifest {
1282 items,
1283 manifest_filename,
1284 chain_id,
1285 protocol_version,
1286 })
1287 }
1288 }
1289
1290 deserializer.deserialize_struct(
1291 "Manifest",
1292 &["items", "manifest_filename", "chain_id", "protocol_version"],
1293 ManifestVisitor,
1294 )
1295 }
1296}
1297
1298impl Serialize for GetLogsByRangeRequest {
1299 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1300 where
1301 S: Serializer,
1302 {
1303 let mut state = serializer.serialize_struct("GetLogsByRangeRequest", 2)?;
1304 state.serialize_field("from_block", &self.from_block)?;
1305 state.serialize_field("to_block", &self.to_block)?;
1306 state.end()
1307 }
1308}
1309
1310impl<'de> Deserialize<'de> for GetLogsByRangeRequest {
1311 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1312 where
1313 D: Deserializer<'de>,
1314 {
1315 #[derive(Deserialize)]
1316 #[serde(field_identifier, rename_all = "snake_case")]
1317 enum Field {
1318 FromBlock,
1319 ToBlock,
1320 }
1321
1322 struct GetLogsByRangeRequestVisitor;
1323
1324 impl<'de> Visitor<'de> for GetLogsByRangeRequestVisitor {
1325 type Value = GetLogsByRangeRequest;
1326
1327 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1328 formatter.write_str("struct GetLogsByRangeRequest")
1329 }
1330
1331 fn visit_map<V>(self, mut map: V) -> Result<GetLogsByRangeRequest, V::Error>
1332 where
1333 V: MapAccess<'de>,
1334 {
1335 let mut from_block = None;
1336 let mut to_block = None;
1337
1338 while let Some(key) = map.next_key()? {
1339 match key {
1340 Field::FromBlock => {
1341 if from_block.is_some() {
1342 return Err(de::Error::duplicate_field("from_block"));
1343 }
1344 from_block = Some(map.next_value()?);
1345 }
1346 Field::ToBlock => {
1347 if to_block.is_some() {
1348 return Err(de::Error::duplicate_field("to_block"));
1349 }
1350 to_block = Some(map.next_value()?);
1351 }
1352 }
1353 }
1354
1355 let from_block =
1356 from_block.ok_or_else(|| de::Error::missing_field("from_block"))?;
1357
1358 Ok(GetLogsByRangeRequest {
1359 from_block,
1360 to_block,
1361 })
1362 }
1363 }
1364
1365 deserializer.deserialize_struct(
1366 "GetLogsByRangeRequest",
1367 &["from_block", "to_block"],
1368 GetLogsByRangeRequestVisitor,
1369 )
1370 }
1371}
1372
1373impl Serialize for CacherStatus {
1374 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1375 where
1376 S: Serializer,
1377 {
1378 let mut state = serializer.serialize_struct("CacherStatus", 8)?;
1379 state.serialize_field("last_cached_block", &self.last_cached_block)?;
1380 state.serialize_field("chain_id", &self.chain_id)?;
1381 state.serialize_field("protocol_version", &self.protocol_version)?;
1382 state.serialize_field(
1383 "next_cache_attempt_in_seconds",
1384 &self.next_cache_attempt_in_seconds,
1385 )?;
1386 state.serialize_field("manifest_filename", &self.manifest_filename)?;
1387 state.serialize_field("log_files_count", &self.log_files_count)?;
1388 state.serialize_field("our_address", &self.our_address)?;
1389 state.serialize_field("is_providing", &self.is_providing)?;
1390 state.end()
1391 }
1392}
1393
1394impl<'de> Deserialize<'de> for CacherStatus {
1395 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1396 where
1397 D: Deserializer<'de>,
1398 {
1399 #[derive(Deserialize)]
1400 #[serde(field_identifier, rename_all = "snake_case")]
1401 enum Field {
1402 LastCachedBlock,
1403 ChainId,
1404 ProtocolVersion,
1405 NextCacheAttemptInSeconds,
1406 ManifestFilename,
1407 LogFilesCount,
1408 OurAddress,
1409 IsProviding,
1410 }
1411
1412 struct CacherStatusVisitor;
1413
1414 impl<'de> Visitor<'de> for CacherStatusVisitor {
1415 type Value = CacherStatus;
1416
1417 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1418 formatter.write_str("struct CacherStatus")
1419 }
1420
1421 fn visit_map<V>(self, mut map: V) -> Result<CacherStatus, V::Error>
1422 where
1423 V: MapAccess<'de>,
1424 {
1425 let mut last_cached_block = None;
1426 let mut chain_id = None;
1427 let mut protocol_version = None;
1428 let mut next_cache_attempt_in_seconds = None;
1429 let mut manifest_filename = None;
1430 let mut log_files_count = None;
1431 let mut our_address = None;
1432 let mut is_providing = None;
1433
1434 while let Some(key) = map.next_key()? {
1435 match key {
1436 Field::LastCachedBlock => {
1437 if last_cached_block.is_some() {
1438 return Err(de::Error::duplicate_field("last_cached_block"));
1439 }
1440 last_cached_block = Some(map.next_value()?);
1441 }
1442 Field::ChainId => {
1443 if chain_id.is_some() {
1444 return Err(de::Error::duplicate_field("chain_id"));
1445 }
1446 chain_id = Some(map.next_value()?);
1447 }
1448 Field::ProtocolVersion => {
1449 if protocol_version.is_some() {
1450 return Err(de::Error::duplicate_field("protocol_version"));
1451 }
1452 protocol_version = Some(map.next_value()?);
1453 }
1454 Field::NextCacheAttemptInSeconds => {
1455 if next_cache_attempt_in_seconds.is_some() {
1456 return Err(de::Error::duplicate_field(
1457 "next_cache_attempt_in_seconds",
1458 ));
1459 }
1460 next_cache_attempt_in_seconds = Some(map.next_value()?);
1461 }
1462 Field::ManifestFilename => {
1463 if manifest_filename.is_some() {
1464 return Err(de::Error::duplicate_field("manifest_filename"));
1465 }
1466 manifest_filename = Some(map.next_value()?);
1467 }
1468 Field::LogFilesCount => {
1469 if log_files_count.is_some() {
1470 return Err(de::Error::duplicate_field("log_files_count"));
1471 }
1472 log_files_count = Some(map.next_value()?);
1473 }
1474 Field::OurAddress => {
1475 if our_address.is_some() {
1476 return Err(de::Error::duplicate_field("our_address"));
1477 }
1478 our_address = Some(map.next_value()?);
1479 }
1480 Field::IsProviding => {
1481 if is_providing.is_some() {
1482 return Err(de::Error::duplicate_field("is_providing"));
1483 }
1484 is_providing = Some(map.next_value()?);
1485 }
1486 }
1487 }
1488
1489 let last_cached_block = last_cached_block
1490 .ok_or_else(|| de::Error::missing_field("last_cached_block"))?;
1491 let chain_id = chain_id.ok_or_else(|| de::Error::missing_field("chain_id"))?;
1492 let protocol_version =
1493 protocol_version.ok_or_else(|| de::Error::missing_field("protocol_version"))?;
1494 let manifest_filename = manifest_filename
1495 .ok_or_else(|| de::Error::missing_field("manifest_filename"))?;
1496 let log_files_count =
1497 log_files_count.ok_or_else(|| de::Error::missing_field("log_files_count"))?;
1498 let our_address =
1499 our_address.ok_or_else(|| de::Error::missing_field("our_address"))?;
1500 let is_providing =
1501 is_providing.ok_or_else(|| de::Error::missing_field("is_providing"))?;
1502
1503 Ok(CacherStatus {
1504 last_cached_block,
1505 chain_id,
1506 protocol_version,
1507 next_cache_attempt_in_seconds,
1508 manifest_filename,
1509 log_files_count,
1510 our_address,
1511 is_providing,
1512 })
1513 }
1514 }
1515
1516 deserializer.deserialize_struct(
1517 "CacherStatus",
1518 &[
1519 "last_cached_block",
1520 "chain_id",
1521 "protocol_version",
1522 "next_cache_attempt_in_seconds",
1523 "manifest_filename",
1524 "log_files_count",
1525 "our_address",
1526 "is_providing",
1527 ],
1528 CacherStatusVisitor,
1529 )
1530 }
1531}
1532
1533impl Serialize for CacherRequest {
1534 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1535 where
1536 S: Serializer,
1537 {
1538 match self {
1539 CacherRequest::GetManifest => serializer.serialize_str("GetManifest"),
1540 CacherRequest::GetLogCacheContent(path) => {
1541 let mut map = serializer.serialize_map(Some(1))?;
1542 map.serialize_entry("GetLogCacheContent", path)?;
1543 map.end()
1544 }
1545 CacherRequest::GetStatus => serializer.serialize_str("GetStatus"),
1546 CacherRequest::GetLogsByRange(request) => {
1547 let mut map = serializer.serialize_map(Some(1))?;
1548 map.serialize_entry("GetLogsByRange", request)?;
1549 map.end()
1550 }
1551 CacherRequest::StartProviding => serializer.serialize_str("StartProviding"),
1552 CacherRequest::StopProviding => serializer.serialize_str("StopProviding"),
1553 CacherRequest::SetNodes(nodes) => {
1554 let mut map = serializer.serialize_map(Some(1))?;
1555 map.serialize_entry("SetNodes", nodes)?;
1556 map.end()
1557 }
1558 CacherRequest::Reset(nodes) => {
1559 let mut map = serializer.serialize_map(Some(1))?;
1560 map.serialize_entry("Reset", nodes)?;
1561 map.end()
1562 }
1563 }
1564 }
1565}
1566
1567impl<'de> Deserialize<'de> for CacherRequest {
1568 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1569 where
1570 D: Deserializer<'de>,
1571 {
1572 struct CacherRequestVisitor;
1573
1574 impl<'de> Visitor<'de> for CacherRequestVisitor {
1575 type Value = CacherRequest;
1576
1577 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1578 formatter.write_str("a string for unit variants or a map for other variants")
1579 }
1580
1581 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1582 where
1583 E: de::Error,
1584 {
1585 match value {
1586 "GetManifest" => Ok(CacherRequest::GetManifest),
1587 "GetStatus" => Ok(CacherRequest::GetStatus),
1588 "StartProviding" => Ok(CacherRequest::StartProviding),
1589 "StopProviding" => Ok(CacherRequest::StopProviding),
1590 _ => Err(de::Error::unknown_variant(
1591 value,
1592 &[
1593 "GetManifest",
1594 "GetLogCacheContent",
1595 "GetStatus",
1596 "GetLogsByRange",
1597 "StartProviding",
1598 "StopProviding",
1599 "SetNodes",
1600 "Reset",
1601 ],
1602 )),
1603 }
1604 }
1605
1606 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1607 where
1608 A: MapAccess<'de>,
1609 {
1610 let (variant, value) = map
1611 .next_entry::<String, serde_json::Value>()?
1612 .ok_or_else(|| de::Error::invalid_length(0, &self))?;
1613
1614 if map.next_entry::<String, serde_json::Value>()?.is_some() {
1616 return Err(de::Error::custom("unexpected extra entries in map"));
1617 }
1618
1619 match variant.as_str() {
1620 "GetLogCacheContent" => {
1621 let path = serde_json::from_value(value).map_err(de::Error::custom)?;
1622 Ok(CacherRequest::GetLogCacheContent(path))
1623 }
1624 "GetLogsByRange" => {
1625 let request = serde_json::from_value(value).map_err(de::Error::custom)?;
1626 Ok(CacherRequest::GetLogsByRange(request))
1627 }
1628 "SetNodes" => {
1629 let nodes = serde_json::from_value(value).map_err(de::Error::custom)?;
1630 Ok(CacherRequest::SetNodes(nodes))
1631 }
1632 "Reset" => {
1633 let nodes = serde_json::from_value(value).map_err(de::Error::custom)?;
1634 Ok(CacherRequest::Reset(nodes))
1635 }
1636 _ => Err(de::Error::unknown_variant(
1637 &variant,
1638 &[
1639 "GetManifest",
1640 "GetLogCacheContent",
1641 "GetStatus",
1642 "GetLogsByRange",
1643 "StartProviding",
1644 "StopProviding",
1645 "SetNodes",
1646 "Reset",
1647 ],
1648 )),
1649 }
1650 }
1651 }
1652
1653 deserializer.deserialize_any(CacherRequestVisitor)
1654 }
1655}
1656
1657impl Serialize for CacherResponse {
1658 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1659 where
1660 S: Serializer,
1661 {
1662 match self {
1663 CacherResponse::GetManifest(manifest) => {
1664 let mut map = serializer.serialize_map(Some(1))?;
1665 map.serialize_entry("GetManifest", manifest)?;
1666 map.end()
1667 }
1668 CacherResponse::GetLogCacheContent(result) => {
1669 let mut map = serializer.serialize_map(Some(1))?;
1670 map.serialize_entry("GetLogCacheContent", result)?;
1671 map.end()
1672 }
1673 CacherResponse::GetStatus(status) => {
1674 let mut map = serializer.serialize_map(Some(1))?;
1675 map.serialize_entry("GetStatus", status)?;
1676 map.end()
1677 }
1678 CacherResponse::GetLogsByRange(result) => {
1679 let mut map = serializer.serialize_map(Some(1))?;
1680 map.serialize_entry("GetLogsByRange", result)?;
1681 map.end()
1682 }
1683 CacherResponse::StartProviding(result) => {
1684 let mut map = serializer.serialize_map(Some(1))?;
1685 map.serialize_entry("StartProviding", result)?;
1686 map.end()
1687 }
1688 CacherResponse::StopProviding(result) => {
1689 let mut map = serializer.serialize_map(Some(1))?;
1690 map.serialize_entry("StopProviding", result)?;
1691 map.end()
1692 }
1693 CacherResponse::Rejected => serializer.serialize_str("Rejected"),
1694 CacherResponse::IsStarting => serializer.serialize_str("IsStarting"),
1695 CacherResponse::SetNodes(result) => {
1696 let mut map = serializer.serialize_map(Some(1))?;
1697 map.serialize_entry("SetNodes", result)?;
1698 map.end()
1699 }
1700 CacherResponse::Reset(result) => {
1701 let mut map = serializer.serialize_map(Some(1))?;
1702 map.serialize_entry("Reset", result)?;
1703 map.end()
1704 }
1705 }
1706 }
1707}
1708
1709impl<'de> Deserialize<'de> for CacherResponse {
1710 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1711 where
1712 D: Deserializer<'de>,
1713 {
1714 struct CacherResponseVisitor;
1715
1716 impl<'de> Visitor<'de> for CacherResponseVisitor {
1717 type Value = CacherResponse;
1718
1719 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1720 formatter.write_str("a string for unit variants or a map for other variants")
1721 }
1722
1723 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1724 where
1725 E: de::Error,
1726 {
1727 match value {
1728 "Rejected" => Ok(CacherResponse::Rejected),
1729 "IsStarting" => Ok(CacherResponse::IsStarting),
1730 _ => Err(de::Error::unknown_variant(
1731 value,
1732 &[
1733 "GetManifest",
1734 "GetLogCacheContent",
1735 "GetStatus",
1736 "GetLogsByRange",
1737 "StartProviding",
1738 "StopProviding",
1739 "Rejected",
1740 "IsStarting",
1741 "SetNodes",
1742 "Reset",
1743 ],
1744 )),
1745 }
1746 }
1747
1748 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1749 where
1750 A: MapAccess<'de>,
1751 {
1752 let (variant, value) = map
1753 .next_entry::<String, serde_json::Value>()?
1754 .ok_or_else(|| de::Error::invalid_length(0, &self))?;
1755
1756 if map.next_entry::<String, serde_json::Value>()?.is_some() {
1758 return Err(de::Error::custom("unexpected extra entries in map"));
1759 }
1760
1761 match variant.as_str() {
1762 "GetManifest" => {
1763 let manifest = serde_json::from_value(value).map_err(de::Error::custom)?;
1764 Ok(CacherResponse::GetManifest(manifest))
1765 }
1766 "GetLogCacheContent" => {
1767 let result = serde_json::from_value(value).map_err(de::Error::custom)?;
1768 Ok(CacherResponse::GetLogCacheContent(result))
1769 }
1770 "GetStatus" => {
1771 let status = serde_json::from_value(value).map_err(de::Error::custom)?;
1772 Ok(CacherResponse::GetStatus(status))
1773 }
1774 "GetLogsByRange" => {
1775 let result = serde_json::from_value(value).map_err(de::Error::custom)?;
1776 Ok(CacherResponse::GetLogsByRange(result))
1777 }
1778 "StartProviding" => {
1779 let result = serde_json::from_value(value).map_err(de::Error::custom)?;
1780 Ok(CacherResponse::StartProviding(result))
1781 }
1782 "StopProviding" => {
1783 let result = serde_json::from_value(value).map_err(de::Error::custom)?;
1784 Ok(CacherResponse::StopProviding(result))
1785 }
1786 "SetNodes" => {
1787 let result = serde_json::from_value(value).map_err(de::Error::custom)?;
1788 Ok(CacherResponse::SetNodes(result))
1789 }
1790 "Reset" => {
1791 let result = serde_json::from_value(value).map_err(de::Error::custom)?;
1792 Ok(CacherResponse::Reset(result))
1793 }
1794 _ => Err(de::Error::unknown_variant(
1795 &variant,
1796 &[
1797 "GetManifest",
1798 "GetLogCacheContent",
1799 "GetStatus",
1800 "GetLogsByRange",
1801 "StartProviding",
1802 "StopProviding",
1803 "Rejected",
1804 "IsStarting",
1805 "SetNodes",
1806 "Reset",
1807 ],
1808 )),
1809 }
1810 }
1811 }
1812
1813 deserializer.deserialize_any(CacherResponseVisitor)
1814 }
1815}
1816
1817impl Serialize for LogsMetadata {
1818 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1819 where
1820 S: Serializer,
1821 {
1822 let mut state = serializer.serialize_struct("LogsMetadata", 6)?;
1823 state.serialize_field("chainId", &self.chain_id)?;
1824 state.serialize_field("fromBlock", &self.from_block)?;
1825 state.serialize_field("toBlock", &self.to_block)?;
1826 state.serialize_field("timeCreated", &self.time_created)?;
1827 state.serialize_field("createdBy", &self.created_by)?;
1828 state.serialize_field("signature", &self.signature)?;
1829 state.end()
1830 }
1831}
1832
1833impl<'de> Deserialize<'de> for LogsMetadata {
1834 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1835 where
1836 D: Deserializer<'de>,
1837 {
1838 #[derive(Deserialize)]
1839 #[serde(field_identifier, rename_all = "camelCase")]
1840 enum Field {
1841 ChainId,
1842 FromBlock,
1843 ToBlock,
1844 TimeCreated,
1845 CreatedBy,
1846 Signature,
1847 }
1848
1849 struct LogsMetadataVisitor;
1850
1851 impl<'de> Visitor<'de> for LogsMetadataVisitor {
1852 type Value = LogsMetadata;
1853
1854 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1855 formatter.write_str("struct LogsMetadata")
1856 }
1857
1858 fn visit_map<V>(self, mut map: V) -> Result<LogsMetadata, V::Error>
1859 where
1860 V: MapAccess<'de>,
1861 {
1862 let mut chain_id = None;
1863 let mut from_block = None;
1864 let mut to_block = None;
1865 let mut time_created = None;
1866 let mut created_by = None;
1867 let mut signature = None;
1868
1869 while let Some(key) = map.next_key()? {
1870 match key {
1871 Field::ChainId => {
1872 if chain_id.is_some() {
1873 return Err(de::Error::duplicate_field("chainId"));
1874 }
1875 chain_id = Some(map.next_value()?);
1876 }
1877 Field::FromBlock => {
1878 if from_block.is_some() {
1879 return Err(de::Error::duplicate_field("fromBlock"));
1880 }
1881 from_block = Some(map.next_value()?);
1882 }
1883 Field::ToBlock => {
1884 if to_block.is_some() {
1885 return Err(de::Error::duplicate_field("toBlock"));
1886 }
1887 to_block = Some(map.next_value()?);
1888 }
1889 Field::TimeCreated => {
1890 if time_created.is_some() {
1891 return Err(de::Error::duplicate_field("timeCreated"));
1892 }
1893 time_created = Some(map.next_value()?);
1894 }
1895 Field::CreatedBy => {
1896 if created_by.is_some() {
1897 return Err(de::Error::duplicate_field("createdBy"));
1898 }
1899 created_by = Some(map.next_value()?);
1900 }
1901 Field::Signature => {
1902 if signature.is_some() {
1903 return Err(de::Error::duplicate_field("signature"));
1904 }
1905 signature = Some(map.next_value()?);
1906 }
1907 }
1908 }
1909
1910 let chain_id = chain_id.ok_or_else(|| de::Error::missing_field("chainId"))?;
1911 let from_block = from_block.ok_or_else(|| de::Error::missing_field("fromBlock"))?;
1912 let to_block = to_block.ok_or_else(|| de::Error::missing_field("toBlock"))?;
1913 let time_created =
1914 time_created.ok_or_else(|| de::Error::missing_field("timeCreated"))?;
1915 let created_by = created_by.ok_or_else(|| de::Error::missing_field("createdBy"))?;
1916 let signature = signature.ok_or_else(|| de::Error::missing_field("signature"))?;
1917
1918 Ok(LogsMetadata {
1919 chain_id,
1920 from_block,
1921 to_block,
1922 time_created,
1923 created_by,
1924 signature,
1925 })
1926 }
1927 }
1928
1929 deserializer.deserialize_struct(
1930 "LogsMetadata",
1931 &[
1932 "chainId",
1933 "fromBlock",
1934 "toBlock",
1935 "timeCreated",
1936 "createdBy",
1937 "signature",
1938 ],
1939 LogsMetadataVisitor,
1940 )
1941 }
1942}
1943
1944impl Serialize for GetLogsByRangeOkResponse {
1945 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1946 where
1947 S: Serializer,
1948 {
1949 match self {
1950 GetLogsByRangeOkResponse::Logs(tuple) => {
1951 let mut map = serializer.serialize_map(Some(1))?;
1952 map.serialize_entry("Logs", tuple)?;
1953 map.end()
1954 }
1955 GetLogsByRangeOkResponse::Latest(block) => {
1956 let mut map = serializer.serialize_map(Some(1))?;
1957 map.serialize_entry("Latest", block)?;
1958 map.end()
1959 }
1960 }
1961 }
1962}
1963
1964impl<'de> Deserialize<'de> for GetLogsByRangeOkResponse {
1965 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1966 where
1967 D: Deserializer<'de>,
1968 {
1969 struct GetLogsByRangeOkResponseVisitor;
1970
1971 impl<'de> Visitor<'de> for GetLogsByRangeOkResponseVisitor {
1972 type Value = GetLogsByRangeOkResponse;
1973
1974 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1975 formatter.write_str(
1976 "a map with a single key representing the GetLogsByRangeOkResponse variant",
1977 )
1978 }
1979
1980 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1981 where
1982 A: MapAccess<'de>,
1983 {
1984 let (variant, value) = map
1985 .next_entry::<String, serde_json::Value>()?
1986 .ok_or_else(|| de::Error::invalid_length(0, &self))?;
1987
1988 match variant.as_str() {
1989 "Logs" => {
1990 let tuple = serde_json::from_value(value).map_err(de::Error::custom)?;
1991 Ok(GetLogsByRangeOkResponse::Logs(tuple))
1992 }
1993 "Latest" => {
1994 let block = serde_json::from_value(value).map_err(de::Error::custom)?;
1995 Ok(GetLogsByRangeOkResponse::Latest(block))
1996 }
1997 _ => Err(de::Error::unknown_variant(&variant, &["Logs", "Latest"])),
1998 }
1999 }
2000 }
2001
2002 deserializer.deserialize_map(GetLogsByRangeOkResponseVisitor)
2003 }
2004}