1use actix::Message;
2use chrono::DateTime;
3use chrono::Utc;
4use std::collections::HashMap;
5use std::sync::atomic::{AtomicBool, Ordering};
6use std::sync::Arc;
7use tracing::debug_span;
8use unc_chain_configs::{ClientConfig, ProtocolConfigView};
9use unc_primitives::errors::EpochError;
10use unc_primitives::hash::CryptoHash;
11use unc_primitives::merkle::{MerklePath, PartialMerkleTree};
12use unc_primitives::network::PeerId;
13use unc_primitives::sharding::ChunkHash;
14use unc_primitives::types::{
15 AccountId, BlockHeight, BlockReference, EpochId, EpochReference, MaybeBlockId, ShardId,
16 TransactionOrReceiptId,
17};
18use unc_primitives::views::validator_power_and_pledge_view::ValidatorPowerAndPledgeView;
19use unc_primitives::views::{
20 AllMinersView, BlockView, ChunkView, DownloadStatusView, EpochValidatorInfo,
21 ExecutionOutcomeWithIdView, GasPriceView, LightClientBlockLiteView, LightClientBlockView,
22 MaintenanceWindowsView, QueryRequest, QueryResponse, ReceiptView, ShardSyncDownloadView,
23 SplitStorageInfoView, StateChangesKindsView, StateChangesRequestView, StateChangesView,
24 SyncStatusView, TxStatusView,
25};
26pub use unc_primitives::views::{StatusResponse, StatusSyncInfo};
27use yansi::Color::Magenta;
28use yansi::Style;
29
30#[derive(Debug, thiserror::Error)]
32pub enum Error {
33 #[error("Chain: {0}")]
34 Chain(#[from] unc_chain_primitives::Error),
35 #[error("Chunk: {0}")]
36 Chunk(#[from] unc_chunks_primitives::Error),
37 #[error("Block Producer: {0}")]
38 BlockProducer(String),
39 #[error("Chunk Producer: {0}")]
40 ChunkProducer(String),
41 #[error("Other: {0}")]
42 Other(String),
43}
44
45impl From<unc_primitives::errors::EpochError> for Error {
46 fn from(err: unc_primitives::errors::EpochError) -> Self {
47 Error::Chain(err.into())
48 }
49}
50
51#[derive(Debug, serde::Serialize)]
52pub struct DownloadStatus {
53 pub start_time: DateTime<Utc>,
54 pub prev_update_time: DateTime<Utc>,
55 pub run_me: Arc<AtomicBool>,
56 pub error: bool,
57 pub done: bool,
58 pub state_requests_count: u64,
59 pub last_target: Option<PeerId>,
60}
61
62impl DownloadStatus {
63 pub fn new(now: DateTime<Utc>) -> Self {
64 Self {
65 start_time: now,
66 prev_update_time: now,
67 run_me: Arc::new(AtomicBool::new(true)),
68 error: false,
69 done: false,
70 state_requests_count: 0,
71 last_target: None,
72 }
73 }
74}
75
76impl Clone for DownloadStatus {
77 fn clone(&self) -> Self {
80 DownloadStatus {
81 start_time: self.start_time,
82 prev_update_time: self.prev_update_time,
83 run_me: Arc::new(AtomicBool::new(self.run_me.load(Ordering::SeqCst))),
85 error: self.error,
86 done: self.done,
87 state_requests_count: self.state_requests_count,
88 last_target: self.last_target.clone(),
89 }
90 }
91}
92
93#[derive(Clone, Debug)]
95pub enum ShardSyncStatus {
96 StateDownloadHeader,
97 StateDownloadParts,
98 StateDownloadScheduling,
99 StateDownloadApplying,
100 StateDownloadComplete,
101 ReshardingScheduling,
102 ReshardingApplying,
103 StateSyncDone,
104}
105
106impl ShardSyncStatus {
107 pub fn repr(&self) -> u8 {
108 match self {
109 ShardSyncStatus::StateDownloadHeader => 0,
110 ShardSyncStatus::StateDownloadParts => 1,
111 ShardSyncStatus::StateDownloadScheduling => 2,
112 ShardSyncStatus::StateDownloadApplying => 3,
113 ShardSyncStatus::StateDownloadComplete => 4,
114 ShardSyncStatus::ReshardingScheduling => 5,
115 ShardSyncStatus::ReshardingApplying => 6,
116 ShardSyncStatus::StateSyncDone => 7,
117 }
118 }
119}
120
121impl PartialEq<Self> for ShardSyncStatus {
123 fn eq(&self, other: &Self) -> bool {
124 std::mem::discriminant(self) == std::mem::discriminant(other)
125 }
126}
127
128impl Eq for ShardSyncStatus {}
129
130impl ToString for ShardSyncStatus {
131 fn to_string(&self) -> String {
132 match self {
133 ShardSyncStatus::StateDownloadHeader => "header".to_string(),
134 ShardSyncStatus::StateDownloadParts => "parts".to_string(),
135 ShardSyncStatus::StateDownloadScheduling => "scheduling".to_string(),
136 ShardSyncStatus::StateDownloadApplying => "applying".to_string(),
137 ShardSyncStatus::StateDownloadComplete => "download complete".to_string(),
138 ShardSyncStatus::ReshardingScheduling => "resharding scheduling".to_string(),
139 ShardSyncStatus::ReshardingApplying => "resharding applying".to_string(),
140 ShardSyncStatus::StateSyncDone => "done".to_string(),
141 }
142 }
143}
144
145impl From<&DownloadStatus> for DownloadStatusView {
146 fn from(status: &DownloadStatus) -> Self {
147 DownloadStatusView { done: status.done, error: status.error }
148 }
149}
150
151impl From<ShardSyncDownload> for ShardSyncDownloadView {
152 fn from(download: ShardSyncDownload) -> Self {
153 ShardSyncDownloadView {
154 downloads: download.downloads.iter().map(|x| x.into()).collect(),
155 status: download.status.to_string(),
156 }
157 }
158}
159
160#[derive(Clone, Debug)]
162pub struct ShardSyncDownload {
163 pub downloads: Vec<DownloadStatus>,
169 pub status: ShardSyncStatus,
170}
171
172impl ShardSyncDownload {
173 pub fn new_download_state_header(now: DateTime<Utc>) -> Self {
175 Self {
176 downloads: vec![DownloadStatus::new(now)],
177 status: ShardSyncStatus::StateDownloadHeader,
178 }
179 }
180
181 pub fn new_download_state_parts(now: DateTime<Utc>, num_parts: u64) -> Self {
183 let mut downloads = Vec::with_capacity(num_parts as usize);
186 for _ in 0..num_parts {
187 downloads.push(DownloadStatus::new(now));
188 }
189 Self { downloads, status: ShardSyncStatus::StateDownloadParts }
190 }
191}
192
193pub fn format_shard_sync_phase_per_shard(
194 new_shard_sync: &HashMap<ShardId, ShardSyncDownload>,
195 use_colour: bool,
196) -> Vec<(ShardId, String)> {
197 new_shard_sync
198 .iter()
199 .map(|(&shard_id, shard_progress)| {
200 (shard_id, format_shard_sync_phase(shard_progress, use_colour))
201 })
202 .collect::<Vec<(_, _)>>()
203}
204
205fn paint(s: &str, style: Style, use_style: bool) -> String {
207 if use_style {
208 style.paint(s).to_string()
209 } else {
210 s.to_string()
211 }
212}
213
214pub fn format_shard_sync_phase(
216 shard_sync_download: &ShardSyncDownload,
217 use_colour: bool,
218) -> String {
219 match &shard_sync_download.status {
220 ShardSyncStatus::StateDownloadHeader => format!(
221 "{} requests sent {}, last target {:?}",
222 paint("HEADER", Magenta.style().bold(), use_colour),
223 shard_sync_download.downloads.get(0).map_or(0, |x| x.state_requests_count),
224 shard_sync_download.downloads.get(0).map_or(None, |x| x.last_target.as_ref()),
225 ),
226 ShardSyncStatus::StateDownloadParts => {
227 let mut num_parts_done = 0;
228 let mut num_parts_not_done = 0;
229 for download in shard_sync_download.downloads.iter() {
230 if download.done {
231 num_parts_done += 1;
232 } else {
233 num_parts_not_done += 1;
234 }
235 }
236 format!("num_parts_done={num_parts_done} num_parts_not_done={num_parts_not_done}")
237 }
238 status => format!("{status:?}"),
239 }
240}
241
242#[derive(Clone)]
243pub struct StateSyncStatus {
244 pub sync_hash: CryptoHash,
245 pub sync_status: HashMap<ShardId, ShardSyncDownload>,
246}
247
248impl std::fmt::Debug for StateSyncStatus {
250 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
251 if f.alternate() {
252 write!(
253 f,
254 "StateSyncStatus {{ sync_hash: {:?}, shard_sync: {:?} }}",
255 self.sync_hash,
256 format_shard_sync_phase_per_shard(&self.sync_status, false)
257 )
258 } else {
259 write!(
260 f,
261 "StateSyncStatus {{ sync_hash: {:?}, sync_status: {:?} }}",
262 self.sync_hash, self.sync_status
263 )
264 }
265 }
266}
267
268#[derive(Clone, Debug, strum::AsRefStr)]
270pub enum SyncStatus {
271 AwaitingPeers,
273 NoSync,
275 EpochSync { epoch_ord: u64 },
279 HeaderSync {
281 start_height: BlockHeight,
284 current_height: BlockHeight,
286 highest_height: BlockHeight,
288 },
289 StateSync(StateSyncStatus),
291 StateSyncDone,
293 BlockSync {
295 start_height: BlockHeight,
298 current_height: BlockHeight,
300 highest_height: BlockHeight,
302 },
303}
304
305impl SyncStatus {
306 pub fn as_variant_name(&self) -> &str {
308 self.as_ref()
309 }
310
311 pub fn is_syncing(&self) -> bool {
313 match self {
314 SyncStatus::NoSync => false,
315 _ => true,
316 }
317 }
318
319 pub fn repr(&self) -> u8 {
320 match self {
321 SyncStatus::NoSync => 0,
323 SyncStatus::AwaitingPeers => 1,
324 SyncStatus::EpochSync { .. } => 2,
325 SyncStatus::HeaderSync { .. } => 3,
326 SyncStatus::StateSync(_) => 4,
327 SyncStatus::StateSyncDone => 5,
328 SyncStatus::BlockSync { .. } => 6,
329 }
330 }
331
332 pub fn start_height(&self) -> Option<BlockHeight> {
333 match self {
334 SyncStatus::HeaderSync { start_height, .. } => Some(*start_height),
335 SyncStatus::BlockSync { start_height, .. } => Some(*start_height),
336 _ => None,
337 }
338 }
339
340 pub fn update(&mut self, new_value: Self) {
341 let _span =
342 debug_span!(target: "sync", "update_sync_status", old_value = ?self, ?new_value)
343 .entered();
344 *self = new_value;
345 }
346}
347
348impl From<SyncStatus> for SyncStatusView {
349 fn from(status: SyncStatus) -> Self {
350 match status {
351 SyncStatus::AwaitingPeers => SyncStatusView::AwaitingPeers,
352 SyncStatus::NoSync => SyncStatusView::NoSync,
353 SyncStatus::EpochSync { epoch_ord } => SyncStatusView::EpochSync { epoch_ord },
354 SyncStatus::HeaderSync { start_height, current_height, highest_height } => {
355 SyncStatusView::HeaderSync { start_height, current_height, highest_height }
356 }
357 SyncStatus::StateSync(state_sync_status) => SyncStatusView::StateSync(
358 state_sync_status.sync_hash,
359 state_sync_status
360 .sync_status
361 .into_iter()
362 .map(|(shard_id, shard_sync)| (shard_id, shard_sync.into()))
363 .collect(),
364 ),
365 SyncStatus::StateSyncDone => SyncStatusView::StateSyncDone,
366 SyncStatus::BlockSync { start_height, current_height, highest_height } => {
367 SyncStatusView::BlockSync { start_height, current_height, highest_height }
368 }
369 }
370 }
371}
372
373#[derive(Debug)]
375pub struct GetProvider(pub EpochId, pub BlockHeight);
376
377#[derive(thiserror::Error, Debug)]
378pub enum GetProviderError {
379 #[error("IO Error: {error_message}")]
380 IOError { error_message: String },
381 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
382 UnknownBlock { error_message: String },
383 #[error("There are no fully synchronized blocks yet")]
384 NotSyncedYet,
385 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
390 Unreachable { error_message: String },
391}
392
393impl From<unc_chain_primitives::Error> for crate::types::GetProviderError {
394 fn from(error: unc_chain_primitives::Error) -> Self {
395 match error {
396 unc_chain_primitives::Error::IOErr(error) => {
397 Self::IOError { error_message: error.to_string() }
398 }
399 unc_chain_primitives::Error::DBNotFoundErr(error_message) => {
400 Self::UnknownBlock { error_message }
401 }
402 _ => Self::Unreachable { error_message: error.to_string() },
403 }
404 }
405}
406
407impl From<EpochError> for GetProviderError {
408 fn from(error: EpochError) -> Self {
409 Self::IOError { error_message: error.to_string() }
410 }
411}
412
413impl Message for crate::types::GetProvider {
414 type Result = Result<AccountId, crate::types::GetProviderError>;
415}
416
417#[derive(Debug)]
419pub struct GetAllMiners(pub CryptoHash);
420
421#[derive(thiserror::Error, Debug)]
422pub enum GetAllMinersError {
423 #[error("IO Error: {error_message}")]
424 IOError { error_message: String },
425 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
426 UnknownBlock { error_message: String },
427 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
432 Unreachable { error_message: String },
433}
434
435impl From<unc_chain_primitives::Error> for crate::types::GetAllMinersError {
436 fn from(error: unc_chain_primitives::Error) -> Self {
437 match error {
438 unc_chain_primitives::Error::IOErr(error) => {
439 Self::IOError { error_message: error.to_string() }
440 }
441 unc_chain_primitives::Error::DBNotFoundErr(error_message) => {
442 Self::UnknownBlock { error_message }
443 }
444 _ => Self::Unreachable { error_message: error.to_string() },
445 }
446 }
447}
448
449impl From<EpochError> for crate::types::GetAllMinersError {
450 fn from(error: EpochError) -> Self {
451 Self::IOError { error_message: error.to_string() }
452 }
453}
454
455impl Message for crate::types::GetAllMiners {
456 type Result = Result<AllMinersView, crate::types::GetAllMinersError>;
457}
458
459#[derive(Debug)]
461pub struct GetBlock(pub BlockReference);
462
463#[derive(thiserror::Error, Debug)]
464pub enum GetBlockError {
465 #[error("IO Error: {error_message}")]
466 IOError { error_message: String },
467 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
468 UnknownBlock { error_message: String },
469 #[error("There are no fully synchronized blocks yet")]
470 NotSyncedYet,
471 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
476 Unreachable { error_message: String },
477}
478
479impl From<unc_chain_primitives::Error> for GetBlockError {
480 fn from(error: unc_chain_primitives::Error) -> Self {
481 match error {
482 unc_chain_primitives::Error::IOErr(error) => {
483 Self::IOError { error_message: error.to_string() }
484 }
485 unc_chain_primitives::Error::DBNotFoundErr(error_message) => {
486 Self::UnknownBlock { error_message }
487 }
488 _ => Self::Unreachable { error_message: error.to_string() },
489 }
490 }
491}
492
493impl GetBlock {
494 pub fn latest() -> Self {
495 Self(BlockReference::latest())
496 }
497}
498
499impl Message for GetBlock {
500 type Result = Result<BlockView, GetBlockError>;
501}
502
503#[derive(Debug)]
505pub struct GetBlockWithMerkleTree(pub BlockReference);
506
507impl GetBlockWithMerkleTree {
508 pub fn latest() -> Self {
509 Self(BlockReference::latest())
510 }
511}
512
513impl Message for GetBlockWithMerkleTree {
514 type Result = Result<(BlockView, Arc<PartialMerkleTree>), GetBlockError>;
515}
516
517#[derive(Debug)]
519pub enum GetChunk {
520 Height(BlockHeight, ShardId),
521 BlockHash(CryptoHash, ShardId),
522 ChunkHash(ChunkHash),
523}
524
525impl Message for GetChunk {
526 type Result = Result<ChunkView, GetChunkError>;
527}
528
529#[derive(thiserror::Error, Debug)]
530pub enum GetChunkError {
531 #[error("IO Error: {error_message}")]
532 IOError { error_message: String },
533 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
534 UnknownBlock { error_message: String },
535 #[error("Shard ID {shard_id} is invalid")]
536 InvalidShardId { shard_id: u64 },
537 #[error("Chunk with hash {chunk_hash:?} has never been observed on this node")]
538 UnknownChunk { chunk_hash: ChunkHash },
539 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
544 Unreachable { error_message: String },
545}
546
547impl From<unc_chain_primitives::Error> for GetChunkError {
548 fn from(error: unc_chain_primitives::Error) -> Self {
549 match error {
550 unc_chain_primitives::Error::IOErr(error) => {
551 Self::IOError { error_message: error.to_string() }
552 }
553 unc_chain_primitives::Error::DBNotFoundErr(error_message) => {
554 Self::UnknownBlock { error_message }
555 }
556 unc_chain_primitives::Error::InvalidShardId(shard_id) => {
557 Self::InvalidShardId { shard_id }
558 }
559 unc_chain_primitives::Error::ChunkMissing(chunk_hash) => {
560 Self::UnknownChunk { chunk_hash }
561 }
562 _ => Self::Unreachable { error_message: error.to_string() },
563 }
564 }
565}
566
567#[derive(Clone, Debug)]
569pub struct Query {
570 pub block_reference: BlockReference,
571 pub request: QueryRequest,
572}
573
574impl Query {
575 pub fn new(block_reference: BlockReference, request: QueryRequest) -> Self {
576 Query { block_reference, request }
577 }
578}
579
580impl Message for Query {
581 type Result = Result<QueryResponse, QueryError>;
582}
583
584#[derive(thiserror::Error, Debug)]
585pub enum QueryError {
586 #[error("There are no fully synchronized blocks on the node yet")]
587 NoSyncedBlocks,
588 #[error("The node does not track the shard ID {requested_shard_id}")]
589 UnavailableShard { requested_shard_id: unc_primitives::types::ShardId },
590 #[error("Account ID {requested_account_id} is invalid")]
591 InvalidAccount {
592 requested_account_id: unc_primitives::types::AccountId,
593 block_height: unc_primitives::types::BlockHeight,
594 block_hash: unc_primitives::hash::CryptoHash,
595 },
596 #[error(
597 "Account {requested_account_id} does not exist while viewing at block #{block_height}"
598 )]
599 UnknownAccount {
600 requested_account_id: unc_primitives::types::AccountId,
601 block_height: unc_primitives::types::BlockHeight,
602 block_hash: unc_primitives::hash::CryptoHash,
603 },
604 #[error("Chip {public_key} does not exist while viewing at block #{block_height}")]
605 UnknownChip {
606 public_key: unc_crypto::PublicKey,
607 block_height: unc_primitives::types::BlockHeight,
608 block_hash: unc_primitives::hash::CryptoHash,
609 },
610 #[error(
611 "Contract code for contract ID {contract_account_id} has never been observed on the node at block #{block_height}"
612 )]
613 NoContractCode {
614 contract_account_id: unc_primitives::types::AccountId,
615 block_height: unc_primitives::types::BlockHeight,
616 block_hash: unc_primitives::hash::CryptoHash,
617 },
618 #[error("State of contract {contract_account_id} is too large to be viewed")]
619 TooLargeContractState {
620 contract_account_id: unc_primitives::types::AccountId,
621 block_height: unc_primitives::types::BlockHeight,
622 block_hash: unc_primitives::hash::CryptoHash,
623 },
624 #[error("Access key for public key {public_key} has never been observed on the node at block #{block_height}")]
625 UnknownAccessKey {
626 public_key: unc_crypto::PublicKey,
627 block_height: unc_primitives::types::BlockHeight,
628 block_hash: unc_primitives::hash::CryptoHash,
629 },
630 #[error("Function call returned an error: {vm_error}")]
631 ContractExecutionError {
632 vm_error: String,
633 block_height: unc_primitives::types::BlockHeight,
634 block_hash: unc_primitives::hash::CryptoHash,
635 },
636 #[error("The node reached its limits. Try again later. More details: {error_message}")]
637 InternalError { error_message: String },
638 #[error(
639 "The data for block #{block_height} is garbage collected on this node, use an archival node to fetch historical data"
640 )]
641 GarbageCollectedBlock {
642 block_height: unc_primitives::types::BlockHeight,
643 block_hash: unc_primitives::hash::CryptoHash,
644 },
645 #[error("Block either has never been observed on the node or has been garbage collected: {block_reference:?}")]
646 UnknownBlock { block_reference: unc_primitives::types::BlockReference },
647 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
652 Unreachable { error_message: String },
653}
654
655#[derive(Debug)]
656pub struct Status {
657 pub is_health_check: bool,
658 pub detailed: bool,
660}
661
662#[derive(thiserror::Error, Debug)]
663pub enum StatusError {
664 #[error("Node is syncing")]
665 NodeIsSyncing,
666 #[error("No blocks for {elapsed:?}")]
667 NoNewBlocks { elapsed: std::time::Duration },
668 #[error("Epoch Out Of Bounds {epoch_id:?}")]
669 EpochOutOfBounds { epoch_id: unc_primitives::types::EpochId },
670 #[error("The node reached its limits. Try again later. More details: {error_message}")]
671 InternalError { error_message: String },
672 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
677 Unreachable { error_message: String },
678}
679
680impl From<unc_chain_primitives::error::Error> for StatusError {
681 fn from(error: unc_chain_primitives::error::Error) -> Self {
682 match error {
683 unc_chain_primitives::error::Error::IOErr(error) => {
684 Self::InternalError { error_message: error.to_string() }
685 }
686 unc_chain_primitives::error::Error::DBNotFoundErr(error_message)
687 | unc_chain_primitives::error::Error::ValidatorError(error_message) => {
688 Self::InternalError { error_message }
689 }
690 unc_chain_primitives::error::Error::EpochOutOfBounds(epoch_id) => {
691 Self::EpochOutOfBounds { epoch_id }
692 }
693 _ => Self::Unreachable { error_message: error.to_string() },
694 }
695 }
696}
697
698impl Message for Status {
699 type Result = Result<StatusResponse, StatusError>;
700}
701
702#[derive(Debug)]
703pub struct GetNextLightClientBlock {
704 pub last_block_hash: CryptoHash,
705}
706
707#[derive(thiserror::Error, Debug)]
708pub enum GetNextLightClientBlockError {
709 #[error("Internal error: {error_message}")]
710 InternalError { error_message: String },
711 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
712 UnknownBlock { error_message: String },
713 #[error("Epoch Out Of Bounds {epoch_id:?}")]
714 EpochOutOfBounds { epoch_id: unc_primitives::types::EpochId },
715 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
720 Unreachable { error_message: String },
721}
722
723impl From<unc_chain_primitives::error::Error> for GetNextLightClientBlockError {
724 fn from(error: unc_chain_primitives::error::Error) -> Self {
725 match error {
726 unc_chain_primitives::error::Error::DBNotFoundErr(error_message) => {
727 Self::UnknownBlock { error_message }
728 }
729 unc_chain_primitives::error::Error::IOErr(error) => {
730 Self::InternalError { error_message: error.to_string() }
731 }
732 unc_chain_primitives::error::Error::EpochOutOfBounds(epoch_id) => {
733 Self::EpochOutOfBounds { epoch_id }
734 }
735 _ => Self::Unreachable { error_message: error.to_string() },
736 }
737 }
738}
739
740impl Message for GetNextLightClientBlock {
741 type Result = Result<Option<Arc<LightClientBlockView>>, GetNextLightClientBlockError>;
742}
743
744#[derive(Debug)]
745pub struct GetNetworkInfo {}
746
747impl Message for GetNetworkInfo {
748 type Result = Result<NetworkInfoResponse, String>;
749}
750
751#[derive(Debug)]
752pub struct GetGasPrice {
753 pub block_id: MaybeBlockId,
754}
755
756impl Message for GetGasPrice {
757 type Result = Result<GasPriceView, GetGasPriceError>;
758}
759
760#[derive(thiserror::Error, Debug)]
761pub enum GetGasPriceError {
762 #[error("Internal error: {error_message}")]
763 InternalError { error_message: String },
764 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
765 UnknownBlock { error_message: String },
766 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
771 Unreachable { error_message: String },
772}
773
774impl From<unc_chain_primitives::Error> for GetGasPriceError {
775 fn from(error: unc_chain_primitives::Error) -> Self {
776 match error {
777 unc_chain_primitives::Error::IOErr(error) => {
778 Self::InternalError { error_message: error.to_string() }
779 }
780 unc_chain_primitives::Error::DBNotFoundErr(error_message) => {
781 Self::UnknownBlock { error_message }
782 }
783 _ => Self::Unreachable { error_message: error.to_string() },
784 }
785 }
786}
787
788#[derive(Clone, Debug)]
789pub struct PeerInfo {
790 pub id: PeerId,
791 pub addr: Option<std::net::SocketAddr>,
792 pub account_id: Option<AccountId>,
793}
794
795#[derive(Clone, Debug)]
796pub struct KnownProducer {
797 pub account_id: AccountId,
798 pub addr: Option<std::net::SocketAddr>,
799 pub peer_id: PeerId,
800 pub next_hops: Option<Vec<PeerId>>,
801}
802
803#[derive(Debug)]
804pub struct NetworkInfoResponse {
805 pub connected_peers: Vec<PeerInfo>,
806 pub num_connected_peers: usize,
807 pub peer_max_count: u32,
808 pub sent_bytes_per_sec: u64,
809 pub received_bytes_per_sec: u64,
810 pub known_producers: Vec<KnownProducer>,
812}
813
814#[derive(Debug)]
816pub struct TxStatus {
817 pub tx_hash: CryptoHash,
818 pub signer_account_id: AccountId,
819 pub fetch_receipt: bool,
820}
821
822#[derive(Debug)]
823pub enum TxStatusError {
824 ChainError(unc_chain_primitives::Error),
825 MissingTransaction(CryptoHash),
826 InternalError(String),
827 TimeoutError,
828}
829
830impl From<unc_chain_primitives::Error> for TxStatusError {
831 fn from(error: unc_chain_primitives::Error) -> Self {
832 Self::ChainError(error)
833 }
834}
835
836impl Message for TxStatus {
837 type Result = Result<TxStatusView, TxStatusError>;
838}
839
840#[derive(Debug)]
841pub struct GetValidatorInfo {
842 pub epoch_reference: EpochReference,
843}
844
845impl Message for GetValidatorInfo {
846 type Result = Result<EpochValidatorInfo, GetValidatorInfoError>;
847}
848
849#[derive(thiserror::Error, Debug)]
850pub enum GetProviderInfoError {
851 #[error("IO Error: {0}")]
852 IOError(String),
853 #[error("Unknown block")]
854 UnknownBlock,
855 #[error("Provider info unavailable")]
856 ProviderInfoUnavailable,
857 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {0}")]
862 Unreachable(String),
863}
864
865impl From<unc_chain_primitives::Error> for crate::types::GetProviderInfoError {
866 fn from(error: unc_chain_primitives::Error) -> Self {
867 match error {
868 unc_chain_primitives::Error::DBNotFoundErr(_)
869 | unc_chain_primitives::Error::BlockOutOfBounds(_) => Self::UnknownBlock,
870 unc_chain_primitives::Error::IOErr(s) => Self::IOError(s.to_string()),
871 _ => Self::Unreachable(error.to_string()),
872 }
873 }
874}
875#[derive(thiserror::Error, Debug)]
876pub enum GetValidatorInfoError {
877 #[error("IO Error: {0}")]
878 IOError(String),
879 #[error("Unknown epoch")]
880 UnknownEpoch,
881 #[error("Validator info unavailable")]
882 ValidatorInfoUnavailable,
883 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {0}")]
888 Unreachable(String),
889}
890
891impl From<unc_chain_primitives::Error> for GetValidatorInfoError {
892 fn from(error: unc_chain_primitives::Error) -> Self {
893 match error {
894 unc_chain_primitives::Error::DBNotFoundErr(_)
895 | unc_chain_primitives::Error::EpochOutOfBounds(_) => Self::UnknownEpoch,
896 unc_chain_primitives::Error::IOErr(s) => Self::IOError(s.to_string()),
897 _ => Self::Unreachable(error.to_string()),
898 }
899 }
900}
901
902#[derive(Debug)]
903pub struct GetValidatorOrdered {
904 pub block_id: MaybeBlockId,
905}
906
907impl Message for GetValidatorOrdered {
908 type Result = Result<Vec<ValidatorPowerAndPledgeView>, GetValidatorInfoError>;
909}
910
911#[derive(Debug)]
912pub struct GetStateChanges {
913 pub block_hash: CryptoHash,
914 pub state_changes_request: StateChangesRequestView,
915}
916
917#[derive(thiserror::Error, Debug)]
918pub enum GetStateChangesError {
919 #[error("IO Error: {error_message}")]
920 IOError { error_message: String },
921 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
922 UnknownBlock { error_message: String },
923 #[error("There are no fully synchronized blocks yet")]
924 NotSyncedYet,
925 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
930 Unreachable { error_message: String },
931}
932
933impl From<unc_chain_primitives::Error> for GetStateChangesError {
934 fn from(error: unc_chain_primitives::Error) -> Self {
935 match error {
936 unc_chain_primitives::Error::IOErr(error) => {
937 Self::IOError { error_message: error.to_string() }
938 }
939 unc_chain_primitives::Error::DBNotFoundErr(error_message) => {
940 Self::UnknownBlock { error_message }
941 }
942 _ => Self::Unreachable { error_message: error.to_string() },
943 }
944 }
945}
946
947impl Message for GetStateChanges {
948 type Result = Result<StateChangesView, GetStateChangesError>;
949}
950
951#[derive(Debug)]
952pub struct GetStateChangesInBlock {
953 pub block_hash: CryptoHash,
954}
955
956impl Message for GetStateChangesInBlock {
957 type Result = Result<StateChangesKindsView, GetStateChangesError>;
958}
959
960#[derive(Debug)]
961pub struct GetStateChangesWithCauseInBlock {
962 pub block_hash: CryptoHash,
963}
964
965impl Message for GetStateChangesWithCauseInBlock {
966 type Result = Result<StateChangesView, GetStateChangesError>;
967}
968
969#[derive(Debug)]
970pub struct GetStateChangesWithCauseInBlockForTrackedShards {
971 pub block_hash: CryptoHash,
972 pub epoch_id: EpochId,
973}
974
975impl Message for GetStateChangesWithCauseInBlockForTrackedShards {
976 type Result = Result<HashMap<ShardId, StateChangesView>, GetStateChangesError>;
977}
978
979#[derive(Debug)]
980pub struct GetExecutionOutcome {
981 pub id: TransactionOrReceiptId,
982}
983
984#[derive(thiserror::Error, Debug)]
985pub enum GetExecutionOutcomeError {
986 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
987 UnknownBlock { error_message: String },
988 #[error("Inconsistent state. Total number of shards is {number_or_shards} but the execution outcome is in shard {execution_outcome_shard_id}")]
989 InconsistentState {
990 number_or_shards: usize,
991 execution_outcome_shard_id: unc_primitives::types::ShardId,
992 },
993 #[error("{transaction_or_receipt_id} has not been confirmed")]
994 NotConfirmed { transaction_or_receipt_id: unc_primitives::hash::CryptoHash },
995 #[error("{transaction_or_receipt_id} does not exist")]
996 UnknownTransactionOrReceipt { transaction_or_receipt_id: unc_primitives::hash::CryptoHash },
997 #[error("Node doesn't track the shard where {transaction_or_receipt_id} is executed")]
998 UnavailableShard {
999 transaction_or_receipt_id: unc_primitives::hash::CryptoHash,
1000 shard_id: unc_primitives::types::ShardId,
1001 },
1002 #[error("Internal error: {error_message}")]
1003 InternalError { error_message: String },
1004 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
1009 Unreachable { error_message: String },
1010}
1011
1012impl From<TxStatusError> for GetExecutionOutcomeError {
1013 fn from(error: TxStatusError) -> Self {
1014 match error {
1015 TxStatusError::ChainError(err) => {
1016 Self::InternalError { error_message: err.to_string() }
1017 }
1018 _ => Self::Unreachable { error_message: format!("{:?}", error) },
1019 }
1020 }
1021}
1022
1023impl From<unc_chain_primitives::error::Error> for GetExecutionOutcomeError {
1024 fn from(error: unc_chain_primitives::error::Error) -> Self {
1025 match error {
1026 unc_chain_primitives::Error::IOErr(error) => {
1027 Self::InternalError { error_message: error.to_string() }
1028 }
1029 unc_chain_primitives::Error::DBNotFoundErr(error_message) => {
1030 Self::UnknownBlock { error_message }
1031 }
1032 _ => Self::Unreachable { error_message: error.to_string() },
1033 }
1034 }
1035}
1036
1037pub struct GetExecutionOutcomeResponse {
1038 pub outcome_proof: ExecutionOutcomeWithIdView,
1039 pub outcome_root_proof: MerklePath,
1040}
1041
1042impl Message for GetExecutionOutcome {
1043 type Result = Result<GetExecutionOutcomeResponse, GetExecutionOutcomeError>;
1044}
1045
1046#[derive(Debug)]
1047pub struct GetExecutionOutcomesForBlock {
1048 pub block_hash: CryptoHash,
1049}
1050
1051impl Message for GetExecutionOutcomesForBlock {
1052 type Result = Result<HashMap<ShardId, Vec<ExecutionOutcomeWithIdView>>, String>;
1053}
1054
1055#[derive(Debug)]
1056pub struct GetBlockProof {
1057 pub block_hash: CryptoHash,
1058 pub head_block_hash: CryptoHash,
1059}
1060
1061pub struct GetBlockProofResponse {
1062 pub block_header_lite: LightClientBlockLiteView,
1063 pub proof: MerklePath,
1064}
1065
1066#[derive(thiserror::Error, Debug)]
1067pub enum GetBlockProofError {
1068 #[error("Block either has never been observed on the node or has been garbage collected: {error_message}")]
1069 UnknownBlock { error_message: String },
1070 #[error("Internal error: {error_message}")]
1071 InternalError { error_message: String },
1072 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {error_message}")]
1077 Unreachable { error_message: String },
1078}
1079
1080impl From<unc_chain_primitives::error::Error> for GetBlockProofError {
1081 fn from(error: unc_chain_primitives::error::Error) -> Self {
1082 match error {
1083 unc_chain_primitives::error::Error::DBNotFoundErr(error_message) => {
1084 Self::UnknownBlock { error_message }
1085 }
1086 unc_chain_primitives::error::Error::Other(error_message) => {
1087 Self::InternalError { error_message }
1088 }
1089 err => Self::Unreachable { error_message: err.to_string() },
1090 }
1091 }
1092}
1093
1094impl Message for GetBlockProof {
1095 type Result = Result<GetBlockProofResponse, GetBlockProofError>;
1096}
1097
1098#[derive(Debug)]
1099pub struct GetReceipt {
1100 pub receipt_id: CryptoHash,
1101}
1102
1103#[derive(thiserror::Error, Debug)]
1104pub enum GetReceiptError {
1105 #[error("IO Error: {0}")]
1106 IOError(String),
1107 #[error("Receipt with id {0} has never been observed on this node")]
1108 UnknownReceipt(unc_primitives::hash::CryptoHash),
1109 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {0}")]
1114 Unreachable(String),
1115}
1116
1117impl From<unc_chain_primitives::Error> for GetReceiptError {
1118 fn from(error: unc_chain_primitives::Error) -> Self {
1119 match error {
1120 unc_chain_primitives::Error::IOErr(error) => Self::IOError(error.to_string()),
1121 _ => Self::Unreachable(error.to_string()),
1122 }
1123 }
1124}
1125
1126impl Message for GetReceipt {
1127 type Result = Result<Option<ReceiptView>, GetReceiptError>;
1128}
1129
1130#[derive(Debug)]
1131pub struct GetProtocolConfig(pub BlockReference);
1132
1133impl Message for GetProtocolConfig {
1134 type Result = Result<ProtocolConfigView, GetProtocolConfigError>;
1135}
1136
1137#[derive(thiserror::Error, Debug)]
1138pub enum GetProtocolConfigError {
1139 #[error("IO Error: {0}")]
1140 IOError(String),
1141 #[error("Block has never been observed: {0}")]
1142 UnknownBlock(String),
1143 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {0}")]
1148 Unreachable(String),
1149}
1150
1151impl From<unc_chain_primitives::Error> for GetProtocolConfigError {
1152 fn from(error: unc_chain_primitives::Error) -> Self {
1153 match error {
1154 unc_chain_primitives::Error::IOErr(error) => Self::IOError(error.to_string()),
1155 unc_chain_primitives::Error::DBNotFoundErr(s) => Self::UnknownBlock(s),
1156 _ => Self::Unreachable(error.to_string()),
1157 }
1158 }
1159}
1160
1161#[derive(Debug)]
1162pub struct GetMaintenanceWindows {
1163 pub account_id: AccountId,
1164}
1165
1166impl Message for GetMaintenanceWindows {
1167 type Result = Result<MaintenanceWindowsView, GetMaintenanceWindowsError>;
1168}
1169
1170#[derive(thiserror::Error, Debug)]
1171pub enum GetMaintenanceWindowsError {
1172 #[error("IO Error: {0}")]
1173 IOError(String),
1174 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {0}")]
1175 Unreachable(String),
1176}
1177
1178impl From<unc_chain_primitives::Error> for GetMaintenanceWindowsError {
1179 fn from(error: unc_chain_primitives::Error) -> Self {
1180 match error {
1181 unc_chain_primitives::Error::IOErr(error) => Self::IOError(error.to_string()),
1182 _ => Self::Unreachable(error.to_string()),
1183 }
1184 }
1185}
1186
1187#[derive(Debug)]
1188pub struct GetClientConfig {}
1189
1190impl Message for GetClientConfig {
1191 type Result = Result<ClientConfig, GetClientConfigError>;
1192}
1193
1194#[derive(thiserror::Error, Debug)]
1195pub enum GetClientConfigError {
1196 #[error("IO Error: {0}")]
1197 IOError(String),
1198 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {0}")]
1203 Unreachable(String),
1204}
1205
1206impl From<unc_chain_primitives::Error> for GetClientConfigError {
1207 fn from(error: unc_chain_primitives::Error) -> Self {
1208 match error {
1209 unc_chain_primitives::Error::IOErr(error) => Self::IOError(error.to_string()),
1210 _ => Self::Unreachable(error.to_string()),
1211 }
1212 }
1213}
1214
1215#[derive(Debug)]
1216pub struct GetSplitStorageInfo {}
1217
1218impl Message for GetSplitStorageInfo {
1219 type Result = Result<SplitStorageInfoView, GetSplitStorageInfoError>;
1220}
1221
1222#[derive(thiserror::Error, Debug)]
1223pub enum GetSplitStorageInfoError {
1224 #[error("IO Error: {0}")]
1225 IOError(String),
1226 #[error("It is a bug if you receive this error type, please, report this incident: https://github.com/utnet-org/utility/issues/new/choose. Details: {0}")]
1231 Unreachable(String),
1232}
1233
1234impl From<unc_chain_primitives::Error> for GetSplitStorageInfoError {
1235 fn from(error: unc_chain_primitives::Error) -> Self {
1236 match error {
1237 unc_chain_primitives::Error::IOErr(error) => Self::IOError(error.to_string()),
1238 _ => Self::Unreachable(error.to_string()),
1239 }
1240 }
1241}
1242
1243impl From<std::io::Error> for GetSplitStorageInfoError {
1244 fn from(error: std::io::Error) -> Self {
1245 Self::IOError(error.to_string())
1246 }
1247}
1248
1249#[cfg(feature = "sandbox")]
1250#[derive(Debug)]
1251pub enum SandboxMessage {
1252 SandboxPatchState(Vec<unc_primitives::state_record::StateRecord>),
1253 SandboxPatchStateStatus,
1254 SandboxFastForward(unc_primitives::types::BlockHeightDelta),
1255 SandboxFastForwardStatus,
1256}
1257
1258#[cfg(feature = "sandbox")]
1259#[derive(Eq, PartialEq, Debug, actix::MessageResponse)]
1260pub enum SandboxResponse {
1261 SandboxPatchStateFinished(bool),
1262 SandboxFastForwardFinished(bool),
1263 SandboxFastForwardFailed(String),
1264 SandboxNoResponse,
1265}
1266#[cfg(feature = "sandbox")]
1267impl Message for SandboxMessage {
1268 type Result = SandboxResponse;
1269}