1#![allow(unused_imports)]
2#![allow(dead_code)]
3use anyhow::{Context, Result};
4use backtrace::Backtrace;
5use itertools::Itertools;
6use prost::{DecodeError, Message};
7use serde::Serialize;
8use std::fmt::Display;
9use std::future::Future;
10use std::str::FromStr;
11use std::sync::atomic::{AtomicBool, Ordering};
12
13use crate::structs::{AboutNodeRequest, BytesDecoder, ContentionKey, NetworkEnvironment, NodeMetadata, PeerId, PeerMetadata, PublicKey, PublicRequest, PublicResponse, SignatureType, StateSelector};
14use crate::message::{Request, Response};
15use crate::util::task_local::task_local_impl::task_local_error_details;
16use observability::errors::EnhanceErrorInfo;
17use proto_serde::{ProtoHashable, ProtoSerde};
18use structs::{
19 Address, BytesData, ErrorCode, ErrorInfo, Hash, HashFormatType, ResponseMetadata,
20 StructMetadata, Transaction,
21};
22use util::{lang_util, times};
23
24pub mod structs {
25 include!(concat!(env!("OUT_DIR"), "/structs.rs"));
26}
27
28pub mod execution {
29 include!(concat!(env!("OUT_DIR"), "/execution.rs"));
30}
31
32pub mod airgap {
33 include!(concat!(env!("OUT_DIR"), "/airgap.rs"));
34}
35
36pub mod parties {
37 include!(concat!(env!("OUT_DIR"), "/parties.rs"));
38}
39
40pub mod message {
41 include!(concat!(env!("OUT_DIR"), "/message.rs"));
42}
43
44pub mod external {
45 include!(concat!(env!("OUT_DIR"), "/external.rs"));
46}
47
48pub mod transact {
49 include!(concat!(env!("OUT_DIR"), "/transact.rs"));
50}
51
52
53pub mod address;
54pub mod hash;
55pub mod block;
56pub mod constants;
57pub mod observation;
58pub mod output;
59pub mod proof;
60pub mod transaction;
61pub mod util;
62pub mod utxo_entry;
63pub mod utxo_id;
64pub mod merkle_proof;
65pub mod response;
66pub mod servers;
67pub mod peers;
68pub mod multiparty;
69pub mod signature;
70pub mod udp;
71pub mod control;
72pub mod public_key;
73pub mod seeds;
74pub mod trust;
75pub mod input;
76pub mod debug_version;
77pub mod transaction_info;
78pub mod exec;
79pub mod contract;
80pub mod weighting;
81pub mod pow;
82pub mod tx_schema_validate;
83pub mod fee_validator;
84pub mod observability;
85pub mod proto_serde;
86pub mod helpers;
87pub mod party;
88pub mod tx;
89pub mod config_data;
90pub mod portfolio;
91pub mod conf;
92pub mod data_folder;
93pub mod errors;
94pub mod peer;
95pub mod explorer;
96pub mod supported_currency;
97pub mod airgap_msg;
98pub mod keys;
99
100impl BytesData {
101 pub fn from(data: Vec<u8>) -> Self {
102 BytesData {
103 value: data,
104 decoder: BytesDecoder::Standard as i32,
105 version: constants::STANDARD_VERSION,
106 }
107 }
108}
109
110pub fn bytes_data(data: Vec<u8>) -> Option<BytesData> {
111 Some(BytesData::from(data))
112}
113
114pub const VERSION: u32 = 0;
115
116pub fn i64_from_string(value: String) -> Result<i64, ErrorInfo> {
117 value.parse::<i64>().map_err(|_| {
118 error_message(
119 ErrorCode::ParseFailure,
120 "unable to parse i64 value from string amount",
121 )
122 })
123}
124
125pub fn from_hex(hex_value: String) -> Result<Vec<u8>, ErrorInfo> {
126 hex::decode(hex_value.clone()).map_err(|e| {
127 error_message(
128 ErrorCode::HexDecodeFailure,
129 format!("Error decoding hex string value to bytes: {} {}", hex_value, e.to_string()),
130 )
131 })
132}
133
134pub fn from_hex_ref(hex_value: &String) -> Result<Vec<u8>, ErrorInfo> {
135 hex::decode(hex_value).map_err(|e| {
136 error_message(
137 ErrorCode::HexDecodeFailure,
138 format!("Error decoding hex string value to bytes: {} {}", hex_value, e.to_string()),
139 )
140 })
141}
142
143pub fn struct_metadata(time: i64) -> Option<StructMetadata> {
152 Some(StructMetadata {
153 time: Some(time),
154 version: VERSION as i32,
155 hash: None,
156 signable_hash: None,
157 signed_hash: None,
158 counter_party_hash: None,
159 confirmation_hash: None,
160 })
161}
162
163pub fn struct_metadata_new() -> Option<StructMetadata> {
164 struct_metadata(times::current_time_millis())
165}
166impl std::fmt::Display for Hash {
244 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245 write!(
246 f,
247 "{}",
248 self.hex()
249 )
250 }
251}
252
253pub trait HashClear {
254 fn hash_clear(&mut self);
255}
256
257pub trait SafeOption<T> {
279 fn safe_get(&self) -> Result<&T, ErrorInfo>;
280 fn safe_get_msg<S: Into<String>>(&self, msg: S) -> Result<&T, ErrorInfo>;
281 fn ok_msg(self, err: impl Into<String>) -> Result<T, ErrorInfo>;
284}
285impl<T> SafeOption<T> for Option<T> {
308 fn safe_get(&self) -> Result<&T, ErrorInfo> {
309 self.as_ref().ok_or(error_message(
310 ErrorCode::MissingField,
311 "unspecified optional value",
312 ))
313 }
314 fn safe_get_msg<S: Into<String>>(&self, msg: S) -> Result<&T, ErrorInfo> {
315 self .as_ref()
317 .ok_or(error_message(
318 ErrorCode::MissingField,
319 format!("{} option empty", msg.into()),
320 ))
321 }
322 fn ok_msg(self, err: impl Into<String>) -> RgResult<T> {
323 match self {
324 Some(v) => Ok(v),
325 None => Err(error_info(err.into())),
326 }
327 }
328
329}
330
331pub fn response_metadata() -> Option<ResponseMetadata> {
332 let mut response_metadata = ResponseMetadata::default();
333 response_metadata.success = true;
334 Some(response_metadata)
335}
336
337#[test]
338fn bool_defaults() {
339 let metadata = ResponseMetadata::default();
340 println!("metadata: {:?}", metadata);
341 assert_eq!(false, metadata.success);
342}
343
344
345pub trait ErrorInfoContext<T, E> {
346 fn error_info<C: Into<String>>(self, context: C) -> Result<T, ErrorInfo>
348 where
349 C: Display + Send + Sync + 'static;
350 fn error_msg<C: Into<String>>(self, code: ErrorCode, context: C) -> Result<T, ErrorInfo>
351 where
352 C: Display + Send + Sync + 'static;
353
354}
355
356impl<T, E> ErrorInfoContext<T, E> for Result<T, E>
357 where
358 E: std::error::Error + Send + Sync + 'static,
359{
360 fn error_info<C: Into<String>>(self, context: C) -> Result<T, ErrorInfo>
361 where
362 C: Display + Send + Sync + 'static {
363 self.map_err(|e| error_msg(ErrorCode::UnknownError, context.into(), e.to_string()))
367 }
368
369 fn error_msg<C: Into<String>>(self, code: ErrorCode, context: C) -> Result<T, ErrorInfo> where C: Display + Send + Sync + 'static {
370 self.map_err(|e| error_msg(code, context.into(), e.to_string()))
371 }
372}
373
374
375pub fn error_info<S: Into<String>>(message: S) -> ErrorInfo {
376 error_message(crate::structs::ErrorCode::UnknownError, message.into())
377}
378
379pub fn error_code(code: ErrorCode) -> ErrorInfo {
380 error_message(code, "".to_string())
381}
382
383pub fn slice_vec_eager<T>(vec: Vec<T>, start: usize, end: usize) -> Vec<T>
384where T : Clone {
385 let mut ret = vec![];
386 for (i, v) in vec.iter().enumerate() {
388 if i >= start && i <= end {
389 ret.push(v.clone());
390 }
391 }
392 ret
393}
394
395pub fn split_to_str(vec: String, splitter: &str) -> Vec<String> {
396 let mut ret = vec![];
397 for seg in vec.split(splitter) {
398 ret.push(seg.to_string());
399 }
400 ret
401}
402
403pub fn error_msg<S: Into<String>, P: Into<String>>(code: ErrorCode, message: S, lib_message: P) -> ErrorInfo {
404
405 static IS_CAPTURING: AtomicBool = AtomicBool::new(false);
407
408 let stack = if !IS_CAPTURING.swap(true, Ordering::SeqCst) {
409
410 let stacktrace = format!("{:?}", Backtrace::new());
411 let stacktrace_abridged: Vec<String> = split_to_str(stacktrace, "\n");
412 let trace = slice_vec_eager(stacktrace_abridged, 0, 50).join("\n").to_string();
413 IS_CAPTURING.store(false, Ordering::SeqCst);
415 trace
416 } else {
417 "Nested error - backtrace skipped".to_string()
418 };
419
420 let details = task_local_error_details();
421
422 ErrorInfo {
423 code: code as i32,
424 description: "".to_string(),
426 description_extended: "".to_string(),
427 message: message.into(),
428 details,
429 retriable: false,
430 stacktrace: stack,
431 lib_message: lib_message.into(),
432 abort: false,
433 skip_logging: false,
434 internal_log_level: None
435 }
436}
437
438pub fn error_message<S: Into<String>>(error_code: structs::ErrorCode, message: S) -> ErrorInfo {
439 error_msg(error_code, message, "".to_string())
440}
441
442pub fn empty_public_response() -> PublicResponse {
443 PublicResponse {
444 response_metadata: None,
445 submit_transaction_response: None,
446 query_transaction_response: None,
447 about_node_response: None,
448 query_addresses_response: None,
449 faucet_response: None,
450 recent_transactions_response: None,
451 hash_search_response: None
452 }
453}
454
455
456pub fn empty_public_request() -> PublicRequest {
457 PublicRequest {
458 submit_transaction_request: None,
459 query_transaction_request: None,
460 about_node_request: None,
461 query_addresses_request: None,
462 faucet_request: None,
463 recent_transactions_request: None,
464 hash_search_request: None
465 }
466}
467
468pub fn signature_data(data: Vec<u8>) -> Option<crate::structs::Signature> {
469 Some(structs::Signature {
470 bytes: bytes_data(data),
471 signature_type: SignatureType::Ecdsa as i32,
472 rsv: None
473 })
474}
475
476pub fn decode_hex(h: String) -> Result<Vec<u8>, ErrorInfo> {
477 from_hex(h)
478}
479
480
481impl PeerMetadata {
482 pub fn proto_serialize(&self) -> Vec<u8> {
483 return self.encode_to_vec();
484 }
485
486 pub fn proto_deserialize(bytes: Vec<u8>) -> Result<Self, DecodeError> {
487 return PeerMetadata::decode(&*bytes);
488 }
489
490}
491
492impl HashClear for Request {
493 fn hash_clear(&mut self) {
494
495 self.proof = None;
496 self.origin = None;
497
498 }
499}
500
501impl Request {
502 pub fn serialize(&self) -> Vec<u8> {
503 return self.encode_to_vec();
504 }
505
506 pub fn deserialize(bytes: Vec<u8>) -> Result<Self, DecodeError> {
507 return Request::decode(&*bytes);
508 }
509
510 pub fn empty() -> Self {
511 Request::default()
512 }
513
514 pub fn about(&mut self) -> Self {
515 self.about_node_request = Some(AboutNodeRequest{verbose: true});
516 self.clone()
517 }
518
519 pub fn with_metadata(mut self, node_metadata: NodeMetadata) -> Request {
520 self.node_metadata = Some(node_metadata);
521 self
522 }
523
524 pub fn auth_required(&self) -> bool {
525 self.initiate_keygen.is_some() || self.initiate_signing.is_some()
526 }
527
528}
529
530
531
532#[cfg(test)]
533mod tests {
534 #[test]
535 fn it_works() {
536 }
539}
540
541impl NetworkEnvironment {
542
543 pub fn btc_explorer_link(&self) -> String {
544 let mut net = "testnet/";
545 if self.is_main() {
546 net = "";
547 }
548 format!("https://blockstream.info/{net}")
549 }
550
551 pub fn btc_address_link(&self, address: String) -> String {
552 format!("{}address/{}", self.btc_explorer_link(), address)
553 }
554
555
556 pub fn btc_tx_link(&self, address: String) -> String {
557 format!("{}tx/{}", self.btc_explorer_link(), address)
558 }
559
560 pub fn eth_explorer_link(&self) -> String {
561 let eth_url = if self.is_main() {
562 "https://etherscan.io"
563 } else {
564 "https://sepolia.etherscan.io"
565 };
566 eth_url.to_string()
567 }
568
569 pub fn eth_address_link(&self, eth_address: String) -> String {
570 format!("{}/address/{}", self.eth_explorer_link(), eth_address)
571 }
572
573 pub fn eth_tx_link(&self, txid: String) -> String {
574 format!("{}/tx/{}", self.eth_explorer_link(), txid)
575 }
576
577
578 pub fn explorer_link(&self) -> String {
579 let self_str = self.to_std_string();
580 let pfx = if self.is_main() {
581 "".to_string()
582 } else {
583 format!("{}.", self_str)
584 };
585 format!("https://{}explorer.redgold.io", pfx)
586 }
587
588 pub fn explorer_hash_link(&self, hash: String) -> String {
589 format!("{}/hash/{}", self.explorer_link(), hash)
590 }
591
592 pub fn to_std_string(&self) -> String {
593 format!("{:?}", &self).to_lowercase()
594 }
595 pub fn parse(from_str: String) -> Self {
596 let mut n = from_str.clone();
597 let string2 = lang_util::make_ascii_titlecase(&mut *n);
598 NetworkEnvironment::from_str(&*string2).expect("error parsing network environment")
599 }
600 pub fn parse_safe(from_str: String) -> Result<Self, ErrorInfo> {
601 let mut n = from_str.clone();
602 let string2 = lang_util::make_ascii_titlecase(&mut *n);
603 NetworkEnvironment::from_str(&*string2).error_info("error parsing network environment")
604 }
605
606 pub fn from_std_string(s: impl Into<String>) -> RgResult<Self> {
607 Self::parse_safe(s.into())
608 }
609
610 pub fn status_networks() -> Vec<NetworkEnvironment> {
611 vec![
612 NetworkEnvironment::Main,
613 NetworkEnvironment::Test,
614 NetworkEnvironment::Staging,
615 NetworkEnvironment::Dev,
616 NetworkEnvironment::Predev,
617 ]
618 }
619
620 pub fn gui_networks() -> Vec<NetworkEnvironment> {
621 vec![
622 NetworkEnvironment::Main,
623 NetworkEnvironment::Test,
624 NetworkEnvironment::Staging,
625 NetworkEnvironment::Dev,
626 NetworkEnvironment::Predev,
627 ]
628 }
629
630 pub fn is_local_debug(&self) -> bool {
631 vec![
632 NetworkEnvironment::Debug, NetworkEnvironment::Local
633 ].contains(self)
634 }
635
636 pub fn is_main_stage_network(&self) -> bool {
637 Self::status_networks().contains(self)
638 }
639
640 pub fn is_all(&self) -> bool {
641 self == &NetworkEnvironment::All
642 }
643
644 pub fn is_main(&self) -> bool {
645 self == &NetworkEnvironment::Main
646 }
647 pub fn is_dev(&self) -> bool {
648 self == &NetworkEnvironment::Dev
649 }
650
651 pub fn default_port_offset(&self) -> u16 {
652 let port = match self {
653 NetworkEnvironment::Main => {16180}
654 NetworkEnvironment::Test => {16280}
655 NetworkEnvironment::Staging => {16380}
656 NetworkEnvironment::Dev => {16480}
657 NetworkEnvironment::Predev => {16580}
658 NetworkEnvironment::Perf => {16680}
659 NetworkEnvironment::Integration => {16780}
660 NetworkEnvironment::Local => {16880}
661 NetworkEnvironment::Debug => {16980}
662 NetworkEnvironment::All => {17080}
663 };
664 port as u16
665 }
666}
667
668#[test]
669fn network_environment_ser() {
670 use std::str::FromStr;
671 println!("{}", format!("{:?}", NetworkEnvironment::Local).to_lowercase());
672 assert_eq!(NetworkEnvironment::Local.to_std_string(), "local");
673}
674
675impl PublicResponse {
676 pub fn accepted(&self) -> bool {
677 self.response_metadata
678 .as_ref()
679 .map(|x| x.success)
680 .unwrap_or(false)
681 }
682 pub fn error_code(&self) -> Option<i32> {
683 self.response_metadata
684 .clone()
685 .and_then(|r| r.error_info.map(|e| e.code))
686 }
687 pub fn error_info(&self) -> Option<ErrorInfo> {
688 self.response_metadata
689 .clone()
690 .and_then(|r| r.error_info)
691 }
692 pub fn as_error(&self) -> Result<Self, ErrorInfo> {
693 self.error_info().map(|o| Err(o)).unwrap_or(Ok(self.clone()))
694 }
695}
696
697impl PeerId {
698 pub fn from_bytes_direct(bytes: Vec<u8>) -> Self {
699 Self {
700 peer_id: Some(PublicKey::from_bytes_direct_ecdsa(bytes)),
701 }
702 }
703
704 pub fn from_pk(pk: PublicKey) -> Self {
705 Self {
706 peer_id: Some(pk),
707 }
708 }
709
710 pub fn raw_hex_or_from_public_key(&self) -> String {
711 self.peer_id.as_ref().map(|x| x.hex()).unwrap_or("missing peer id".to_string())
712 }
713
714
715}
716
717impl HashClear for StructMetadata {
718 fn hash_clear(&mut self) {
719 self.hash = None;
720 self.signable_hash = None;
721 self.signed_hash = None;
722 self.counter_party_hash = None;
723 self.confirmation_hash = None;
724 }
725}
726
727impl StructMetadata {
728
729}
730
731pub trait ShortString {
732 fn short_string(&self) -> Result<String, ErrorInfo>;
733 fn first_four_last_four_ellipses(&self) -> Result<String, ErrorInfo>;
734 fn last_n(&self, n: impl Into<i32>) -> Result<String, ErrorInfo>;
735 fn first_n(&self, n: impl Into<i32>) -> Result<String, ErrorInfo>;
736}
737
738impl ShortString for String {
739 fn short_string(&self) -> Result<String, ErrorInfo> {
740 self.last_n(6)
741 }
742
743 fn first_four_last_four_ellipses(&self) -> Result<String, ErrorInfo> {
744 let exclude_prefixes = ["0a220a20", "0a230a2103", "0a230a2102"];
745 let stripped = {
746 exclude_prefixes.iter()
747 .find(|&prefix| self.starts_with(prefix))
748 .map(|prefix| self[prefix.len()..].to_string())
749 .unwrap_or_else(|| self.clone())
750 };
751
752 let first_4 = stripped.first_n(4)?;
753 let last_4 = self.last_n(4)?;
754 Ok(format!("{}...{}", first_4, last_4))
755 }
756
757 fn last_n(&self, n: impl Into<i32>) -> Result<String, ErrorInfo> {
758 let len = self.len();
759 let start = (len as i32) - n.into();
760 if start < 0 {
761 return Ok("".to_string());
762 }
764 let start = start as usize;
765 let x = &self[start..len];
766 Ok(x.to_string())
767 }
768
769 fn first_n(&self, n: impl Into<i32>) -> Result<String, ErrorInfo> {
770 let len = self.len();
771 let start = 0i32;
772 let end = n.into() as usize;
773 if len < end {
774 return Err(error_info("string too short to short_string"));
775 }
776 let start = start as usize;
777 let x = &self[start..end];
778 Ok(x.to_string())
779 }
780
781}
782
783pub type RgResult<T> = Result<T, ErrorInfo>;
784
785
786impl HashClear for BytesData {
787 fn hash_clear(&mut self) {}
788}
789
790impl HashClear for structs::ContentionKey {
791 fn hash_clear(&mut self) {}
792}
793
794impl ContentionKey {
795 pub fn contract_request(address: &Address, selector: Option<&StateSelector>) -> ContentionKey {
796 let mut s = Self::default();
797 s.address = Some(address.clone());
798 s.selector = selector.cloned();
799 s
800 }
801}